@astryxdesign/core 0.6.2-canary.bc93547 → 0.6.2-canary.bfee8a4
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 +1 -1
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +3 -1
- package/dist/BottomSheet/BottomSheetPanel.d.ts +7 -5
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +56 -19
- package/dist/astryx.css +3 -1
- package/dist/hooks/scrollKeyboardDelegation.d.ts +3 -0
- package/dist/hooks/scrollKeyboardDelegation.d.ts.map +1 -0
- package/dist/hooks/scrollKeyboardDelegation.js +146 -0
- package/dist/hooks/useScrollableArea.d.ts +6 -2
- package/dist/hooks/useScrollableArea.d.ts.map +1 -1
- package/dist/hooks/useScrollableArea.js +17 -5
- package/package.json +3 -3
- package/src/BottomSheet/BottomSheet.doc.mjs +8 -1
- package/src/BottomSheet/BottomSheet.spec.md +46 -20
- package/src/BottomSheet/BottomSheet.test.tsx +6 -3
- package/src/BottomSheet/BottomSheet.tsx +3 -1
- package/src/BottomSheet/BottomSheetKeyboard.test.tsx +195 -0
- package/src/BottomSheet/BottomSheetPanel.test.tsx +11 -1
- package/src/BottomSheet/BottomSheetPanel.tsx +49 -16
- package/src/BottomSheet/__tests__/BottomSheetKeyboard.a11y.browser.spec.ts +344 -0
- package/src/ScrollableArea/modules/useScrollableArea.spec.md +50 -22
- package/src/hooks/scrollKeyboardDelegation.test.ts +155 -0
- package/src/hooks/scrollKeyboardDelegation.ts +233 -0
- package/src/hooks/useScrollableArea.doc.mjs +15 -3
- package/src/hooks/useScrollableArea.test.tsx +59 -1
- package/src/hooks/useScrollableArea.ts +34 -10
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file BottomSheet.tsx
|
|
3
|
-
* @input Uses React, StyleX, core hooks/utils, BottomSheetPanel, BottomSheetSwitcherContext
|
|
3
|
+
* @input Uses React, StyleX, core hooks/utils, named BottomSheetPanel, BottomSheetSwitcherContext
|
|
4
4
|
* @output Exports BottomSheet component and BottomSheetProps
|
|
5
5
|
* @position Public BottomSheet router plus private standalone/switcher hosts
|
|
6
6
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AAgB7C,YAAY,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAyEhF,UAAU,sBAAuB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,qDAAqD;IACrD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IAEd,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IAEpB,wGAAwG;IACxG,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;IAE7C;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAEjD;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,UAAU,0BAA2B,SAAQ,sBAAsB;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,UAAU,wBAAyB,SAAQ,sBAAsB;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GAC1B,0BAA0B,GAAG,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AAgB7C,YAAY,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAyEhF,UAAU,sBAAuB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,qDAAqD;IACrD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IAEd,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IAEpB,wGAAwG;IACxG,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;IAE7C;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAEjD;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,UAAU,0BAA2B,SAAQ,sBAAsB;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,UAAU,wBAAyB,SAAQ,sBAAsB;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GAC1B,0BAA0B,GAAG,wBAAwB,CAAC;AA8XxD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BA6BlD;yBA7Be,WAAW"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file BottomSheet.tsx
|
|
7
|
-
* @input Uses React, StyleX, core hooks/utils, BottomSheetPanel, BottomSheetSwitcherContext
|
|
7
|
+
* @input Uses React, StyleX, core hooks/utils, named BottomSheetPanel, BottomSheetSwitcherContext
|
|
8
8
|
* @output Exports BottomSheet component and BottomSheetProps
|
|
9
9
|
* @position Public BottomSheet router plus private standalone/switcher hosts
|
|
10
10
|
*
|
|
@@ -266,6 +266,7 @@ function StandaloneBottomSheet({
|
|
|
266
266
|
ref: ref,
|
|
267
267
|
state: panelState,
|
|
268
268
|
height: height,
|
|
269
|
+
label: label,
|
|
269
270
|
snapPoints: snapPoints,
|
|
270
271
|
isSwipeDismissAllowed: purpose === 'info',
|
|
271
272
|
isPageScrollLocked: shouldPresent && hasScrim,
|
|
@@ -397,6 +398,7 @@ function SwitcherBottomSheetItem({
|
|
|
397
398
|
ref: ref,
|
|
398
399
|
state: panelState,
|
|
399
400
|
height: height,
|
|
401
|
+
label: label,
|
|
400
402
|
snapPoints: snapPoints,
|
|
401
403
|
isSwipeDismissAllowed: purpose === 'info',
|
|
402
404
|
isPageScrollLocked: hasScrim,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file BottomSheetPanel.tsx
|
|
3
|
-
* @input Uses React, StyleX, theme tokens,
|
|
4
|
-
* @output Internal BottomSheetPanel
|
|
3
|
+
* @input Uses React, StyleX, theme tokens, sheet gestures, shared scroll behavior, and the host label
|
|
4
|
+
* @output Internal BottomSheetPanel with a keyboard-reachable scrolling body and motion-state types
|
|
5
5
|
* @position Shared presentation layer for standalone and switcher BottomSheets
|
|
6
6
|
*
|
|
7
7
|
* This component owns everything intrinsic to a sheet surface: height budgets,
|
|
8
8
|
* drag and snap gestures, the handle and scrolling body, motion styles, and
|
|
9
|
-
* transition completion. It
|
|
10
|
-
* state,
|
|
9
|
+
* transition completion. It owns the body's keyboard access; dialog focus
|
|
10
|
+
* entry/return, inert state, and switcher registration belong to the host.
|
|
11
11
|
*
|
|
12
12
|
* SYNC: When modified, update these files to stay in sync:
|
|
13
13
|
* - /packages/core/src/BottomSheet/BottomSheet.tsx
|
|
@@ -44,6 +44,8 @@ interface BottomSheetPanelProps extends BaseProps<HTMLDivElement> {
|
|
|
44
44
|
ref?: React.Ref<HTMLDivElement>;
|
|
45
45
|
state: BottomSheetPanelState;
|
|
46
46
|
height: BottomSheetHeight | number | string;
|
|
47
|
+
/** Existing host name, reused for the keyboard scrolling group. */
|
|
48
|
+
label: string;
|
|
47
49
|
children: ReactNode;
|
|
48
50
|
snapPoints?: ReadonlyArray<BottomSheetSnapPoint>;
|
|
49
51
|
isSwipeDismissAllowed?: boolean;
|
|
@@ -56,7 +58,7 @@ interface BottomSheetPanelProps extends BaseProps<HTMLDivElement> {
|
|
|
56
58
|
onMotionComplete?: (motion: BottomSheetPanelMotion) => void;
|
|
57
59
|
}
|
|
58
60
|
/** Internal visual and gesture surface shared by every BottomSheet host. */
|
|
59
|
-
export declare function BottomSheetPanel({ ref, state, height, children, snapPoints, className, style, tabIndex, xstyle, isSwipeDismissAllowed, isPageScrollLocked, onDismiss, onScrimOpacity, onElementChange, onMotionStart, onMotionComplete, ...props }: BottomSheetPanelProps): import("react").JSX.Element;
|
|
61
|
+
export declare function BottomSheetPanel({ ref, state, height, label, children, snapPoints, className, style, tabIndex, xstyle, isSwipeDismissAllowed, isPageScrollLocked, onDismiss, onScrimOpacity, onElementChange, onMotionStart, onMotionComplete, ...props }: BottomSheetPanelProps): import("react").JSX.Element;
|
|
60
62
|
export declare namespace BottomSheetPanel {
|
|
61
63
|
var displayName: string;
|
|
62
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheetPanel.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheetPanel.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"BottomSheetPanel.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheetPanel.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAiB5C,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAIvB,QAAA,MAAM,cAAc;;;;CAIV,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,cAAc,CAAC;AAC5D,YAAY,EAAC,oBAAoB,EAAC,CAAC;AAsMnC,MAAM,MAAM,sBAAsB,GAChC,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjD,MAAM,MAAM,qBAAqB,GAC7B;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GAChB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAC,GACjC;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC1C,eAAe,EAAE,MAAM,CAAC;CACzB,GACD;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,CAAC;AAEtB,UAAU,qBAAsB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC/D,+CAA+C;IAC/C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,KAAK,EAAE,qBAAqB,CAAC;IAC7B,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;IAC5C,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IACjD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3D,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACzD,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,IAAI,CAAC;CAC7D;AA+GD,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,EAC/B,GAAG,EACH,KAAK,EACL,MAAM,EACN,KAAK,EACL,QAAQ,EACR,UAAU,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,MAAM,EACN,qBAA4B,EAC5B,kBAA0B,EAC1B,SAAS,EACT,cAAc,EACd,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,GAAG,KAAK,EACT,EAAE,qBAAqB,+BAyRvB;yBA5Se,gBAAgB"}
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file BottomSheetPanel.tsx
|
|
7
|
-
* @input Uses React, StyleX, theme tokens,
|
|
8
|
-
* @output Internal BottomSheetPanel
|
|
7
|
+
* @input Uses React, StyleX, theme tokens, sheet gestures, shared scroll behavior, and the host label
|
|
8
|
+
* @output Internal BottomSheetPanel with a keyboard-reachable scrolling body and motion-state types
|
|
9
9
|
* @position Shared presentation layer for standalone and switcher BottomSheets
|
|
10
10
|
*
|
|
11
11
|
* This component owns everything intrinsic to a sheet surface: height budgets,
|
|
12
12
|
* drag and snap gestures, the handle and scrolling body, motion styles, and
|
|
13
|
-
* transition completion. It
|
|
14
|
-
* state,
|
|
13
|
+
* transition completion. It owns the body's keyboard access; dialog focus
|
|
14
|
+
* entry/return, inert state, and switcher registration belong to the host.
|
|
15
15
|
*
|
|
16
16
|
* SYNC: When modified, update these files to stay in sync:
|
|
17
17
|
* - /packages/core/src/BottomSheet/BottomSheet.tsx
|
|
@@ -23,9 +23,11 @@
|
|
|
23
23
|
import { useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef } from 'react';
|
|
24
24
|
import * as stylex from '@stylexjs/stylex';
|
|
25
25
|
import { useDevWarning } from "../hooks/index.js";
|
|
26
|
+
import { useScrollableArea } from "../hooks/useScrollableArea.js";
|
|
26
27
|
import "../theme/tokens.stylex.js";
|
|
27
|
-
import { borderVars, colorVars, durationVars, easeVars, radiusVars, shadowVars, sizeVars, spacingVars } from "../theme/tokens.stylex.js";
|
|
28
|
+
import { borderVars, colorVars, durationVars, easeVars, focusVars, radiusVars, shadowVars, sizeVars, spacingVars } from "../theme/tokens.stylex.js";
|
|
28
29
|
import { mergeProps, themeProps } from "../utils/index.js";
|
|
30
|
+
import { focusOutlineStyles } from "../utils/focusOutline.stylex.js";
|
|
29
31
|
import { overlayPaddingReset } from "../Layout/padding.stylex.js";
|
|
30
32
|
import { isValidSnapPoint, resolveSnapPoints } from "./snapOffsets.js";
|
|
31
33
|
import { useMobileKeyboard } from "./useMobileKeyboard.js";
|
|
@@ -120,6 +122,24 @@ const styles = {
|
|
|
120
122
|
kfzvcC: "x47corl",
|
|
121
123
|
$$css: true
|
|
122
124
|
},
|
|
125
|
+
body: {
|
|
126
|
+
kzQI83: "x1iyjqo2",
|
|
127
|
+
kAzted: "x2lwn1j",
|
|
128
|
+
kB7OPa: "x9f619",
|
|
129
|
+
kFalU9: "xx69xxh",
|
|
130
|
+
kInvED: "x1wfwxd8 x1nw7mhf",
|
|
131
|
+
kWkggS: "x10xzikg",
|
|
132
|
+
kGO01o: "x18d9i69",
|
|
133
|
+
$$css: true
|
|
134
|
+
},
|
|
135
|
+
tallKeyboardBody: {
|
|
136
|
+
kFlMNQ: "xrw9175",
|
|
137
|
+
k5JduY: "x1s928wv",
|
|
138
|
+
kc3QkE: "xhkezso",
|
|
139
|
+
k4zj60: "xu6fald",
|
|
140
|
+
kloYau: "x2q1x1w",
|
|
141
|
+
$$css: true
|
|
142
|
+
},
|
|
123
143
|
budget: {
|
|
124
144
|
kZKoxP: "x1tpcejd",
|
|
125
145
|
$$css: true
|
|
@@ -222,6 +242,7 @@ export function BottomSheetPanel({
|
|
|
222
242
|
ref,
|
|
223
243
|
state,
|
|
224
244
|
height,
|
|
245
|
+
label,
|
|
225
246
|
children,
|
|
226
247
|
snapPoints,
|
|
227
248
|
className,
|
|
@@ -312,6 +333,22 @@ export function BottomSheetPanel({
|
|
|
312
333
|
snapHeights,
|
|
313
334
|
onScrimOpacity
|
|
314
335
|
});
|
|
336
|
+
const {
|
|
337
|
+
getViewportProps,
|
|
338
|
+
getContentProps
|
|
339
|
+
} = useScrollableArea({
|
|
340
|
+
// The previous overflow-y:auto also computed overflow-x:auto. Keep wide
|
|
341
|
+
// content reachable instead of clipping that existing inline scroll path.
|
|
342
|
+
axis: 'both',
|
|
343
|
+
keyboardAccess: {
|
|
344
|
+
owner: 'contentOrViewport',
|
|
345
|
+
label
|
|
346
|
+
},
|
|
347
|
+
overscroll: 'contain',
|
|
348
|
+
// The sheet body deliberately remains the boundary for sheet-local sticky
|
|
349
|
+
// content while fitting, as it was before shared scroll adoption.
|
|
350
|
+
stickyContainment: 'always'
|
|
351
|
+
});
|
|
315
352
|
const setElement = useCallback(element => {
|
|
316
353
|
sheetRef(element);
|
|
317
354
|
elementRef.current = element;
|
|
@@ -438,20 +475,20 @@ export function BottomSheetPanel({
|
|
|
438
475
|
}
|
|
439
476
|
})
|
|
440
477
|
}), /*#__PURE__*/_jsx("div", {
|
|
441
|
-
...
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
478
|
+
...getViewportProps({
|
|
479
|
+
...bodyProps,
|
|
480
|
+
...mergeProps(stylex.props(focusOutlineStyles.focusVisible, styles.body, height === 'tall' && styles.tallKeyboardBody), scrollPreservationInset > 0 ? {
|
|
481
|
+
style: {
|
|
482
|
+
paddingBlockEnd: `${scrollPreservationInset}px`
|
|
483
|
+
}
|
|
484
|
+
} : {})
|
|
485
|
+
}),
|
|
486
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
487
|
+
...getContentProps({
|
|
488
|
+
className: "xufnvkl x9f619 x5yr21d x121v3j4"
|
|
489
|
+
}),
|
|
490
|
+
children: children
|
|
491
|
+
})
|
|
455
492
|
})]
|
|
456
493
|
});
|
|
457
494
|
}
|
package/dist/astryx.css
CHANGED
|
@@ -516,7 +516,6 @@
|
|
|
516
516
|
.xb3r6kr:not(#\#):not(#\#){overflow:hidden}
|
|
517
517
|
.x1rea2x4:not(#\#):not(#\#){overflow:visible}
|
|
518
518
|
.xish69e:not(#\#):not(#\#){overscroll-behavior:contain}
|
|
519
|
-
.x8du1vd:not(#\#):not(#\#){overscroll-behavior:none}
|
|
520
519
|
.xt970qd:not(#\#):not(#\#){padding-block:0}
|
|
521
520
|
.x1vn5h1t:not(#\#):not(#\#){padding-block:calc((var(--size-element-lg) - var(--spacing-5) - 2 * var(--border-width)) / 2)}
|
|
522
521
|
.x1ioay2v:not(#\#):not(#\#){padding-block:calc((var(--size-element-md) - var(--spacing-5) - 2 * var(--border-width)) / 2)}
|
|
@@ -867,6 +866,7 @@
|
|
|
867
866
|
.x1lliihq:not(#\#):not(#\#):not(#\#){display:block}
|
|
868
867
|
.xjp7ctv:not(#\#):not(#\#):not(#\#){display:contents}
|
|
869
868
|
.x78zum5:not(#\#):not(#\#):not(#\#){display:flex}
|
|
869
|
+
.xufnvkl:not(#\#):not(#\#):not(#\#){display:flow-root}
|
|
870
870
|
.xrvj5dj:not(#\#):not(#\#):not(#\#){display:grid}
|
|
871
871
|
.x1rg5ohu:not(#\#):not(#\#):not(#\#){display:inline-block}
|
|
872
872
|
.x3nfvp2:not(#\#):not(#\#):not(#\#){display:inline-flex}
|
|
@@ -1363,6 +1363,7 @@
|
|
|
1363
1363
|
.x1e0x2sz:focus-visible:not(#\#):not(#\#):not(#\#){outline-color:var(--color-error)}
|
|
1364
1364
|
.xx47ajj:focus-visible:not(#\#):not(#\#):not(#\#){outline-color:var(--focus-outline-color)}
|
|
1365
1365
|
.x7s97pk:focus-visible:not(#\#):not(#\#):not(#\#){outline-offset:2px}
|
|
1366
|
+
.x1nw7mhf:focus-visible:not(#\#):not(#\#):not(#\#){outline-offset:calc(-1 * var(--focus-outline-width))}
|
|
1366
1367
|
.x13aywxo:focus-visible:not(#\#):not(#\#):not(#\#){outline-offset:var(--button-focus-offset)}
|
|
1367
1368
|
.x1vwwbsn:focus-visible:not(#\#):not(#\#):not(#\#){outline-offset:var(--focus-outline-offset)}
|
|
1368
1369
|
.xwz5zln.xwz5zln:where(.x1iwu4tg:has(:focus-visible) *):not(#\#):not(#\#):not(#\#){outline-offset:var(--focus-outline-offset)}
|
|
@@ -1676,6 +1677,7 @@
|
|
|
1676
1677
|
.xjwf9q1:not(#\#):not(#\#):not(#\#):not(#\#){min-height:24px}
|
|
1677
1678
|
.xe0p6wg:not(#\#):not(#\#):not(#\#):not(#\#){min-height:28px}
|
|
1678
1679
|
.x21xpn4:not(#\#):not(#\#):not(#\#):not(#\#){min-height:32px}
|
|
1680
|
+
.x121v3j4:not(#\#):not(#\#):not(#\#):not(#\#){min-height:min-content}
|
|
1679
1681
|
.x1xf4nls:not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--size-element-lg)}
|
|
1680
1682
|
.x1uogy3y:not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--size-element-md)}
|
|
1681
1683
|
.x1gdqauq:not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--size-element-sm)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrollKeyboardDelegation.d.ts","sourceRoot":"","sources":["../../src/hooks/scrollKeyboardDelegation.ts"],"names":[],"mappings":"AAkIA,0EAA0E;AAC1E,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,WAAW,GACnB,MAAM,IAAI,CAkGZ"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file scrollKeyboardDelegation.ts
|
|
5
|
+
* @input A named, overflowing viewport and its real content box
|
|
6
|
+
* @output Focus-time delegation with native forward and reverse Tab traversal
|
|
7
|
+
* @position Private useScrollableArea keyboard behavior; no DOM observers or scrolling
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { FOCUSABLE_SELECTOR } from "./focusableSelector.js";
|
|
11
|
+
import { getRegisteredScrollOwnerState } from "./scrollOwnerRegistry.js";
|
|
12
|
+
|
|
13
|
+
// Structural roles may contain ordinary links/buttons. Unknown or interactive
|
|
14
|
+
// roles are deliberately excluded until their navigation contract is proven.
|
|
15
|
+
const PASSIVE_ROLES = new Set(['article', 'banner', 'complementary', 'contentinfo', 'definition', 'directory', 'document', 'figure', 'form', 'generic', 'group', 'heading', 'list', 'listitem', 'main', 'navigation', 'none', 'note', 'paragraph', 'presentation', 'region', 'section', 'status', 'table', 'term']);
|
|
16
|
+
function isSequential(element) {
|
|
17
|
+
if (element.tabIndex < 0 || element.matches(':disabled') || element.closest('[inert], [hidden]') != null || element.getClientRects().length === 0) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const visibility = getComputedStyle(element).visibility;
|
|
21
|
+
return visibility !== 'hidden' && visibility !== 'collapse';
|
|
22
|
+
}
|
|
23
|
+
function firstDelegationTarget(viewport, content) {
|
|
24
|
+
const candidates = content.querySelectorAll(FOCUSABLE_SELECTOR);
|
|
25
|
+
let first = content.matches(FOCUSABLE_SELECTOR) && isSequential(content) ? content : null;
|
|
26
|
+
for (const candidate of candidates) {
|
|
27
|
+
// After finding the first target, only positive tabindex can precede it.
|
|
28
|
+
// Ordinary trailing controls need no visibility or layout reads.
|
|
29
|
+
if (first != null && candidate.tabIndex <= 0) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (!isSequential(candidate)) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// Positive tabindex participates before the zero-index viewport. Do not
|
|
36
|
+
// revisit it or skip its ordering by delegating to a later zero-index child.
|
|
37
|
+
if (candidate.tabIndex > 0) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
first ??= candidate;
|
|
41
|
+
}
|
|
42
|
+
if (first == null || first.tabIndex !== 0 || !first.matches('a[href], button') || first.closest('[aria-hidden="true"]') != null || first.matches('[aria-disabled="true"], [aria-haspopup]:not([aria-haspopup="false"])')) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
let ancestor = first;
|
|
46
|
+
while (ancestor != null && ancestor !== viewport) {
|
|
47
|
+
const role = ancestor.getAttribute('role')?.trim().toLowerCase();
|
|
48
|
+
const nativeRole = ancestor === first && (role === 'button' && first.localName === 'button' || role === 'link' && first.localName === 'a');
|
|
49
|
+
if (role != null && role !== '' && !nativeRole && !PASSIVE_ROLES.has(role) || ancestor === first && role != null && role !== '' && !nativeRole || ancestor.hasAttribute('aria-activedescendant') || ancestor.isContentEditable || ancestor.matches('[contenteditable]:not([contenteditable="false"])') || getRegisteredScrollOwnerState(ancestor) != null) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
// Also respect native scroll owners that have not adopted the shared hook.
|
|
53
|
+
const style = getComputedStyle(ancestor);
|
|
54
|
+
if (/^(auto|scroll|overlay)$/.test(style.overflowX) && ancestor.scrollWidth > ancestor.clientWidth + 1 || /^(auto|scroll|overlay)$/.test(style.overflowY) && ancestor.scrollHeight > ancestor.clientHeight + 1) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
ancestor = ancestor.parentElement;
|
|
58
|
+
}
|
|
59
|
+
return ancestor === viewport ? first : null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Attach only while automatic ownership has an effective scroll axis. */
|
|
63
|
+
export function attachScrollKeyboardDelegation(viewport, content) {
|
|
64
|
+
const document = viewport.ownerDocument;
|
|
65
|
+
const window = document.defaultView;
|
|
66
|
+
if (window == null) {
|
|
67
|
+
return () => {};
|
|
68
|
+
}
|
|
69
|
+
let entry = null;
|
|
70
|
+
let origin = null;
|
|
71
|
+
let delegated = null;
|
|
72
|
+
let timer;
|
|
73
|
+
let restoreTabStop;
|
|
74
|
+
const reset = () => {
|
|
75
|
+
entry = null;
|
|
76
|
+
origin = null;
|
|
77
|
+
window.clearTimeout(timer);
|
|
78
|
+
restoreTabStop?.();
|
|
79
|
+
restoreTabStop = undefined;
|
|
80
|
+
};
|
|
81
|
+
const onKeyDown = event => {
|
|
82
|
+
reset();
|
|
83
|
+
if (event.key !== 'Tab' || event.ctrlKey || event.metaKey) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// Keep the actual event: focus() during keydown is programmatic (nonzero
|
|
87
|
+
// eventPhase), whereas native Tab focus follows completed event dispatch.
|
|
88
|
+
entry = event;
|
|
89
|
+
origin = event.target;
|
|
90
|
+
if (event.shiftKey && delegated != null && document.activeElement === delegated && viewport.contains(delegated)) {
|
|
91
|
+
const tabIndex = viewport.getAttribute('tabindex');
|
|
92
|
+
viewport.tabIndex = -1;
|
|
93
|
+
restoreTabStop = () => {
|
|
94
|
+
if (viewport.getAttribute('tabindex') === '-1') {
|
|
95
|
+
if (tabIndex == null) {
|
|
96
|
+
viewport.removeAttribute('tabindex');
|
|
97
|
+
} else {
|
|
98
|
+
viewport.setAttribute('tabindex', tabIndex);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// A canceled Tab, focus leaving the document, or a held key must not leave
|
|
104
|
+
// stale keyboard intent for a later pointer/programmatic focus operation.
|
|
105
|
+
timer = window.setTimeout(reset, 0);
|
|
106
|
+
};
|
|
107
|
+
const onFocusIn = event => {
|
|
108
|
+
const keyboardEntry = entry;
|
|
109
|
+
const previous = origin;
|
|
110
|
+
reset();
|
|
111
|
+
if (event.target !== viewport) {
|
|
112
|
+
if (!viewport.contains(event.target)) {
|
|
113
|
+
delegated = null;
|
|
114
|
+
}
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
delegated = null;
|
|
118
|
+
if (keyboardEntry == null || keyboardEntry.shiftKey || keyboardEntry.defaultPrevented || keyboardEntry.eventPhase !== 0 || event.relatedTarget != null && event.relatedTarget !== previous) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const target = firstDelegationTarget(viewport, content);
|
|
122
|
+
if (target == null) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
delegated = target;
|
|
126
|
+
// Let native focus reveal the action. Arrow/Page scrolling remains entirely
|
|
127
|
+
// browser-owned, including scroll chaining and the full viewport range.
|
|
128
|
+
target.focus();
|
|
129
|
+
if (document.activeElement !== target) {
|
|
130
|
+
delegated = null;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
document.addEventListener('keydown', onKeyDown, true);
|
|
134
|
+
document.addEventListener('keyup', reset, true);
|
|
135
|
+
document.addEventListener('pointerdown', reset, true);
|
|
136
|
+
document.addEventListener('focusin', onFocusIn, true);
|
|
137
|
+
window.addEventListener('blur', reset);
|
|
138
|
+
return () => {
|
|
139
|
+
reset();
|
|
140
|
+
document.removeEventListener('keydown', onKeyDown, true);
|
|
141
|
+
document.removeEventListener('keyup', reset, true);
|
|
142
|
+
document.removeEventListener('pointerdown', reset, true);
|
|
143
|
+
document.removeEventListener('focusin', onFocusIn, true);
|
|
144
|
+
window.removeEventListener('blur', reset);
|
|
145
|
+
};
|
|
146
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file useScrollableArea.ts
|
|
3
|
-
* @input Logical scroll intent, keyboard
|
|
4
|
-
* @output Safe prop getters and stable per-axis effective scroll state
|
|
3
|
+
* @input Logical scroll intent, focus-time keyboard delegation, caller-owned viewport/content props
|
|
4
|
+
* @output Safe prop getters, native keyboard entry, and stable per-axis effective scroll state
|
|
5
5
|
* @position Canonical behavior core for ScrollableArea and structure-owning adopters
|
|
6
6
|
*
|
|
7
7
|
* SYNC: When modified, update:
|
|
@@ -20,6 +20,10 @@ export type ScrollKeyboardAccess = {
|
|
|
20
20
|
owner: 'viewport';
|
|
21
21
|
label: string;
|
|
22
22
|
role?: 'group' | 'region';
|
|
23
|
+
} | {
|
|
24
|
+
owner: 'contentOrViewport';
|
|
25
|
+
label: string;
|
|
26
|
+
role?: 'group' | 'region';
|
|
23
27
|
};
|
|
24
28
|
export interface ScrollAxisState {
|
|
25
29
|
isScrollable: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useScrollableArea.d.ts","sourceRoot":"","sources":["../../src/hooks/useScrollableArea.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,EAOL,KAAK,aAAa,EAEnB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"useScrollableArea.d.ts","sourceRoot":"","sources":["../../src/hooks/useScrollableArea.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,EAOL,KAAK,aAAa,EAEnB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAkB5C,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AACrD,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,SAAS,CAAC;AACnD,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,GAAG,QAAQ,CAAC;AAElE,MAAM,MAAM,oBAAoB,GAC5B;IAAC,KAAK,EAAE,SAAS,CAAA;CAAC,GAClB;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;CAAC,GAC7D;IACE,KAAK,EAAE,mBAAmB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC3B,CAAC;AAEN,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,cAAc,EAAE,oBAAoB,CAAC;IACrC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;CAC7C;AAED,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,WAAW,IAAI,SAAS,CAAC,CAAC,CAAC,GACtE,aAAa,CAAC,CAAC,CAAC,CAAC;AAEnB,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,CAAC,CAAC,SAAS,WAAW,EACpC,KAAK,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAChC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC7B,eAAe,CAAC,CAAC,SAAS,WAAW,EACnC,KAAK,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAChC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC7B,KAAK,EAAE,mBAAmB,CAAC;CAC5B;AAiGD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,cAAc,EACd,UAAoB,EACpB,iBAAoC,GACrC,EAAE,wBAAwB,GAAG,uBAAuB,CA0SpD"}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file useScrollableArea.ts
|
|
7
|
-
* @input Logical scroll intent, keyboard
|
|
8
|
-
* @output Safe prop getters and stable per-axis effective scroll state
|
|
7
|
+
* @input Logical scroll intent, focus-time keyboard delegation, caller-owned viewport/content props
|
|
8
|
+
* @output Safe prop getters, native keyboard entry, and stable per-axis effective scroll state
|
|
9
9
|
* @position Canonical behavior core for ScrollableArea and structure-owning adopters
|
|
10
10
|
*
|
|
11
11
|
* SYNC: When modified, update:
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
17
17
|
import * as stylex from '@stylexjs/stylex';
|
|
18
|
+
import { attachScrollKeyboardDelegation } from "./scrollKeyboardDelegation.js";
|
|
18
19
|
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
19
20
|
import { mergeProps } from "../utils/mergeProps.js";
|
|
20
21
|
import { mergeRefs } from "../utils/mergeRefs.js";
|
|
@@ -172,6 +173,9 @@ export function useScrollableArea({
|
|
|
172
173
|
viewport.addEventListener('animationend', scheduleMeasure);
|
|
173
174
|
content.addEventListener('transitionend', scheduleMeasure);
|
|
174
175
|
content.addEventListener('animationend', scheduleMeasure);
|
|
176
|
+
|
|
177
|
+
// Geometry invalidation is independent of keyboard eligibility. The latter
|
|
178
|
+
// is inspected only on native keyboard entry, never by these observers.
|
|
175
179
|
const mutationObserver = typeof MutationObserver === 'undefined' ? null : new MutationObserver(scheduleMeasure);
|
|
176
180
|
mutationObserver?.observe(viewport, {
|
|
177
181
|
attributes: true,
|
|
@@ -219,6 +223,13 @@ export function useScrollableArea({
|
|
|
219
223
|
inline: axisIsRequested(axis, 'inline') ? measured.inline : INACTIVE_AXIS_STATE,
|
|
220
224
|
block: axisIsRequested(axis, 'block') ? measured.block : INACTIVE_AXIS_STATE
|
|
221
225
|
}), [axis, measured]);
|
|
226
|
+
const hasEffectiveAxis = state.inline.isScrollable || state.block.isScrollable;
|
|
227
|
+
useIsomorphicLayoutEffect(() => {
|
|
228
|
+
if (keyboardAccess.owner !== 'contentOrViewport' || !hasEffectiveAxis || viewport == null || content == null) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
return attachScrollKeyboardDelegation(viewport, content);
|
|
232
|
+
}, [content, hasEffectiveAxis, keyboardAccess.owner, viewport]);
|
|
222
233
|
const getViewportProps = useCallback((props = {}) => {
|
|
223
234
|
const hasEffectiveAxis = state.inline.isScrollable || state.block.isScrollable;
|
|
224
235
|
const requestedX = axisIsRequested(axis, 'inline') && mapping.inline === 'x' || axisIsRequested(axis, 'block') && mapping.block === 'x';
|
|
@@ -237,7 +248,8 @@ export function useScrollableArea({
|
|
|
237
248
|
style: withoutOwnedOverflow(domProps.style)
|
|
238
249
|
};
|
|
239
250
|
const styledProps = mergeProps(callerProps, stylex.props(xstyle, styles.overflow(containsSticky ? scrollsOnX ? 'auto' : 'hidden' : 'clip', containsSticky ? scrollsOnY ? 'auto' : 'hidden' : 'clip')));
|
|
240
|
-
const
|
|
251
|
+
const viewportIsKeyboardOwner = keyboardAccess.owner !== 'content';
|
|
252
|
+
const keepsProgrammaticFocus = (!viewportIsKeyboardOwner || !hasEffectiveAxis) && viewport != null && typeof document !== 'undefined' && document.activeElement === viewport;
|
|
241
253
|
const behaviorStyle = {
|
|
242
254
|
...styledProps.style
|
|
243
255
|
};
|
|
@@ -251,10 +263,10 @@ export function useScrollableArea({
|
|
|
251
263
|
if (axisIsRequested(axis, 'block')) {
|
|
252
264
|
behaviorStyle[blockPhysical === 'x' ? 'overscrollBehaviorX' : 'overscrollBehaviorY'] = containBlock ? 'contain' : 'auto';
|
|
253
265
|
}
|
|
254
|
-
const keyboardProps = keyboardAccess.owner
|
|
266
|
+
const keyboardProps = keyboardAccess.owner !== 'content' ? {
|
|
255
267
|
role: keyboardAccess.role ?? 'group',
|
|
256
268
|
'aria-label': keyboardAccess.label,
|
|
257
|
-
tabIndex: hasEffectiveAxis ? 0 : keepsProgrammaticFocus ? -1 : undefined
|
|
269
|
+
tabIndex: viewportIsKeyboardOwner && hasEffectiveAxis ? 0 : keepsProgrammaticFocus ? -1 : undefined
|
|
258
270
|
} : {};
|
|
259
271
|
const result = {
|
|
260
272
|
...styledProps,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/core",
|
|
3
|
-
"version": "0.6.2-canary.
|
|
3
|
+
"version": "0.6.2-canary.bfee8a4",
|
|
4
4
|
"displayName": "Astryx Core",
|
|
5
5
|
"description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -672,8 +672,8 @@
|
|
|
672
672
|
"react-dom": ">=19.0.0"
|
|
673
673
|
},
|
|
674
674
|
"devDependencies": {
|
|
675
|
-
"@astryxdesign/a11y-spec": "0.6.2-canary.
|
|
676
|
-
"@astryxdesign/cli": "0.6.2-canary.
|
|
675
|
+
"@astryxdesign/a11y-spec": "0.6.2-canary.bfee8a4",
|
|
676
|
+
"@astryxdesign/cli": "0.6.2-canary.bfee8a4",
|
|
677
677
|
"@babel/cli": "^7.29.7",
|
|
678
678
|
"@babel/core": "^7.29.7",
|
|
679
679
|
"@babel/preset-react": "^7.29.7",
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @file BottomSheet.doc.mjs
|
|
5
|
+
* @input BottomSheet props, sheet anatomy, and focus-time keyboard scrolling behavior
|
|
6
|
+
* @output Consumer documentation and examples for BottomSheet
|
|
7
|
+
* @position CLI and rendered component documentation
|
|
8
|
+
*/
|
|
9
|
+
|
|
3
10
|
/** @type {import('@astryxdesign/cli/authoring').ComponentAnatomyElement[]} */
|
|
4
11
|
const anatomy = [
|
|
5
12
|
{
|
|
@@ -130,7 +137,7 @@ export const docs = {
|
|
|
130
137
|
name: 'children',
|
|
131
138
|
type: 'ReactNode',
|
|
132
139
|
description:
|
|
133
|
-
"Sheet content,
|
|
140
|
+
"Sheet content in a scrollable area. The named body is keyboard reachable while overflowing. Forward Tab entry may move directly to the first native link or button; input controls, composite widgets, and nested scroll areas retain the body stop. Shift+Tab from a delegated first child skips the body. Fitting content adds no body stop. The internal observed content box preserves block flow and percentage heights. If it includes a text-entry control that can bring up the mobile keyboard, use height='tall' and keep the sheet fully expanded while editing.",
|
|
134
141
|
required: true,
|
|
135
142
|
},
|
|
136
143
|
{
|