@mindlogic-ai/logician-ui 4.0.0-alpha.42 → 4.0.0-alpha.43
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.
- package/dist/components/Button/Button.d.ts.map +1 -1
- package/dist/components/Button/Button.js +14 -3
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Button/Button.mjs +14 -3
- package/dist/components/Button/Button.mjs.map +1 -1
- package/dist/components/Menu/MenuItem.d.ts.map +1 -1
- package/dist/components/Menu/MenuItem.js +3 -1
- package/dist/components/Menu/MenuItem.js.map +1 -1
- package/dist/components/Menu/MenuItem.mjs +3 -1
- package/dist/components/Menu/MenuItem.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/Button/Button.cursor.test.tsx +60 -0
- package/src/components/Button/Button.tsx +18 -3
- package/src/components/Menu/MenuItem.tsx +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/Button/Button.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/Button/Button.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAe,MAAM,gBAAgB,CAAC;AAmI7D,eAAO,MAAM,MAAM,gEAA0C,CAAC"}
|
|
@@ -5,6 +5,7 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
5
5
|
var React = require('react');
|
|
6
6
|
var react = require('@chakra-ui/react');
|
|
7
7
|
var focusRing = require('../../utils/focusRing.js');
|
|
8
|
+
var mergeCss = require('../../utils/mergeCss.js');
|
|
8
9
|
var polymorphic = require('../../types/polymorphic.js');
|
|
9
10
|
var Button_styles = require('./Button.styles.js');
|
|
10
11
|
|
|
@@ -26,7 +27,7 @@ var Button_styles = require('./Button.styles.js');
|
|
|
26
27
|
* <Button as="a" href="/docs" target="_blank">문서</Button>
|
|
27
28
|
* ```
|
|
28
29
|
*/
|
|
29
|
-
const ButtonImpl = React.forwardRef(({ colorPalette, variant = 'soft', size, lift, children, _hover: hoverProp, _active: activeProp, ...rest }, ref) => {
|
|
30
|
+
const ButtonImpl = React.forwardRef(({ colorPalette, variant = 'soft', size, lift, children, _hover: hoverProp, _active: activeProp, _disabled: disabledProp, ...rest }, ref) => {
|
|
30
31
|
const palette = colorPalette ?? 'primary';
|
|
31
32
|
const base = Button_styles.getButtonStyles(palette, variant);
|
|
32
33
|
// Merged rather than spread after: each variant already owns `_hover` and
|
|
@@ -69,8 +70,18 @@ const ButtonImpl = React.forwardRef(({ colorPalette, variant = 'soft', size, lif
|
|
|
69
70
|
// FactChat puts on its quiz buttons — used to silently drop the
|
|
70
71
|
// variant's pressed colour *and* the scale with it, and the button
|
|
71
72
|
// stopped reading as pressed at all. Its own keys still win; it just
|
|
72
|
-
// no longer erases the ones it did not mention.
|
|
73
|
-
|
|
73
|
+
// no longer erases the ones it did not mention. Deep, so a nested
|
|
74
|
+
// condition (lift's `_hover._dark`) survives a call site's own `_dark`.
|
|
75
|
+
_hover: mergeCss.mergeCss(styles._hover, hoverProp), _active: mergeCss.mergeCss(styles._active, activeProp),
|
|
76
|
+
// `cursor` is a style prop, so it lands outside Chakra's
|
|
77
|
+
// `@layer recipes` and beat the recipe's disabled cursor — every
|
|
78
|
+
// disabled Button showed a pointer and read as clickable. The
|
|
79
|
+
// disabled cursor has to sit at this level, merged like the two above
|
|
80
|
+
// so a call site's `_disabled` cannot drop it.
|
|
81
|
+
_disabled: mergeCss.mergeCss('_disabled' in styles ? styles._disabled : undefined,
|
|
82
|
+
// Chakra disables a `loading` button too; it is working, not
|
|
83
|
+
// forbidden, so it gets `progress`.
|
|
84
|
+
{ cursor: rest.loading ? 'progress' : 'not-allowed' }, disabledProp), ...focusRing.focusRing, cursor: "pointer",
|
|
74
85
|
// Explicit identity so the press transitions from a definite value
|
|
75
86
|
// rather than relying on `scale: none` being read as 1.
|
|
76
87
|
scale: "1",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.js","sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":[null],"names":["forwardRef","getButtonStyles","_jsx","ChakraButton","focusRing","buttonTransition","polymorphic"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Button.js","sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":[null],"names":["forwardRef","getButtonStyles","_jsx","ChakraButton","mergeCss","focusRing","buttonTransition","polymorphic"],"mappings":";;;;;;;;;;;AAUA;;;;;;;;;;;;;;;;;AAiBG;AACH,MAAM,UAAU,GAAGA,gBAAU,CAC3B,CACE,EACE,YAAY,EACZ,OAAO,GAAG,MAAM,EAChB,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,YAAY,EACvB,GAAG,IAAI,EACR,EACD,GAAG,KACD;AACF,IAAA,MAAM,OAAO,GAAG,YAAY,IAAI,SAAS;IAEzC,MAAM,IAAI,GAAGC,6BAAe,CAAC,OAAO,EAAE,OAAO,CAAC;;;IAI9C,MAAM,MAAM,GAAG;AACb,UAAE;AACE,YAAA,GAAG,IAAI;AACP,YAAA,MAAM,EAAE;gBACN,GAAG,IAAI,CAAC,MAAM;AACd,gBAAA,SAAS,EAAE,QAAQ;;;;;;AAMnB,gBAAA,MAAM,EAAE,4CAA4C;;AAEpD,gBAAA,KAAK,EAAE,EAAE,MAAM,EAAE,4CAA4C,EAAE;AAChE,aAAA;;AAED,YAAA,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE;;;YAG9D,SAAS,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE;AAChD;UACD,IAAI;AAER;;;;;;;;;AASG;IACH,QACEC,cAAA,CAACC,YAAY,EAAA,EACX,MAAM,EAAC,WAAW,EAClB,UAAU,EAAC,KAAK,EAChB,UAAU,EAAC,UAAU,EACrB,IAAI,EAAE,IAAI,EACV,YAAY,EAAC,IAAI,EAAA,GACb,MAAM;;;;;;;;AAQV,QAAA,MAAM,EAAEC,iBAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAC1C,OAAO,EAAEA,iBAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC;;;;;;AAM7C,QAAA,SAAS,EAAEA,iBAAQ,CACjB,WAAW,IAAI,MAAM,GAAG,MAAM,CAAC,SAAS,GAAG,SAAS;;;QAGpD,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,GAAG,UAAU,GAAG,aAAa,EAAE,EACrD,YAAY,CACb,KACGC,mBAAS,EACb,MAAM,EAAC,SAAS;;;AAGhB,QAAA,KAAK,EAAC,GAAG;;;;AAIT,QAAA,UAAU,EAAEC,8BAAgB,EAC5B,cAAc,EAAC,WAAW,EAC1B,GAAG,EAAE,GAAG,KACJ,IAAI,EAAA,QAAA,EAEP,QAAQ,EAAA,CACI;AAEnB,CAAC,CACF;AAED;;;;;;AAMG;AACH,UAAU,CAAC,WAAW,GAAG,QAAQ;MAEpB,MAAM,GAAGC,uBAAW,CAAiB,UAAU;;;;"}
|
|
@@ -3,6 +3,7 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
4
|
import { Button as Button$1 } from '@chakra-ui/react';
|
|
5
5
|
import { focusRing } from '../../utils/focusRing.mjs';
|
|
6
|
+
import { mergeCss } from '../../utils/mergeCss.mjs';
|
|
6
7
|
import { polymorphic } from '../../types/polymorphic.mjs';
|
|
7
8
|
import { getButtonStyles, buttonTransition } from './Button.styles.mjs';
|
|
8
9
|
|
|
@@ -24,7 +25,7 @@ import { getButtonStyles, buttonTransition } from './Button.styles.mjs';
|
|
|
24
25
|
* <Button as="a" href="/docs" target="_blank">문서</Button>
|
|
25
26
|
* ```
|
|
26
27
|
*/
|
|
27
|
-
const ButtonImpl = forwardRef(({ colorPalette, variant = 'soft', size, lift, children, _hover: hoverProp, _active: activeProp, ...rest }, ref) => {
|
|
28
|
+
const ButtonImpl = forwardRef(({ colorPalette, variant = 'soft', size, lift, children, _hover: hoverProp, _active: activeProp, _disabled: disabledProp, ...rest }, ref) => {
|
|
28
29
|
const palette = colorPalette ?? 'primary';
|
|
29
30
|
const base = getButtonStyles(palette, variant);
|
|
30
31
|
// Merged rather than spread after: each variant already owns `_hover` and
|
|
@@ -67,8 +68,18 @@ const ButtonImpl = forwardRef(({ colorPalette, variant = 'soft', size, lift, chi
|
|
|
67
68
|
// FactChat puts on its quiz buttons — used to silently drop the
|
|
68
69
|
// variant's pressed colour *and* the scale with it, and the button
|
|
69
70
|
// stopped reading as pressed at all. Its own keys still win; it just
|
|
70
|
-
// no longer erases the ones it did not mention.
|
|
71
|
-
|
|
71
|
+
// no longer erases the ones it did not mention. Deep, so a nested
|
|
72
|
+
// condition (lift's `_hover._dark`) survives a call site's own `_dark`.
|
|
73
|
+
_hover: mergeCss(styles._hover, hoverProp), _active: mergeCss(styles._active, activeProp),
|
|
74
|
+
// `cursor` is a style prop, so it lands outside Chakra's
|
|
75
|
+
// `@layer recipes` and beat the recipe's disabled cursor — every
|
|
76
|
+
// disabled Button showed a pointer and read as clickable. The
|
|
77
|
+
// disabled cursor has to sit at this level, merged like the two above
|
|
78
|
+
// so a call site's `_disabled` cannot drop it.
|
|
79
|
+
_disabled: mergeCss('_disabled' in styles ? styles._disabled : undefined,
|
|
80
|
+
// Chakra disables a `loading` button too; it is working, not
|
|
81
|
+
// forbidden, so it gets `progress`.
|
|
82
|
+
{ cursor: rest.loading ? 'progress' : 'not-allowed' }, disabledProp), ...focusRing, cursor: "pointer",
|
|
72
83
|
// Explicit identity so the press transitions from a definite value
|
|
73
84
|
// rather than relying on `scale: none` being read as 1.
|
|
74
85
|
scale: "1",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.mjs","sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":[null],"names":["_jsx","ChakraButton"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Button.mjs","sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":[null],"names":["_jsx","ChakraButton"],"mappings":";;;;;;;;;AAUA;;;;;;;;;;;;;;;;;AAiBG;AACH,MAAM,UAAU,GAAG,UAAU,CAC3B,CACE,EACE,YAAY,EACZ,OAAO,GAAG,MAAM,EAChB,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,YAAY,EACvB,GAAG,IAAI,EACR,EACD,GAAG,KACD;AACF,IAAA,MAAM,OAAO,GAAG,YAAY,IAAI,SAAS;IAEzC,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC;;;IAI9C,MAAM,MAAM,GAAG;AACb,UAAE;AACE,YAAA,GAAG,IAAI;AACP,YAAA,MAAM,EAAE;gBACN,GAAG,IAAI,CAAC,MAAM;AACd,gBAAA,SAAS,EAAE,QAAQ;;;;;;AAMnB,gBAAA,MAAM,EAAE,4CAA4C;;AAEpD,gBAAA,KAAK,EAAE,EAAE,MAAM,EAAE,4CAA4C,EAAE;AAChE,aAAA;;AAED,YAAA,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE;;;YAG9D,SAAS,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE;AAChD;UACD,IAAI;AAER;;;;;;;;;AASG;IACH,QACEA,GAAA,CAACC,QAAY,EAAA,EACX,MAAM,EAAC,WAAW,EAClB,UAAU,EAAC,KAAK,EAChB,UAAU,EAAC,UAAU,EACrB,IAAI,EAAE,IAAI,EACV,YAAY,EAAC,IAAI,EAAA,GACb,MAAM;;;;;;;;AAQV,QAAA,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAC1C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC;;;;;;AAM7C,QAAA,SAAS,EAAE,QAAQ,CACjB,WAAW,IAAI,MAAM,GAAG,MAAM,CAAC,SAAS,GAAG,SAAS;;;QAGpD,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,GAAG,UAAU,GAAG,aAAa,EAAE,EACrD,YAAY,CACb,KACG,SAAS,EACb,MAAM,EAAC,SAAS;;;AAGhB,QAAA,KAAK,EAAC,GAAG;;;;AAIT,QAAA,UAAU,EAAE,gBAAgB,EAC5B,cAAc,EAAC,WAAW,EAC1B,GAAG,EAAE,GAAG,KACJ,IAAI,EAAA,QAAA,EAEP,QAAQ,EAAA,CACI;AAEnB,CAAC,CACF;AAED;;;;;;AAMG;AACH,UAAU,CAAC,WAAW,GAAG,QAAQ;MAEpB,MAAM,GAAG,WAAW,CAAiB,UAAU;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuItem.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/MenuItem.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAe,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"MenuItem.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/MenuItem.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAe,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AA4CjE,eAAO,MAAM,QAAQ,+DAAqD,CAAC"}
|
|
@@ -13,7 +13,9 @@ const MenuItemImpl = ({ variant = MenuItem_types.ItemVariant.Default, value, chi
|
|
|
13
13
|
// Map item text/hover onto semantic tokens so they flip with the mode.
|
|
14
14
|
// Was gray.1000 / hover gray.1500 / hover bg gray.50 — none flipped, so
|
|
15
15
|
// items rendered dim and hover went near-black on a dark menu.
|
|
16
|
-
color: isDangerVariant ? 'danger.main' : 'fg.muted', py: 2, minW: "fit-content", fontWeight: "semibold", gap: 3, cursor: "pointer",
|
|
16
|
+
color: isDangerVariant ? 'danger.main' : 'fg.muted', py: 2, minW: "fit-content", fontWeight: "semibold", gap: 3, cursor: "pointer",
|
|
17
|
+
// Same as `Button`: the style prop outranks the recipe's disabled cursor.
|
|
18
|
+
_disabled: { cursor: 'not-allowed' }, _hover: {
|
|
17
19
|
color: isDangerVariant ? 'danger.main' : 'fg.default',
|
|
18
20
|
backgroundColor: isDangerVariant ? 'danger.lightest' : 'bg.subtle',
|
|
19
21
|
}, ...focusRing.focusRing, ...rest, children: [icon, children, rightIcon && jsxRuntime.jsx(react.Spacer, {}), rightIcon] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuItem.js","sources":["../../../src/components/Menu/MenuItem.tsx"],"sourcesContent":[null],"names":["ItemVariant","_jsxs","Menu","focusRing","_jsx","Spacer","polymorphic"],"mappings":";;;;;;;;;AAOA,MAAM,YAAY,GAAG,CAAC,EACpB,OAAO,GAAGA,0BAAW,CAAC,OAAO,EAC7B,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,GAAG,IAAI,EACU,KAAI;AACrB,IAAA,MAAM,eAAe,GAAG,OAAO,KAAKA,0BAAW,CAAC,MAAM;IAEtD,QACEC,gBAACC,UAAI,CAAC,IAAI,EAAA,EACR,KAAK,EAAE,KAAK;;;;AAIZ,QAAA,KAAK,EAAE,eAAe,GAAG,aAAa,GAAG,UAAU,EACnD,EAAE,EAAE,CAAC,EACL,IAAI,EAAC,aAAa,EAClB,UAAU,EAAC,UAAU,EACrB,GAAG,EAAE,CAAC,EACN,MAAM,EAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"MenuItem.js","sources":["../../../src/components/Menu/MenuItem.tsx"],"sourcesContent":[null],"names":["ItemVariant","_jsxs","Menu","focusRing","_jsx","Spacer","polymorphic"],"mappings":";;;;;;;;;AAOA,MAAM,YAAY,GAAG,CAAC,EACpB,OAAO,GAAGA,0BAAW,CAAC,OAAO,EAC7B,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,GAAG,IAAI,EACU,KAAI;AACrB,IAAA,MAAM,eAAe,GAAG,OAAO,KAAKA,0BAAW,CAAC,MAAM;IAEtD,QACEC,gBAACC,UAAI,CAAC,IAAI,EAAA,EACR,KAAK,EAAE,KAAK;;;;AAIZ,QAAA,KAAK,EAAE,eAAe,GAAG,aAAa,GAAG,UAAU,EACnD,EAAE,EAAE,CAAC,EACL,IAAI,EAAC,aAAa,EAClB,UAAU,EAAC,UAAU,EACrB,GAAG,EAAE,CAAC,EACN,MAAM,EAAC,SAAS;;QAEhB,SAAS,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,EACpC,MAAM,EAAE;YACN,KAAK,EAAE,eAAe,GAAG,aAAa,GAAG,YAAY;YACrD,eAAe,EAAE,eAAe,GAAG,iBAAiB,GAAG,WAAW;AACnE,SAAA,EAAA,GACGC,mBAAS,EAAA,GACT,IAAI,EAAA,QAAA,EAAA,CAEP,IAAI,EACJ,QAAQ,EACR,SAAS,IAAIC,eAACC,YAAM,EAAA,EAAA,CAAG,EACvB,SAAS,CAAA,EAAA,CACA;AAEhB,CAAC;AAED;AACA,YAAY,CAAC,WAAW,GAAG,UAAU;MAExB,QAAQ,GAAGC,uBAAW,CAA0B,YAAY;;;;"}
|
|
@@ -11,7 +11,9 @@ const MenuItemImpl = ({ variant = ItemVariant.Default, value, children, icon, ri
|
|
|
11
11
|
// Map item text/hover onto semantic tokens so they flip with the mode.
|
|
12
12
|
// Was gray.1000 / hover gray.1500 / hover bg gray.50 — none flipped, so
|
|
13
13
|
// items rendered dim and hover went near-black on a dark menu.
|
|
14
|
-
color: isDangerVariant ? 'danger.main' : 'fg.muted', py: 2, minW: "fit-content", fontWeight: "semibold", gap: 3, cursor: "pointer",
|
|
14
|
+
color: isDangerVariant ? 'danger.main' : 'fg.muted', py: 2, minW: "fit-content", fontWeight: "semibold", gap: 3, cursor: "pointer",
|
|
15
|
+
// Same as `Button`: the style prop outranks the recipe's disabled cursor.
|
|
16
|
+
_disabled: { cursor: 'not-allowed' }, _hover: {
|
|
15
17
|
color: isDangerVariant ? 'danger.main' : 'fg.default',
|
|
16
18
|
backgroundColor: isDangerVariant ? 'danger.lightest' : 'bg.subtle',
|
|
17
19
|
}, ...focusRing, ...rest, children: [icon, children, rightIcon && jsx(Spacer, {}), rightIcon] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuItem.mjs","sources":["../../../src/components/Menu/MenuItem.tsx"],"sourcesContent":[null],"names":["_jsxs","_jsx"],"mappings":";;;;;;;AAOA,MAAM,YAAY,GAAG,CAAC,EACpB,OAAO,GAAG,WAAW,CAAC,OAAO,EAC7B,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,GAAG,IAAI,EACU,KAAI;AACrB,IAAA,MAAM,eAAe,GAAG,OAAO,KAAK,WAAW,CAAC,MAAM;IAEtD,QACEA,KAAC,IAAI,CAAC,IAAI,EAAA,EACR,KAAK,EAAE,KAAK;;;;AAIZ,QAAA,KAAK,EAAE,eAAe,GAAG,aAAa,GAAG,UAAU,EACnD,EAAE,EAAE,CAAC,EACL,IAAI,EAAC,aAAa,EAClB,UAAU,EAAC,UAAU,EACrB,GAAG,EAAE,CAAC,EACN,MAAM,EAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"MenuItem.mjs","sources":["../../../src/components/Menu/MenuItem.tsx"],"sourcesContent":[null],"names":["_jsxs","_jsx"],"mappings":";;;;;;;AAOA,MAAM,YAAY,GAAG,CAAC,EACpB,OAAO,GAAG,WAAW,CAAC,OAAO,EAC7B,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,GAAG,IAAI,EACU,KAAI;AACrB,IAAA,MAAM,eAAe,GAAG,OAAO,KAAK,WAAW,CAAC,MAAM;IAEtD,QACEA,KAAC,IAAI,CAAC,IAAI,EAAA,EACR,KAAK,EAAE,KAAK;;;;AAIZ,QAAA,KAAK,EAAE,eAAe,GAAG,aAAa,GAAG,UAAU,EACnD,EAAE,EAAE,CAAC,EACL,IAAI,EAAC,aAAa,EAClB,UAAU,EAAC,UAAU,EACrB,GAAG,EAAE,CAAC,EACN,MAAM,EAAC,SAAS;;QAEhB,SAAS,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,EACpC,MAAM,EAAE;YACN,KAAK,EAAE,eAAe,GAAG,aAAa,GAAG,YAAY;YACrD,eAAe,EAAE,eAAe,GAAG,iBAAiB,GAAG,WAAW;AACnE,SAAA,EAAA,GACG,SAAS,EAAA,GACT,IAAI,EAAA,QAAA,EAAA,CAEP,IAAI,EACJ,QAAQ,EACR,SAAS,IAAIC,IAAC,MAAM,EAAA,EAAA,CAAG,EACvB,SAAS,CAAA,EAAA,CACA;AAEhB,CAAC;AAED;AACA,YAAY,CAAC,WAAW,GAAG,UAAU;MAExB,QAAQ,GAAG,WAAW,CAA0B,YAAY;;;;"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ChakraProvider } from '@chakra-ui/react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
|
|
5
|
+
import { system } from '../../theme';
|
|
6
|
+
import { Button } from './Button';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A disabled Button must not show the pointer.
|
|
10
|
+
*
|
|
11
|
+
* The Button sets `cursor="pointer"` as a style prop, which Chakra emits
|
|
12
|
+
* outside its cascade layers, while the recipe's disabled cursor sits inside
|
|
13
|
+
* `@layer recipes` — so the pointer won and a disabled button read as
|
|
14
|
+
* clickable (FactChat's 「현재 플랜」 button).
|
|
15
|
+
*/
|
|
16
|
+
const wrap = (ui: React.ReactNode) =>
|
|
17
|
+
render(<ChakraProvider value={system}>{ui}</ChakraProvider>);
|
|
18
|
+
|
|
19
|
+
describe('Button disabled cursor', () => {
|
|
20
|
+
it('enabled keeps the pointer', () => {
|
|
21
|
+
wrap(<Button>on</Button>);
|
|
22
|
+
expect(getComputedStyle(screen.getByRole('button')).cursor).toBe('pointer');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('disabled shows not-allowed', () => {
|
|
26
|
+
wrap(<Button disabled>off</Button>);
|
|
27
|
+
expect(getComputedStyle(screen.getByRole('button')).cursor).toBe(
|
|
28
|
+
'not-allowed'
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('a call-site _disabled does not drop it', () => {
|
|
33
|
+
wrap(
|
|
34
|
+
<Button disabled _disabled={{ opacity: 0.3 }}>
|
|
35
|
+
off
|
|
36
|
+
</Button>
|
|
37
|
+
);
|
|
38
|
+
expect(getComputedStyle(screen.getByRole('button')).cursor).toBe(
|
|
39
|
+
'not-allowed'
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('lift keeps it too', () => {
|
|
44
|
+
wrap(
|
|
45
|
+
<Button disabled lift>
|
|
46
|
+
off
|
|
47
|
+
</Button>
|
|
48
|
+
);
|
|
49
|
+
expect(getComputedStyle(screen.getByRole('button')).cursor).toBe(
|
|
50
|
+
'not-allowed'
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('loading shows progress, not not-allowed', () => {
|
|
55
|
+
wrap(<Button loading>busy</Button>);
|
|
56
|
+
const button = screen.getByRole('button');
|
|
57
|
+
expect(button).toBeDisabled();
|
|
58
|
+
expect(getComputedStyle(button).cursor).toBe('progress');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -2,6 +2,7 @@ import { forwardRef } from 'react';
|
|
|
2
2
|
import { Button as ChakraButton } from '@chakra-ui/react';
|
|
3
3
|
|
|
4
4
|
import { focusRing } from '@/utils/focusRing';
|
|
5
|
+
import { mergeCss } from '@/utils/mergeCss';
|
|
5
6
|
|
|
6
7
|
import { polymorphic } from '../../types/polymorphic';
|
|
7
8
|
import { buttonTransition, getButtonStyles } from './Button.styles';
|
|
@@ -35,6 +36,7 @@ const ButtonImpl = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
35
36
|
children,
|
|
36
37
|
_hover: hoverProp,
|
|
37
38
|
_active: activeProp,
|
|
39
|
+
_disabled: disabledProp,
|
|
38
40
|
...rest
|
|
39
41
|
},
|
|
40
42
|
ref
|
|
@@ -91,9 +93,22 @@ const ButtonImpl = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
91
93
|
// FactChat puts on its quiz buttons — used to silently drop the
|
|
92
94
|
// variant's pressed colour *and* the scale with it, and the button
|
|
93
95
|
// stopped reading as pressed at all. Its own keys still win; it just
|
|
94
|
-
// no longer erases the ones it did not mention.
|
|
95
|
-
_hover
|
|
96
|
-
|
|
96
|
+
// no longer erases the ones it did not mention. Deep, so a nested
|
|
97
|
+
// condition (lift's `_hover._dark`) survives a call site's own `_dark`.
|
|
98
|
+
_hover={mergeCss(styles._hover, hoverProp)}
|
|
99
|
+
_active={mergeCss(styles._active, activeProp)}
|
|
100
|
+
// `cursor` is a style prop, so it lands outside Chakra's
|
|
101
|
+
// `@layer recipes` and beat the recipe's disabled cursor — every
|
|
102
|
+
// disabled Button showed a pointer and read as clickable. The
|
|
103
|
+
// disabled cursor has to sit at this level, merged like the two above
|
|
104
|
+
// so a call site's `_disabled` cannot drop it.
|
|
105
|
+
_disabled={mergeCss(
|
|
106
|
+
'_disabled' in styles ? styles._disabled : undefined,
|
|
107
|
+
// Chakra disables a `loading` button too; it is working, not
|
|
108
|
+
// forbidden, so it gets `progress`.
|
|
109
|
+
{ cursor: rest.loading ? 'progress' : 'not-allowed' },
|
|
110
|
+
disabledProp
|
|
111
|
+
)}
|
|
97
112
|
{...focusRing}
|
|
98
113
|
cursor="pointer"
|
|
99
114
|
// Explicit identity so the press transitions from a definite value
|
|
@@ -27,6 +27,8 @@ const MenuItemImpl = ({
|
|
|
27
27
|
fontWeight="semibold"
|
|
28
28
|
gap={3}
|
|
29
29
|
cursor="pointer"
|
|
30
|
+
// Same as `Button`: the style prop outranks the recipe's disabled cursor.
|
|
31
|
+
_disabled={{ cursor: 'not-allowed' }}
|
|
30
32
|
_hover={{
|
|
31
33
|
color: isDangerVariant ? 'danger.main' : 'fg.default',
|
|
32
34
|
backgroundColor: isDangerVariant ? 'danger.lightest' : 'bg.subtle',
|