@gooddata/sdk-ui-kit 11.57.0-alpha.3 → 11.57.0-alpha.4

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 (139) hide show
  1. package/esm/@ui/@utils/keyboardNavigation.d.ts +10 -0
  2. package/esm/@ui/@utils/keyboardNavigation.d.ts.map +1 -1
  3. package/esm/@ui/@utils/keyboardNavigation.js +9 -0
  4. package/esm/@ui/UiAddGranteeDialog/UiAddGranteeDialogCard.d.ts +4 -6
  5. package/esm/@ui/UiAddGranteeDialog/UiAddGranteeDialogCard.d.ts.map +1 -1
  6. package/esm/@ui/UiAddGranteeDialog/UiAddGranteeDialogCard.js +10 -8
  7. package/esm/@ui/UiAutocomplete/useAsyncListSource.js +1 -1
  8. package/esm/@ui/UiGranteeAsyncPicker/UiGranteeAsyncPicker.d.ts +8 -1
  9. package/esm/@ui/UiGranteeAsyncPicker/UiGranteeAsyncPicker.d.ts.map +1 -1
  10. package/esm/@ui/UiGranteeAsyncPicker/UiGranteeAsyncPicker.js +10 -6
  11. package/esm/@ui/UiListbox/defaults/DefaultUiListboxInteractiveItemComponent.d.ts.map +1 -1
  12. package/esm/@ui/UiListbox/defaults/DefaultUiListboxInteractiveItemComponent.js +6 -2
  13. package/esm/@ui/UiMenu/components/defaults/DefaultUiMenuContentItem.d.ts.map +1 -1
  14. package/esm/@ui/UiMenu/components/defaults/DefaultUiMenuContentItem.js +7 -2
  15. package/esm/@ui/UiMenu/components/defaults/DefaultUiMenuInteractiveItem.d.ts.map +1 -1
  16. package/esm/@ui/UiMenu/components/defaults/DefaultUiMenuInteractiveItem.js +7 -2
  17. package/esm/@ui/UiModalDialog/UiDialogHeader.d.ts.map +1 -1
  18. package/esm/@ui/UiModalDialog/UiDialogHeader.js +6 -3
  19. package/esm/@ui/UiObjectShareDialog/UiObjectShareDialogCard.d.ts +16 -3
  20. package/esm/@ui/UiObjectShareDialog/UiObjectShareDialogCard.d.ts.map +1 -1
  21. package/esm/@ui/UiObjectShareDialog/UiObjectShareDialogCard.js +2 -3
  22. package/esm/@ui/UiPermissionMenu/UiPermissionMenu.d.ts +9 -4
  23. package/esm/@ui/UiPermissionMenu/UiPermissionMenu.d.ts.map +1 -1
  24. package/esm/@ui/UiPermissionMenu/UiPermissionMenu.js +20 -29
  25. package/esm/@ui/UiTags/hooks/useResponsiveTags.js +1 -1
  26. package/esm/@ui/UiToolbar/UiToolbar.d.ts +52 -0
  27. package/esm/@ui/UiToolbar/UiToolbar.d.ts.map +1 -0
  28. package/esm/@ui/UiToolbar/UiToolbar.js +44 -0
  29. package/esm/@ui/UiToolbar/UiToolbarChevron.d.ts +8 -0
  30. package/esm/@ui/UiToolbar/UiToolbarChevron.d.ts.map +1 -0
  31. package/esm/@ui/UiToolbar/UiToolbarChevron.js +12 -0
  32. package/esm/@ui/UiToolbar/UiToolbarItemTooltip.d.ts +14 -0
  33. package/esm/@ui/UiToolbar/UiToolbarItemTooltip.d.ts.map +1 -0
  34. package/esm/@ui/UiToolbar/UiToolbarItemTooltip.js +11 -0
  35. package/esm/@ui/UiToolbar/constants.d.ts +5 -0
  36. package/esm/@ui/UiToolbar/constants.d.ts.map +1 -0
  37. package/esm/@ui/UiToolbar/constants.js +6 -0
  38. package/esm/@ui/UiToolbar/context.d.ts +23 -0
  39. package/esm/@ui/UiToolbar/context.d.ts.map +1 -0
  40. package/esm/@ui/UiToolbar/context.js +6 -0
  41. package/esm/@ui/UiToolbar/rovingFocusUtils.d.ts +55 -0
  42. package/esm/@ui/UiToolbar/rovingFocusUtils.d.ts.map +1 -0
  43. package/esm/@ui/UiToolbar/rovingFocusUtils.js +220 -0
  44. package/esm/@ui/UiToolbar/toolbarItemProps.d.ts +35 -0
  45. package/esm/@ui/UiToolbar/toolbarItemProps.d.ts.map +1 -0
  46. package/esm/@ui/UiToolbar/toolbarItemProps.js +2 -0
  47. package/esm/@ui/UiToolbar/useToolbarRovingFocus.d.ts +19 -0
  48. package/esm/@ui/UiToolbar/useToolbarRovingFocus.d.ts.map +1 -0
  49. package/esm/@ui/UiToolbar/useToolbarRovingFocus.js +172 -0
  50. package/esm/@ui/UiToolbarButton/UiToolbarButton.d.ts +19 -0
  51. package/esm/@ui/UiToolbarButton/UiToolbarButton.d.ts.map +1 -0
  52. package/esm/@ui/UiToolbarButton/UiToolbarButton.js +29 -0
  53. package/esm/@ui/UiToolbarButton/useToolbarItemRole.d.ts +38 -0
  54. package/esm/@ui/UiToolbarButton/useToolbarItemRole.d.ts.map +1 -0
  55. package/esm/@ui/UiToolbarButton/useToolbarItemRole.js +67 -0
  56. package/esm/@ui/UiToolbarColorSwatch/UiToolbarColorSwatch.d.ts +38 -0
  57. package/esm/@ui/UiToolbarColorSwatch/UiToolbarColorSwatch.d.ts.map +1 -0
  58. package/esm/@ui/UiToolbarColorSwatch/UiToolbarColorSwatch.js +13 -0
  59. package/esm/@ui/UiToolbarDivider/UiToolbarDivider.d.ts +7 -0
  60. package/esm/@ui/UiToolbarDivider/UiToolbarDivider.d.ts.map +1 -0
  61. package/esm/@ui/UiToolbarDivider/UiToolbarDivider.js +12 -0
  62. package/esm/@ui/UiToolbarIconButton/UiToolbarIconButton.d.ts +34 -0
  63. package/esm/@ui/UiToolbarIconButton/UiToolbarIconButton.d.ts.map +1 -0
  64. package/esm/@ui/UiToolbarIconButton/UiToolbarIconButton.js +34 -0
  65. package/esm/@ui/UiToolbarIconSelect/UiToolbarIconSelect.d.ts +54 -0
  66. package/esm/@ui/UiToolbarIconSelect/UiToolbarIconSelect.d.ts.map +1 -0
  67. package/esm/@ui/UiToolbarIconSelect/UiToolbarIconSelect.js +26 -0
  68. package/esm/@ui/UiToolbarMoreButton/UiToolbarMoreButton.d.ts +41 -0
  69. package/esm/@ui/UiToolbarMoreButton/UiToolbarMoreButton.d.ts.map +1 -0
  70. package/esm/@ui/UiToolbarMoreButton/UiToolbarMoreButton.js +12 -0
  71. package/esm/@ui/UiToolbarSegmentedControl/UiToolbarSegmentedControl.d.ts +37 -0
  72. package/esm/@ui/UiToolbarSegmentedControl/UiToolbarSegmentedControl.d.ts.map +1 -0
  73. package/esm/@ui/UiToolbarSegmentedControl/UiToolbarSegmentedControl.js +145 -0
  74. package/esm/@ui/UiToolbarSegmentedControl/context.d.ts +12 -0
  75. package/esm/@ui/UiToolbarSegmentedControl/context.d.ts.map +1 -0
  76. package/esm/@ui/UiToolbarSegmentedControl/context.js +3 -0
  77. package/esm/@ui/UiToolbarSelect/UiToolbarSelect.d.ts +51 -0
  78. package/esm/@ui/UiToolbarSelect/UiToolbarSelect.d.ts.map +1 -0
  79. package/esm/@ui/UiToolbarSelect/UiToolbarSelect.js +24 -0
  80. package/esm/@ui/UiToolbarStepper/UiToolbarStepper.d.ts +75 -0
  81. package/esm/@ui/UiToolbarStepper/UiToolbarStepper.d.ts.map +1 -0
  82. package/esm/@ui/UiToolbarStepper/UiToolbarStepper.js +85 -0
  83. package/esm/@ui/UiTooltip/UiTooltip.d.ts +1 -1
  84. package/esm/@ui/UiTooltip/UiTooltip.d.ts.map +1 -1
  85. package/esm/@ui/UiTooltip/UiTooltip.js +26 -8
  86. package/esm/@ui/UiTooltip/types.d.ts +12 -0
  87. package/esm/@ui/UiTooltip/types.d.ts.map +1 -1
  88. package/esm/@ui/hooks/useElementSize.d.ts.map +1 -1
  89. package/esm/@ui/hooks/useElementSize.js +2 -1
  90. package/esm/@ui/hooks/useIsTextTruncated.d.ts +12 -0
  91. package/esm/@ui/hooks/useIsTextTruncated.d.ts.map +1 -0
  92. package/esm/@ui/hooks/useIsTextTruncated.js +29 -0
  93. package/esm/Dropdown/Dropdown.js +1 -1
  94. package/esm/EditableLabel/EditableLabel.js +1 -1
  95. package/esm/List/LegacyList.js +1 -1
  96. package/esm/List/List.js +1 -1
  97. package/esm/Messages/toasts/NonContextToastsInterop.js +1 -1
  98. package/esm/Messages/toasts/ToastsCenterMessage.d.ts.map +1 -1
  99. package/esm/Messages/toasts/ToastsCenterMessage.js +1 -1
  100. package/esm/ResponsiveText/ResponsiveText.js +3 -3
  101. package/esm/ShortenedText/ShortenedText.js +1 -1
  102. package/esm/index.d.ts +15 -1
  103. package/esm/index.d.ts.map +1 -1
  104. package/esm/index.js +12 -1
  105. package/esm/locales.d.ts +4 -16
  106. package/esm/locales.d.ts.map +1 -1
  107. package/esm/locales.js +2 -6
  108. package/esm/sdk-ui-kit.d.ts +513 -15
  109. package/esm/syntaxHighlightingInput/hooks/useCodemirror.js +1 -1
  110. package/esm/utils/domUtilities.d.ts +4 -0
  111. package/esm/utils/domUtilities.d.ts.map +1 -1
  112. package/esm/utils/domUtilities.js +4 -1
  113. package/esm/utils/events.d.ts +3 -0
  114. package/esm/utils/events.d.ts.map +1 -1
  115. package/esm/utils/events.js +4 -1
  116. package/package.json +12 -13
  117. package/src/@ui/UiAddGranteeDialog/UiAddGranteeDialog.scss +8 -0
  118. package/src/@ui/UiGranteeAsyncPicker/UiGranteeAsyncPicker.scss +0 -6
  119. package/src/@ui/UiGranteeRow/UiGranteeRow.scss +5 -0
  120. package/src/@ui/UiListbox/UiListbox.scss +4 -0
  121. package/src/@ui/UiMenu/UiMenu.scss +3 -0
  122. package/src/@ui/UiModalDialog/UiModalDialog.scss +16 -3
  123. package/src/@ui/UiObjectShareDialog/UiObjectShareDialog.scss +40 -1
  124. package/src/@ui/UiPermissionMenu/UiPermissionMenu.scss +7 -3
  125. package/src/@ui/UiToolbar/UiToolbar.scss +15 -0
  126. package/src/@ui/UiToolbar/UiToolbarChevron.scss +11 -0
  127. package/src/@ui/UiToolbar/toolbarItem.scss +133 -0
  128. package/src/@ui/UiToolbarButton/UiToolbarButton.scss +15 -0
  129. package/src/@ui/UiToolbarColorSwatch/UiToolbarColorSwatch.scss +66 -0
  130. package/src/@ui/UiToolbarDivider/UiToolbarDivider.scss +11 -0
  131. package/src/@ui/UiToolbarIconButton/UiToolbarIconButton.scss +30 -0
  132. package/src/@ui/UiToolbarIconSelect/UiToolbarIconSelect.scss +12 -0
  133. package/src/@ui/UiToolbarSegmentedControl/UiToolbarSegmentedControl.scss +10 -0
  134. package/src/@ui/UiToolbarSelect/UiToolbarSelect.scss +29 -0
  135. package/src/@ui/UiToolbarStepper/UiToolbarStepper.scss +53 -0
  136. package/src/@ui/defaultTheme.scss +1 -0
  137. package/src/@ui/index.scss +10 -0
  138. package/styles/css/main.css +563 -9
  139. package/styles/css/main.css.map +1 -1
@@ -0,0 +1,172 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, } from "react";
3
+ import { useAutoupdateRef } from "@gooddata/sdk-ui";
4
+ import { makeHorizontalKeyboardNavigation } from "../@utils/keyboardNavigation.js";
5
+ import { TOOLBAR_COMPOSITE_ATTR, TOOLBAR_SKIP_ATTR, applyRovingTabIndex, getStopFocusTarget, getToolbarStops, hasSystemModifier, isCaretAtEdge, isEditingTarget, isEligibleFocusable, isSkipped, resolveStop, } from "./rovingFocusUtils.js";
6
+ /**
7
+ * Roving tabindex over the focusable descendants of a container, driven by the DOM.
8
+ *
9
+ * Children must not render a tabIndex that changes between renders. React only rewrites the
10
+ * attribute when the prop changes, so a constant value never overrides what this hook writes.
11
+ */
12
+ export function useToolbarRovingFocus({ containerRef, isDisabledFocusable, loop, }) {
13
+ const rememberedRef = useRef(null);
14
+ const hadFocusRef = useRef(false);
15
+ const optionsRef = useAutoupdateRef({ isDisabledFocusable, loop });
16
+ const sync = useCallback(() => {
17
+ const container = containerRef.current;
18
+ if (!container) {
19
+ return null;
20
+ }
21
+ return applyRovingTabIndex(container, rememberedRef.current, optionsRef.current);
22
+ }, [containerRef, optionsRef]);
23
+ // Re-applies the tabindexes and, when the focused item stopped being an eligible stop (removed,
24
+ // hidden, disabled, or excluded by an option change), hands focus to the fallback. Browsers move
25
+ // focus to <body> silently on removal; a hidden element may keep it.
26
+ const syncAndRepairFocus = useCallback(() => {
27
+ const container = containerRef.current;
28
+ const remembered = rememberedRef.current;
29
+ const target = sync();
30
+ if (!container ||
31
+ !hadFocusRef.current ||
32
+ remembered === null ||
33
+ target === null ||
34
+ target === remembered) {
35
+ return;
36
+ }
37
+ // A subtree that opted out keeps its focus; it only leaves the roving management.
38
+ if (isSkipped(container, remembered)) {
39
+ return;
40
+ }
41
+ const rememberedIsGone = !isEligibleFocusable(container, remembered, optionsRef.current);
42
+ const active = document.activeElement;
43
+ const focusWasLost = active === null || active === document.body || active === remembered;
44
+ if (rememberedIsGone && focusWasLost) {
45
+ target.focus();
46
+ }
47
+ }, [containerRef, optionsRef, sync]);
48
+ useLayoutEffect(() => {
49
+ syncAndRepairFocus();
50
+ });
51
+ // Media queries can hide an item without any DOM mutation; a viewport change is the cue.
52
+ useEffect(() => {
53
+ window.addEventListener("resize", syncAndRepairFocus);
54
+ return () => window.removeEventListener("resize", syncAndRepairFocus);
55
+ }, [syncAndRepairFocus]);
56
+ useEffect(() => {
57
+ const container = containerRef.current;
58
+ if (!container || typeof MutationObserver === "undefined") {
59
+ return undefined;
60
+ }
61
+ const observer = new MutationObserver(syncAndRepairFocus);
62
+ // "tabindex" is excluded so the observer does not react to its own writes. "class" and
63
+ // "style" are included because CSS can hide an item.
64
+ observer.observe(container, {
65
+ childList: true,
66
+ subtree: true,
67
+ attributes: true,
68
+ attributeFilter: [
69
+ "disabled",
70
+ "aria-disabled",
71
+ "aria-checked",
72
+ "aria-hidden",
73
+ "hidden",
74
+ "class",
75
+ "style",
76
+ // Attributes that make an element focusable or not.
77
+ "href",
78
+ "contenteditable",
79
+ "type",
80
+ "role",
81
+ TOOLBAR_COMPOSITE_ATTR,
82
+ TOOLBAR_SKIP_ATTR,
83
+ ],
84
+ });
85
+ return () => observer.disconnect();
86
+ }, [containerRef, syncAndRepairFocus]);
87
+ const onFocusCapture = useCallback((event) => {
88
+ const container = containerRef.current;
89
+ // Portaled popups bubble React focus events through the toolbar tree.
90
+ if (!container || !container.contains(event.target)) {
91
+ return;
92
+ }
93
+ rememberedRef.current = event.target;
94
+ hadFocusRef.current = true;
95
+ sync();
96
+ }, [containerRef, sync]);
97
+ const onBlurCapture = useCallback((event) => {
98
+ const container = containerRef.current;
99
+ if (!container) {
100
+ return;
101
+ }
102
+ const next = event.relatedTarget;
103
+ const leftToOutside = next instanceof Node && !container.contains(next);
104
+ // A null relatedTarget with the item still mounted is a click on non-focusable content.
105
+ const leftToNothing = next === null && event.target.isConnected;
106
+ if (leftToOutside || leftToNothing) {
107
+ hadFocusRef.current = false;
108
+ }
109
+ }, [containerRef]);
110
+ const moveTo = useCallback((index) => {
111
+ const container = containerRef.current;
112
+ if (!container) {
113
+ return;
114
+ }
115
+ const stops = getToolbarStops(container, optionsRef.current);
116
+ const stop = stops.at(index);
117
+ if (!stop) {
118
+ return;
119
+ }
120
+ getStopFocusTarget(stop, null, optionsRef.current)?.focus();
121
+ }, [containerRef, optionsRef]);
122
+ const moveBy = useCallback((delta) => {
123
+ const container = containerRef.current;
124
+ if (!container) {
125
+ return;
126
+ }
127
+ const stops = getToolbarStops(container, optionsRef.current);
128
+ const current = resolveStop(container, document.activeElement);
129
+ const index = current ? stops.indexOf(current) : -1;
130
+ if (index === -1) {
131
+ moveTo(0);
132
+ return;
133
+ }
134
+ const last = stops.length - 1;
135
+ const next = optionsRef.current.loop
136
+ ? (index + delta + stops.length) % stops.length
137
+ : Math.min(last, Math.max(0, index + delta));
138
+ moveTo(next);
139
+ }, [containerRef, moveTo, optionsRef]);
140
+ const navigate = useMemo(() => makeHorizontalKeyboardNavigation({
141
+ onFocusPrevious: () => moveBy(-1),
142
+ onFocusNext: () => moveBy(1),
143
+ onFocusFirst: () => moveTo(0),
144
+ onFocusLast: () => moveTo(-1),
145
+ }), [moveBy, moveTo]);
146
+ const onKeyDown = useCallback((event) => {
147
+ const container = containerRef.current;
148
+ const target = event.target;
149
+ if (!container || !(target instanceof HTMLElement) || !container.contains(target)) {
150
+ return;
151
+ }
152
+ // A skipped subtree owns its own keyboard handling. While an IME is composing, the
153
+ // arrows walk its candidate list, so the toolbar keeps its hands off every key.
154
+ if (event.defaultPrevented ||
155
+ event.nativeEvent.isComposing ||
156
+ hasSystemModifier(event) ||
157
+ isSkipped(container, target)) {
158
+ return;
159
+ }
160
+ // Inside a text input the keys move the caret; a horizontal arrow at the edge of the
161
+ // text is the way out to the neighbouring item.
162
+ if (isEditingTarget(target)) {
163
+ const isEdgeExit = (event.code === "ArrowLeft" || event.code === "ArrowRight") &&
164
+ isCaretAtEdge(target, event.code);
165
+ if (!isEdgeExit) {
166
+ return;
167
+ }
168
+ }
169
+ navigate(event);
170
+ }, [containerRef, navigate]);
171
+ return { onKeyDown, onFocusCapture, onBlurCapture };
172
+ }
@@ -0,0 +1,19 @@
1
+ import { type ReactNode } from "react";
2
+ import { type IUiToolbarItemBaseProps } from "../UiToolbar/toolbarItemProps.js";
3
+ /**
4
+ * @internal
5
+ */
6
+ export interface IUiToolbarButtonProps extends IUiToolbarItemBaseProps {
7
+ label: string;
8
+ /**
9
+ * Shown on hover and focus. Use it when the label is not self-explanatory.
10
+ */
11
+ tooltip?: ReactNode;
12
+ }
13
+ /**
14
+ * Label-only toolbar item.
15
+ *
16
+ * @internal
17
+ */
18
+ export declare const UiToolbarButton: import("react").ForwardRefExoticComponent<IUiToolbarButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
19
+ //# sourceMappingURL=UiToolbarButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UiToolbarButton.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiToolbarButton/UiToolbarButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AAMnD,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAKhF;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,uBAAuB;IAClE,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;CACvB;AAID;;;;GAIG;AACH,eAAO,MAAM,eAAe,qHAqD1B,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { forwardRef } from "react";
4
+ import { simplifyText } from "@gooddata/util";
5
+ import { accessibilityConfigToAttributes } from "../../typings/utilities.js";
6
+ import { bem } from "../@utils/bem.js";
7
+ import { UiToolbarItemTooltip } from "../UiToolbar/UiToolbarItemTooltip.js";
8
+ import { useToolbarItemRole } from "./useToolbarItemRole.js";
9
+ const { b, e } = bem("gd-ui-kit-toolbar-button");
10
+ /**
11
+ * Label-only toolbar item.
12
+ *
13
+ * @internal
14
+ */
15
+ export const UiToolbarButton = forwardRef(function UiToolbarButton({ label, value, isSelected, isDestructive = false, isDisabled, isActive = false, tooltip, onClick, onKeyDown, id, dataId, dataTestId, accessibilityConfig, ariaAttributes, }, ref) {
16
+ const { isChecked, buttonProps } = useToolbarItemRole({
17
+ value,
18
+ isSelected,
19
+ isDisabled,
20
+ onClick,
21
+ onKeyDown,
22
+ });
23
+ const testId = dataTestId ?? simplifyText(label);
24
+ const button = (_jsx("button", { ref: ref, id: id, type: "button", className: b({ isSelected: isChecked, isDestructive, isActive }), ...accessibilityConfigToAttributes(accessibilityConfig), "data-id": dataId, "data-testid": testId, ...buttonProps, ...ariaAttributes, children: _jsx("span", { className: e("label"), children: label }) }));
25
+ if (tooltip === undefined) {
26
+ return button;
27
+ }
28
+ return (_jsx(UiToolbarItemTooltip, { content: tooltip, isDisabled: isActive, children: button }));
29
+ });
@@ -0,0 +1,38 @@
1
+ import { type KeyboardEvent, type MouseEvent } from "react";
2
+ export interface IToolbarItemRoleInput {
3
+ value?: string;
4
+ isSelected?: boolean;
5
+ isDisabled?: boolean;
6
+ onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
7
+ onKeyDown?: (event: KeyboardEvent<HTMLButtonElement>) => void;
8
+ }
9
+ /**
10
+ * True for the keys an enclosing dropdown wrapper reacts to: the activation keys plus the vertical
11
+ * arrows that open and close its popup.
12
+ */
13
+ export declare function isPopupKey(event: KeyboardEvent<HTMLElement>): boolean;
14
+ export interface IToolbarItemRoleButtonProps {
15
+ role?: "radio";
16
+ "aria-checked"?: boolean;
17
+ "aria-pressed"?: boolean;
18
+ "aria-disabled"?: true;
19
+ "data-value"?: string;
20
+ onClick: (event: MouseEvent<HTMLButtonElement>) => void;
21
+ onKeyDown: (event: KeyboardEvent<HTMLButtonElement>) => void;
22
+ }
23
+ export interface IToolbarItemRoleResult {
24
+ isChecked: boolean;
25
+ isDisabled: boolean;
26
+ buttonProps: IToolbarItemRoleButtonProps;
27
+ }
28
+ /**
29
+ * Button attributes of a toolbar item. Inside a segmented control the item is a radio; elsewhere it
30
+ * is a toggle button when `isSelected` is given.
31
+ *
32
+ * Disabled items use `aria-disabled` instead of `disabled` so they stay reachable with arrow keys.
33
+ * No tabIndex is rendered: a toolbar or a group writes the roving tabindex into the DOM, and an item
34
+ * rendered through a portal keeps the browser default. React only rewrites the attribute when the
35
+ * prop changes, so leaving it out is what keeps the DOM writes in place.
36
+ */
37
+ export declare function useToolbarItemRole({ value, isSelected, isDisabled: isDisabledProp, onClick, onKeyDown, }: IToolbarItemRoleInput): IToolbarItemRoleResult;
38
+ //# sourceMappingURL=useToolbarItemRole.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToolbarItemRole.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiToolbarButton/useToolbarItemRole.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAA2B,MAAM,OAAO,CAAC;AAKrF,MAAM,WAAW,qBAAqB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IACzD,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;CACjE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,OAAO,CAErE;AAED,MAAM,WAAW,2BAA2B;IACxC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IACxD,SAAS,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;CAChE;AAED,MAAM,WAAW,sBAAsB;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,2BAA2B,CAAC;CAC5C;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,EAC/B,KAAK,EACL,UAAU,EACV,UAAU,EAAE,cAAc,EAC1B,OAAO,EACP,SAAS,GACZ,EAAE,qBAAqB,GAAG,sBAAsB,CAwDhD"}
@@ -0,0 +1,67 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { useCallback, useContext } from "react";
3
+ import { isActionKey } from "../../utils/events.js";
4
+ import { UiToolbarSegmentedControlContext } from "../UiToolbarSegmentedControl/context.js";
5
+ /**
6
+ * True for the keys an enclosing dropdown wrapper reacts to: the activation keys plus the vertical
7
+ * arrows that open and close its popup.
8
+ */
9
+ export function isPopupKey(event) {
10
+ return isActionKey(event) || event.code === "ArrowDown" || event.code === "ArrowUp";
11
+ }
12
+ /**
13
+ * Button attributes of a toolbar item. Inside a segmented control the item is a radio; elsewhere it
14
+ * is a toggle button when `isSelected` is given.
15
+ *
16
+ * Disabled items use `aria-disabled` instead of `disabled` so they stay reachable with arrow keys.
17
+ * No tabIndex is rendered: a toolbar or a group writes the roving tabindex into the DOM, and an item
18
+ * rendered through a portal keeps the browser default. React only rewrites the attribute when the
19
+ * prop changes, so leaving it out is what keeps the DOM writes in place.
20
+ */
21
+ export function useToolbarItemRole({ value, isSelected, isDisabled: isDisabledProp, onClick, onKeyDown, }) {
22
+ const group = useContext(UiToolbarSegmentedControlContext);
23
+ const isRadio = group !== null;
24
+ const isChecked = isRadio ? value !== undefined && group.value === value : !!isSelected;
25
+ const isDisabled = !!isDisabledProp || (group?.isDisabled ?? false);
26
+ const handleClick = useCallback((event) => {
27
+ if (isDisabled) {
28
+ event.preventDefault();
29
+ return;
30
+ }
31
+ // Both run by design: the group owns selection, the item keeps its own click handler for
32
+ // whatever else the consumer hangs off the same press.
33
+ if (isRadio && value !== undefined) {
34
+ group.onChange(value, event);
35
+ }
36
+ onClick?.(event);
37
+ }, [group, isDisabled, isRadio, onClick, value]);
38
+ // A disabled item uses aria-disabled, so it still receives key events. The keys an enclosing
39
+ // dropdown wrapper reacts to are swallowed here so it cannot open its popup; horizontal arrows
40
+ // still bubble to the toolbar. A radio keeps the vertical arrows: they navigate its group.
41
+ const handleKeyDown = useCallback((event) => {
42
+ if (isDisabled) {
43
+ if (isRadio ? isActionKey(event) : isPopupKey(event)) {
44
+ event.preventDefault();
45
+ event.stopPropagation();
46
+ }
47
+ return;
48
+ }
49
+ onKeyDown?.(event);
50
+ }, [isDisabled, isRadio, onKeyDown]);
51
+ // Only defined keys are returned so a spread never clears attributes set before it.
52
+ const buttonProps = { onClick: handleClick, onKeyDown: handleKeyDown };
53
+ if (isRadio) {
54
+ buttonProps.role = "radio";
55
+ buttonProps["aria-checked"] = isChecked;
56
+ }
57
+ else if (isSelected !== undefined) {
58
+ buttonProps["aria-pressed"] = isSelected;
59
+ }
60
+ if (isDisabled) {
61
+ buttonProps["aria-disabled"] = true;
62
+ }
63
+ if (value !== undefined) {
64
+ buttonProps["data-value"] = value;
65
+ }
66
+ return { isChecked, isDisabled, buttonProps };
67
+ }
@@ -0,0 +1,38 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * @internal
4
+ */
5
+ export interface IUiToolbarColorSwatchProps {
6
+ /**
7
+ * "fill" paints the whole chip. "text" shows a glyph with the colour as a bar beneath it.
8
+ * @defaultValue "fill"
9
+ */
10
+ variant?: "fill" | "text";
11
+ /**
12
+ * Any CSS colour.
13
+ */
14
+ color?: string;
15
+ /**
16
+ * Outline for colours too pale to read against the toolbar.
17
+ * @defaultValue false
18
+ */
19
+ hasBorder?: boolean;
20
+ /**
21
+ * No colour is set. Applies to the "fill" variant only.
22
+ * @defaultValue false
23
+ */
24
+ isTransparent?: boolean;
25
+ /**
26
+ * Glyph of the "text" variant.
27
+ * @defaultValue "A"
28
+ */
29
+ glyph?: ReactNode;
30
+ }
31
+ /**
32
+ * 20x20 preview of the colour a toolbar control is set to. Decorative: the owning control carries
33
+ * the accessible name.
34
+ *
35
+ * @internal
36
+ */
37
+ export declare function UiToolbarColorSwatch({ variant, color, hasBorder, isTransparent, glyph, }: IUiToolbarColorSwatchProps): import("react/jsx-runtime").JSX.Element;
38
+ //# sourceMappingURL=UiToolbarColorSwatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UiToolbarColorSwatch.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiToolbarColorSwatch/UiToolbarColorSwatch.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACvC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;CACrB;AAID;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,EACjC,OAAgB,EAChB,KAAK,EACL,SAAiB,EACjB,aAAqB,EACrB,KAAW,GACd,EAAE,0BAA0B,2CAoB5B"}
@@ -0,0 +1,13 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { bem } from "../@utils/bem.js";
3
+ const { b, e } = bem("gd-ui-kit-toolbar-color-swatch");
4
+ /**
5
+ * 20x20 preview of the colour a toolbar control is set to. Decorative: the owning control carries
6
+ * the accessible name.
7
+ *
8
+ * @internal
9
+ */
10
+ export function UiToolbarColorSwatch({ variant = "fill", color, hasBorder = false, isTransparent = false, glyph = "A", }) {
11
+ const isTransparentFill = variant === "fill" && isTransparent;
12
+ return (_jsx("span", { className: b({ variant, hasBorder, isTransparent: isTransparentFill }), "aria-hidden": true, children: variant === "fill" ? (_jsx("span", { className: e("fill"), style: { backgroundColor: isTransparentFill ? undefined : color }, children: isTransparentFill ? _jsx("span", { className: e("transparent") }) : null })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: e("glyph"), children: glyph }), _jsx("span", { className: e("bar"), style: { backgroundColor: color } })] })) }));
13
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Vertical rule that separates groups inside a {@link UiToolbar}.
3
+ *
4
+ * @internal
5
+ */
6
+ export declare function UiToolbarDivider(): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=UiToolbarDivider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UiToolbarDivider.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiToolbarDivider/UiToolbarDivider.tsx"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,wBAAgB,gBAAgB,4CAE/B"}
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { bem } from "../@utils/bem.js";
4
+ const { b } = bem("gd-ui-kit-toolbar-divider");
5
+ /**
6
+ * Vertical rule that separates groups inside a {@link UiToolbar}.
7
+ *
8
+ * @internal
9
+ */
10
+ export function UiToolbarDivider() {
11
+ return _jsx("div", { className: b(), role: "separator", "aria-orientation": "vertical" });
12
+ }
@@ -0,0 +1,34 @@
1
+ import { type ReactNode } from "react";
2
+ import { type IconType } from "../@types/icon.js";
3
+ import { type SizeMedium, type SizeSmall } from "../@types/size.js";
4
+ import { type IUiToolbarItemBaseProps } from "../UiToolbar/toolbarItemProps.js";
5
+ /**
6
+ * @internal
7
+ */
8
+ export interface IUiToolbarIconButtonProps extends IUiToolbarItemBaseProps {
9
+ /**
10
+ * Icon name, or a custom node such as {@link UiToolbarColorSwatch}.
11
+ */
12
+ icon: IconType | ReactNode;
13
+ /**
14
+ * Accessible name. It is also the tooltip text.
15
+ */
16
+ label: string;
17
+ /**
18
+ * "medium" is 28x28 with a 20px icon. "small" is 14x14 with a 14px icon and is meant for the
19
+ * side controls of {@link UiToolbarStepper}.
20
+ * @defaultValue "medium"
21
+ */
22
+ size?: SizeSmall | SizeMedium;
23
+ /**
24
+ * @defaultValue false
25
+ */
26
+ hideTooltip?: boolean;
27
+ }
28
+ /**
29
+ * Icon-only toolbar item. It shows its label as a tooltip on hover and on keyboard focus.
30
+ *
31
+ * @internal
32
+ */
33
+ export declare const UiToolbarIconButton: import("react").ForwardRefExoticComponent<IUiToolbarIconButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
34
+ //# sourceMappingURL=UiToolbarIconButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UiToolbarIconButton.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiToolbarIconButton/UiToolbarIconButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AAKnD,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAGpE,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAShF;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,uBAAuB;IACtE;;OAEG;IACH,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC3B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IAC9B;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAID;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,yHA8D/B,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { forwardRef } from "react";
4
+ import { simplifyText } from "@gooddata/util";
5
+ import { accessibilityConfigToAttributes } from "../../typings/utilities.js";
6
+ import { bem } from "../@utils/bem.js";
7
+ import { UiIcon } from "../UiIcon/UiIcon.js";
8
+ import { UiToolbarItemTooltip } from "../UiToolbar/UiToolbarItemTooltip.js";
9
+ import { useToolbarItemRole } from "../UiToolbarButton/useToolbarItemRole.js";
10
+ const ICON_SIZE = {
11
+ small: 14,
12
+ medium: 20,
13
+ };
14
+ const { b } = bem("gd-ui-kit-toolbar-icon-button");
15
+ /**
16
+ * Icon-only toolbar item. It shows its label as a tooltip on hover and on keyboard focus.
17
+ *
18
+ * @internal
19
+ */
20
+ export const UiToolbarIconButton = forwardRef(function UiToolbarIconButton({ icon, label, size = "medium", value, isSelected, isDestructive = false, isDisabled, isActive = false, hideTooltip = false, onClick, onKeyDown, id, dataId, dataTestId, accessibilityConfig, ariaAttributes, }, ref) {
21
+ const { isChecked, buttonProps } = useToolbarItemRole({
22
+ value,
23
+ isSelected,
24
+ isDisabled,
25
+ onClick,
26
+ onKeyDown,
27
+ });
28
+ const testId = dataTestId ?? simplifyText(label);
29
+ const button = (_jsx("button", { ref: ref, id: id, type: "button", className: b({ size, isSelected: isChecked, isDestructive, isActive }), ...accessibilityConfigToAttributes(accessibilityConfig), "aria-label": accessibilityConfig?.ariaLabel ?? label, "data-id": dataId, "data-testid": testId, ...buttonProps, ...ariaAttributes, children: typeof icon === "string" ? (_jsx(UiIcon, { type: icon, size: ICON_SIZE[size], layout: "block" })) : (icon) }));
30
+ if (hideTooltip) {
31
+ return button;
32
+ }
33
+ return (_jsx(UiToolbarItemTooltip, { content: label, isDisabled: isActive, children: button }));
34
+ });
@@ -0,0 +1,54 @@
1
+ import { type KeyboardEvent, type MouseEvent, type ReactNode } from "react";
2
+ import { type IAccessibilityConfigBase } from "../../typings/accessibility.js";
3
+ import { type IconType } from "../@types/icon.js";
4
+ import { type IUiDropdownButtonRenderProps } from "../UiDropdown/types.js";
5
+ /**
6
+ * @internal
7
+ */
8
+ export interface IUiToolbarIconSelectProps {
9
+ /**
10
+ * Icon name, or a custom node such as {@link UiToolbarColorSwatch}.
11
+ * @defaultValue a fill colour swatch
12
+ */
13
+ icon?: IconType | ReactNode;
14
+ /**
15
+ * Accessible name. It is also the tooltip text.
16
+ */
17
+ label: string;
18
+ /**
19
+ * Held while the popup is on screen. Flips the chevron and keeps the pressed look.
20
+ * @defaultValue false
21
+ */
22
+ isOpen?: boolean;
23
+ /**
24
+ * What the trigger opens. Ignored when `ariaAttributes` are given.
25
+ * @defaultValue "listbox"
26
+ */
27
+ popupType?: "listbox" | "menu" | "dialog";
28
+ /**
29
+ * Toggle state, exposed as `aria-pressed`.
30
+ */
31
+ isSelected?: boolean;
32
+ isDisabled?: boolean;
33
+ /**
34
+ * @defaultValue false
35
+ */
36
+ hideTooltip?: boolean;
37
+ onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
38
+ onKeyDown?: (event: KeyboardEvent<HTMLButtonElement>) => void;
39
+ id?: string;
40
+ dataId?: string;
41
+ dataTestId?: string;
42
+ accessibilityConfig?: IAccessibilityConfigBase;
43
+ /**
44
+ * Attributes from the `renderButton` callback of {@link UiDropdown}.
45
+ */
46
+ ariaAttributes?: IUiDropdownButtonRenderProps["ariaAttributes"];
47
+ }
48
+ /**
49
+ * Icon-driven dropdown trigger of a toolbar: a colour picker, a style menu, a list.
50
+ *
51
+ * @internal
52
+ */
53
+ export declare const UiToolbarIconSelect: import("react").ForwardRefExoticComponent<IUiToolbarIconSelectProps & import("react").RefAttributes<HTMLButtonElement>>;
54
+ //# sourceMappingURL=UiToolbarIconSelect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UiToolbarIconSelect.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiToolbarIconSelect/UiToolbarIconSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AAIxF,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE/E,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAE,KAAK,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAO3E;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACtC;;;OAGG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC1C;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IACzD,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC9D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,wBAAwB,CAAC;IAC/C;;OAEG;IACH,cAAc,CAAC,EAAE,4BAA4B,CAAC,gBAAgB,CAAC,CAAC;CACnE;AAID;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,yHAyD/B,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { forwardRef } from "react";
4
+ import { simplifyText } from "@gooddata/util";
5
+ import { accessibilityConfigToAttributes } from "../../typings/utilities.js";
6
+ import { bem } from "../@utils/bem.js";
7
+ import { UiIcon } from "../UiIcon/UiIcon.js";
8
+ import { UiToolbarChevron } from "../UiToolbar/UiToolbarChevron.js";
9
+ import { UiToolbarItemTooltip } from "../UiToolbar/UiToolbarItemTooltip.js";
10
+ import { useToolbarItemRole } from "../UiToolbarButton/useToolbarItemRole.js";
11
+ import { UiToolbarColorSwatch } from "../UiToolbarColorSwatch/UiToolbarColorSwatch.js";
12
+ const { b } = bem("gd-ui-kit-toolbar-icon-select");
13
+ /**
14
+ * Icon-driven dropdown trigger of a toolbar: a colour picker, a style menu, a list.
15
+ *
16
+ * @internal
17
+ */
18
+ export const UiToolbarIconSelect = forwardRef(function UiToolbarIconSelect({ icon = _jsx(UiToolbarColorSwatch, { variant: "fill" }), label, isOpen = false, popupType = "listbox", isSelected, isDisabled, hideTooltip = false, onClick, onKeyDown, id, dataId, dataTestId, accessibilityConfig, ariaAttributes, }, ref) {
19
+ const { isChecked, buttonProps } = useToolbarItemRole({ isSelected, isDisabled, onClick, onKeyDown });
20
+ const testId = dataTestId ?? simplifyText(label);
21
+ const button = (_jsxs("button", { ref: ref, id: id, type: "button", className: b({ isSelected: isChecked, isActive: isOpen }), ...accessibilityConfigToAttributes(accessibilityConfig), "aria-label": accessibilityConfig?.ariaLabel ?? label, "aria-haspopup": accessibilityConfig?.ariaHaspopup ?? popupType, "aria-expanded": accessibilityConfig?.ariaExpanded ?? isOpen, "data-id": dataId, "data-testid": testId, ...buttonProps, ...ariaAttributes, children: [typeof icon === "string" ? (_jsx(UiIcon, { type: icon, size: 20, layout: "block" })) : (icon), _jsx(UiToolbarChevron, { isOpen: isOpen })] }));
22
+ if (hideTooltip) {
23
+ return button;
24
+ }
25
+ return (_jsx(UiToolbarItemTooltip, { content: label, isDisabled: isOpen, children: button }));
26
+ });
@@ -0,0 +1,41 @@
1
+ import { type KeyboardEvent, type MouseEvent, type ReactNode } from "react";
2
+ import { type IAccessibilityConfigBase } from "../../typings/accessibility.js";
3
+ import { type IconType } from "../@types/icon.js";
4
+ import { type IUiDropdownButtonRenderProps } from "../UiDropdown/types.js";
5
+ /**
6
+ * @internal
7
+ */
8
+ export interface IUiToolbarMoreButtonProps {
9
+ /**
10
+ * Accessible name, for example "More actions". It is also the tooltip text.
11
+ */
12
+ label: string;
13
+ /**
14
+ * @defaultValue "ellipsis"
15
+ */
16
+ icon?: IconType | ReactNode;
17
+ /**
18
+ * Held while the menu is on screen.
19
+ * @defaultValue false
20
+ */
21
+ isOpen?: boolean;
22
+ isDisabled?: boolean;
23
+ onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
24
+ onKeyDown?: (event: KeyboardEvent<HTMLButtonElement>) => void;
25
+ id?: string;
26
+ dataId?: string;
27
+ dataTestId?: string;
28
+ accessibilityConfig?: IAccessibilityConfigBase;
29
+ /**
30
+ * Attributes from the `renderButton` callback of {@link UiDropdown}. Without them the trigger
31
+ * announces a menu popup.
32
+ */
33
+ ariaAttributes?: IUiDropdownButtonRenderProps["ariaAttributes"];
34
+ }
35
+ /**
36
+ * Overflow trigger of a toolbar. Build the menu it opens from {@link UiMenu} in a {@link UiDropdown}.
37
+ *
38
+ * @internal
39
+ */
40
+ export declare const UiToolbarMoreButton: import("react").ForwardRefExoticComponent<IUiToolbarMoreButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
41
+ //# sourceMappingURL=UiToolbarMoreButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UiToolbarMoreButton.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiToolbarMoreButton/UiToolbarMoreButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AAExF,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,KAAK,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAG3E;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACtC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IACzD,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC9D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,wBAAwB,CAAC;IAC/C;;;OAGG;IACH,cAAc,CAAC,EAAE,4BAA4B,CAAC,gBAAgB,CAAC,CAAC;CACnE;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,yHAc/B,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { forwardRef } from "react";
4
+ import { UiToolbarIconButton } from "../UiToolbarIconButton/UiToolbarIconButton.js";
5
+ /**
6
+ * Overflow trigger of a toolbar. Build the menu it opens from {@link UiMenu} in a {@link UiDropdown}.
7
+ *
8
+ * @internal
9
+ */
10
+ export const UiToolbarMoreButton = forwardRef(function UiToolbarMoreButton({ icon = "ellipsis", isOpen = false, ariaAttributes, ...props }, ref) {
11
+ return (_jsx(UiToolbarIconButton, { ref: ref, icon: icon, isActive: isOpen, ariaAttributes: ariaAttributes ?? { role: "button", "aria-haspopup": "menu", "aria-expanded": isOpen }, ...props }));
12
+ });