@mindlogic-ai/logician-ui 5.0.0-alpha.24 → 5.0.0-alpha.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"SwitchControl.d.ts","sourceRoot":"","sources":["../../../src/components/Switch/SwitchControl.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAsB,MAAM,kBAAkB,CAAC;AAK9E,eAAO,MAAM,aAAa,uHAkCzB,CAAC"}
1
+ {"version":3,"file":"SwitchControl.d.ts","sourceRoot":"","sources":["../../../src/components/Switch/SwitchControl.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAsB,MAAM,kBAAkB,CAAC;AAS9E,eAAO,MAAM,aAAa,uHA4CzB,CAAC"}
@@ -7,13 +7,26 @@ var react = require('@chakra-ui/react');
7
7
  var disabledControl = require('../../utils/disabledControl.js');
8
8
  var focusRing = require('../../utils/focusRing.js');
9
9
 
10
+ // Drawn as an inset shadow, not a border, so the thumb's travel and the
11
+ // track's size stay exactly what Chakra's recipe computes.
12
+ const OFF_OUTLINE = 'inset 0 0 0 1px var(--chakra-colors-border-control)';
10
13
  const SwitchControl = React.forwardRef((props, ref) => (jsxRuntime.jsx(react.Switch.Control, { ref: ref,
11
- // The off-state track is a meter surface — its extent is the information —
12
- // so it needs a visible fill, not just an edge. bg.muted (gray.100) is
13
- // only ~1.03:1 against the bg.sunken page wash (gray.50) and vanishes
14
- // there; bg.track (gray.300) reads as a filled track on any background.
15
- // The checked state is the self-defining primary.main fill.
16
- bg: "bg.track", _checked: { bg: 'primary.main' }, animationStyle: "feedback", transitionProperty: "background-color", _disabled: { ...disabledControl.disabledControl, cursor: 'not-allowed' }, ...focusRing.focusRing, ...props, children: jsxRuntime.jsx(react.Switch.Thumb
14
+ // Off is drawn the way an unchecked Checkbox is: a bg.surface track with a
15
+ // border.control outline and a border.control thumb, each at least 3:1
16
+ // against what it sits on (WCAG 1.4.11). The previous off state, a
17
+ // bg.track fill with a bg.surface thumb, measured 1.3:1 (light) and
18
+ // 1.4:1 (dark) between thumb and track, so the thumb's position, the only
19
+ // thing that tells off from on, could not be seen.
20
+ // On is success.solid with a success.onSolid thumb. With a black (light) or
21
+ // pale (dark) primary fill, neither state carried colour, and dark-mode
22
+ // "on" read as light-mode "off"; green gives both modes one meaning.
23
+ bg: "bg.surface", boxShadow: OFF_OUTLINE, _checked: { bg: 'success.solid', boxShadow: 'none' }, animationStyle: "feedback", transitionProperty: "background-color, box-shadow", _disabled: { ...disabledControl.disabledControl, cursor: 'not-allowed' }, ...focusRing.focusRing,
24
+ // focusRing's shadow would replace the outline; keep both while off.
25
+ _focusVisible: {
26
+ ...focusRing.focusRing._focusVisible,
27
+ boxShadow: `${OFF_OUTLINE}, ${focusRing.FOCUS_RING_SHADOW}`,
28
+ _checked: { boxShadow: focusRing.FOCUS_RING_SHADOW },
29
+ }, ...props, children: jsxRuntime.jsx(react.Switch.Thumb
17
30
  // A toggle is the metaphor of a physical switch, so the thumb settles
18
31
  // slightly past its stop rather than easing to a halt. Chakra's default
19
32
  // is `translate` over `fast` on a plain curve; `overshoot` is the one
@@ -26,11 +39,10 @@ const SwitchControl = React.forwardRef((props, ref) => (jsxRuntime.jsx(react.Swi
26
39
  // curve that stays legible over the thumb's ~16px of travel, because it
27
40
  // reverses direction — `standard` vs `emphasized` would not.
28
41
  animationStyle: "spring", transitionProperty: "translate",
29
- // Chakra's default is a raw `white` thumb that stays `white` when
30
- // checked via an undefined `colorPalette.contrast`. bg.surface reads
31
- // as the same near-white in light and flips correctly in dark; the
32
- // checked thumb is fg.onPrimary (cream) to match Checkbox/Radio.
33
- bg: "bg.surface", _checked: { bg: 'fg.onPrimary' } }) })));
42
+ // Off: border.control, the same 3:1 control token as the outline.
43
+ // On: success.onSolid, the text colour success buttons put on the same
44
+ // fill (white in light, ink in dark).
45
+ bg: "border.control", _checked: { bg: 'success.onSolid' } }) })));
34
46
  SwitchControl.displayName = 'Switch.Control';
35
47
 
36
48
  exports.SwitchControl = SwitchControl;
@@ -1 +1 @@
1
- {"version":3,"file":"SwitchControl.js","sources":["../../../src/components/Switch/SwitchControl.tsx"],"sourcesContent":[null],"names":["forwardRef","_jsx","ChakraSwitch","disabledControl","focusRing"],"mappings":";;;;;;;;;MAMa,aAAa,GAAGA,gBAAU,CACrC,CAAC,KAAK,EAAE,GAAG,MACTC,cAAA,CAACC,YAAY,CAAC,OAAO,EAAA,EACnB,GAAG,EAAE,GAAG;;;;;;AAMR,IAAA,EAAE,EAAC,UAAU,EACb,QAAQ,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,EAChC,cAAc,EAAC,UAAU,EACzB,kBAAkB,EAAC,kBAAkB,EACrC,SAAS,EAAE,EAAE,GAAGC,+BAAe,EAAE,MAAM,EAAE,aAAa,EAAE,EAAA,GACpDC,mBAAS,EAAA,GACT,KAAK,YAETH,cAAA,CAACC,YAAY,CAAC;;;;;;;;;;;;AAMZ,QAAA,cAAc,EAAC,QAAQ,EACvB,kBAAkB,EAAC,WAAW;;;;;AAK9B,QAAA,EAAE,EAAC,YAAY,EACf,QAAQ,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,EAAA,CAChC,EAAA,CACmB,CACxB;AAEH,aAAa,CAAC,WAAW,GAAG,gBAAgB;;;;"}
1
+ {"version":3,"file":"SwitchControl.js","sources":["../../../src/components/Switch/SwitchControl.tsx"],"sourcesContent":[null],"names":["forwardRef","_jsx","ChakraSwitch","disabledControl","focusRing","FOCUS_RING_SHADOW"],"mappings":";;;;;;;;;AAMA;AACA;AACA,MAAM,WAAW,GAAG,qDAAqD;MAE5D,aAAa,GAAGA,gBAAU,CACrC,CAAC,KAAK,EAAE,GAAG,MACTC,cAAA,CAACC,YAAY,CAAC,OAAO,EAAA,EACnB,GAAG,EAAE,GAAG;;;;;;;;;;AAUR,IAAA,EAAE,EAAC,YAAY,EACf,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,EACpD,cAAc,EAAC,UAAU,EACzB,kBAAkB,EAAC,8BAA8B,EACjD,SAAS,EAAE,EAAE,GAAGC,+BAAe,EAAE,MAAM,EAAE,aAAa,EAAE,KACpDC,mBAAS;;AAEb,IAAA,aAAa,EAAE;QACb,GAAGA,mBAAS,CAAC,aAAa;AAC1B,QAAA,SAAS,EAAE,CAAA,EAAG,WAAW,CAAA,EAAA,EAAKC,2BAAiB,CAAA,CAAE;AACjD,QAAA,QAAQ,EAAE,EAAE,SAAS,EAAEA,2BAAiB,EAAE;AAC3C,KAAA,EAAA,GACG,KAAK,EAAA,QAAA,EAETJ,cAAA,CAACC,YAAY,CAAC;;;;;;;;;;;;AAMZ,QAAA,cAAc,EAAC,QAAQ,EACvB,kBAAkB,EAAC,WAAW;;;;AAI9B,QAAA,EAAE,EAAC,gBAAgB,EACnB,QAAQ,EAAE,EAAE,EAAE,EAAE,iBAAiB,EAAE,EAAA,CACnC,EAAA,CACmB,CACxB;AAEH,aAAa,CAAC,WAAW,GAAG,gBAAgB;;;;"}
@@ -3,15 +3,28 @@ import { jsx } from 'react/jsx-runtime';
3
3
  import { forwardRef } from 'react';
4
4
  import { Switch } from '@chakra-ui/react';
5
5
  import { disabledControl } from '../../utils/disabledControl.mjs';
6
- import { focusRing } from '../../utils/focusRing.mjs';
6
+ import { FOCUS_RING_SHADOW, focusRing } from '../../utils/focusRing.mjs';
7
7
 
8
+ // Drawn as an inset shadow, not a border, so the thumb's travel and the
9
+ // track's size stay exactly what Chakra's recipe computes.
10
+ const OFF_OUTLINE = 'inset 0 0 0 1px var(--chakra-colors-border-control)';
8
11
  const SwitchControl = forwardRef((props, ref) => (jsx(Switch.Control, { ref: ref,
9
- // The off-state track is a meter surface — its extent is the information —
10
- // so it needs a visible fill, not just an edge. bg.muted (gray.100) is
11
- // only ~1.03:1 against the bg.sunken page wash (gray.50) and vanishes
12
- // there; bg.track (gray.300) reads as a filled track on any background.
13
- // The checked state is the self-defining primary.main fill.
14
- bg: "bg.track", _checked: { bg: 'primary.main' }, animationStyle: "feedback", transitionProperty: "background-color", _disabled: { ...disabledControl, cursor: 'not-allowed' }, ...focusRing, ...props, children: jsx(Switch.Thumb
12
+ // Off is drawn the way an unchecked Checkbox is: a bg.surface track with a
13
+ // border.control outline and a border.control thumb, each at least 3:1
14
+ // against what it sits on (WCAG 1.4.11). The previous off state, a
15
+ // bg.track fill with a bg.surface thumb, measured 1.3:1 (light) and
16
+ // 1.4:1 (dark) between thumb and track, so the thumb's position, the only
17
+ // thing that tells off from on, could not be seen.
18
+ // On is success.solid with a success.onSolid thumb. With a black (light) or
19
+ // pale (dark) primary fill, neither state carried colour, and dark-mode
20
+ // "on" read as light-mode "off"; green gives both modes one meaning.
21
+ bg: "bg.surface", boxShadow: OFF_OUTLINE, _checked: { bg: 'success.solid', boxShadow: 'none' }, animationStyle: "feedback", transitionProperty: "background-color, box-shadow", _disabled: { ...disabledControl, cursor: 'not-allowed' }, ...focusRing,
22
+ // focusRing's shadow would replace the outline; keep both while off.
23
+ _focusVisible: {
24
+ ...focusRing._focusVisible,
25
+ boxShadow: `${OFF_OUTLINE}, ${FOCUS_RING_SHADOW}`,
26
+ _checked: { boxShadow: FOCUS_RING_SHADOW },
27
+ }, ...props, children: jsx(Switch.Thumb
15
28
  // A toggle is the metaphor of a physical switch, so the thumb settles
16
29
  // slightly past its stop rather than easing to a halt. Chakra's default
17
30
  // is `translate` over `fast` on a plain curve; `overshoot` is the one
@@ -24,11 +37,10 @@ const SwitchControl = forwardRef((props, ref) => (jsx(Switch.Control, { ref: ref
24
37
  // curve that stays legible over the thumb's ~16px of travel, because it
25
38
  // reverses direction — `standard` vs `emphasized` would not.
26
39
  animationStyle: "spring", transitionProperty: "translate",
27
- // Chakra's default is a raw `white` thumb that stays `white` when
28
- // checked via an undefined `colorPalette.contrast`. bg.surface reads
29
- // as the same near-white in light and flips correctly in dark; the
30
- // checked thumb is fg.onPrimary (cream) to match Checkbox/Radio.
31
- bg: "bg.surface", _checked: { bg: 'fg.onPrimary' } }) })));
40
+ // Off: border.control, the same 3:1 control token as the outline.
41
+ // On: success.onSolid, the text colour success buttons put on the same
42
+ // fill (white in light, ink in dark).
43
+ bg: "border.control", _checked: { bg: 'success.onSolid' } }) })));
32
44
  SwitchControl.displayName = 'Switch.Control';
33
45
 
34
46
  export { SwitchControl };
@@ -1 +1 @@
1
- {"version":3,"file":"SwitchControl.mjs","sources":["../../../src/components/Switch/SwitchControl.tsx"],"sourcesContent":[null],"names":["_jsx","ChakraSwitch"],"mappings":";;;;;;;MAMa,aAAa,GAAG,UAAU,CACrC,CAAC,KAAK,EAAE,GAAG,MACTA,GAAA,CAACC,MAAY,CAAC,OAAO,EAAA,EACnB,GAAG,EAAE,GAAG;;;;;;AAMR,IAAA,EAAE,EAAC,UAAU,EACb,QAAQ,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,EAChC,cAAc,EAAC,UAAU,EACzB,kBAAkB,EAAC,kBAAkB,EACrC,SAAS,EAAE,EAAE,GAAG,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,EAAA,GACpD,SAAS,EAAA,GACT,KAAK,YAETD,GAAA,CAACC,MAAY,CAAC;;;;;;;;;;;;AAMZ,QAAA,cAAc,EAAC,QAAQ,EACvB,kBAAkB,EAAC,WAAW;;;;;AAK9B,QAAA,EAAE,EAAC,YAAY,EACf,QAAQ,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,EAAA,CAChC,EAAA,CACmB,CACxB;AAEH,aAAa,CAAC,WAAW,GAAG,gBAAgB;;;;"}
1
+ {"version":3,"file":"SwitchControl.mjs","sources":["../../../src/components/Switch/SwitchControl.tsx"],"sourcesContent":[null],"names":["_jsx","ChakraSwitch"],"mappings":";;;;;;;AAMA;AACA;AACA,MAAM,WAAW,GAAG,qDAAqD;MAE5D,aAAa,GAAG,UAAU,CACrC,CAAC,KAAK,EAAE,GAAG,MACTA,GAAA,CAACC,MAAY,CAAC,OAAO,EAAA,EACnB,GAAG,EAAE,GAAG;;;;;;;;;;AAUR,IAAA,EAAE,EAAC,YAAY,EACf,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,EACpD,cAAc,EAAC,UAAU,EACzB,kBAAkB,EAAC,8BAA8B,EACjD,SAAS,EAAE,EAAE,GAAG,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,KACpD,SAAS;;AAEb,IAAA,aAAa,EAAE;QACb,GAAG,SAAS,CAAC,aAAa;AAC1B,QAAA,SAAS,EAAE,CAAA,EAAG,WAAW,CAAA,EAAA,EAAK,iBAAiB,CAAA,CAAE;AACjD,QAAA,QAAQ,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE;AAC3C,KAAA,EAAA,GACG,KAAK,EAAA,QAAA,EAETD,GAAA,CAACC,MAAY,CAAC;;;;;;;;;;;;AAMZ,QAAA,cAAc,EAAC,QAAQ,EACvB,kBAAkB,EAAC,WAAW;;;;AAI9B,QAAA,EAAE,EAAC,gBAAgB,EACnB,QAAQ,EAAE,EAAE,EAAE,EAAE,iBAAiB,EAAE,EAAA,CACnC,EAAA,CACmB,CACxB;AAEH,aAAa,CAAC,WAAW,GAAG,gBAAgB;;;;"}
@@ -324,7 +324,7 @@ export declare const SCHEMES: {
324
324
  readonly "success-bg": "#E5EDDD";
325
325
  readonly "success-border": "#C5D4B5";
326
326
  readonly "success-fg": "#556344";
327
- readonly "success-solid": "#5E7A37";
327
+ readonly "success-solid": "#30862D";
328
328
  readonly "success-onSolid": "#FFFFFF";
329
329
  readonly "warning-bg": "#FEE9BC";
330
330
  readonly "warning-border": "#F0CF83";
@@ -506,7 +506,7 @@ export declare const SCHEMES: {
506
506
  readonly "success-bg": "#E5EDDD";
507
507
  readonly "success-border": "#7D8B6E";
508
508
  readonly "success-fg": "#445133";
509
- readonly "success-solid": "#47611D";
509
+ readonly "success-solid": "#036805";
510
510
  readonly "success-onSolid": "#FFFFFF";
511
511
  readonly "warning-bg": "#FEE9BC";
512
512
  readonly "warning-border": "#A28336";
@@ -690,7 +690,7 @@ export declare const SCHEMES: {
690
690
  readonly "success-bg": "#E5EDDD";
691
691
  readonly "success-border": "#C5D4B5";
692
692
  readonly "success-fg": "#556344";
693
- readonly "success-solid": "#5E7A37";
693
+ readonly "success-solid": "#30862D";
694
694
  readonly "success-onSolid": "#FFFFFF";
695
695
  readonly "warning-bg": "#FEE9BC";
696
696
  readonly "warning-border": "#F0CF83";
@@ -872,7 +872,7 @@ export declare const SCHEMES: {
872
872
  readonly "success-bg": "#E5EDDD";
873
873
  readonly "success-border": "#7D8B6E";
874
874
  readonly "success-fg": "#445133";
875
- readonly "success-solid": "#47611D";
875
+ readonly "success-solid": "#036805";
876
876
  readonly "success-onSolid": "#FFFFFF";
877
877
  readonly "warning-bg": "#FEE9BC";
878
878
  readonly "warning-border": "#A28336";
@@ -330,7 +330,7 @@ const SCHEMES = {
330
330
  "success-bg": "#E5EDDD",
331
331
  "success-border": "#C5D4B5",
332
332
  "success-fg": "#556344",
333
- "success-solid": "#5E7A37",
333
+ "success-solid": "#30862D",
334
334
  "success-onSolid": "#FFFFFF",
335
335
  "warning-bg": "#FEE9BC",
336
336
  "warning-border": "#F0CF83",
@@ -512,7 +512,7 @@ const SCHEMES = {
512
512
  "success-bg": "#E5EDDD",
513
513
  "success-border": "#7D8B6E",
514
514
  "success-fg": "#445133",
515
- "success-solid": "#47611D",
515
+ "success-solid": "#036805",
516
516
  "success-onSolid": "#FFFFFF",
517
517
  "warning-bg": "#FEE9BC",
518
518
  "warning-border": "#A28336",
@@ -696,7 +696,7 @@ const SCHEMES = {
696
696
  "success-bg": "#E5EDDD",
697
697
  "success-border": "#C5D4B5",
698
698
  "success-fg": "#556344",
699
- "success-solid": "#5E7A37",
699
+ "success-solid": "#30862D",
700
700
  "success-onSolid": "#FFFFFF",
701
701
  "warning-bg": "#FEE9BC",
702
702
  "warning-border": "#F0CF83",
@@ -878,7 +878,7 @@ const SCHEMES = {
878
878
  "success-bg": "#E5EDDD",
879
879
  "success-border": "#7D8B6E",
880
880
  "success-fg": "#445133",
881
- "success-solid": "#47611D",
881
+ "success-solid": "#036805",
882
882
  "success-onSolid": "#FFFFFF",
883
883
  "warning-bg": "#FEE9BC",
884
884
  "warning-border": "#A28336",
@@ -328,7 +328,7 @@ const SCHEMES = {
328
328
  "success-bg": "#E5EDDD",
329
329
  "success-border": "#C5D4B5",
330
330
  "success-fg": "#556344",
331
- "success-solid": "#5E7A37",
331
+ "success-solid": "#30862D",
332
332
  "success-onSolid": "#FFFFFF",
333
333
  "warning-bg": "#FEE9BC",
334
334
  "warning-border": "#F0CF83",
@@ -510,7 +510,7 @@ const SCHEMES = {
510
510
  "success-bg": "#E5EDDD",
511
511
  "success-border": "#7D8B6E",
512
512
  "success-fg": "#445133",
513
- "success-solid": "#47611D",
513
+ "success-solid": "#036805",
514
514
  "success-onSolid": "#FFFFFF",
515
515
  "warning-bg": "#FEE9BC",
516
516
  "warning-border": "#A28336",
@@ -694,7 +694,7 @@ const SCHEMES = {
694
694
  "success-bg": "#E5EDDD",
695
695
  "success-border": "#C5D4B5",
696
696
  "success-fg": "#556344",
697
- "success-solid": "#5E7A37",
697
+ "success-solid": "#30862D",
698
698
  "success-onSolid": "#FFFFFF",
699
699
  "warning-bg": "#FEE9BC",
700
700
  "warning-border": "#F0CF83",
@@ -876,7 +876,7 @@ const SCHEMES = {
876
876
  "success-bg": "#E5EDDD",
877
877
  "success-border": "#7D8B6E",
878
878
  "success-fg": "#445133",
879
- "success-solid": "#47611D",
879
+ "success-solid": "#036805",
880
880
  "success-onSolid": "#FFFFFF",
881
881
  "warning-bg": "#FEE9BC",
882
882
  "warning-border": "#A28336",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindlogic-ai/logician-ui",
3
- "version": "5.0.0-alpha.24",
3
+ "version": "5.0.0-alpha.25",
4
4
  "description": "A comprehensive React design system built on Chakra UI",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -179,14 +179,22 @@ export const UsageTokens: Story = {
179
179
  render: () => (
180
180
  <TokenTable
181
181
  rows={[
182
- { token: 'bg.track', use: <T en="Track when off" ko="꺼짐 트랙" /> },
183
- { token: 'primary.main', use: <T en="Track when on" ko="켜짐 트랙" /> },
182
+ { token: 'bg.surface', use: <T en="Track when off" ko="꺼짐 트랙" /> },
184
183
  {
185
- token: 'bg.surface',
186
- use: <T en="Thumb when off" ko="꺼짐 손잡이" />,
184
+ token: 'border.control',
185
+ use: (
186
+ <T
187
+ en="Track outline and thumb when off"
188
+ ko="꺼짐 트랙 테두리·손잡이"
189
+ />
190
+ ),
187
191
  },
188
192
  {
189
- token: 'fg.onPrimary',
193
+ token: 'success.solid',
194
+ use: <T en="Track when on" ko="켜짐 트랙" />,
195
+ },
196
+ {
197
+ token: 'success.onSolid',
190
198
  use: <T en="Thumb when on" ko="켜짐 손잡이" />,
191
199
  },
192
200
  {
@@ -128,8 +128,9 @@ What Switch does for you:
128
128
 
129
129
  - A native checkbox input carries the state, so Tab focuses it and Space
130
130
  toggles it.
131
- - The keyboard focus ring shows on the track (WCAG 2.4.7). The off track is
132
- `bg.track`, a filled track that stays visible on any surface (WCAG 1.4.11).
131
+ - The keyboard focus ring shows on the track (WCAG 2.4.7). Off is drawn like an
132
+ unchecked Checkbox: a `border.control` outline and thumb, at least 3:1 on any
133
+ surface (WCAG 1.4.11).
133
134
 
134
135
  What you still have to do:
135
136
 
@@ -160,8 +161,8 @@ Switch가 알아서 하는 일
160
161
 
161
162
  - 상태는 네이티브 체크박스 입력이 가지고 있어서 Tab으로 초점을 옮기고 Space로 바꿀 수
162
163
  있습니다.
163
- - 키보드 초점 링이 트랙에 보입니다(WCAG 2.4.7). 꺼짐 트랙은 어떤 면 위에서도 보이도록
164
- 채워진 `bg.track`을 씁니다(WCAG 1.4.11).
164
+ - 키보드 초점 링이 트랙에 보입니다(WCAG 2.4.7). 꺼짐은 체크하지 않은 Checkbox처럼
165
+ `border.control` 테두리와 손잡이로 그려, 어떤 면 위에서도 3:1 이상입니다(WCAG 1.4.11).
165
166
 
166
167
  직접 챙겨야 하는 일
167
168
 
@@ -2,23 +2,38 @@ import { forwardRef } from 'react';
2
2
  import { Switch as ChakraSwitch, SwitchControlProps } from '@chakra-ui/react';
3
3
 
4
4
  import { disabledControl } from '@/utils/disabledControl';
5
- import { focusRing } from '@/utils/focusRing';
5
+ import { FOCUS_RING_SHADOW, focusRing } from '@/utils/focusRing';
6
+
7
+ // Drawn as an inset shadow, not a border, so the thumb's travel and the
8
+ // track's size stay exactly what Chakra's recipe computes.
9
+ const OFF_OUTLINE = 'inset 0 0 0 1px var(--chakra-colors-border-control)';
6
10
 
7
11
  export const SwitchControl = forwardRef<HTMLSpanElement, SwitchControlProps>(
8
12
  (props, ref) => (
9
13
  <ChakraSwitch.Control
10
14
  ref={ref}
11
- // The off-state track is a meter surface — its extent is the information —
12
- // so it needs a visible fill, not just an edge. bg.muted (gray.100) is
13
- // only ~1.03:1 against the bg.sunken page wash (gray.50) and vanishes
14
- // there; bg.track (gray.300) reads as a filled track on any background.
15
- // The checked state is the self-defining primary.main fill.
16
- bg="bg.track"
17
- _checked={{ bg: 'primary.main' }}
15
+ // Off is drawn the way an unchecked Checkbox is: a bg.surface track with a
16
+ // border.control outline and a border.control thumb, each at least 3:1
17
+ // against what it sits on (WCAG 1.4.11). The previous off state, a
18
+ // bg.track fill with a bg.surface thumb, measured 1.3:1 (light) and
19
+ // 1.4:1 (dark) between thumb and track, so the thumb's position, the only
20
+ // thing that tells off from on, could not be seen.
21
+ // On is success.solid with a success.onSolid thumb. With a black (light) or
22
+ // pale (dark) primary fill, neither state carried colour, and dark-mode
23
+ // "on" read as light-mode "off"; green gives both modes one meaning.
24
+ bg="bg.surface"
25
+ boxShadow={OFF_OUTLINE}
26
+ _checked={{ bg: 'success.solid', boxShadow: 'none' }}
18
27
  animationStyle="feedback"
19
- transitionProperty="background-color"
28
+ transitionProperty="background-color, box-shadow"
20
29
  _disabled={{ ...disabledControl, cursor: 'not-allowed' }}
21
30
  {...focusRing}
31
+ // focusRing's shadow would replace the outline; keep both while off.
32
+ _focusVisible={{
33
+ ...focusRing._focusVisible,
34
+ boxShadow: `${OFF_OUTLINE}, ${FOCUS_RING_SHADOW}`,
35
+ _checked: { boxShadow: FOCUS_RING_SHADOW },
36
+ }}
22
37
  {...props}
23
38
  >
24
39
  <ChakraSwitch.Thumb
@@ -29,12 +44,11 @@ export const SwitchControl = forwardRef<HTMLSpanElement, SwitchControlProps>(
29
44
  // reverses direction — `standard` vs `emphasized` would not.
30
45
  animationStyle="spring"
31
46
  transitionProperty="translate"
32
- // Chakra's default is a raw `white` thumb that stays `white` when
33
- // checked via an undefined `colorPalette.contrast`. bg.surface reads
34
- // as the same near-white in light and flips correctly in dark; the
35
- // checked thumb is fg.onPrimary (cream) to match Checkbox/Radio.
36
- bg="bg.surface"
37
- _checked={{ bg: 'fg.onPrimary' }}
47
+ // Off: border.control, the same 3:1 control token as the outline.
48
+ // On: success.onSolid, the text colour success buttons put on the same
49
+ // fill (white in light, ink in dark).
50
+ bg="border.control"
51
+ _checked={{ bg: 'success.onSolid' }}
38
52
  />
39
53
  </ChakraSwitch.Control>
40
54
  )
@@ -332,7 +332,7 @@ export const SCHEMES = {
332
332
  "success-bg": "#E5EDDD",
333
333
  "success-border": "#C5D4B5",
334
334
  "success-fg": "#556344",
335
- "success-solid": "#5E7A37",
335
+ "success-solid": "#30862D",
336
336
  "success-onSolid": "#FFFFFF",
337
337
  "warning-bg": "#FEE9BC",
338
338
  "warning-border": "#F0CF83",
@@ -514,7 +514,7 @@ export const SCHEMES = {
514
514
  "success-bg": "#E5EDDD",
515
515
  "success-border": "#7D8B6E",
516
516
  "success-fg": "#445133",
517
- "success-solid": "#47611D",
517
+ "success-solid": "#036805",
518
518
  "success-onSolid": "#FFFFFF",
519
519
  "warning-bg": "#FEE9BC",
520
520
  "warning-border": "#A28336",
@@ -698,7 +698,7 @@ export const SCHEMES = {
698
698
  "success-bg": "#E5EDDD",
699
699
  "success-border": "#C5D4B5",
700
700
  "success-fg": "#556344",
701
- "success-solid": "#5E7A37",
701
+ "success-solid": "#30862D",
702
702
  "success-onSolid": "#FFFFFF",
703
703
  "warning-bg": "#FEE9BC",
704
704
  "warning-border": "#F0CF83",
@@ -880,7 +880,7 @@ export const SCHEMES = {
880
880
  "success-bg": "#E5EDDD",
881
881
  "success-border": "#7D8B6E",
882
882
  "success-fg": "#445133",
883
- "success-solid": "#47611D",
883
+ "success-solid": "#036805",
884
884
  "success-onSolid": "#FFFFFF",
885
885
  "warning-bg": "#FEE9BC",
886
886
  "warning-border": "#A28336",