@edux-design/chips 0.0.1 → 0.2.0
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/CHANGELOG.md +19 -0
- package/README.md +12 -0
- package/dist/index.d.mts +14 -3
- package/dist/index.d.ts +14 -3
- package/dist/index.js +17 -5
- package/dist/index.mjs +17 -5
- package/docs/removal.md +26 -0
- package/package.json +8 -22
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @edux-design/chips
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add typed removeButtonProps for native remove-button descriptions, refs and composed handlers while preserving Chip removal, label and disabled semantics. Keep collection state and post-removal focus with the host.
|
|
8
|
+
|
|
9
|
+
## 0.1.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- Moved react / dom to peer deps
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
- @edux-design/icons@0.1.0
|
|
19
|
+
- @edux-design/utils@0.1.0
|
package/README.md
CHANGED
|
@@ -14,6 +14,18 @@ npm install @edux-design/chips @edux-design/utils @edux-design/icons
|
|
|
14
14
|
|
|
15
15
|
The package ships React components and depends on `react@^19.1.0` / `react-dom@^19.1.0`.
|
|
16
16
|
|
|
17
|
+
## Token contract
|
|
18
|
+
|
|
19
|
+
Small chips use the shared `min-h-32` token and both chip sizes use the shared
|
|
20
|
+
`size-16` token for the remove control. The default chip remains `40px` tall
|
|
21
|
+
through an explicit component-owned `min-h-[40px]` value because the current
|
|
22
|
+
theme has no 40px spacing or control token; introducing a new semantic token
|
|
23
|
+
would be broader than this package change and is intentionally deferred.
|
|
24
|
+
|
|
25
|
+
Padding, gaps, borders, colours, and focus treatment use existing Edux numeric
|
|
26
|
+
and semantic tokens. Consumers should import `@edux-design/tokens/theme` so
|
|
27
|
+
those utilities resolve consistently.
|
|
28
|
+
|
|
17
29
|
---
|
|
18
30
|
|
|
19
31
|
## Usage
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import * as react from 'react';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Token-driven chip that composes existing primitives (i.e. TagNumber) inside.
|
|
5
3
|
*
|
|
@@ -9,8 +7,21 @@ import * as react from 'react';
|
|
|
9
7
|
* onRemove?: (event: React.MouseEvent<HTMLButtonElement>) => void,
|
|
10
8
|
* removeLabel?: string,
|
|
11
9
|
* disabled?: boolean,
|
|
10
|
+
* removeButtonProps?: Omit<React.ComponentPropsWithRef<"button">, "type"|"disabled"|"aria-label"|"aria-labelledby"|"children">,
|
|
12
11
|
* }} ChipProps
|
|
13
12
|
*/
|
|
14
|
-
|
|
13
|
+
/** @type {React.ForwardRefExoticComponent<ChipProps & React.RefAttributes<HTMLDivElement>>} */
|
|
14
|
+
declare const Chip: React.ForwardRefExoticComponent<ChipProps & React.RefAttributes<HTMLDivElement>>;
|
|
15
|
+
/**
|
|
16
|
+
* Token-driven chip that composes existing primitives (i.e. TagNumber) inside.
|
|
17
|
+
*/
|
|
18
|
+
type ChipProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
19
|
+
label?: React.ReactNode;
|
|
20
|
+
size?: "default" | "small";
|
|
21
|
+
onRemove?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
22
|
+
removeLabel?: string;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
removeButtonProps?: Omit<React.ComponentPropsWithRef<"button">, "type" | "disabled" | "aria-label" | "aria-labelledby" | "children">;
|
|
25
|
+
};
|
|
15
26
|
|
|
16
27
|
export { Chip };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import * as react from 'react';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Token-driven chip that composes existing primitives (i.e. TagNumber) inside.
|
|
5
3
|
*
|
|
@@ -9,8 +7,21 @@ import * as react from 'react';
|
|
|
9
7
|
* onRemove?: (event: React.MouseEvent<HTMLButtonElement>) => void,
|
|
10
8
|
* removeLabel?: string,
|
|
11
9
|
* disabled?: boolean,
|
|
10
|
+
* removeButtonProps?: Omit<React.ComponentPropsWithRef<"button">, "type"|"disabled"|"aria-label"|"aria-labelledby"|"children">,
|
|
12
11
|
* }} ChipProps
|
|
13
12
|
*/
|
|
14
|
-
|
|
13
|
+
/** @type {React.ForwardRefExoticComponent<ChipProps & React.RefAttributes<HTMLDivElement>>} */
|
|
14
|
+
declare const Chip: React.ForwardRefExoticComponent<ChipProps & React.RefAttributes<HTMLDivElement>>;
|
|
15
|
+
/**
|
|
16
|
+
* Token-driven chip that composes existing primitives (i.e. TagNumber) inside.
|
|
17
|
+
*/
|
|
18
|
+
type ChipProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
19
|
+
label?: React.ReactNode;
|
|
20
|
+
size?: "default" | "small";
|
|
21
|
+
onRemove?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
22
|
+
removeLabel?: string;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
removeButtonProps?: Omit<React.ComponentPropsWithRef<"button">, "type" | "disabled" | "aria-label" | "aria-labelledby" | "children">;
|
|
25
|
+
};
|
|
15
26
|
|
|
16
27
|
export { Chip };
|
package/dist/index.js
CHANGED
|
@@ -41,11 +41,11 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
41
41
|
var SIZE_MAP = {
|
|
42
42
|
default: {
|
|
43
43
|
container: "text-sm min-h-[40px] px-8 py-6 gap-8",
|
|
44
|
-
close: "
|
|
44
|
+
close: "size-16"
|
|
45
45
|
},
|
|
46
46
|
small: {
|
|
47
|
-
container: "text-xs min-h-
|
|
48
|
-
close: "
|
|
47
|
+
container: "text-xs min-h-32 px-8 py-4 gap-6",
|
|
48
|
+
close: "size-16"
|
|
49
49
|
}
|
|
50
50
|
};
|
|
51
51
|
var BASE_STYLES = (0, import_utils.cx)(
|
|
@@ -64,9 +64,15 @@ var Chip = (0, import_react.forwardRef)(function Chip2({
|
|
|
64
64
|
onRemove,
|
|
65
65
|
removeLabel = "Remove chip",
|
|
66
66
|
disabled = false,
|
|
67
|
+
removeButtonProps = {},
|
|
67
68
|
className,
|
|
68
69
|
...rest
|
|
69
70
|
}, ref) {
|
|
71
|
+
const {
|
|
72
|
+
className: removeClassName,
|
|
73
|
+
onClick: onRemoveClick,
|
|
74
|
+
...buttonProps
|
|
75
|
+
} = removeButtonProps;
|
|
70
76
|
const sizeStyles = SIZE_MAP[size] ?? SIZE_MAP.default;
|
|
71
77
|
const containerClass = (0, import_utils.cx)(
|
|
72
78
|
BASE_STYLES,
|
|
@@ -86,6 +92,7 @@ var Chip = (0, import_react.forwardRef)(function Chip2({
|
|
|
86
92
|
className: containerClass,
|
|
87
93
|
"data-disabled": disabled ? "true" : void 0,
|
|
88
94
|
...rest,
|
|
95
|
+
"aria-disabled": disabled ? true : rest["aria-disabled"],
|
|
89
96
|
children: [
|
|
90
97
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex min-w-0 flex-1 items-center gap-6", children: [
|
|
91
98
|
shouldRenderChildren && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex items-center gap-4 shrink-0 [&>*]:shrink-0", children: normalizedChildren.map(
|
|
@@ -96,12 +103,16 @@ var Chip = (0, import_react.forwardRef)(function Chip2({
|
|
|
96
103
|
onRemove && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
97
104
|
"button",
|
|
98
105
|
{
|
|
106
|
+
...buttonProps,
|
|
99
107
|
type: "button",
|
|
100
108
|
disabled,
|
|
101
109
|
"aria-label": removeLabel,
|
|
110
|
+
"aria-labelledby": void 0,
|
|
102
111
|
onClick: (event) => {
|
|
103
112
|
event.stopPropagation();
|
|
104
|
-
|
|
113
|
+
if (disabled) return;
|
|
114
|
+
onRemoveClick == null ? void 0 : onRemoveClick(event);
|
|
115
|
+
if (!event.defaultPrevented) onRemove(event);
|
|
105
116
|
},
|
|
106
117
|
className: (0, import_utils.cx)(
|
|
107
118
|
"ml-4 inline-flex items-center justify-center rounded-full text-fg-subtle",
|
|
@@ -110,7 +121,8 @@ var Chip = (0, import_react.forwardRef)(function Chip2({
|
|
|
110
121
|
"focus-visible:shadow-focus focus-visible:outline-none",
|
|
111
122
|
"active:bg-bg-primary-subtle-90",
|
|
112
123
|
disabled && "opacity-60 pointer-events-none bg-transparent text-fg-inactive",
|
|
113
|
-
sizeStyles.close
|
|
124
|
+
sizeStyles.close,
|
|
125
|
+
removeClassName
|
|
114
126
|
),
|
|
115
127
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.Close, {})
|
|
116
128
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -6,11 +6,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
var SIZE_MAP = {
|
|
7
7
|
default: {
|
|
8
8
|
container: "text-sm min-h-[40px] px-8 py-6 gap-8",
|
|
9
|
-
close: "
|
|
9
|
+
close: "size-16"
|
|
10
10
|
},
|
|
11
11
|
small: {
|
|
12
|
-
container: "text-xs min-h-
|
|
13
|
-
close: "
|
|
12
|
+
container: "text-xs min-h-32 px-8 py-4 gap-6",
|
|
13
|
+
close: "size-16"
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
16
|
var BASE_STYLES = cx(
|
|
@@ -29,9 +29,15 @@ var Chip = forwardRef(function Chip2({
|
|
|
29
29
|
onRemove,
|
|
30
30
|
removeLabel = "Remove chip",
|
|
31
31
|
disabled = false,
|
|
32
|
+
removeButtonProps = {},
|
|
32
33
|
className,
|
|
33
34
|
...rest
|
|
34
35
|
}, ref) {
|
|
36
|
+
const {
|
|
37
|
+
className: removeClassName,
|
|
38
|
+
onClick: onRemoveClick,
|
|
39
|
+
...buttonProps
|
|
40
|
+
} = removeButtonProps;
|
|
35
41
|
const sizeStyles = SIZE_MAP[size] ?? SIZE_MAP.default;
|
|
36
42
|
const containerClass = cx(
|
|
37
43
|
BASE_STYLES,
|
|
@@ -51,6 +57,7 @@ var Chip = forwardRef(function Chip2({
|
|
|
51
57
|
className: containerClass,
|
|
52
58
|
"data-disabled": disabled ? "true" : void 0,
|
|
53
59
|
...rest,
|
|
60
|
+
"aria-disabled": disabled ? true : rest["aria-disabled"],
|
|
54
61
|
children: [
|
|
55
62
|
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-6", children: [
|
|
56
63
|
shouldRenderChildren && /* @__PURE__ */ jsx("span", { className: "flex items-center gap-4 shrink-0 [&>*]:shrink-0", children: normalizedChildren.map(
|
|
@@ -61,12 +68,16 @@ var Chip = forwardRef(function Chip2({
|
|
|
61
68
|
onRemove && /* @__PURE__ */ jsx(
|
|
62
69
|
"button",
|
|
63
70
|
{
|
|
71
|
+
...buttonProps,
|
|
64
72
|
type: "button",
|
|
65
73
|
disabled,
|
|
66
74
|
"aria-label": removeLabel,
|
|
75
|
+
"aria-labelledby": void 0,
|
|
67
76
|
onClick: (event) => {
|
|
68
77
|
event.stopPropagation();
|
|
69
|
-
|
|
78
|
+
if (disabled) return;
|
|
79
|
+
onRemoveClick == null ? void 0 : onRemoveClick(event);
|
|
80
|
+
if (!event.defaultPrevented) onRemove(event);
|
|
70
81
|
},
|
|
71
82
|
className: cx(
|
|
72
83
|
"ml-4 inline-flex items-center justify-center rounded-full text-fg-subtle",
|
|
@@ -75,7 +86,8 @@ var Chip = forwardRef(function Chip2({
|
|
|
75
86
|
"focus-visible:shadow-focus focus-visible:outline-none",
|
|
76
87
|
"active:bg-bg-primary-subtle-90",
|
|
77
88
|
disabled && "opacity-60 pointer-events-none bg-transparent text-fg-inactive",
|
|
78
|
-
sizeStyles.close
|
|
89
|
+
sizeStyles.close,
|
|
90
|
+
removeClassName
|
|
79
91
|
),
|
|
80
92
|
children: /* @__PURE__ */ jsx(Close, {})
|
|
81
93
|
}
|
package/docs/removal.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Removal, descriptions and focus
|
|
2
|
+
|
|
3
|
+
`Chip` remains a static native div with a forwarded `HTMLDivElement` ref. Passing
|
|
4
|
+
`onRemove` renders its existing native button. Set a specific `removeLabel`, such
|
|
5
|
+
as `Remove AC9M3N01`.
|
|
6
|
+
|
|
7
|
+
`removeButtonProps` forwards attributes, native handlers, style, className and an
|
|
8
|
+
`HTMLButtonElement` ref to that same button. It adds no wrapper or tab stop. Use
|
|
9
|
+
`aria-describedby` to associate host-owned context with the actual remove action;
|
|
10
|
+
descriptions on an ancestor are not inherited. A visual tooltip can still use
|
|
11
|
+
`TooltipTrigger asChild` around the Chip root.
|
|
12
|
+
|
|
13
|
+
Chip owns the remove button's `type="button"`, `disabled`, accessible name and
|
|
14
|
+
icon children. `type`, `disabled`, `aria-label`, `aria-labelledby` and `children`
|
|
15
|
+
are excluded from the public slot props and cannot override those core semantics.
|
|
16
|
+
The slot's click handler runs before `onRemove`; `event.preventDefault()` cancels
|
|
17
|
+
removal. Click propagation is stopped, including when cancelled, so an ancestor
|
|
18
|
+
does not also toggle the selection. A disabled Chip invokes neither click
|
|
19
|
+
callback. Other native events, including keyboard and focus handlers, forward
|
|
20
|
+
normally. Class names merge with the existing button presentation.
|
|
21
|
+
|
|
22
|
+
Collection state and focus after removal belong to the host. Use the public
|
|
23
|
+
button refs to focus the next enabled remove action, then the previous action,
|
|
24
|
+
then a stable host control when the last chip disappears. Do not query private
|
|
25
|
+
button markup or focus the noninteractive root. The Selection adoption story
|
|
26
|
+
demonstrates this recipe with descriptions and keyboard/pointer removal.
|
package/package.json
CHANGED
|
@@ -1,41 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@edux-design/chips",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css"
|
|
7
7
|
],
|
|
8
8
|
"files": [
|
|
9
|
-
"dist"
|
|
9
|
+
"dist",
|
|
10
|
+
"docs",
|
|
11
|
+
"README.md",
|
|
12
|
+
"CHANGELOG.md"
|
|
10
13
|
],
|
|
11
14
|
"types": "./dist/index.d.ts",
|
|
12
15
|
"exports": {
|
|
13
16
|
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
14
18
|
"import": "./dist/index.mjs",
|
|
15
|
-
"require": "./dist/index.js"
|
|
16
|
-
"types": "./dist/index.d.ts"
|
|
19
|
+
"require": "./dist/index.js"
|
|
17
20
|
}
|
|
18
21
|
},
|
|
19
|
-
"scripts": {
|
|
20
|
-
"lint": "eslint . --max-warnings 0",
|
|
21
|
-
"build": "tsup src/index.js --format esm,cjs --dts",
|
|
22
|
-
"dev": "tsup src/index.js --watch --format esm,cjs --dts",
|
|
23
|
-
"generate:component": "turbo gen react-component",
|
|
24
|
-
"check-types": "tsc --noEmit"
|
|
25
|
-
},
|
|
26
|
-
"devDependencies": {
|
|
27
|
-
"typescript": "^5.9.2",
|
|
28
|
-
"tailwindcss": "^4.1.12",
|
|
29
|
-
"postcss": "^8.5.6",
|
|
30
|
-
"tsup": "^8.5.0",
|
|
31
|
-
"@tailwindcss/cli": "^4.1.12",
|
|
32
|
-
"@tailwindcss/postcss": "^4.1.12"
|
|
33
|
-
},
|
|
34
22
|
"dependencies": {
|
|
35
23
|
"@edux-design/utils": "*",
|
|
36
|
-
"@edux-design/icons": "*"
|
|
37
|
-
"react": "^19.1.0",
|
|
38
|
-
"react-dom": "^19.1.0"
|
|
24
|
+
"@edux-design/icons": "*"
|
|
39
25
|
},
|
|
40
26
|
"peerDependencies": {
|
|
41
27
|
"react": "^19.1.0",
|