@astryxdesign/core 0.5.2-canary.c9c8564 → 0.5.2-canary.e03511b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BottomSheet/BottomSheet.d.ts +3 -1
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +4 -3
- package/dist/BottomSheet/BottomSheetEdgeTint.d.ts +2 -2
- package/dist/BottomSheet/BottomSheetEdgeTint.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetEdgeTint.js +7 -10
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetSwitcher.js +1 -1
- package/dist/Button/Button.d.ts +2 -1
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +11 -4
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +2 -2
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +34 -17
- package/dist/ContextMenu/ContextMenu.d.ts +14 -3
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +149 -26
- package/dist/ContextMenu/index.d.ts +1 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts +24 -5
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +340 -26
- package/dist/DropdownMenu/DropdownMenuContext.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +6 -2
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +43 -14
- package/dist/DropdownMenu/MenuBottomSheet.d.ts +20 -0
- package/dist/DropdownMenu/MenuBottomSheet.d.ts.map +1 -0
- package/dist/DropdownMenu/MenuBottomSheet.js +36 -0
- package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts +10 -0
- package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -0
- package/dist/DropdownMenu/MenuBottomSheetActionList.js +111 -0
- package/dist/DropdownMenu/index.d.ts +2 -1
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/menuWidth.d.ts +14 -0
- package/dist/DropdownMenu/menuWidth.d.ts.map +1 -0
- package/dist/DropdownMenu/menuWidth.js +35 -0
- package/dist/DropdownMenu/useMenuOverflow.d.ts +10 -0
- package/dist/DropdownMenu/useMenuOverflow.d.ts.map +1 -0
- package/dist/DropdownMenu/useMenuOverflow.js +60 -0
- package/dist/MoreMenu/MoreMenu.d.ts +8 -2
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +2 -0
- package/dist/MultiSelector/MultiSelector.d.ts +11 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +97 -68
- package/dist/MultiSelector/index.d.ts +1 -1
- package/dist/MultiSelector/index.d.ts.map +1 -1
- package/dist/Popover/Popover.d.ts +10 -6
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +141 -16
- package/dist/Popover/usePopover.d.ts +4 -0
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +52 -5
- package/dist/Selector/Selector.d.ts +10 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +106 -80
- package/dist/Selector/SelectorBottomSheet.d.ts +21 -0
- package/dist/Selector/SelectorBottomSheet.d.ts.map +1 -0
- package/dist/Selector/SelectorBottomSheet.js +83 -0
- package/dist/Selector/index.d.ts +1 -1
- package/dist/Selector/index.d.ts.map +1 -1
- package/dist/Selector/selectorPresentation.stylex.d.ts +16 -0
- package/dist/Selector/selectorPresentation.stylex.d.ts.map +1 -0
- package/dist/Selector/selectorPresentation.stylex.js +21 -0
- package/dist/Selector/useSelectorPresentation.d.ts +32 -0
- package/dist/Selector/useSelectorPresentation.d.ts.map +1 -0
- package/dist/Selector/useSelectorPresentation.js +90 -0
- package/dist/Toast/useToastGesture.d.ts.map +1 -1
- package/dist/Toast/useToastGesture.js +46 -9
- package/dist/astryx.css +19 -1
- package/dist/hooks/useAdaptivePresentation.d.ts +5 -0
- package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -0
- package/dist/hooks/useAdaptivePresentation.js +19 -0
- package/dist/hooks/useFocusReturnVisibility.d.ts +7 -0
- package/dist/hooks/useFocusReturnVisibility.d.ts.map +1 -0
- package/dist/hooks/useFocusReturnVisibility.js +35 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +12 -0
- package/locales/en.json +20 -0
- package/locales/pseudo.json +15 -0
- package/package.json +2 -2
- package/src/BottomSheet/BottomSheet.doc.mjs +37 -0
- package/src/BottomSheet/BottomSheet.spec.md +177 -0
- package/src/BottomSheet/BottomSheet.test.tsx +29 -0
- package/src/BottomSheet/BottomSheet.tsx +7 -4
- package/src/BottomSheet/BottomSheetEdgeTint.test.tsx +4 -6
- package/src/BottomSheet/BottomSheetEdgeTint.tsx +7 -10
- package/src/BottomSheet/BottomSheetSwitcher.tsx +1 -2
- package/src/Button/Button.doc.mjs +56 -0
- package/src/Button/Button.test.tsx +10 -0
- package/src/Button/Button.tsx +13 -5
- package/src/ButtonGroup/ButtonGroup.doc.mjs +47 -0
- package/src/Carousel/Carousel.test.tsx +83 -0
- package/src/Carousel/Carousel.tsx +8 -2
- package/src/Chat/ChatToolCalls.test.tsx +44 -0
- package/src/Chat/ChatToolCalls.tsx +36 -15
- package/src/CheckboxList/CheckboxList.doc.mjs +172 -31
- package/src/CheckboxList/CheckboxList.spec.md +214 -0
- package/src/CommandPalette/CommandPalette.doc.mjs +72 -0
- package/src/CommandPalette/CommandPalette.spec.md +223 -0
- package/src/ComplexSelector/ComplexSelector.doc.mjs +42 -0
- package/src/ComplexSelector/ComplexSelector.spec.md +189 -0
- package/src/ContextMenu/ContextMenu.doc.mjs +61 -1
- package/src/ContextMenu/ContextMenu.spec.md +206 -0
- package/src/ContextMenu/ContextMenu.test.tsx +131 -1
- package/src/ContextMenu/ContextMenu.tsx +199 -32
- package/src/ContextMenu/index.ts +1 -0
- package/src/Divider/Divider.doc.mjs +24 -0
- package/src/Divider/Divider.spec.md +150 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +305 -40
- package/src/DropdownMenu/DropdownMenu.spec.md +245 -0
- package/src/DropdownMenu/DropdownMenu.test.tsx +518 -7
- package/src/DropdownMenu/DropdownMenu.tsx +459 -28
- package/src/DropdownMenu/DropdownMenuContext.tsx +1 -1
- package/src/DropdownMenu/DropdownMenuItem.tsx +2 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +4 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +124 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +72 -17
- package/src/DropdownMenu/MenuBottomSheet.tsx +46 -0
- package/src/DropdownMenu/MenuBottomSheetActionList.tsx +141 -0
- package/src/DropdownMenu/index.ts +2 -0
- package/src/DropdownMenu/menuWidth.ts +51 -0
- package/src/DropdownMenu/useMenuOverflow.ts +77 -0
- package/src/FieldStatus/FieldStatus.doc.mjs +21 -0
- package/src/FieldStatus/FieldStatus.spec.md +212 -0
- package/src/Grid/Grid.doc.mjs +19 -0
- package/src/Grid/Grid.spec.md +161 -0
- package/src/Icon/Icon.doc.mjs +196 -48
- package/src/Icon/Icon.spec.md +191 -0
- package/src/IconButton/IconButton.doc.mjs +38 -0
- package/src/Kbd/Kbd.doc.mjs +18 -0
- package/src/Kbd/Kbd.spec.md +141 -0
- package/src/Layout/Layout.doc.mjs +32 -0
- package/src/Layout/Layout.spec.md +199 -0
- package/src/Lightbox/Lightbox.doc.mjs +149 -33
- package/src/Lightbox/Lightbox.spec.md +197 -0
- package/src/Markdown/Markdown.doc.mjs +60 -0
- package/src/Markdown/Markdown.spec.md +200 -0
- package/src/MobileNav/MobileNav.doc.mjs +140 -32
- package/src/MobileNav/MobileNav.spec.md +208 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +59 -0
- package/src/MoreMenu/MoreMenu.spec.md +221 -0
- package/src/MoreMenu/MoreMenu.test.tsx +47 -0
- package/src/MoreMenu/MoreMenu.tsx +13 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +128 -0
- package/src/MultiSelector/MultiSelector.spec.md +266 -0
- package/src/MultiSelector/MultiSelector.test.tsx +127 -0
- package/src/MultiSelector/MultiSelector.tsx +121 -73
- package/src/MultiSelector/index.ts +1 -0
- package/src/NavIcon/NavIcon.doc.mjs +17 -0
- package/src/NavIcon/NavIcon.spec.md +133 -0
- package/src/NavMenu/NavHeadingMenu.spec.md +205 -0
- package/src/NavMenu/NavMenu.doc.mjs +37 -0
- package/src/Outline/Outline.doc.mjs +35 -0
- package/src/Outline/Outline.spec.md +161 -0
- package/src/OverflowList/OverflowList.doc.mjs +24 -0
- package/src/OverflowList/OverflowList.spec.md +156 -0
- package/src/Pagination/Pagination.doc.mjs +74 -0
- package/src/Pagination/Pagination.spec.md +225 -0
- package/src/Popover/Popover.doc.mjs +11 -11
- package/src/Popover/Popover.test.tsx +397 -2
- package/src/Popover/Popover.tsx +228 -21
- package/src/Popover/usePopover.tsx +92 -15
- package/src/ProgressBar/ProgressBar.doc.mjs +198 -38
- package/src/ProgressBar/ProgressBar.spec.md +260 -0
- package/src/Resizable/Resizable.doc.mjs +59 -16
- package/src/Resizable/Resizable.spec.md +194 -0
- package/src/Section/Section.doc.mjs +17 -0
- package/src/Section/Section.spec.md +138 -0
- package/src/SegmentedControl/SegmentedControl.doc.mjs +83 -0
- package/src/SegmentedControl/SegmentedControl.spec.md +151 -0
- package/src/Selector/Selector.doc.mjs +12 -0
- package/src/Selector/Selector.spec.md +202 -0
- package/src/Selector/Selector.test.tsx +135 -0
- package/src/Selector/Selector.tsx +141 -82
- package/src/Selector/SelectorBottomSheet.tsx +97 -0
- package/src/Selector/index.ts +1 -0
- package/src/Selector/selectorPresentation.stylex.ts +20 -0
- package/src/Selector/useSelectorPresentation.ts +147 -0
- package/src/Skeleton/Skeleton.doc.mjs +12 -0
- package/src/Skeleton/Skeleton.spec.md +126 -0
- package/src/Slider/Slider.doc.mjs +184 -30
- package/src/Slider/Slider.spec.md +223 -0
- package/src/Stack/Stack.doc.mjs +22 -0
- package/src/Stack/Stack.spec.md +154 -0
- package/src/StatusDot/StatusDot.doc.mjs +17 -0
- package/src/StatusDot/StatusDot.spec.md +137 -0
- package/src/Switch/Switch.doc.mjs +40 -0
- package/src/Switch/Switch.spec.md +174 -0
- package/src/Table/Table.doc.mjs +102 -24
- package/src/Table/Table.spec.md +283 -0
- package/src/Text/Text.doc.mjs +190 -43
- package/src/Text/Text.spec.md +205 -0
- package/src/TextArea/TextArea.doc.mjs +255 -45
- package/src/TextArea/TextArea.spec.md +204 -0
- package/src/Toast/ToastViewport.test.tsx +118 -4
- package/src/Toast/useToastGesture.ts +61 -8
- package/src/ToggleButton/ToggleButton.doc.mjs +56 -0
- package/src/Toolbar/Toolbar.doc.mjs +19 -0
- package/src/Toolbar/Toolbar.spec.md +173 -0
- package/src/Tooltip/Tooltip.doc.mjs +17 -0
- package/src/Tooltip/Tooltip.spec.md +141 -0
- package/src/TreeList/TreeList.doc.mjs +58 -0
- package/src/TreeList/TreeList.spec.md +220 -0
- package/src/Typeahead/Typeahead.doc.mjs +83 -1
- package/src/Typeahead/Typeahead.spec.md +250 -0
- package/src/hooks/useAdaptivePresentation.ts +35 -0
- package/src/hooks/useFocusReturnVisibility.ts +45 -0
- package/src/hooks/useFocusTrap.test.tsx +40 -0
- package/src/hooks/useFocusTrap.ts +13 -0
- package/src/theme/themingTargets.test.ts +91 -25
|
@@ -793,6 +793,11 @@ describe('Toast swipe dismissal', () => {
|
|
|
793
793
|
expect(visualToast.style.getPropertyValue('--_toast-swipe-exit-y')).toBe(
|
|
794
794
|
'120%',
|
|
795
795
|
);
|
|
796
|
+
expect(visualToast.style.getPropertyValue('--_toast-swipe-y')).toBe('');
|
|
797
|
+
expect(visualToast.style.getPropertyValue('--_toast-swipe-opacity')).toBe(
|
|
798
|
+
'',
|
|
799
|
+
);
|
|
800
|
+
expect(visualToast.style.getPropertyValue('--_toast-swipe-scale')).toBe('');
|
|
796
801
|
expect(getComputedStyle(visualToast).transform).not.toContain('translateX');
|
|
797
802
|
});
|
|
798
803
|
|
|
@@ -1147,11 +1152,9 @@ describe('Toast swipe dismissal', () => {
|
|
|
1147
1152
|
|
|
1148
1153
|
expect(onHide).toHaveBeenCalledWith('manual');
|
|
1149
1154
|
expect(visualToast.style.getPropertyValue('--_toast-swipe-opacity')).toBe(
|
|
1150
|
-
'
|
|
1151
|
-
);
|
|
1152
|
-
expect(visualToast.style.getPropertyValue('--_toast-swipe-scale')).toBe(
|
|
1153
|
-
'0.985',
|
|
1155
|
+
'',
|
|
1154
1156
|
);
|
|
1157
|
+
expect(visualToast.style.getPropertyValue('--_toast-swipe-scale')).toBe('');
|
|
1155
1158
|
expect(visualToast.style.getPropertyValue('--_toast-swipe-exit-y')).toBe(
|
|
1156
1159
|
'calc(-1 * 120%)',
|
|
1157
1160
|
);
|
|
@@ -1248,6 +1251,117 @@ describe('Toast swipe dismissal', () => {
|
|
|
1248
1251
|
);
|
|
1249
1252
|
});
|
|
1250
1253
|
|
|
1254
|
+
it('abandons a one-finger swipe when a second touch starts', () => {
|
|
1255
|
+
const {visualToast, onHide} = renderSwipeToast();
|
|
1256
|
+
const dispatchTouch = (
|
|
1257
|
+
type: 'touchstart' | 'touchmove',
|
|
1258
|
+
touches: {identifier: number; clientX: number; clientY: number}[],
|
|
1259
|
+
changedTouches = touches,
|
|
1260
|
+
) => {
|
|
1261
|
+
const event = new Event(type, {bubbles: true, cancelable: true});
|
|
1262
|
+
Object.defineProperty(event, 'touches', {value: touches});
|
|
1263
|
+
Object.defineProperty(event, 'changedTouches', {value: changedTouches});
|
|
1264
|
+
visualToast.dispatchEvent(event);
|
|
1265
|
+
return event;
|
|
1266
|
+
};
|
|
1267
|
+
const first = {identifier: 51, clientX: 10, clientY: 0};
|
|
1268
|
+
const second = {identifier: 52, clientX: 30, clientY: 40};
|
|
1269
|
+
|
|
1270
|
+
act(() => {
|
|
1271
|
+
dispatchTouch('touchstart', [first]);
|
|
1272
|
+
dispatchTouch('touchmove', [{...first, clientY: 40}]);
|
|
1273
|
+
});
|
|
1274
|
+
expect(visualToast.style.getPropertyValue('--_toast-swipe-y')).toBe('40px');
|
|
1275
|
+
|
|
1276
|
+
act(() => {
|
|
1277
|
+
dispatchTouch('touchstart', [first, second], [second]);
|
|
1278
|
+
});
|
|
1279
|
+
const multitouchMove = dispatchTouch('touchmove', [first, second]);
|
|
1280
|
+
|
|
1281
|
+
expect(multitouchMove.defaultPrevented).toBe(false);
|
|
1282
|
+
expect(visualToast.style.getPropertyValue('--_toast-swipe-y')).toBe('');
|
|
1283
|
+
expect(visualToast.style.getPropertyValue('--_toast-swipe-opacity')).toBe(
|
|
1284
|
+
'',
|
|
1285
|
+
);
|
|
1286
|
+
expect(onHide).not.toHaveBeenCalled();
|
|
1287
|
+
});
|
|
1288
|
+
|
|
1289
|
+
it('does not dismiss when another touch remains outside the Toast', () => {
|
|
1290
|
+
const {visualToast, onHide} = renderSwipeToast();
|
|
1291
|
+
const first = {identifier: 61, clientX: 10, clientY: 0};
|
|
1292
|
+
const second = {identifier: 62, clientX: 200, clientY: 200};
|
|
1293
|
+
const dispatchTouch = (
|
|
1294
|
+
type: 'touchstart' | 'touchmove' | 'touchend',
|
|
1295
|
+
touches: (typeof first)[],
|
|
1296
|
+
changedTouches: (typeof first)[],
|
|
1297
|
+
) => {
|
|
1298
|
+
const event = new Event(type, {bubbles: true, cancelable: true});
|
|
1299
|
+
Object.defineProperty(event, 'touches', {value: touches});
|
|
1300
|
+
Object.defineProperty(event, 'changedTouches', {value: changedTouches});
|
|
1301
|
+
visualToast.dispatchEvent(event);
|
|
1302
|
+
return event;
|
|
1303
|
+
};
|
|
1304
|
+
|
|
1305
|
+
act(() => {
|
|
1306
|
+
dispatchTouch('touchstart', [first], [first]);
|
|
1307
|
+
dispatchTouch(
|
|
1308
|
+
'touchmove',
|
|
1309
|
+
[{...first, clientY: 60}],
|
|
1310
|
+
[{...first, clientY: 60}],
|
|
1311
|
+
);
|
|
1312
|
+
});
|
|
1313
|
+
expect(visualToast.style.getPropertyValue('--_toast-swipe-y')).toBe('60px');
|
|
1314
|
+
|
|
1315
|
+
// The second contact began outside the Toast, so its touchstart did not
|
|
1316
|
+
// reach the Toast listener. Ending the tracked finger must still cancel
|
|
1317
|
+
// while that other contact remains active.
|
|
1318
|
+
act(() => {
|
|
1319
|
+
dispatchTouch('touchend', [second], [{...first, clientY: 60}]);
|
|
1320
|
+
});
|
|
1321
|
+
|
|
1322
|
+
expect(onHide).not.toHaveBeenCalled();
|
|
1323
|
+
expect(visualToast.style.getPropertyValue('--_toast-swipe-y')).toBe('');
|
|
1324
|
+
expect(visualToast.style.getPropertyValue('--_toast-swipe-opacity')).toBe(
|
|
1325
|
+
'',
|
|
1326
|
+
);
|
|
1327
|
+
});
|
|
1328
|
+
|
|
1329
|
+
it('does not let a pen event with the same numeric ID control a touch gesture', () => {
|
|
1330
|
+
const {visualToast, onHide} = renderSwipeToast();
|
|
1331
|
+
const touch = {identifier: 7, clientX: 10, clientY: 0};
|
|
1332
|
+
const touchStart = new Event('touchstart', {
|
|
1333
|
+
bubbles: true,
|
|
1334
|
+
cancelable: true,
|
|
1335
|
+
});
|
|
1336
|
+
Object.defineProperty(touchStart, 'touches', {value: [touch]});
|
|
1337
|
+
Object.defineProperty(touchStart, 'changedTouches', {value: [touch]});
|
|
1338
|
+
|
|
1339
|
+
act(() => {
|
|
1340
|
+
visualToast.dispatchEvent(touchStart);
|
|
1341
|
+
fireEvent.pointerMove(visualToast, {
|
|
1342
|
+
pointerId: 7,
|
|
1343
|
+
pointerType: 'pen',
|
|
1344
|
+
clientX: 10,
|
|
1345
|
+
clientY: 60,
|
|
1346
|
+
});
|
|
1347
|
+
fireEvent.pointerUp(visualToast, {
|
|
1348
|
+
pointerId: 7,
|
|
1349
|
+
pointerType: 'pen',
|
|
1350
|
+
clientX: 10,
|
|
1351
|
+
clientY: 60,
|
|
1352
|
+
});
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
expect(onHide).not.toHaveBeenCalled();
|
|
1356
|
+
expect(visualToast.style.getPropertyValue('--_toast-swipe-y')).toBe('');
|
|
1357
|
+
|
|
1358
|
+
act(() => {
|
|
1359
|
+
visualToast.dispatchEvent(
|
|
1360
|
+
new Event('touchcancel', {bubbles: true, cancelable: true}),
|
|
1361
|
+
);
|
|
1362
|
+
});
|
|
1363
|
+
});
|
|
1364
|
+
|
|
1251
1365
|
it('removes native touch listeners when a Toast unmounts', () => {
|
|
1252
1366
|
const {visualToast, unmount} = renderSwipeToast();
|
|
1253
1367
|
const removeListener = vi.spyOn(visualToast, 'removeEventListener');
|
|
@@ -25,12 +25,14 @@ const SWIPE_ACTIVE_SCALE_MAX = 0.02;
|
|
|
25
25
|
export type ToastGestureDirection = 1 | -1;
|
|
26
26
|
|
|
27
27
|
interface GesturePoint {
|
|
28
|
+
source: 'touch' | 'pen';
|
|
28
29
|
pointerId: number;
|
|
29
30
|
clientX: number;
|
|
30
31
|
clientY: number;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
interface GestureState {
|
|
35
|
+
source: GesturePoint['source'];
|
|
34
36
|
pointerId: number;
|
|
35
37
|
startX: number;
|
|
36
38
|
startY: number;
|
|
@@ -126,6 +128,7 @@ export function useToastGesture({
|
|
|
126
128
|
}
|
|
127
129
|
const surfaceSize = Math.max(root.getBoundingClientRect().height, 1);
|
|
128
130
|
gestureRef.current = {
|
|
131
|
+
source: point.source,
|
|
129
132
|
pointerId: point.pointerId,
|
|
130
133
|
startX: point.clientX,
|
|
131
134
|
startY: point.clientY,
|
|
@@ -159,7 +162,12 @@ export function useToastGesture({
|
|
|
159
162
|
) => {
|
|
160
163
|
const state = gestureRef.current;
|
|
161
164
|
const root = rootRef.current;
|
|
162
|
-
if (
|
|
165
|
+
if (
|
|
166
|
+
!state ||
|
|
167
|
+
!root ||
|
|
168
|
+
point.source !== state.source ||
|
|
169
|
+
point.pointerId !== state.pointerId
|
|
170
|
+
) {
|
|
163
171
|
return;
|
|
164
172
|
}
|
|
165
173
|
const deltaX = point.clientX - state.startX;
|
|
@@ -209,7 +217,12 @@ export function useToastGesture({
|
|
|
209
217
|
(point: GesturePoint) => {
|
|
210
218
|
const state = gestureRef.current;
|
|
211
219
|
const root = rootRef.current;
|
|
212
|
-
if (
|
|
220
|
+
if (
|
|
221
|
+
!state ||
|
|
222
|
+
!root ||
|
|
223
|
+
point.source !== state.source ||
|
|
224
|
+
point.pointerId !== state.pointerId
|
|
225
|
+
) {
|
|
213
226
|
return;
|
|
214
227
|
}
|
|
215
228
|
const travel = Math.max(
|
|
@@ -225,6 +238,10 @@ export function useToastGesture({
|
|
|
225
238
|
gestureRef.current = null;
|
|
226
239
|
root.style.removeProperty('transition-duration');
|
|
227
240
|
if (isDismissed) {
|
|
241
|
+
// The exit animation owns the final translation. Clear the live-drag
|
|
242
|
+
// transform/fade/scale first so a standalone Toast does not remain
|
|
243
|
+
// partially translated or faded after its dismiss callback fires.
|
|
244
|
+
clearTransientStyles(root);
|
|
228
245
|
root.style.setProperty(
|
|
229
246
|
'--_toast-swipe-exit-y',
|
|
230
247
|
state.direction === 1
|
|
@@ -247,7 +264,15 @@ export function useToastGesture({
|
|
|
247
264
|
if (
|
|
248
265
|
event.pointerType === 'pen' &&
|
|
249
266
|
(event.button == null || event.button === 0) &&
|
|
250
|
-
beginGesture(
|
|
267
|
+
beginGesture(
|
|
268
|
+
{
|
|
269
|
+
source: 'pen',
|
|
270
|
+
pointerId: event.pointerId,
|
|
271
|
+
clientX: event.clientX,
|
|
272
|
+
clientY: event.clientY,
|
|
273
|
+
},
|
|
274
|
+
event.target,
|
|
275
|
+
)
|
|
251
276
|
) {
|
|
252
277
|
rootRef.current?.setPointerCapture?.(event.pointerId);
|
|
253
278
|
}
|
|
@@ -261,7 +286,12 @@ export function useToastGesture({
|
|
|
261
286
|
return;
|
|
262
287
|
}
|
|
263
288
|
moveGesture(
|
|
264
|
-
|
|
289
|
+
{
|
|
290
|
+
source: 'pen',
|
|
291
|
+
pointerId: event.pointerId,
|
|
292
|
+
clientX: event.clientX,
|
|
293
|
+
clientY: event.clientY,
|
|
294
|
+
},
|
|
265
295
|
() => event.preventDefault(),
|
|
266
296
|
() => rootRef.current?.releasePointerCapture?.(event.pointerId),
|
|
267
297
|
);
|
|
@@ -275,7 +305,12 @@ export function useToastGesture({
|
|
|
275
305
|
return;
|
|
276
306
|
}
|
|
277
307
|
rootRef.current?.releasePointerCapture?.(event.pointerId);
|
|
278
|
-
endGesture(
|
|
308
|
+
endGesture({
|
|
309
|
+
source: 'pen',
|
|
310
|
+
pointerId: event.pointerId,
|
|
311
|
+
clientX: event.clientX,
|
|
312
|
+
clientY: event.clientY,
|
|
313
|
+
});
|
|
279
314
|
},
|
|
280
315
|
[endGesture],
|
|
281
316
|
);
|
|
@@ -284,6 +319,7 @@ export function useToastGesture({
|
|
|
284
319
|
(event: ReactPointerEvent<HTMLDivElement>) => {
|
|
285
320
|
if (
|
|
286
321
|
event.pointerType === 'pen' &&
|
|
322
|
+
gestureRef.current?.source === 'pen' &&
|
|
287
323
|
gestureRef.current?.pointerId === event.pointerId
|
|
288
324
|
) {
|
|
289
325
|
resetGesture(true);
|
|
@@ -298,12 +334,14 @@ export function useToastGesture({
|
|
|
298
334
|
return;
|
|
299
335
|
}
|
|
300
336
|
const point = (touch: Touch): GesturePoint => ({
|
|
337
|
+
source: 'touch',
|
|
301
338
|
pointerId: touch.identifier,
|
|
302
339
|
clientX: touch.clientX,
|
|
303
340
|
clientY: touch.clientY,
|
|
304
341
|
});
|
|
305
342
|
const changedTouch = (event: TouchEvent) => {
|
|
306
|
-
const
|
|
343
|
+
const state = gestureRef.current;
|
|
344
|
+
const pointerId = state?.source === 'touch' ? state.pointerId : null;
|
|
307
345
|
return pointerId == null
|
|
308
346
|
? undefined
|
|
309
347
|
: [...event.changedTouches].find(
|
|
@@ -311,12 +349,23 @@ export function useToastGesture({
|
|
|
311
349
|
);
|
|
312
350
|
};
|
|
313
351
|
const handleTouchStart = (event: TouchEvent) => {
|
|
314
|
-
|
|
315
|
-
|
|
352
|
+
if (event.touches?.length !== 1) {
|
|
353
|
+
// A second contact means the browser may be handling pinch zoom or
|
|
354
|
+
// two-finger scrolling. Abandon any accepted one-finger swipe before
|
|
355
|
+
// touchmove can suppress that native gesture.
|
|
356
|
+
resetGesture(true);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const touch = event.changedTouches[0];
|
|
360
|
+
if (touch != null) {
|
|
316
361
|
beginGesture(point(touch), event.target);
|
|
317
362
|
}
|
|
318
363
|
};
|
|
319
364
|
const handleTouchMove = (event: TouchEvent) => {
|
|
365
|
+
if (event.touches?.length !== 1) {
|
|
366
|
+
resetGesture(true);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
320
369
|
const touch = changedTouch(event);
|
|
321
370
|
if (touch) {
|
|
322
371
|
moveGesture(point(touch), () => {
|
|
@@ -327,6 +376,10 @@ export function useToastGesture({
|
|
|
327
376
|
}
|
|
328
377
|
};
|
|
329
378
|
const handleTouchEnd = (event: TouchEvent) => {
|
|
379
|
+
if (event.touches.length > 0) {
|
|
380
|
+
resetGesture(true);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
330
383
|
const touch = changedTouch(event);
|
|
331
384
|
if (touch) {
|
|
332
385
|
endGesture(point(touch));
|
|
@@ -122,6 +122,62 @@ export const docs = {
|
|
|
122
122
|
usage: {
|
|
123
123
|
description:
|
|
124
124
|
'ToggleButton switches between selected and unselected states to represent a persistent on/off choice. Use it standalone for binary actions like bold, mute, or favorite, or inside a ToggleButtonGroup for single-select or multi-select toolbar controls.',
|
|
125
|
+
accessibility: [
|
|
126
|
+
{
|
|
127
|
+
name: 'Text label',
|
|
128
|
+
category: 'Color contrast',
|
|
129
|
+
criterion: '1.4.3 Contrast (Minimum)',
|
|
130
|
+
requirement: '4.5:1',
|
|
131
|
+
states: ['Unselected', 'Selected', 'Hover', 'Pointer down'],
|
|
132
|
+
description:
|
|
133
|
+
'The label must have at least 4.5:1 contrast with the button background when selected and unselected. For Hover and Pointer down, measure the final background after the overlay is applied.',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: 'Essential icon or spinner arc',
|
|
137
|
+
category: 'Color contrast',
|
|
138
|
+
criterion: '1.4.11 Non-text Contrast',
|
|
139
|
+
requirement: '3:1',
|
|
140
|
+
states: ['Icon only', 'Loading'],
|
|
141
|
+
description:
|
|
142
|
+
'An icon-only ToggleButton must have at least 3:1 contrast between its icon and button background. The moving spinner arc must also meet 3:1. An icon beside a visible label does not need its own check.',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'Selected state indicator',
|
|
146
|
+
category: 'Color contrast',
|
|
147
|
+
criterion: '1.4.11 Non-text Contrast',
|
|
148
|
+
requirement: '3:1 if relied upon',
|
|
149
|
+
states: ['Selected'],
|
|
150
|
+
description:
|
|
151
|
+
'The selected background must reach 3:1 only when users need it to tell selected from unselected. Label weight or a changed icon can also show selection.',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: 'Visible control boundary',
|
|
155
|
+
category: 'Color contrast',
|
|
156
|
+
criterion: '1.4.11 Non-text Contrast',
|
|
157
|
+
requirement: '3:1 if needed',
|
|
158
|
+
states: ['Rest'],
|
|
159
|
+
description:
|
|
160
|
+
'The button edge needs 3:1 contrast only when users need it to see the control. A visible label or icon can show the control instead.',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'Keyboard focus indicator',
|
|
164
|
+
category: 'Color contrast',
|
|
165
|
+
criterion: '1.4.11 Non-text Contrast',
|
|
166
|
+
requirement: '3:1',
|
|
167
|
+
states: ['Focus visible'],
|
|
168
|
+
description:
|
|
169
|
+
'The focus outline must have at least 3:1 contrast with the area around the button. Check both selected and unselected states.',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: 'Disabled appearance',
|
|
173
|
+
category: 'Color contrast',
|
|
174
|
+
criterion: '1.4.3 and 1.4.11 exceptions',
|
|
175
|
+
requirement: 'Not required',
|
|
176
|
+
states: ['Disabled'],
|
|
177
|
+
description:
|
|
178
|
+
'Disabled controls do not need to meet these contrast ratios.',
|
|
179
|
+
},
|
|
180
|
+
],
|
|
125
181
|
bestPractices: [
|
|
126
182
|
{guidance: true, description: 'Use a filled or colored icon for the pressed state so users can see the current state at a glance: an outline star vs a solid star, for example.'},
|
|
127
183
|
{guidance: true, description: 'Keep the label identical between pressed and unpressed states. Let the visual treatment (icon, weight, background) communicate the change.'},
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
2
|
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').ComponentAnatomyElement[]} */
|
|
4
|
+
const anatomy = [
|
|
5
|
+
{
|
|
6
|
+
name: 'Outer chrome',
|
|
7
|
+
required: true,
|
|
8
|
+
description:
|
|
9
|
+
'Section-owned container that supplies the toolbar surface, padding, and selected divider edges.',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: 'Toolbar',
|
|
13
|
+
required: true,
|
|
14
|
+
description:
|
|
15
|
+
'Named toolbar row that owns toolbar semantics and the start, optional center, and end layout.',
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
|
|
3
19
|
/** @type {import('@astryxdesign/cli/authoring').ComponentDoc} */
|
|
4
20
|
|
|
5
21
|
export const docs = {
|
|
@@ -147,6 +163,7 @@ export const docs = {
|
|
|
147
163
|
], },
|
|
148
164
|
],
|
|
149
165
|
usage: {
|
|
166
|
+
anatomy,
|
|
150
167
|
description:
|
|
151
168
|
'Toolbar is a horizontal bar with left, center, and right areas. Use it for contextual actions within a content area (above a table, inside a card, or in a panel), not as a page-level header. Set the size once on the toolbar and all buttons, inputs, and tabs inside it match automatically.',
|
|
152
169
|
bestPractices: [
|
|
@@ -182,6 +199,7 @@ export const docsZh = {
|
|
|
182
199
|
},
|
|
183
200
|
],
|
|
184
201
|
usage: {
|
|
202
|
+
anatomy,
|
|
185
203
|
description:
|
|
186
204
|
'Toolbar is a horizontal bar with left, center, and right areas. Use it for contextual actions within a content area (above a table, inside a card, or in a panel), not as a page-level header. Set the size once on the toolbar and all buttons, inputs, and tabs inside it match automatically.',
|
|
187
205
|
bestPractices: [
|
|
@@ -200,6 +218,7 @@ export const docsZh = {
|
|
|
200
218
|
export const docsDense = {
|
|
201
219
|
description: 'Horizontal bar w/ left, center, right areas. For contextual actions in content, not page headers. Size cascades to children.',
|
|
202
220
|
usage: {
|
|
221
|
+
anatomy,
|
|
203
222
|
description:
|
|
204
223
|
'Horizontal bar w/ left, optional center, right. For contextual actions within content (tables, cards, panels), not page-level headers. Size cascades to children.',
|
|
205
224
|
bestPractices: [
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
schema_version: 1
|
|
3
|
+
template_version: 3
|
|
4
|
+
kind: component
|
|
5
|
+
id: component:Toolbar
|
|
6
|
+
authority: draft
|
|
7
|
+
archive_reason: null
|
|
8
|
+
superseded_by: null
|
|
9
|
+
approved_by: null
|
|
10
|
+
approved_at: null
|
|
11
|
+
owners: [cixzhang]
|
|
12
|
+
review_triggers: [layout, theming, accessibility]
|
|
13
|
+
verified_by:
|
|
14
|
+
[
|
|
15
|
+
packages/core/src/Toolbar/Toolbar.test.tsx,
|
|
16
|
+
packages/core/src/Section/Section.test.tsx,
|
|
17
|
+
packages/core/src/theme/themingTargets.test.ts,
|
|
18
|
+
scripts/check-knowledge.mjs,
|
|
19
|
+
]
|
|
20
|
+
families: [family:layout-regions]
|
|
21
|
+
design_specs: []
|
|
22
|
+
architecture:
|
|
23
|
+
[
|
|
24
|
+
architecture:component-theming-surface,
|
|
25
|
+
architecture:container-padding,
|
|
26
|
+
architecture:public-component-api,
|
|
27
|
+
]
|
|
28
|
+
contributing: []
|
|
29
|
+
system_specs: []
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
# Toolbar component contract
|
|
33
|
+
|
|
34
|
+
## Intent
|
|
35
|
+
|
|
36
|
+
Toolbar presents a named contextual action region with one semantic toolbar row
|
|
37
|
+
inside Section-owned outer chrome. This draft records the current consumer
|
|
38
|
+
anatomy and theming ownership without changing layout, keyboard behavior,
|
|
39
|
+
targets, or public API.
|
|
40
|
+
|
|
41
|
+
## Compatibility and migration
|
|
42
|
+
|
|
43
|
+
- Released default preserved: `yes`
|
|
44
|
+
- Compatibility class: additive documentation only; runtime, DOM, styling,
|
|
45
|
+
targets, and public API remain unchanged
|
|
46
|
+
- Controlled/uncontrolled behavior: not applicable
|
|
47
|
+
- Migration decision: none
|
|
48
|
+
|
|
49
|
+
Consumer migration instructions belong in consumer docs and release notes.
|
|
50
|
+
|
|
51
|
+
## Ownership boundary
|
|
52
|
+
|
|
53
|
+
**Owns**
|
|
54
|
+
|
|
55
|
+
- The named toolbar row, toolbar semantics, start/optional-center/end layout,
|
|
56
|
+
keyboard movement, size cascade, and current `toolbar` target.
|
|
57
|
+
|
|
58
|
+
**Does not own / non-goals**
|
|
59
|
+
|
|
60
|
+
- The painted outer chrome, variant, block padding, and selected divider edges —
|
|
61
|
+
delegated to `component:Section`.
|
|
62
|
+
- Content supplied through the three layout slots — owned by the caller or its
|
|
63
|
+
rendered components.
|
|
64
|
+
- A general arbitrary-child layout primitive contract.
|
|
65
|
+
- New runtime behavior, targets, props, or target placement.
|
|
66
|
+
|
|
67
|
+
## Public concepts
|
|
68
|
+
|
|
69
|
+
No new public concept is introduced. Consumer props, slots, and usage remain
|
|
70
|
+
documented in `Toolbar.doc.mjs`; `family:layout-regions` owns the shared
|
|
71
|
+
structural-region boundary.
|
|
72
|
+
|
|
73
|
+
## Behavioral and layout contract
|
|
74
|
+
|
|
75
|
+
| ID | Candidate invariant | Basis | Draft review state |
|
|
76
|
+
| --- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | -------------------------------------------------- |
|
|
77
|
+
| FR1 | The current render contains Section-owned Outer chrome around one named Toolbar carrying `role="toolbar"` and the current `toolbar` target. | Current source, docs, tests, and family | Verified current behavior; no new behavior decided |
|
|
78
|
+
| FR2 | The Toolbar uses its current two-lane layout without center content and its current three-lane layout when center content is supplied. | Current source and focused structure tests | Verified current behavior; no layout change |
|
|
79
|
+
| FR3 | Variant, selected divider edges, and outer padding remain delegated to Section, while Toolbar retains toolbar semantics, keyboard behavior, and internal layout. | Current source, docs, and family contract | Verified current ownership; no target change |
|
|
80
|
+
|
|
81
|
+
### Allowed variation
|
|
82
|
+
|
|
83
|
+
- Caller content may be absent or supplied in the start, center, and end slots
|
|
84
|
+
without changing Outer chrome or Toolbar ownership.
|
|
85
|
+
- Size and orientation may change the current row geometry and keyboard axis
|
|
86
|
+
without creating separate anatomy parts or targets.
|
|
87
|
+
|
|
88
|
+
### Representative states
|
|
89
|
+
|
|
90
|
+
| State | Required invariant | Allowed variation |
|
|
91
|
+
| ----------------- | ------------------------------------------------------- | --------------------------------------------------- |
|
|
92
|
+
| Empty toolbar | Outer chrome and named Toolbar remain rendered. | No caller slot content. |
|
|
93
|
+
| Two-lane layout | Start and/or end content use the current flex layout. | Either lane may be absent. |
|
|
94
|
+
| Three-lane layout | Center content selects the current three-column layout. | Start or end content may be absent. |
|
|
95
|
+
| Vertical toolbar | Toolbar semantics and target remain unchanged. | Layout and keyboard movement use the vertical axis. |
|
|
96
|
+
|
|
97
|
+
### Transformation and precedence order
|
|
98
|
+
|
|
99
|
+
- No new slot, layout, edge-compensation, padding, or event precedence rule is
|
|
100
|
+
introduced.
|
|
101
|
+
|
|
102
|
+
### Performance and resources
|
|
103
|
+
|
|
104
|
+
- No new performance or resource rule is introduced.
|
|
105
|
+
|
|
106
|
+
## Accessibility contract
|
|
107
|
+
|
|
108
|
+
This draft does not change or extend Toolbar's current accessible name,
|
|
109
|
+
orientation, roving-tabindex, keyboard-hint, caret-guard, or event-composition
|
|
110
|
+
behavior.
|
|
111
|
+
|
|
112
|
+
## Design relationships
|
|
113
|
+
|
|
114
|
+
| Anatomy or state | Design requirement | Representation authority | Hierarchy role | Component contract |
|
|
115
|
+
| ---------------- | -------------------------------------------------------------------------------- | ----------------------------------------- | -------------- | ------------------ |
|
|
116
|
+
| Outer chrome | Supplies the painted surface, padding, and selected boundaries around the row. | `component:Section` | Supporting | FR1, FR3 |
|
|
117
|
+
| Toolbar | Presents the named toolbar semantics and current two- or three-lane arrangement. | Current source, docs, and family contract | Prominent | FR1, FR2, FR3 |
|
|
118
|
+
|
|
119
|
+
The slot contents are caller-owned content inside Toolbar's layout. They do not
|
|
120
|
+
become additional Toolbar-owned anatomy or targets.
|
|
121
|
+
|
|
122
|
+
### Theming anatomy
|
|
123
|
+
|
|
124
|
+
<!-- anatomy-theming:v1 -->
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"Outer chrome": {
|
|
129
|
+
"delegatesTo": {"owner": "component:Section", "target": "section"}
|
|
130
|
+
},
|
|
131
|
+
"Toolbar": {"target": "toolbar"}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Family and system relationships
|
|
136
|
+
|
|
137
|
+
- `family:layout-regions` owns the structural-region vocabulary and records
|
|
138
|
+
Toolbar as a Section-backed contextual action region.
|
|
139
|
+
- `architecture:container-padding` owns the inherited inset and edge-compensation
|
|
140
|
+
geometry used by the composed Section and Toolbar.
|
|
141
|
+
- `architecture:component-theming-surface` owns anatomy qualification, local
|
|
142
|
+
target mapping, and component delegation.
|
|
143
|
+
- `architecture:public-component-api` owns the stable prop and slot surface; this
|
|
144
|
+
documentation adds no API.
|
|
145
|
+
|
|
146
|
+
## Verification map
|
|
147
|
+
|
|
148
|
+
| Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
|
|
149
|
+
| ------------------- | --------------------------------------------------------------- | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ----------------------- |
|
|
150
|
+
| FR1 | `Toolbar.test.tsx` role, name, pass-through, and Section suites | Empty and populated Toolbar | Removing the role/name, Toolbar target, Section composition, or delegated Section target fails current evidence. | `audit:Toolbar/anatomy` |
|
|
151
|
+
| FR2 | `Toolbar.test.tsx` slot and child-count suites | Start-only, end-only, two-lane, and three-lane | Changing current slot presence or two-/three-lane structure fails focused assertions. | `audit:Toolbar/layout` |
|
|
152
|
+
| FR3 | Toolbar and Section source plus their focused tests | Variant, divider, size, and orientation states | Moving outer chrome ownership into Toolbar or moving toolbar semantics onto Section contradicts source and coverage. | `audit:Toolbar/theming` |
|
|
153
|
+
| Target inventory | `packages/core/src/theme/themingTargets.test.ts` | Toolbar and delegated Section targets | Runtime and documented target metadata drift fails target validation. | `audit:Toolbar/theming` |
|
|
154
|
+
| Theming anatomy map | `scripts/check-knowledge.mjs` | Canonical anatomy and current local target | Missing, extra, prefixed, or stale mappings fail repository validation. | `audit:Toolbar/theming` |
|
|
155
|
+
|
|
156
|
+
Existing tests assert the semantic row, slot structure, and Section composition.
|
|
157
|
+
They do not prove computed inset or edge-compensation geometry for every parent
|
|
158
|
+
padding state; this documentation does not claim that coverage.
|
|
159
|
+
|
|
160
|
+
## Decision log
|
|
161
|
+
|
|
162
|
+
None. This draft records current facts and introduces no component-local design,
|
|
163
|
+
layout, accessibility, or API decision.
|
|
164
|
+
|
|
165
|
+
## Open questions
|
|
166
|
+
|
|
167
|
+
None.
|
|
168
|
+
|
|
169
|
+
## Content boundary
|
|
170
|
+
|
|
171
|
+
This file does not duplicate consumer prop tables, examples, family layout
|
|
172
|
+
rules, container-padding mechanics, keyboard algorithms, implementation steps,
|
|
173
|
+
or system rules. It links to their owners.
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
2
|
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').ComponentAnatomyElement[]} */
|
|
4
|
+
const anatomy = [
|
|
5
|
+
{
|
|
6
|
+
name: 'Tooltip surface',
|
|
7
|
+
required: true,
|
|
8
|
+
description: 'Painted overlay surface that presents the tooltip.',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
name: 'Tooltip text',
|
|
12
|
+
required: true,
|
|
13
|
+
description: 'Tooltip content rendered within the surface.',
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
|
|
3
17
|
/** @type {import('@astryxdesign/cli/authoring').ComponentDoc} */
|
|
4
18
|
|
|
5
19
|
export const docs = {
|
|
@@ -110,6 +124,7 @@ export const docs = {
|
|
|
110
124
|
],
|
|
111
125
|
},
|
|
112
126
|
usage: {
|
|
127
|
+
anatomy,
|
|
113
128
|
description:
|
|
114
129
|
'A short text hint that appears on hover or focus, anchored to a trigger element. Use it to describe icon-only buttons, show the full text of truncated labels, or provide supplementary context without cluttering the UI.',
|
|
115
130
|
bestPractices: [
|
|
@@ -217,6 +232,7 @@ export const docsZh = {
|
|
|
217
232
|
],
|
|
218
233
|
},
|
|
219
234
|
usage: {
|
|
235
|
+
anatomy,
|
|
220
236
|
description:
|
|
221
237
|
'A short text hint that appears on hover or focus, anchored to a trigger element. Use it to describe icon-only buttons, show the full text of truncated labels, or provide supplementary context without cluttering the UI.',
|
|
222
238
|
bestPractices: [
|
|
@@ -233,6 +249,7 @@ export const docsZh = {
|
|
|
233
249
|
export const docsDense = {
|
|
234
250
|
description: 'Hover/focus triggered tooltip for displaying short, non-interactive text anchored to trigger element.',
|
|
235
251
|
usage: {
|
|
252
|
+
anatomy,
|
|
236
253
|
description:
|
|
237
254
|
'A short text hint that appears on hover or focus, anchored to a trigger element. Use it to describe icon-only buttons, show the full text of truncated labels, or provide supplementary context without cluttering the UI.',
|
|
238
255
|
bestPractices: [
|