@itwin/itwinui-react 5.0.0-alpha.12 → 5.0.0-alpha.13

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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.0.0-alpha.13
4
+
5
+ - Added new `unstable_ErrorRegion` component for displaying errors originating from `Tree`. See [#454](https://github.com/iTwin/design-system/pull/454).
6
+ - Added initial `unstable_Toolbar` component. See [#529](https://github.com/iTwin/design-system/pull/529).
7
+ - Added `dot` prop to `<Tree.ItemAction>`, matching the `dot` prop from `<IconButton>`.
8
+ - Also added `unstable_dot` prop to `<DropdownMenu.Item>`, although it's not meant to be used currently.
9
+ - Styling changes:
10
+ - Improved forced-colors mode styling for `<Icon>`, `<Button>` as anchor, and `<Tree.Item>`.
11
+ - Updated the color of `dot` used in `<IconButton>`.
12
+
3
13
  ## 5.0.0-alpha.12
4
14
 
5
15
  - **breaking**: Introduce composition API for `Field`. See [#449](https://github.com/iTwin/design-system/pull/449).
@@ -21,6 +21,7 @@ import {
21
21
  import { useStoreState } from "@ariakit/react/store";
22
22
  import { predefinedSymbols } from "./Kbd.internal.js";
23
23
  import { usePopoverContext } from "@ariakit/react/popover";
24
+ import { Dot } from "./~utils.Dot.js";
24
25
  function DropdownMenuRoot(props) {
25
26
  const {
26
27
  children,
@@ -84,7 +85,8 @@ const DropdownMenuButton = forwardRef(
84
85
  DEV: DropdownMenuButton.displayName = "DropdownMenu.Button";
85
86
  const DropdownMenuItem = forwardRef(
86
87
  (props, forwardedRef) => {
87
- const { label, shortcuts, icon, ...rest } = props;
88
+ const { label, shortcuts, icon, unstable_dot, ...rest } = props;
89
+ const dotId = React.useId();
88
90
  return /* @__PURE__ */ jsxs(
89
91
  MenuItem,
90
92
  {
@@ -96,6 +98,7 @@ const DropdownMenuItem = forwardRef(
96
98
  ButtonAk,
97
99
  {
98
100
  accessibleWhenDisabled: true,
101
+ "aria-describedby": dotId,
99
102
  ...rest,
100
103
  className: cx("\u{1F95D}-dropdown-menu-item", props.className),
101
104
  ref: forwardedRef
@@ -106,7 +109,13 @@ const DropdownMenuItem = forwardRef(
106
109
  children: [
107
110
  icon ? /* @__PURE__ */ jsx(DropdownMenuIcon, { icon }) : null,
108
111
  /* @__PURE__ */ jsx(ListItem.Content, { render: /* @__PURE__ */ jsx("span", {}), children: label }),
109
- shortcuts ? /* @__PURE__ */ jsx(DropdownMenuItemShortcuts, { shortcuts }) : null
112
+ shortcuts ? /* @__PURE__ */ jsx(DropdownMenuItemShortcuts, { shortcuts }) : null,
113
+ unstable_dot ? /* @__PURE__ */ jsx(
114
+ ListItem.Decoration,
115
+ {
116
+ render: /* @__PURE__ */ jsx(Dot, { id: dotId, className: "\u{1F95D}-dropdown-menu-item-dot", children: unstable_dot })
117
+ }
118
+ ) : null
110
119
  ]
111
120
  }
112
121
  );
@@ -0,0 +1,137 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import cx from "classnames";
4
+ import {
5
+ DialogProvider,
6
+ DialogDisclosure,
7
+ Dialog
8
+ } from "@ariakit/react/dialog";
9
+ import { Role } from "@ariakit/react/role";
10
+ import { forwardRef } from "./~utils.js";
11
+ import { ChevronDown, Dismiss, StatusWarning } from "./Icon.js";
12
+ import { Text } from "./Text.js";
13
+ import { IconButton } from "./IconButton.js";
14
+ import { Button } from "./Button.js";
15
+ import { useControlledState } from "./~hooks.js";
16
+ import { VisuallyHidden } from "./VisuallyHidden.js";
17
+ const ErrorRegionRoot = forwardRef(
18
+ (props, forwardedRef) => {
19
+ const { label, items, expanded, onExpandedChange, ...rest } = props;
20
+ const labelId = React.useId();
21
+ const sectionLabelledBy = props["aria-labelledby"] ?? (props["aria-label"] ? void 0 : labelId);
22
+ const [open, setOpen] = useControlledState(
23
+ false,
24
+ expanded,
25
+ onExpandedChange
26
+ );
27
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
28
+ /* @__PURE__ */ jsx(VisuallyHidden, { "aria-live": "polite", "aria-atomic": true, children: label }),
29
+ /* @__PURE__ */ jsx(DialogProvider, { open, setOpen, children: /* @__PURE__ */ jsx(
30
+ Role.section,
31
+ {
32
+ ...rest,
33
+ "aria-labelledby": sectionLabelledBy,
34
+ className: cx("\u{1F95D}-error-region", props.className),
35
+ "data-kiwi-visible": !!label,
36
+ "data-kiwi-expanded": open,
37
+ ref: forwardedRef,
38
+ children: /* @__PURE__ */ jsxs("div", { className: "\u{1F95D}-error-region-container", children: [
39
+ /* @__PURE__ */ jsxs(
40
+ DialogDisclosure,
41
+ {
42
+ className: "\u{1F95D}-error-region-header",
43
+ render: /* @__PURE__ */ jsx(Button, { variant: "ghost" }),
44
+ children: [
45
+ /* @__PURE__ */ jsx(StatusWarning, { className: "\u{1F95D}-error-region-icon" }),
46
+ /* @__PURE__ */ jsx(
47
+ Text,
48
+ {
49
+ id: labelId,
50
+ className: "\u{1F95D}-error-region-label",
51
+ variant: "body-sm",
52
+ children: label
53
+ }
54
+ ),
55
+ /* @__PURE__ */ jsx(
56
+ IconButton,
57
+ {
58
+ inert: true,
59
+ render: /* @__PURE__ */ jsx("span", {}),
60
+ role: void 0,
61
+ label: "",
62
+ icon: /* @__PURE__ */ jsx(ChevronDown, {}),
63
+ variant: "ghost"
64
+ }
65
+ )
66
+ ]
67
+ }
68
+ ),
69
+ /* @__PURE__ */ jsx(
70
+ Dialog,
71
+ {
72
+ className: "\u{1F95D}-error-region-dialog",
73
+ portal: false,
74
+ modal: false,
75
+ autoFocusOnShow: false,
76
+ "aria-labelledby": labelId,
77
+ children: /* @__PURE__ */ jsx("div", { className: "\u{1F95D}-error-region-items", role: "list", children: items })
78
+ }
79
+ )
80
+ ] })
81
+ }
82
+ ) })
83
+ ] });
84
+ }
85
+ );
86
+ DEV: ErrorRegionRoot.displayName = "ErrorRegion.Root";
87
+ const ErrorRegionItem = forwardRef(
88
+ (props, forwardedRef) => {
89
+ const generatedId = React.useId();
90
+ const {
91
+ message,
92
+ messageId = `${generatedId}-message`,
93
+ actions,
94
+ onDismiss,
95
+ ...rest
96
+ } = props;
97
+ const dismissButtonId = `${generatedId}-dismiss`;
98
+ return /* @__PURE__ */ jsxs(
99
+ Role.div,
100
+ {
101
+ ...rest,
102
+ role: "listitem",
103
+ className: cx("\u{1F95D}-error-region-item", props.className),
104
+ ref: forwardedRef,
105
+ children: [
106
+ /* @__PURE__ */ jsx(
107
+ Text,
108
+ {
109
+ id: messageId,
110
+ variant: "body-sm",
111
+ className: "\u{1F95D}-error-region-item-message",
112
+ children: message
113
+ }
114
+ ),
115
+ onDismiss && /* @__PURE__ */ jsx(
116
+ IconButton,
117
+ {
118
+ id: dismissButtonId,
119
+ className: "\u{1F95D}-error-region-item-dismiss",
120
+ variant: "ghost",
121
+ label: "Dismiss",
122
+ "aria-labelledby": `${dismissButtonId} ${messageId}`,
123
+ icon: /* @__PURE__ */ jsx(Dismiss, {}),
124
+ onClick: onDismiss
125
+ }
126
+ ),
127
+ /* @__PURE__ */ jsx("div", { className: "\u{1F95D}-error-region-item-actions", children: actions })
128
+ ]
129
+ }
130
+ );
131
+ }
132
+ );
133
+ DEV: ErrorRegionItem.displayName = "ErrorRegion.Item";
134
+ export {
135
+ ErrorRegionItem as Item,
136
+ ErrorRegionRoot as Root
137
+ };
@@ -35,11 +35,12 @@ DEV: FieldRoot.displayName = "Field";
35
35
  const FieldLabel = forwardRef(
36
36
  (props, forwardedRef) => {
37
37
  const store = useCollectionContext();
38
- const renderedItems = useStoreState(store, "renderedItems");
38
+ const renderedItems = useStoreState(
39
+ store,
40
+ "renderedItems"
41
+ );
39
42
  const fieldId = React.useMemo(
40
- () => renderedItems?.find(
41
- (item) => item.elementType === "control"
42
- )?.id,
43
+ () => renderedItems?.find((item) => item.elementType === "control")?.id,
43
44
  [renderedItems]
44
45
  );
45
46
  const getData = React.useCallback(
@@ -87,7 +88,10 @@ const FieldControl = forwardRef(
87
88
  const store = useCollectionContext();
88
89
  const generatedId = React.useId();
89
90
  const { id = store ? generatedId : void 0, ...rest } = props;
90
- const renderedItems = useStoreState(store, "renderedItems");
91
+ const renderedItems = useStoreState(
92
+ store,
93
+ "renderedItems"
94
+ );
91
95
  const describedBy = React.useMemo(() => {
92
96
  const idRefList = renderedItems?.filter(
93
97
  (item) => item.elementType === "description" || item.elementType === "error"
@@ -251,8 +251,33 @@ const MoreHorizontal = forwardRef(
251
251
  }
252
252
  );
253
253
  DEV: MoreHorizontal.displayName = "MoreHorizontal";
254
+ const ChevronDown = forwardRef(
255
+ (props, forwardedRef) => {
256
+ return /* @__PURE__ */ jsx(
257
+ Icon,
258
+ {
259
+ ...props,
260
+ render: /* @__PURE__ */ jsx(
261
+ Role.svg,
262
+ {
263
+ width: "16",
264
+ height: "16",
265
+ fill: "currentColor",
266
+ viewBox: "0 0 16 16",
267
+ render: props.render,
268
+ children: /* @__PURE__ */ jsx("path", { d: "M4.146 6.146a.5.5 0 0 1 .708 0L8 9.293l3.146-3.147a.5.5 0 0 1 .708.708l-3.5 3.5a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 0 1 0-.708Z" })
269
+ }
270
+ ),
271
+ className: cx("\u{1F95D}-chevron-down", props.className),
272
+ ref: forwardedRef
273
+ }
274
+ );
275
+ }
276
+ );
277
+ DEV: ChevronDown.displayName = "ChevronDown";
254
278
  export {
255
279
  Checkmark,
280
+ ChevronDown,
256
281
  DisclosureArrow,
257
282
  Dismiss,
258
283
  Icon,
@@ -1,19 +1,18 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import cx from "classnames";
4
- import { useToolbarContext, ToolbarItem } from "@ariakit/react/toolbar";
5
4
  import { Button } from "./Button.js";
6
5
  import { VisuallyHidden } from "./VisuallyHidden.js";
7
6
  import { Icon } from "./Icon.js";
8
7
  import { Tooltip } from "./Tooltip.js";
9
8
  import { forwardRef } from "./~utils.js";
9
+ import { Dot } from "./~utils.Dot.js";
10
10
  const IconButton = forwardRef(
11
11
  (props, forwardedRef) => {
12
12
  const { label, icon, isActive, labelVariant, dot, ...rest } = props;
13
13
  const baseId = React.useId();
14
14
  const labelId = `${baseId}-label`;
15
15
  const dotId = `${baseId}-dot`;
16
- const toolbar = useToolbarContext();
17
16
  const button = /* @__PURE__ */ jsxs(
18
17
  Button,
19
18
  {
@@ -21,14 +20,12 @@ const IconButton = forwardRef(
21
20
  "aria-labelledby": labelId,
22
21
  "aria-describedby": dot ? dotId : void 0,
23
22
  ...rest,
24
- "data-kiwi-dot": dot ? "true" : void 0,
25
- render: toolbar ? /* @__PURE__ */ jsx(ToolbarItem, { render: props.render }) : props.render,
26
23
  className: cx("\u{1F95D}-icon-button", props.className),
27
24
  ref: forwardedRef,
28
25
  children: [
29
26
  /* @__PURE__ */ jsx(VisuallyHidden, { id: labelId, children: label }),
30
27
  typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { href: icon }) : icon,
31
- dot ? /* @__PURE__ */ jsx(VisuallyHidden, { id: dotId, "aria-hidden": "true", children: dot }) : null
28
+ dot ? /* @__PURE__ */ jsx(Dot, { id: dotId, className: "\u{1F95D}-icon-button-dot", children: dot }) : null
32
29
  ]
33
30
  }
34
31
  );
@@ -0,0 +1,25 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import cx from "classnames";
3
+ import * as Toolbar from "@ariakit/react/toolbar";
4
+ import { forwardRef } from "./~utils.js";
5
+ const ToolbarGroup = forwardRef((props, forwardedRef) => {
6
+ return /* @__PURE__ */ jsx(
7
+ Toolbar.Toolbar,
8
+ {
9
+ ...props,
10
+ className: cx("\u{1F95D}-toolbar", props.className),
11
+ ref: forwardedRef
12
+ }
13
+ );
14
+ });
15
+ DEV: ToolbarGroup.displayName = "Toolbar.Group";
16
+ const ToolbarItem = forwardRef(
17
+ (props, forwardedRef) => {
18
+ return /* @__PURE__ */ jsx(Toolbar.ToolbarItem, { ...props, ref: forwardedRef });
19
+ }
20
+ );
21
+ DEV: ToolbarItem.displayName = "Toolbar.Item";
22
+ export {
23
+ ToolbarGroup as Group,
24
+ ToolbarItem as Item
25
+ };
@@ -6,11 +6,11 @@ import { PopoverProvider } from "@ariakit/react/popover";
6
6
  import {
7
7
  CompositeItem
8
8
  } from "@ariakit/react/composite";
9
- import { Toolbar } from "@ariakit/react/toolbar";
9
+ import { Toolbar, ToolbarItem } from "@ariakit/react/toolbar";
10
10
  import * as ListItem from "./~utils.ListItem.js";
11
11
  import { IconButton } from "./IconButton.js";
12
12
  import * as DropdownMenu from "./DropdownMenu.js";
13
- import { Icon, StatusWarning, MoreHorizontal } from "./Icon.js";
13
+ import { ChevronDown, Icon, StatusWarning, MoreHorizontal } from "./Icon.js";
14
14
  import { forwardRef } from "./~utils.js";
15
15
  import { useEventHandlers, useSafeContext } from "./~hooks.js";
16
16
  import { GhostAligner, useGhostAlignment } from "./~utils.GhostAligner.js";
@@ -51,13 +51,22 @@ const TreeItemRoot = forwardRef(
51
51
  const labelId = React.useId();
52
52
  const descriptionId = React.useId();
53
53
  const decorationId = React.useId();
54
+ const errorId = typeof error === "string" ? error : void 0;
54
55
  const icon = error ? /* @__PURE__ */ jsx(StatusWarning, {}) : iconProp;
55
56
  const describedBy = React.useMemo(() => {
56
57
  const idRefs = [];
57
58
  if (description) idRefs.push(descriptionId);
58
59
  if (unstable_decorations || icon) idRefs.push(decorationId);
60
+ if (errorId) idRefs.push(errorId);
59
61
  return idRefs.length > 0 ? idRefs.join(" ") : void 0;
60
- }, [unstable_decorations, icon, decorationId, description, descriptionId]);
62
+ }, [
63
+ unstable_decorations,
64
+ icon,
65
+ decorationId,
66
+ description,
67
+ descriptionId,
68
+ errorId
69
+ ]);
61
70
  return /* @__PURE__ */ jsx(
62
71
  TreeItemContext.Provider,
63
72
  {
@@ -213,6 +222,7 @@ const TreeItemAction = forwardRef(
213
222
  // visible by default during error state
214
223
  label,
215
224
  icon,
225
+ dot,
216
226
  ...rest
217
227
  } = props;
218
228
  if (React.useContext(TreeItemActionsOverflowMenuContext)) {
@@ -226,6 +236,7 @@ const TreeItemAction = forwardRef(
226
236
  ...rest,
227
237
  label,
228
238
  icon,
239
+ unstable_dot: dot,
229
240
  ref: forwardedRef
230
241
  }
231
242
  );
@@ -237,16 +248,22 @@ const TreeItemAction = forwardRef(
237
248
  );
238
249
  }
239
250
  return /* @__PURE__ */ jsx(
240
- IconButton,
251
+ ToolbarItem,
241
252
  {
242
- label,
243
- icon,
244
- inert: visible === false ? true : void 0,
245
- ...rest,
246
- variant: "ghost",
247
- className: cx("\u{1F95D}-tree-item-action", props.className),
248
- "data-kiwi-visible": visible,
249
- ref: forwardedRef
253
+ render: /* @__PURE__ */ jsx(
254
+ IconButton,
255
+ {
256
+ label,
257
+ icon,
258
+ inert: visible === false ? true : void 0,
259
+ ...rest,
260
+ dot,
261
+ variant: "ghost",
262
+ className: cx("\u{1F95D}-tree-item-action", props.className),
263
+ "data-kiwi-visible": visible,
264
+ ref: forwardedRef
265
+ }
266
+ )
250
267
  }
251
268
  );
252
269
  }
@@ -270,36 +287,12 @@ const TreeItemExpander = forwardRef(
270
287
  "data-kiwi-variant": "ghost",
271
288
  "data-kiwi-ghost-align": useGhostAlignment(),
272
289
  ref: forwardedRef,
273
- children: /* @__PURE__ */ jsx(TreeChevron, {})
290
+ children: /* @__PURE__ */ jsx(ChevronDown, {})
274
291
  }
275
292
  );
276
293
  }
277
294
  );
278
295
  DEV: TreeItemExpander.displayName = "TreeItemExpander";
279
- const TreeChevron = forwardRef(
280
- (props, forwardedRef) => {
281
- return /* @__PURE__ */ jsx(
282
- Icon,
283
- {
284
- ...props,
285
- render: /* @__PURE__ */ jsx(
286
- Role.svg,
287
- {
288
- width: "16",
289
- height: "16",
290
- fill: "currentColor",
291
- viewBox: "0 0 16 16",
292
- render: props.render,
293
- children: /* @__PURE__ */ jsx("path", { d: "M4.146 6.146a.5.5 0 0 1 .708 0L8 9.293l3.146-3.147a.5.5 0 0 1 .708.708l-3.5 3.5a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 0 1 0-.708Z" })
294
- }
295
- ),
296
- className: cx("\u{1F95D}-tree-chevron", props.className),
297
- ref: forwardedRef
298
- }
299
- );
300
- }
301
- );
302
- DEV: TreeChevron.displayName = "TreeChevron";
303
296
  export {
304
297
  TreeItemAction as Action,
305
298
  TreeItemRoot as Root
@@ -8,6 +8,7 @@ import { Checkbox } from "./Checkbox.js";
8
8
  import { Chip } from "./Chip.js";
9
9
  import { Description } from "./Description.js";
10
10
  import * as DropdownMenu from "./DropdownMenu.js";
11
+ import * as unstable_ErrorRegion from "./ErrorRegion.js";
11
12
  import { Divider } from "./Divider.js";
12
13
  import { Icon } from "./Icon.js";
13
14
  import { IconButton } from "./IconButton.js";
@@ -24,8 +25,9 @@ import * as Table from "./Table.js";
24
25
  import * as Tabs from "./Tabs.js";
25
26
  import { Text } from "./Text.js";
26
27
  import * as TextBox from "./TextBox.js";
27
- import * as Tree from "./Tree.js";
28
+ import * as unstable_Toolbar from "./Toolbar.js";
28
29
  import { Tooltip } from "./Tooltip.js";
30
+ import * as Tree from "./Tree.js";
29
31
  import { VisuallyHidden } from "./VisuallyHidden.js";
30
32
  export {
31
33
  Anchor,
@@ -55,5 +57,7 @@ export {
55
57
  TextBox,
56
58
  Tooltip,
57
59
  Tree,
58
- VisuallyHidden
60
+ VisuallyHidden,
61
+ unstable_ErrorRegion,
62
+ unstable_Toolbar
59
63
  };