@openwarelabs/ui 0.10.0 → 0.10.1

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.
Files changed (33) hide show
  1. package/README.md +5 -1
  2. package/dist/components/Avatar/Avatar.d.cts +2 -13
  3. package/dist/components/Avatar/Avatar.d.ts +2 -13
  4. package/dist/components/Avatar/Avatar.types.d.cts +13 -0
  5. package/dist/components/Avatar/Avatar.types.d.ts +13 -0
  6. package/dist/components/Calendar/DatePicker.d.cts +2 -19
  7. package/dist/components/Calendar/DatePicker.d.ts +2 -19
  8. package/dist/components/Calendar/DatePicker.types.d.cts +19 -0
  9. package/dist/components/Calendar/DatePicker.types.d.ts +19 -0
  10. package/dist/components/Calendar/DateRangePicker.d.cts +2 -34
  11. package/dist/components/Calendar/DateRangePicker.d.ts +2 -34
  12. package/dist/components/Calendar/DateRangePicker.types.d.cts +34 -0
  13. package/dist/components/Calendar/DateRangePicker.types.d.ts +34 -0
  14. package/dist/components/ColorPicker/ColorPicker.d.cts +2 -55
  15. package/dist/components/ColorPicker/ColorPicker.d.ts +2 -55
  16. package/dist/components/ColorPicker/ColorPicker.types.d.cts +54 -0
  17. package/dist/components/ColorPicker/ColorPicker.types.d.ts +54 -0
  18. package/dist/components/ListBox/ListBox.d.cts +3 -61
  19. package/dist/components/ListBox/ListBox.d.ts +3 -61
  20. package/dist/components/ListBox/ListBox.types.d.cts +61 -0
  21. package/dist/components/ListBox/ListBox.types.d.ts +61 -0
  22. package/dist/components/Prose/Prose.d.cts +2 -16
  23. package/dist/components/Prose/Prose.d.ts +2 -16
  24. package/dist/components/Prose/Prose.types.d.cts +16 -0
  25. package/dist/components/Prose/Prose.types.d.ts +16 -0
  26. package/dist/components.css +16 -0
  27. package/dist/index.cjs +34 -13
  28. package/dist/index.cjs.map +2 -2
  29. package/dist/index.js +103 -82
  30. package/dist/index.js.map +3 -3
  31. package/dist/openware-ui.iife.js +6 -6
  32. package/dist/styles.css +16 -0
  33. package/package.json +4 -4
@@ -1,64 +1,6 @@
1
- import { type ReactElement, type ReactNode, type RefAttributes } from "react";
2
- import type { SelectOption } from "../Select/Select.js";
3
- /** An option, shaped like Select's, with an optional icon. */
4
- export interface ListBoxOption extends SelectOption {
5
- /** A 16px icon between the checkmark and the label. */
6
- icon?: ReactNode;
7
- /** Plain text for type-to-find, when `label` isn't a string. */
8
- textValue?: string;
9
- }
10
- /** Options under a heading, like a Select's groups. */
11
- export interface ListBoxGroup {
12
- /** The heading, shown in uppercase above the options and read out as the group's name. */
13
- label: string;
14
- options: ListBoxOption[];
15
- }
16
- export type ListBoxItem = ListBoxOption | ListBoxGroup;
17
- export type ListBoxSelectionMode = "single" | "multiple";
18
- /** ListBox's props for one selection mode: `value` is a string in single mode and an array in multiple mode. */
19
- export interface ListBoxModeProps<Mode extends ListBoxSelectionMode> {
20
- /** The options, and groups of options under a heading. */
21
- options: ListBoxItem[];
22
- /** `single` chooses one option; `multiple` any number.
23
- * @default "single" */
24
- selectionMode?: Mode;
25
- /** The selected option's value in single mode ("" for none), or the selected values in multiple mode. */
26
- value?: Mode extends "multiple" ? string[] : string;
27
- /** The starting value when uncontrolled.
28
- * @default "" or [] */
29
- defaultValue?: Mode extends "multiple" ? string[] : string;
30
- /** Called with the new value: a string in single mode, the selected values in the options' order in multiple mode. */
31
- onChange?(value: Mode extends "multiple" ? string[] : string): void;
32
- /** Keeps at least one option selected: choosing the selected option again doesn't clear it.
33
- * @default false */
34
- disallowEmptySelection?: boolean;
35
- /** Shown in the list when there are no options.
36
- * @default "No options" */
37
- emptyMessage?: ReactNode;
38
- /** Scrolls the options past this height, e.g. 240 or "40vh". */
39
- maxHeight?: number | string;
40
- /** md rows are 36px; sm rows are 32px with 12px text, like a small Select's list.
41
- * @default "md" */
42
- size?: "sm" | "md";
43
- /** Shows the list as wrong: a red border, and a red halo when focused. Also sets aria-invalid. Field passes it.
44
- * @default false */
45
- isInvalid?: boolean;
46
- /** The options can be moved through and read, but the selection can't change.
47
- * @default false */
48
- isReadOnly?: boolean;
49
- /** Fades the list and takes it out of the tab order.
50
- * @default false */
51
- disabled?: boolean;
52
- id?: string;
53
- /** Names the list for screen readers when it isn't in a Field. */
54
- "aria-label"?: string;
55
- "aria-labelledby"?: string;
56
- "aria-describedby"?: string;
57
- className?: string;
58
- }
59
- /** ListBox's props. `value`, `defaultValue` and `onChange` take a string in single mode and an array in multiple mode. */
60
- export interface ListBoxProps extends ListBoxModeProps<ListBoxSelectionMode> {
61
- }
1
+ import { type ReactElement, type RefAttributes } from "react";
2
+ import type { ListBoxModeProps, ListBoxSelectionMode } from "./ListBox.types.js";
3
+ export type { ListBoxGroup, ListBoxItem, ListBoxModeProps, ListBoxOption, ListBoxProps, ListBoxSelectionMode } from "./ListBox.types.js";
62
4
  /**
63
5
  * Select's list of options on its own: a choice that stays on the page. `selectionMode="multiple"` makes `value` an array.
64
6
  */
@@ -0,0 +1,61 @@
1
+ import type { ReactNode } from "react";
2
+ import type { SelectOption } from "../Select/Select.cjs";
3
+ /** An option, shaped like Select's, with an optional icon. */
4
+ export interface ListBoxOption extends SelectOption {
5
+ /** A 16px icon between the checkmark and the label. */
6
+ icon?: ReactNode;
7
+ /** Plain text for type-to-find, when `label` isn't a string. */
8
+ textValue?: string;
9
+ }
10
+ /** Options under a heading, like a Select's groups. */
11
+ export interface ListBoxGroup {
12
+ /** The heading, shown in uppercase above the options and read out as the group's name. */
13
+ label: string;
14
+ options: ListBoxOption[];
15
+ }
16
+ export type ListBoxItem = ListBoxOption | ListBoxGroup;
17
+ export type ListBoxSelectionMode = "single" | "multiple";
18
+ /** ListBox's props for one selection mode: `value` is a string in single mode and an array in multiple mode. */
19
+ export interface ListBoxModeProps<Mode extends ListBoxSelectionMode> {
20
+ /** The options, and groups of options under a heading. */
21
+ options: ListBoxItem[];
22
+ /** `single` chooses one option; `multiple` any number.
23
+ * @default "single" */
24
+ selectionMode?: Mode;
25
+ /** The selected option's value in single mode ("" for none), or the selected values in multiple mode. */
26
+ value?: Mode extends "multiple" ? string[] : string;
27
+ /** The starting value when uncontrolled.
28
+ * @default "" or [] */
29
+ defaultValue?: Mode extends "multiple" ? string[] : string;
30
+ /** Called with the new value: a string in single mode, the selected values in the options' order in multiple mode. */
31
+ onChange?(value: Mode extends "multiple" ? string[] : string): void;
32
+ /** Keeps at least one option selected: choosing the selected option again doesn't clear it.
33
+ * @default false */
34
+ disallowEmptySelection?: boolean;
35
+ /** Shown in the list when there are no options.
36
+ * @default "No options" */
37
+ emptyMessage?: ReactNode;
38
+ /** Scrolls the options past this height, e.g. 240 or "40vh". */
39
+ maxHeight?: number | string;
40
+ /** md rows are 36px; sm rows are 32px with 12px text, like a small Select's list.
41
+ * @default "md" */
42
+ size?: "sm" | "md";
43
+ /** Shows the list as wrong: a red border, and a red halo when focused. Also sets aria-invalid. Field passes it.
44
+ * @default false */
45
+ isInvalid?: boolean;
46
+ /** The options can be moved through and read, but the selection can't change.
47
+ * @default false */
48
+ isReadOnly?: boolean;
49
+ /** Fades the list and takes it out of the tab order.
50
+ * @default false */
51
+ disabled?: boolean;
52
+ id?: string;
53
+ /** Names the list for screen readers when it isn't in a Field. */
54
+ "aria-label"?: string;
55
+ "aria-labelledby"?: string;
56
+ "aria-describedby"?: string;
57
+ className?: string;
58
+ }
59
+ /** ListBox's props. `value`, `defaultValue` and `onChange` take a string in single mode and an array in multiple mode. */
60
+ export interface ListBoxProps extends ListBoxModeProps<ListBoxSelectionMode> {
61
+ }
@@ -0,0 +1,61 @@
1
+ import type { ReactNode } from "react";
2
+ import type { SelectOption } from "../Select/Select.js";
3
+ /** An option, shaped like Select's, with an optional icon. */
4
+ export interface ListBoxOption extends SelectOption {
5
+ /** A 16px icon between the checkmark and the label. */
6
+ icon?: ReactNode;
7
+ /** Plain text for type-to-find, when `label` isn't a string. */
8
+ textValue?: string;
9
+ }
10
+ /** Options under a heading, like a Select's groups. */
11
+ export interface ListBoxGroup {
12
+ /** The heading, shown in uppercase above the options and read out as the group's name. */
13
+ label: string;
14
+ options: ListBoxOption[];
15
+ }
16
+ export type ListBoxItem = ListBoxOption | ListBoxGroup;
17
+ export type ListBoxSelectionMode = "single" | "multiple";
18
+ /** ListBox's props for one selection mode: `value` is a string in single mode and an array in multiple mode. */
19
+ export interface ListBoxModeProps<Mode extends ListBoxSelectionMode> {
20
+ /** The options, and groups of options under a heading. */
21
+ options: ListBoxItem[];
22
+ /** `single` chooses one option; `multiple` any number.
23
+ * @default "single" */
24
+ selectionMode?: Mode;
25
+ /** The selected option's value in single mode ("" for none), or the selected values in multiple mode. */
26
+ value?: Mode extends "multiple" ? string[] : string;
27
+ /** The starting value when uncontrolled.
28
+ * @default "" or [] */
29
+ defaultValue?: Mode extends "multiple" ? string[] : string;
30
+ /** Called with the new value: a string in single mode, the selected values in the options' order in multiple mode. */
31
+ onChange?(value: Mode extends "multiple" ? string[] : string): void;
32
+ /** Keeps at least one option selected: choosing the selected option again doesn't clear it.
33
+ * @default false */
34
+ disallowEmptySelection?: boolean;
35
+ /** Shown in the list when there are no options.
36
+ * @default "No options" */
37
+ emptyMessage?: ReactNode;
38
+ /** Scrolls the options past this height, e.g. 240 or "40vh". */
39
+ maxHeight?: number | string;
40
+ /** md rows are 36px; sm rows are 32px with 12px text, like a small Select's list.
41
+ * @default "md" */
42
+ size?: "sm" | "md";
43
+ /** Shows the list as wrong: a red border, and a red halo when focused. Also sets aria-invalid. Field passes it.
44
+ * @default false */
45
+ isInvalid?: boolean;
46
+ /** The options can be moved through and read, but the selection can't change.
47
+ * @default false */
48
+ isReadOnly?: boolean;
49
+ /** Fades the list and takes it out of the tab order.
50
+ * @default false */
51
+ disabled?: boolean;
52
+ id?: string;
53
+ /** Names the list for screen readers when it isn't in a Field. */
54
+ "aria-label"?: string;
55
+ "aria-labelledby"?: string;
56
+ "aria-describedby"?: string;
57
+ className?: string;
58
+ }
59
+ /** ListBox's props. `value`, `defaultValue` and `onChange` take a string in single mode and an array in multiple mode. */
60
+ export interface ListBoxProps extends ListBoxModeProps<ListBoxSelectionMode> {
61
+ }
@@ -1,19 +1,5 @@
1
- import { type HTMLAttributes, type ReactNode } from "react";
2
- export interface ProseProps extends HTMLAttributes<HTMLElement> {
3
- /** sm sets 14px interface text with a tight rhythm and modest headings, for chat answers and comments. md sets the prose
4
- * style (16.5px, 1.7 leading) with headings from the type scale, for articles and docs.
5
- * @default "md" */
6
- size?: "sm" | "md";
7
- /** Drops the readable width (about 68 characters a line at md) so the text runs the full width of its container. sm has no
8
- * maximum width to drop.
9
- * @default false */
10
- fullWidth?: boolean;
11
- /** The element: article for a post, section for part of a page.
12
- * @default "div" */
13
- as?: "div" | "article" | "section" | "main" | "aside";
14
- /** Plain HTML elements to style: what a Markdown renderer, a CMS or a server gives back. */
15
- children?: ReactNode;
16
- }
1
+ import type { ProseProps } from "./Prose.types.cjs";
2
+ export type { ProseProps } from "./Prose.types.cjs";
17
3
  /**
18
4
  * Styles content you don't write element by element: Markdown rendered to HTML, a CMS body, an agent's answer. It sets
19
5
  * the plain elements inside it (headings, paragraphs, lists, quotes, code, tables, images, details) in Openware's type
@@ -1,19 +1,5 @@
1
- import { type HTMLAttributes, type ReactNode } from "react";
2
- export interface ProseProps extends HTMLAttributes<HTMLElement> {
3
- /** sm sets 14px interface text with a tight rhythm and modest headings, for chat answers and comments. md sets the prose
4
- * style (16.5px, 1.7 leading) with headings from the type scale, for articles and docs.
5
- * @default "md" */
6
- size?: "sm" | "md";
7
- /** Drops the readable width (about 68 characters a line at md) so the text runs the full width of its container. sm has no
8
- * maximum width to drop.
9
- * @default false */
10
- fullWidth?: boolean;
11
- /** The element: article for a post, section for part of a page.
12
- * @default "div" */
13
- as?: "div" | "article" | "section" | "main" | "aside";
14
- /** Plain HTML elements to style: what a Markdown renderer, a CMS or a server gives back. */
15
- children?: ReactNode;
16
- }
1
+ import type { ProseProps } from "./Prose.types.js";
2
+ export type { ProseProps } from "./Prose.types.js";
17
3
  /**
18
4
  * Styles content you don't write element by element: Markdown rendered to HTML, a CMS body, an agent's answer. It sets
19
5
  * the plain elements inside it (headings, paragraphs, lists, quotes, code, tables, images, details) in Openware's type
@@ -0,0 +1,16 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ export interface ProseProps extends HTMLAttributes<HTMLElement> {
3
+ /** sm sets 14px interface text with a tight rhythm and modest headings, for chat answers and comments. md sets the prose
4
+ * style (16.5px, 1.7 leading) with headings from the type scale, for articles and docs.
5
+ * @default "md" */
6
+ size?: "sm" | "md";
7
+ /** Drops the readable width (about 68 characters a line at md) so the text runs the full width of its container. sm has no
8
+ * maximum width to drop.
9
+ * @default false */
10
+ fullWidth?: boolean;
11
+ /** The element: article for a post, section for part of a page.
12
+ * @default "div" */
13
+ as?: "div" | "article" | "section" | "main" | "aside";
14
+ /** Plain HTML elements to style: what a Markdown renderer, a CMS or a server gives back. */
15
+ children?: ReactNode;
16
+ }
@@ -0,0 +1,16 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ export interface ProseProps extends HTMLAttributes<HTMLElement> {
3
+ /** sm sets 14px interface text with a tight rhythm and modest headings, for chat answers and comments. md sets the prose
4
+ * style (16.5px, 1.7 leading) with headings from the type scale, for articles and docs.
5
+ * @default "md" */
6
+ size?: "sm" | "md";
7
+ /** Drops the readable width (about 68 characters a line at md) so the text runs the full width of its container. sm has no
8
+ * maximum width to drop.
9
+ * @default false */
10
+ fullWidth?: boolean;
11
+ /** The element: article for a post, section for part of a page.
12
+ * @default "div" */
13
+ as?: "div" | "article" | "section" | "main" | "aside";
14
+ /** Plain HTML elements to style: what a Markdown renderer, a CMS or a server gives back. */
15
+ children?: ReactNode;
16
+ }
@@ -1221,7 +1221,14 @@
1221
1221
  }
1222
1222
 
1223
1223
  .ow-date-field__segment {
1224
+ /* At least 24px each way, the smallest a pointer target may be (WCAG 2.2, 2.5.8). */
1225
+ box-sizing: border-box;
1226
+ display: inline-flex;
1227
+ min-width: 24px;
1228
+ min-height: 24px;
1224
1229
  flex-shrink: 0;
1230
+ align-items: center;
1231
+ justify-content: center;
1225
1232
  border-radius: var(--ow-radius-sm);
1226
1233
  padding: 2px;
1227
1234
  color: var(--ow-text);
@@ -1233,6 +1240,11 @@
1233
1240
  transition-timing-function: var(--ow-ease-standard);
1234
1241
  }
1235
1242
 
1243
+ .ow-date-field__segment[data-segment="0"] {
1244
+ /* The first, often one digit ("6:12"), keeps to the separator after it; the spare width goes before it. */
1245
+ justify-content: flex-end;
1246
+ }
1247
+
1236
1248
  .ow-date-field__segment::selection {
1237
1249
  background: transparent;
1238
1250
  }
@@ -5080,6 +5092,10 @@
5080
5092
  line-height: 1;
5081
5093
  }
5082
5094
 
5095
+ .ow-avatar[data-initials]::before {
5096
+ content: attr(data-initials);
5097
+ }
5098
+
5083
5099
  .ow-avatar--empty {
5084
5100
  background: var(--ow-avatar-empty);
5085
5101
  color: var(--ow-on-avatar-empty);
package/dist/index.cjs CHANGED
@@ -3431,7 +3431,7 @@ function ListBoxWithRef({
3431
3431
  );
3432
3432
  };
3433
3433
  const isEmpty = flat.length === 0;
3434
- const describedBy = [ariaDescribedBy, isEmpty ? emptyId : void 0].filter(Boolean).join(" ") || void 0;
3434
+ const describedBy = ariaDescribedBy;
3435
3435
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
3436
3436
  "div",
3437
3437
  {
@@ -3474,7 +3474,10 @@ function ListBoxWithRef({
3474
3474
  item.options.map(renderOption)
3475
3475
  ] }, `group-${item.label}-${groupIndex}`) : renderOption(item)
3476
3476
  ),
3477
- isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { id: emptyId, className: "ow-listbox__empty", role: "presentation", children: emptyMessage }) : null
3477
+ isEmpty ? (
3478
+ // A listbox holds options, so an empty one says so with one that can't be chosen.
3479
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { id: emptyId, className: "ow-listbox__empty", role: "option", "aria-disabled": "true", "aria-selected": "false", children: emptyMessage })
3480
+ ) : null
3478
3481
  ]
3479
3482
  }
3480
3483
  );
@@ -4235,9 +4238,9 @@ var DatePicker = /* @__PURE__ */ (0, import_react32.forwardRef)(function DatePic
4235
4238
  "aria-haspopup": "dialog",
4236
4239
  "aria-expanded": isOpen,
4237
4240
  "aria-controls": isOpen ? panelId : void 0,
4238
- "aria-label": ariaLabel,
4239
- "aria-labelledby": ariaLabelledBy,
4240
- "aria-describedby": [`${panelId}-value`, ariaDescribedBy].filter(Boolean).join(" "),
4241
+ "aria-label": ariaLabel && !ariaLabelledBy ? `${ariaLabel}, ${label}` : void 0,
4242
+ "aria-labelledby": ariaLabelledBy ? `${ariaLabelledBy} ${panelId}-value` : void 0,
4243
+ "aria-describedby": ariaDescribedBy,
4241
4244
  "aria-invalid": isInvalid || void 0,
4242
4245
  disabled,
4243
4246
  className: cx(
@@ -4540,9 +4543,9 @@ var DateRangePicker = /* @__PURE__ */ (0, import_react34.forwardRef)(function Da
4540
4543
  "aria-haspopup": "dialog",
4541
4544
  "aria-expanded": isOpen,
4542
4545
  "aria-controls": isOpen ? panelId : void 0,
4543
- "aria-label": ariaLabel,
4544
- "aria-labelledby": ariaLabelledBy,
4545
- "aria-describedby": [`${panelId}-value`, ariaDescribedBy].filter(Boolean).join(" "),
4546
+ "aria-label": ariaLabel && !ariaLabelledBy ? `${ariaLabel}, ${label}` : void 0,
4547
+ "aria-labelledby": ariaLabelledBy ? `${ariaLabelledBy} ${panelId}-value` : void 0,
4548
+ "aria-describedby": ariaDescribedBy,
4546
4549
  "aria-invalid": isInvalid || void 0,
4547
4550
  disabled,
4548
4551
  className: cx("ow-select", "ow-date-range-picker__trigger", `ow-select--${size2}`, {
@@ -6256,7 +6259,8 @@ function Avatar({ name, src, size: size2 = "md", label, className }) {
6256
6259
  className: cx("ow-avatar", sizing.className, !initials && !showImage && "ow-avatar--empty", className),
6257
6260
  style: sizing.style,
6258
6261
  ...label ? { role: "img", "aria-label": label } : { "aria-hidden": true },
6259
- children: showImage ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("img", { src, alt: "", className: "ow-avatar__image", onError: () => setFailedImage(src) }) : initials || /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(UserIcon, { size: Math.round(sizing.pixels * 0.52) })
6262
+ "data-initials": !showImage && initials ? initials : void 0,
6263
+ children: showImage ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("img", { src, alt: "", className: "ow-avatar__image", onError: () => setFailedImage(src) }) : initials ? null : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(UserIcon, { size: Math.round(sizing.pixels * 0.52) })
6260
6264
  }
6261
6265
  );
6262
6266
  }
@@ -6484,10 +6488,27 @@ var import_react57 = require("react");
6484
6488
  var import_jsx_runtime62 = require("react/jsx-runtime");
6485
6489
  var Prose = /* @__PURE__ */ (0, import_react57.forwardRef)(function Prose2({ size: size2 = "md", fullWidth = false, as = "div", className, children, ...props }, ref) {
6486
6490
  const Element2 = as;
6491
+ const root = (0, import_react57.useRef)(null);
6492
+ (0, import_react57.useEffect)(() => {
6493
+ const element = root.current;
6494
+ if (!element) return;
6495
+ for (const scroller of element.querySelectorAll("pre, .ow-table-wrap")) {
6496
+ if (scroller.scrollWidth > scroller.clientWidth && !scroller.hasAttribute("tabindex")) scroller.tabIndex = 0;
6497
+ }
6498
+ for (const box of element.querySelectorAll('li > input[type="checkbox"], li > p > input[type="checkbox"]')) {
6499
+ if (box.labels?.length || box.hasAttribute("aria-label") || box.hasAttribute("aria-labelledby")) continue;
6500
+ const text = box.closest("li")?.textContent?.trim();
6501
+ if (text) box.setAttribute("aria-label", text);
6502
+ }
6503
+ });
6487
6504
  return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
6488
6505
  Element2,
6489
6506
  {
6490
- ref,
6507
+ ref: (node) => {
6508
+ root.current = node;
6509
+ if (typeof ref === "function") ref(node);
6510
+ else if (ref) ref.current = node;
6511
+ },
6491
6512
  className: cx("ow-prose", `ow-prose--${size2}`, size2 === "md" ? "ow-type-prose" : "ow-type-copy", fullWidth && "ow-prose--full", className),
6492
6513
  ...props,
6493
6514
  children
@@ -8065,9 +8086,9 @@ var ColorField = /* @__PURE__ */ (0, import_react65.forwardRef)(function ColorFi
8065
8086
  "aria-haspopup": "dialog",
8066
8087
  "aria-expanded": isOpen,
8067
8088
  "aria-controls": isOpen ? panelId : void 0,
8068
- "aria-label": ariaLabel,
8069
- "aria-labelledby": ariaLabelledBy,
8070
- "aria-describedby": [`${panelId}-value`, ariaDescribedBy].filter(Boolean).join(" "),
8089
+ "aria-label": ariaLabel && !ariaLabelledBy ? `${ariaLabel}, ${color.toUpperCase()}` : void 0,
8090
+ "aria-labelledby": ariaLabelledBy ? `${ariaLabelledBy} ${panelId}-value` : void 0,
8091
+ "aria-describedby": ariaDescribedBy,
8071
8092
  "aria-invalid": isInvalid || void 0,
8072
8093
  disabled,
8073
8094
  className: cx(