@astryxdesign/core 0.4.4 → 0.4.5-canary.1fdecb1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/dist/BottomSheet/BottomSheet.d.ts +11 -2
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +4 -0
- package/dist/BottomSheet/BottomSheetPanel.d.ts +5 -2
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +65 -15
- package/dist/BottomSheet/index.d.ts +1 -1
- package/dist/BottomSheet/index.d.ts.map +1 -1
- package/dist/BottomSheet/snapOffsets.d.ts +57 -20
- package/dist/BottomSheet/snapOffsets.d.ts.map +1 -1
- package/dist/BottomSheet/snapOffsets.js +106 -30
- package/dist/BottomSheet/useSheetGestures.d.ts +13 -8
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +160 -64
- package/dist/Calendar/Calendar.d.ts +17 -0
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +34 -3
- package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts +14 -0
- package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts.map +1 -0
- package/dist/Calendar/getStandaloneShortWeekdayNames.js +26 -0
- package/dist/Calendar/hooks/useCalendarConstraints.d.ts +22 -1
- package/dist/Calendar/hooks/useCalendarConstraints.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarConstraints.js +26 -4
- package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarDays.js +14 -10
- package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts +47 -0
- package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts.map +1 -0
- package/dist/Calendar/standaloneShortWeekdayNames.generated.js +40 -0
- package/dist/Center/Center.d.ts +23 -1
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +12 -6
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +9 -0
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +6 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +6 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +38 -3
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +7 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +3 -3
- package/dist/Field/FieldLabel.d.ts +2 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +21 -3
- package/dist/Field/InputClearButton.d.ts +2 -1
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +6 -1
- package/dist/FormLayout/FormLayout.d.ts +24 -2
- package/dist/FormLayout/FormLayout.d.ts.map +1 -1
- package/dist/FormLayout/FormLayout.js +7 -2
- package/dist/FormLayout/FormLayoutContext.d.ts +15 -2
- package/dist/FormLayout/FormLayoutContext.d.ts.map +1 -1
- package/dist/FormLayout/FormLayoutContext.js +19 -4
- package/dist/FormLayout/index.d.ts +1 -1
- package/dist/FormLayout/index.d.ts.map +1 -1
- package/dist/Item/Item.d.ts +9 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +45 -7
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +3 -2
- package/dist/Layout/container.stylex.d.ts +4 -2
- package/dist/Layout/container.stylex.d.ts.map +1 -1
- package/dist/Layout/container.stylex.js +19 -11
- package/dist/Layout/index.d.ts +1 -0
- package/dist/Layout/index.d.ts.map +1 -1
- package/dist/Layout/index.js +4 -0
- package/dist/Layout/padding.stylex.d.ts +315 -12
- package/dist/Layout/padding.stylex.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.js +389 -12
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +2 -1
- package/dist/Markdown/Markdown.d.ts +8 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +31 -3
- package/dist/Markdown/parser.d.ts +14 -2
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +50 -2
- package/dist/MobileNav/MobileNav.d.ts +1 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +24 -6
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +6 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +36 -3
- package/dist/Outline/parseOutlineFromMarkdown.d.ts +2 -0
- package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/parseOutlineFromMarkdown.js +5 -31
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +12 -1
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +3 -3
- package/dist/Section/Section.d.ts +36 -1
- package/dist/Section/Section.d.ts.map +1 -1
- package/dist/Section/Section.js +12 -2
- package/dist/Selector/Selector.d.ts +26 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +93 -15
- package/dist/Selector/SelectorOption.d.ts +14 -1
- package/dist/Selector/SelectorOption.d.ts.map +1 -1
- package/dist/Selector/SelectorOption.js +6 -0
- package/dist/Selector/SelectorRowLayoutContext.d.ts +8 -0
- package/dist/Selector/SelectorRowLayoutContext.d.ts.map +1 -0
- package/dist/Selector/SelectorRowLayoutContext.js +27 -0
- package/dist/Selector/types.d.ts +1 -0
- package/dist/Selector/types.d.ts.map +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +2 -2
- package/dist/Stack/Stack.d.ts +23 -1
- package/dist/Stack/Stack.d.ts.map +1 -1
- package/dist/Stack/Stack.js +12 -6
- package/dist/StatusDot/StatusDot.d.ts +43 -3
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +42 -5
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +9 -0
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +6 -1
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +6 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +6 -1
- package/dist/astryx.css +40 -21
- package/dist/hooks/scrollbarGutter.d.ts +28 -0
- package/dist/hooks/scrollbarGutter.d.ts.map +1 -0
- package/dist/hooks/scrollbarGutter.js +103 -0
- package/dist/hooks/useResolvedRequired.d.ts +19 -0
- package/dist/hooks/useResolvedRequired.d.ts.map +1 -0
- package/dist/hooks/useResolvedRequired.js +40 -0
- package/dist/hooks/useScrollLock.d.ts +4 -0
- package/dist/hooks/useScrollLock.d.ts.map +1 -1
- package/dist/hooks/useScrollLock.js +13 -1
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +7 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +37 -4
- package/dist/utils/plainDate.d.ts +6 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +12 -0
- package/locales/af-ZA.json +958 -0
- package/locales/ar-SA.json +998 -0
- package/locales/ca-ES.json +974 -0
- package/locales/cs-CZ.json +990 -0
- package/locales/da-DK.json +966 -0
- package/locales/de-DE.json +966 -0
- package/locales/el-GR.json +990 -0
- package/locales/en.json +8 -0
- package/locales/es-ES.json +978 -0
- package/locales/fi-FI.json +990 -0
- package/locales/fr-FR.json +928 -0
- package/locales/he-IL.json +990 -0
- package/locales/hu-HU.json +990 -0
- package/locales/it-IT.json +978 -0
- package/locales/ja-JP.json +998 -0
- package/locales/ko-KR.json +990 -0
- package/locales/nl-NL.json +954 -0
- package/locales/no-NO.json +978 -0
- package/locales/pl-PL.json +982 -0
- package/locales/pseudo.json +6 -0
- package/locales/pt-BR.json +982 -0
- package/locales/pt-PT.json +982 -0
- package/locales/ro-RO.json +982 -0
- package/locales/ru-RU.json +990 -0
- package/locales/sr-SP.json +990 -0
- package/locales/sv-SE.json +986 -0
- package/locales/tr-TR.json +990 -0
- package/locales/uk-UA.json +990 -0
- package/locales/vi-VN.json +986 -0
- package/locales/zh-CN.json +998 -0
- package/locales/zh-TW.json +998 -0
- package/package.json +3 -3
- package/src/BottomSheet/BottomSheet.doc.mjs +36 -3
- package/src/BottomSheet/BottomSheet.test.tsx +177 -2
- package/src/BottomSheet/BottomSheet.tsx +16 -2
- package/src/BottomSheet/BottomSheetPanel.test.tsx +41 -0
- package/src/BottomSheet/BottomSheetPanel.tsx +95 -15
- package/src/BottomSheet/index.ts +5 -1
- package/src/BottomSheet/snapOffsets.test.ts +114 -47
- package/src/BottomSheet/snapOffsets.ts +119 -33
- package/src/BottomSheet/useSheetGestures.test.ts +113 -15
- package/src/BottomSheet/useSheetGestures.ts +196 -100
- package/src/Calendar/Calendar.doc.mjs +16 -0
- package/src/Calendar/Calendar.test.tsx +137 -0
- package/src/Calendar/Calendar.tsx +65 -2
- package/src/Calendar/getStandaloneShortWeekdayNames.test.ts +54 -0
- package/src/Calendar/getStandaloneShortWeekdayNames.ts +38 -0
- package/src/Calendar/hooks/useCalendarConstraints.ts +54 -3
- package/src/Calendar/hooks/useCalendarDays.ts +13 -10
- package/src/Calendar/standaloneShortWeekdayNames.generated.ts +50 -0
- package/src/Center/Center.doc.mjs +48 -0
- package/src/Center/Center.test.tsx +158 -0
- package/src/Center/Center.tsx +50 -9
- package/src/CheckboxInput/CheckboxInput.tsx +6 -0
- package/src/ComplexSelector/ComplexSelector.tsx +3 -1
- package/src/DateInput/DateInput.tsx +3 -1
- package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +81 -1
- package/src/DateRangeInput/DateRangeInput.tsx +72 -1
- package/src/DateTimeInput/DateTimeInput.tsx +4 -2
- package/src/Dialog/Dialog.test.tsx +24 -0
- package/src/Dialog/Dialog.tsx +3 -0
- package/src/Field/Field.doc.mjs +1 -0
- package/src/Field/FieldLabel.tsx +20 -4
- package/src/Field/InputClearButton.test.tsx +25 -0
- package/src/Field/InputClearButton.tsx +4 -1
- package/src/FormLayout/FormLayout.doc.mjs +13 -0
- package/src/FormLayout/FormLayout.test.tsx +181 -4
- package/src/FormLayout/FormLayout.tsx +33 -2
- package/src/FormLayout/FormLayoutContext.ts +22 -7
- package/src/FormLayout/index.ts +1 -1
- package/src/Item/Item.doc.mjs +1 -0
- package/src/Item/Item.test.tsx +50 -0
- package/src/Item/Item.tsx +40 -1
- package/src/Layer/useLayer.tsx +13 -2
- package/src/Layout/Layout.doc.mjs +18 -0
- package/src/Layout/container.stylex.ts +11 -3
- package/src/Layout/index.ts +4 -0
- package/src/Layout/overlayPaddingReset.test.tsx +222 -0
- package/src/Layout/padding.stylex.ts +192 -12
- package/src/Lightbox/Lightbox.tsx +2 -1
- package/src/Markdown/Markdown.doc.mjs +3 -0
- package/src/Markdown/Markdown.test.tsx +78 -0
- package/src/Markdown/Markdown.tsx +41 -1
- package/src/Markdown/parser.ts +60 -2
- package/src/MobileNav/MobileNav.tsx +61 -5
- package/src/MobileNav/MobileNavEntryAnimation.test.tsx +212 -0
- package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +109 -0
- package/src/MultiSelector/MultiSelector.tsx +3 -1
- package/src/NumberInput/NumberInput.doc.mjs +24 -0
- package/src/NumberInput/NumberInput.test.tsx +138 -0
- package/src/NumberInput/NumberInput.tsx +43 -5
- package/src/Outline/Outline.doc.mjs +2 -0
- package/src/Outline/parseOutlineFromMarkdown.ts +10 -40
- package/src/RadioList/RadioList.tsx +9 -1
- package/src/Resizable/ResizeHandle.test.tsx +22 -0
- package/src/Resizable/ResizeHandle.tsx +9 -3
- package/src/Section/Section.doc.mjs +55 -0
- package/src/Section/Section.test.tsx +201 -4
- package/src/Section/Section.tsx +69 -0
- package/src/Selector/Selector.doc.mjs +16 -2
- package/src/Selector/Selector.test.tsx +524 -0
- package/src/Selector/Selector.tsx +161 -17
- package/src/Selector/SelectorOption.doc.mjs +7 -0
- package/src/Selector/SelectorOption.tsx +21 -0
- package/src/Selector/SelectorRowLayoutContext.ts +32 -0
- package/src/Selector/types.ts +4 -4
- package/src/Slider/Slider.tsx +10 -0
- package/src/Stack/Stack.doc.mjs +72 -0
- package/src/Stack/Stack.test.tsx +156 -0
- package/src/Stack/Stack.tsx +50 -8
- package/src/StatusDot/StatusDot.doc.mjs +13 -0
- package/src/StatusDot/StatusDot.test.tsx +115 -8
- package/src/StatusDot/StatusDot.tsx +74 -9
- package/src/Switch/Switch.tsx +6 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +20 -2
- package/src/TextArea/TextArea.tsx +3 -1
- package/src/TextInput/TextInput.tsx +3 -1
- package/src/TimeInput/TimeInput.tsx +3 -1
- package/src/hooks/scrollbarGutter.test.ts +167 -0
- package/src/hooks/scrollbarGutter.ts +121 -0
- package/src/hooks/useResolvedRequired.ts +42 -0
- package/src/hooks/useScrollLock.doc.mjs +4 -4
- package/src/hooks/useScrollLock.test.ts +73 -0
- package/src/hooks/useScrollLock.ts +14 -0
- package/src/theme/derivedVarRegistry.test.ts +14 -3
- package/src/theme/derivedVarRegistry.ts +4 -0
- package/src/theme/generateThemeRules.test.ts +79 -0
- package/src/theme/generateThemeRules.ts +49 -4
- package/src/utils/plainDate.test.ts +50 -0
- package/src/utils/plainDate.ts +12 -0
package/src/Item/Item.tsx
CHANGED
|
@@ -106,6 +106,15 @@ export interface ItemProps extends BaseProps<HTMLElement> {
|
|
|
106
106
|
*/
|
|
107
107
|
descriptionLines?: number;
|
|
108
108
|
|
|
109
|
+
/**
|
|
110
|
+
* How the label and description sit together. `stacked` puts the description
|
|
111
|
+
* on its own line below the label; `inline` keeps both on one line, with the
|
|
112
|
+
* description ellipsizing first, so the row fits a fixed-height host.
|
|
113
|
+
*
|
|
114
|
+
* @default 'stacked'
|
|
115
|
+
*/
|
|
116
|
+
layout?: 'stacked' | 'inline';
|
|
117
|
+
|
|
109
118
|
/**
|
|
110
119
|
* Click handler. Makes the item clickable with button semantics.
|
|
111
120
|
*/
|
|
@@ -264,6 +273,25 @@ const styles = stylex.create({
|
|
|
264
273
|
minWidth: 0,
|
|
265
274
|
textAlign: 'start',
|
|
266
275
|
},
|
|
276
|
+
// `layout="inline"`: label and description share one line, so the row fits a
|
|
277
|
+
// fixed-height host such as a Selector trigger inside an InputGroup.
|
|
278
|
+
inlineContent: {
|
|
279
|
+
flexDirection: 'row',
|
|
280
|
+
// Centered, not baseline-aligned: two different font sizes on a shared
|
|
281
|
+
// baseline make a line box taller than either line, which would push a
|
|
282
|
+
// fixed-height host (a Selector trigger) a pixel off its size token.
|
|
283
|
+
alignItems: 'center',
|
|
284
|
+
columnGap: spacingVars['--spacing-1'],
|
|
285
|
+
},
|
|
286
|
+
inlineLabel: {
|
|
287
|
+
flexShrink: 0,
|
|
288
|
+
},
|
|
289
|
+
// The description yields width first, so the label — the part that identifies
|
|
290
|
+
// the item — is the last thing to ellipsize.
|
|
291
|
+
inlineDescription: {
|
|
292
|
+
flexShrink: 1,
|
|
293
|
+
minWidth: 0,
|
|
294
|
+
},
|
|
267
295
|
label: {
|
|
268
296
|
// Falls back to the primary text token; a parent (e.g. a destructive menu
|
|
269
297
|
// item) can recolor the label by setting --_item-label-color.
|
|
@@ -358,6 +386,7 @@ export function Item({
|
|
|
358
386
|
density = 'balanced',
|
|
359
387
|
labelLines,
|
|
360
388
|
descriptionLines,
|
|
389
|
+
layout = 'stacked',
|
|
361
390
|
onClick,
|
|
362
391
|
interactiveRef,
|
|
363
392
|
href,
|
|
@@ -420,12 +449,16 @@ export function Item({
|
|
|
420
449
|
? styles.labelSingleTruncate
|
|
421
450
|
: null;
|
|
422
451
|
|
|
452
|
+
// Inline rows are one line by definition, so the description always
|
|
453
|
+
// ellipsizes there — a ReactNode description cannot wrap the row open.
|
|
454
|
+
const isInline = layout === 'inline' && description != null;
|
|
455
|
+
|
|
423
456
|
const descriptionTruncateStyle =
|
|
424
457
|
descriptionLines != null
|
|
425
458
|
? descriptionLines === 1
|
|
426
459
|
? styles.descriptionSingleTruncate
|
|
427
460
|
: styles.descriptionMultiTruncate
|
|
428
|
-
: isStringDescription
|
|
461
|
+
: isStringDescription || isInline
|
|
429
462
|
? styles.descriptionSingleTruncate
|
|
430
463
|
: null;
|
|
431
464
|
|
|
@@ -434,6 +467,7 @@ export function Item({
|
|
|
434
467
|
<span
|
|
435
468
|
{...stylex.props(
|
|
436
469
|
styles.label,
|
|
470
|
+
isInline && styles.inlineLabel,
|
|
437
471
|
labelTruncateStyle,
|
|
438
472
|
labelLines != null &&
|
|
439
473
|
labelLines > 1 &&
|
|
@@ -445,6 +479,7 @@ export function Item({
|
|
|
445
479
|
<span
|
|
446
480
|
{...stylex.props(
|
|
447
481
|
styles.description,
|
|
482
|
+
isInline && styles.inlineDescription,
|
|
448
483
|
descriptionTruncateStyle,
|
|
449
484
|
descriptionLines != null &&
|
|
450
485
|
descriptionLines > 1 &&
|
|
@@ -481,6 +516,7 @@ export function Item({
|
|
|
481
516
|
<span
|
|
482
517
|
{...stylex.props(
|
|
483
518
|
styles.content,
|
|
519
|
+
isInline && styles.inlineContent,
|
|
484
520
|
isDisabled && styles.disabledContent,
|
|
485
521
|
)}>
|
|
486
522
|
{labelAndDescription}
|
|
@@ -494,6 +530,7 @@ export function Item({
|
|
|
494
530
|
tabIndex={isDisabled ? -1 : undefined}
|
|
495
531
|
{...stylex.props(
|
|
496
532
|
styles.invisibleAnchor,
|
|
533
|
+
isInline && styles.inlineContent,
|
|
497
534
|
isDisabled && styles.disabledContent,
|
|
498
535
|
)}>
|
|
499
536
|
{labelAndDescription}
|
|
@@ -505,6 +542,7 @@ export function Item({
|
|
|
505
542
|
disabled={isDisabled}
|
|
506
543
|
{...stylex.props(
|
|
507
544
|
styles.invisibleButton,
|
|
545
|
+
isInline && styles.inlineContent,
|
|
508
546
|
isDisabled && styles.disabledContent,
|
|
509
547
|
)}>
|
|
510
548
|
{labelAndDescription}
|
|
@@ -513,6 +551,7 @@ export function Item({
|
|
|
513
551
|
<span
|
|
514
552
|
{...stylex.props(
|
|
515
553
|
styles.content,
|
|
554
|
+
isInline && styles.inlineContent,
|
|
516
555
|
isDisabled && styles.disabledContent,
|
|
517
556
|
)}>
|
|
518
557
|
{labelAndDescription}
|
package/src/Layer/useLayer.tsx
CHANGED
|
@@ -29,6 +29,7 @@ import {createPortal} from 'react-dom';
|
|
|
29
29
|
import {addAnchorName, removeAnchorName} from './anchorName';
|
|
30
30
|
import {resolveLayerPortalTarget} from './layerHost';
|
|
31
31
|
import {typeScaleVars, typographyVars} from '../theme/tokens.stylex';
|
|
32
|
+
import {overlayPaddingReset} from '../Layout/padding.stylex';
|
|
32
33
|
|
|
33
34
|
const styles = stylex.create({
|
|
34
35
|
// Base reset for all layers
|
|
@@ -771,7 +772,12 @@ export function useLayer(
|
|
|
771
772
|
: styles.offsetInline(toCssLength(offset))
|
|
772
773
|
: null;
|
|
773
774
|
|
|
774
|
-
const stylexResult = stylex.props(
|
|
775
|
+
const stylexResult = stylex.props(
|
|
776
|
+
styles.base,
|
|
777
|
+
overlayPaddingReset.reset,
|
|
778
|
+
offsetStyle,
|
|
779
|
+
xstyle,
|
|
780
|
+
);
|
|
775
781
|
const combinedClassName = extraClassName
|
|
776
782
|
? `${extraClassName} ${stylexResult.className ?? ''}`
|
|
777
783
|
: stylexResult.className;
|
|
@@ -835,7 +841,12 @@ export function useLayer(
|
|
|
835
841
|
left: x,
|
|
836
842
|
};
|
|
837
843
|
|
|
838
|
-
const stylexResult = stylex.props(
|
|
844
|
+
const stylexResult = stylex.props(
|
|
845
|
+
styles.base,
|
|
846
|
+
overlayPaddingReset.reset,
|
|
847
|
+
styles.fixed,
|
|
848
|
+
xstyle,
|
|
849
|
+
);
|
|
839
850
|
const combinedClassName = extraClassName
|
|
840
851
|
? `${extraClassName} ${stylexResult.className ?? ''}`
|
|
841
852
|
: stylexResult.className;
|
|
@@ -93,6 +93,24 @@ export const docs = {
|
|
|
93
93
|
description: 'Height behavior: fill the container or grow with content.',
|
|
94
94
|
default: "'fill'",
|
|
95
95
|
},
|
|
96
|
+
{
|
|
97
|
+
name: 'contentWidth',
|
|
98
|
+
type: 'number | string',
|
|
99
|
+
description:
|
|
100
|
+
'Maximum width of the content within each slot (header, content, footer, panels), centered when narrower than the available space. Dividers stay full-bleed. Numbers are pixels, strings are used as-is (e.g. `60ch`). Common page widths: 640 for forms, settings, and text-focused pages; 960 for content pages and wider layouts.',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: 'padding',
|
|
104
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
105
|
+
description:
|
|
106
|
+
"Padding at the layout's outer edges using the spacing scale.",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'defaultHasDividers',
|
|
110
|
+
type: 'boolean',
|
|
111
|
+
description:
|
|
112
|
+
"Default divider visibility for LayoutHeader and LayoutFooter children. Headers and footers that don't pass `hasDivider` use this value; when unset, nested layouts inherit from their parent context.",
|
|
113
|
+
},
|
|
96
114
|
],
|
|
97
115
|
components: [
|
|
98
116
|
{name: 'LayoutHeader'},
|
|
@@ -28,8 +28,10 @@
|
|
|
28
28
|
* }
|
|
29
29
|
* ```
|
|
30
30
|
*
|
|
31
|
-
* Internal variables (`--layout-padding-inner-x`, `--container-padding
|
|
32
|
-
* are implementation details and must not be
|
|
31
|
+
* Internal variables (`--layout-padding-inner-x`, `--container-padding-*`,
|
|
32
|
+
* `--_section-padding-propagated`) are implementation details and must not be
|
|
33
|
+
* referenced by themes. They also do not cross an overlay boundary — see
|
|
34
|
+
* `overlayPaddingReset` in padding.stylex.ts.
|
|
33
35
|
*
|
|
34
36
|
* SYNC: When modified, update /packages/core/src/Layout/Layout.doc.mjs
|
|
35
37
|
*/
|
|
@@ -105,7 +107,13 @@ const cardBlockEnd = `var(--astryx-card-padding-block-end, ${cardShorthand})`;
|
|
|
105
107
|
// Section padding chains: --astryx-* then the next specificity level, terminating
|
|
106
108
|
// at --spacing-4. Built as chained const strings (no function calls) so StyleX
|
|
107
109
|
// can statically analyze them; see naming.ts for the prefix policy.
|
|
108
|
-
|
|
110
|
+
// `--_section-padding-propagated` (set by an ancestor Section with explicit
|
|
111
|
+
// padding) is read AHEAD of the public theme token, so a propagated value
|
|
112
|
+
// still wins over the theme for nested sections. Splitting the two names is
|
|
113
|
+
// what lets an overlay drop the inherited value at its boundary while keeping
|
|
114
|
+
// the theme's — see `overlayPaddingReset` in padding.stylex.ts.
|
|
115
|
+
const sectionThemeShorthand = `var(--astryx-section-padding, ${SP4})`;
|
|
116
|
+
const sectionShorthand = `var(--_section-padding-propagated, ${sectionThemeShorthand})`;
|
|
109
117
|
const sectionInline = `var(--astryx-section-padding-inline, ${sectionShorthand})`;
|
|
110
118
|
const sectionInlineStart = `var(--astryx-section-padding-inline-start, ${sectionInline})`;
|
|
111
119
|
const sectionInlineEnd = `var(--astryx-section-padding-inline-end, ${sectionInline})`;
|
package/src/Layout/index.ts
CHANGED
|
@@ -19,6 +19,10 @@ export type {
|
|
|
19
19
|
SpacingToken,
|
|
20
20
|
} from './container.stylex';
|
|
21
21
|
|
|
22
|
+
// Overlay padding-variable reset (applied on overlay roots so the container
|
|
23
|
+
// padding system does not cross a fixed/top-layer boundary)
|
|
24
|
+
export {overlayPaddingReset} from './padding.stylex';
|
|
25
|
+
|
|
22
26
|
// Edge compensation utility
|
|
23
27
|
export {edgeCompSlot, EDGE_COMP_ATTR} from './edgeCompensation.stylex';
|
|
24
28
|
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file overlayPaddingReset.test.tsx
|
|
5
|
+
* @input Uses vitest, @testing-library/react, overlay components from core
|
|
6
|
+
* @output Tests that overlay roots stop the container padding system at their
|
|
7
|
+
* boundary, and that the public theme token still crosses it
|
|
8
|
+
* @position Layout tests; validates overlayPaddingReset in padding.stylex.ts
|
|
9
|
+
*
|
|
10
|
+
* The container padding system talks to descendants through INHERITED custom
|
|
11
|
+
* properties, but an overlay leaves its parent's visual box while staying a DOM
|
|
12
|
+
* descendant of it. Every overlay root therefore has to stop those values (see
|
|
13
|
+
* #5208: a Section in a 640px sheet rendered 672px wide).
|
|
14
|
+
*
|
|
15
|
+
* jsdom does no layout, so these assert on the custom properties themselves —
|
|
16
|
+
* the definitions the layout is computed from. The widths they stand in for are
|
|
17
|
+
* verified in a browser; see the PR description.
|
|
18
|
+
*
|
|
19
|
+
* SYNC: When an overlay is added, add it to OVERLAYS below.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
|
|
23
|
+
import {readFileSync} from 'node:fs';
|
|
24
|
+
import {join} from 'node:path';
|
|
25
|
+
import {render, screen} from '@testing-library/react';
|
|
26
|
+
import type {ReactNode} from 'react';
|
|
27
|
+
import {Dialog} from '../Dialog';
|
|
28
|
+
import {BottomSheet} from '../BottomSheet';
|
|
29
|
+
import {MobileNav} from '../MobileNav';
|
|
30
|
+
import {Lightbox} from '../Lightbox';
|
|
31
|
+
import {Popover} from '../Popover';
|
|
32
|
+
import {Section} from '../Section';
|
|
33
|
+
|
|
34
|
+
// jsdom implements neither the <dialog> methods nor matchMedia.
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
HTMLDialogElement.prototype.showModal = vi.fn(function (
|
|
37
|
+
this: HTMLDialogElement,
|
|
38
|
+
) {
|
|
39
|
+
this.setAttribute('open', '');
|
|
40
|
+
});
|
|
41
|
+
HTMLDialogElement.prototype.show = vi.fn(function (this: HTMLDialogElement) {
|
|
42
|
+
this.setAttribute('open', '');
|
|
43
|
+
});
|
|
44
|
+
HTMLDialogElement.prototype.close = vi.fn(function (this: HTMLDialogElement) {
|
|
45
|
+
this.removeAttribute('open');
|
|
46
|
+
});
|
|
47
|
+
vi.stubGlobal(
|
|
48
|
+
'matchMedia',
|
|
49
|
+
vi.fn().mockReturnValue({
|
|
50
|
+
matches: false,
|
|
51
|
+
media: '',
|
|
52
|
+
onchange: null,
|
|
53
|
+
addEventListener: vi.fn(),
|
|
54
|
+
removeEventListener: vi.fn(),
|
|
55
|
+
addListener: vi.fn(),
|
|
56
|
+
removeListener: vi.fn(),
|
|
57
|
+
dispatchEvent: vi.fn(),
|
|
58
|
+
}),
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
afterEach(() => {
|
|
63
|
+
vi.unstubAllGlobals();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Values descendants SUBTRACT (bleed margins). The overlay root has no padding
|
|
68
|
+
* of its own to escape, so these must read a literal zero.
|
|
69
|
+
*/
|
|
70
|
+
const SUBTRACTED = [
|
|
71
|
+
'--container-padding-inline-start',
|
|
72
|
+
'--container-padding-inline-end',
|
|
73
|
+
'--container-padding-block-start',
|
|
74
|
+
'--container-padding-block-end',
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Values descendants ADD. These must be guaranteed-invalid (`initial`) rather
|
|
79
|
+
* than zero, so readers fall through to their own default instead of losing
|
|
80
|
+
* their padding — a computed empty string is what `initial` looks like here.
|
|
81
|
+
*/
|
|
82
|
+
const CLEARED = [
|
|
83
|
+
'--layout-padding-outer-x',
|
|
84
|
+
'--layout-padding-outer-y',
|
|
85
|
+
'--layout-padding-inner-x',
|
|
86
|
+
'--layout-padding-inner-y',
|
|
87
|
+
'--_section-padding-propagated',
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
/** What a cleared custom property reads back as. See the assertion below. */
|
|
91
|
+
const CLEARED_READBACK = ['', 'initial'];
|
|
92
|
+
|
|
93
|
+
/** Each overlay, rendered open inside a page Section that leaks 40px. */
|
|
94
|
+
const OVERLAYS: {
|
|
95
|
+
name: string;
|
|
96
|
+
render: (child: ReactNode) => ReactNode;
|
|
97
|
+
root: () => HTMLElement;
|
|
98
|
+
}[] = [
|
|
99
|
+
{
|
|
100
|
+
name: 'Dialog',
|
|
101
|
+
render: child => (
|
|
102
|
+
<Dialog isOpen onOpenChange={() => {}}>
|
|
103
|
+
{child}
|
|
104
|
+
</Dialog>
|
|
105
|
+
),
|
|
106
|
+
root: () => screen.getByRole('dialog'),
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'BottomSheet',
|
|
110
|
+
render: child => (
|
|
111
|
+
<BottomSheet isOpen onOpenChange={() => {}} label="S">
|
|
112
|
+
{child}
|
|
113
|
+
</BottomSheet>
|
|
114
|
+
),
|
|
115
|
+
root: () =>
|
|
116
|
+
document.querySelector<HTMLElement>(
|
|
117
|
+
'.astryx-bottom-sheet',
|
|
118
|
+
) as HTMLElement,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'MobileNav',
|
|
122
|
+
render: child => (
|
|
123
|
+
<MobileNav isOpen onOpenChange={() => {}} label="N">
|
|
124
|
+
{child}
|
|
125
|
+
</MobileNav>
|
|
126
|
+
),
|
|
127
|
+
root: () => screen.getByRole('dialog'),
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: 'Lightbox',
|
|
131
|
+
render: () => (
|
|
132
|
+
<Lightbox
|
|
133
|
+
isOpen
|
|
134
|
+
onOpenChange={() => {}}
|
|
135
|
+
media={{src: 'a.png', alt: 'a'}}
|
|
136
|
+
/>
|
|
137
|
+
),
|
|
138
|
+
root: () => screen.getByRole('dialog'),
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'Popover (useLayer surface)',
|
|
142
|
+
render: child => (
|
|
143
|
+
<Popover isOpen onOpenChange={() => {}} label="P" content={child}>
|
|
144
|
+
<button type="button">t</button>
|
|
145
|
+
</Popover>
|
|
146
|
+
),
|
|
147
|
+
root: () => document.querySelector<HTMLElement>('[popover]') as HTMLElement,
|
|
148
|
+
},
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
describe('overlayPaddingReset', () => {
|
|
152
|
+
describe.each(OVERLAYS)('$name', ({render: renderOverlay, root}) => {
|
|
153
|
+
it('zeroes the values descendants subtract', () => {
|
|
154
|
+
render(<Section padding={10}>{renderOverlay(<div>c</div>)}</Section>);
|
|
155
|
+
const computed = getComputedStyle(root());
|
|
156
|
+
for (const name of SUBTRACTED) {
|
|
157
|
+
expect(computed.getPropertyValue(name), name).toBe('0px');
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('clears the values descendants add, so they fall to their default', () => {
|
|
162
|
+
render(<Section padding={10}>{renderOverlay(<div>c</div>)}</Section>);
|
|
163
|
+
const computed = getComputedStyle(root());
|
|
164
|
+
for (const name of CLEARED) {
|
|
165
|
+
// A browser resolves `initial` on a custom property to the
|
|
166
|
+
// guaranteed-invalid value and reports '' here; jsdom does not
|
|
167
|
+
// implement that and echoes the keyword. Either proves the
|
|
168
|
+
// declaration landed — and neither is the leaked '40px'.
|
|
169
|
+
expect(CLEARED_READBACK, name).toContain(
|
|
170
|
+
computed.getPropertyValue(name),
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('does not clear the public theme token', () => {
|
|
177
|
+
// The reset clears the PRIVATE propagation var only. The public
|
|
178
|
+
// `--astryx-section-padding` is theme surface, set once at the theme root,
|
|
179
|
+
// so it has to keep reaching inside every overlay — clearing it would
|
|
180
|
+
// blank a theme's section padding in every dialog. That is the whole
|
|
181
|
+
// reason the two names were split, and it is the mistake a later
|
|
182
|
+
// "simplification" would most plausibly make.
|
|
183
|
+
//
|
|
184
|
+
// jsdom does not inherit custom properties, so the cascade cannot show
|
|
185
|
+
// this; assert it where it is decided instead. (Verified in a browser: a
|
|
186
|
+
// theme's 20px still reaches a Section inside a Dialog nested under a
|
|
187
|
+
// 40px page Section.)
|
|
188
|
+
const source = readFileSync(join(__dirname, 'padding.stylex.ts'), 'utf8');
|
|
189
|
+
const reset = source.slice(
|
|
190
|
+
source.indexOf('export const overlayPaddingReset'),
|
|
191
|
+
);
|
|
192
|
+
expect(reset).toContain("'--_section-padding-propagated': 'initial'");
|
|
193
|
+
expect(reset).not.toContain('--astryx-section-padding');
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it("stops an ancestor Section's propagated padding at the boundary", () => {
|
|
197
|
+
// The page Section propagates 40px. Without the reset it would reach the
|
|
198
|
+
// Section inside the overlay, which would pad itself 40px instead of the
|
|
199
|
+
// theme default — the second half of #5208.
|
|
200
|
+
render(
|
|
201
|
+
<Section padding={10}>
|
|
202
|
+
<Dialog isOpen onOpenChange={() => {}}>
|
|
203
|
+
<div data-testid="content">c</div>
|
|
204
|
+
</Dialog>
|
|
205
|
+
</Section>,
|
|
206
|
+
);
|
|
207
|
+
const dialog = screen.getByRole('dialog');
|
|
208
|
+
expect(CLEARED_READBACK).toContain(
|
|
209
|
+
getComputedStyle(dialog).getPropertyValue(
|
|
210
|
+
'--_section-padding-propagated',
|
|
211
|
+
),
|
|
212
|
+
);
|
|
213
|
+
// ...while the page Section outside the overlay still propagates it.
|
|
214
|
+
// (jsdom does not resolve the token reference to its 40px value.)
|
|
215
|
+
const pageSection = document.querySelector<HTMLElement>('.astryx-section');
|
|
216
|
+
expect(
|
|
217
|
+
getComputedStyle(pageSection as HTMLElement).getPropertyValue(
|
|
218
|
+
'--_section-padding-propagated',
|
|
219
|
+
),
|
|
220
|
+
).toBe('var(--spacing-10)');
|
|
221
|
+
});
|
|
222
|
+
});
|
|
@@ -326,21 +326,201 @@ export const paddingBlockStyles = stylex.create({
|
|
|
326
326
|
});
|
|
327
327
|
|
|
328
328
|
/**
|
|
329
|
-
*
|
|
329
|
+
* Inline-start-only padding override styles.
|
|
330
|
+
* Use when a component needs to override the inline-start edge independently
|
|
331
|
+
* of inline-end. Logical, so it follows the writing direction (left in LTR,
|
|
332
|
+
* right in RTL).
|
|
333
|
+
*/
|
|
334
|
+
export const paddingInlineStartStyles = stylex.create({
|
|
335
|
+
0: {paddingInlineStart: spacingVars['--spacing-0']},
|
|
336
|
+
0.5: {paddingInlineStart: spacingVars['--spacing-0-5']},
|
|
337
|
+
1: {paddingInlineStart: spacingVars['--spacing-1']},
|
|
338
|
+
1.5: {paddingInlineStart: spacingVars['--spacing-1-5']},
|
|
339
|
+
2: {paddingInlineStart: spacingVars['--spacing-2']},
|
|
340
|
+
3: {paddingInlineStart: spacingVars['--spacing-3']},
|
|
341
|
+
4: {paddingInlineStart: spacingVars['--spacing-4']},
|
|
342
|
+
5: {paddingInlineStart: spacingVars['--spacing-5']},
|
|
343
|
+
6: {paddingInlineStart: spacingVars['--spacing-6']},
|
|
344
|
+
8: {paddingInlineStart: spacingVars['--spacing-8']},
|
|
345
|
+
10: {paddingInlineStart: spacingVars['--spacing-10']},
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Inline-end-only padding override styles.
|
|
350
|
+
* The inline-end counterpart of paddingInlineStartStyles.
|
|
351
|
+
*/
|
|
352
|
+
export const paddingInlineEndStyles = stylex.create({
|
|
353
|
+
0: {paddingInlineEnd: spacingVars['--spacing-0']},
|
|
354
|
+
0.5: {paddingInlineEnd: spacingVars['--spacing-0-5']},
|
|
355
|
+
1: {paddingInlineEnd: spacingVars['--spacing-1']},
|
|
356
|
+
1.5: {paddingInlineEnd: spacingVars['--spacing-1-5']},
|
|
357
|
+
2: {paddingInlineEnd: spacingVars['--spacing-2']},
|
|
358
|
+
3: {paddingInlineEnd: spacingVars['--spacing-3']},
|
|
359
|
+
4: {paddingInlineEnd: spacingVars['--spacing-4']},
|
|
360
|
+
5: {paddingInlineEnd: spacingVars['--spacing-5']},
|
|
361
|
+
6: {paddingInlineEnd: spacingVars['--spacing-6']},
|
|
362
|
+
8: {paddingInlineEnd: spacingVars['--spacing-8']},
|
|
363
|
+
10: {paddingInlineEnd: spacingVars['--spacing-10']},
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Container padding inline-start CSS variable style, set independently of
|
|
368
|
+
* inline-end so a per-edge override keeps edge-compensating children (Card,
|
|
369
|
+
* Divider, a nested Section) compensating against the padding actually
|
|
370
|
+
* applied on that edge.
|
|
371
|
+
*/
|
|
372
|
+
export const containerPaddingInlineStartVarStyles = stylex.create({
|
|
373
|
+
0: {'--container-padding-inline-start': spacingVars['--spacing-0']},
|
|
374
|
+
0.5: {'--container-padding-inline-start': spacingVars['--spacing-0-5']},
|
|
375
|
+
1: {'--container-padding-inline-start': spacingVars['--spacing-1']},
|
|
376
|
+
1.5: {'--container-padding-inline-start': spacingVars['--spacing-1-5']},
|
|
377
|
+
2: {'--container-padding-inline-start': spacingVars['--spacing-2']},
|
|
378
|
+
3: {'--container-padding-inline-start': spacingVars['--spacing-3']},
|
|
379
|
+
4: {'--container-padding-inline-start': spacingVars['--spacing-4']},
|
|
380
|
+
5: {'--container-padding-inline-start': spacingVars['--spacing-5']},
|
|
381
|
+
6: {'--container-padding-inline-start': spacingVars['--spacing-6']},
|
|
382
|
+
8: {'--container-padding-inline-start': spacingVars['--spacing-8']},
|
|
383
|
+
10: {'--container-padding-inline-start': spacingVars['--spacing-10']},
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Container padding inline-end CSS variable style, the counterpart of
|
|
388
|
+
* containerPaddingInlineStartVarStyles.
|
|
389
|
+
*/
|
|
390
|
+
export const containerPaddingInlineEndVarStyles = stylex.create({
|
|
391
|
+
0: {'--container-padding-inline-end': spacingVars['--spacing-0']},
|
|
392
|
+
0.5: {'--container-padding-inline-end': spacingVars['--spacing-0-5']},
|
|
393
|
+
1: {'--container-padding-inline-end': spacingVars['--spacing-1']},
|
|
394
|
+
1.5: {'--container-padding-inline-end': spacingVars['--spacing-1-5']},
|
|
395
|
+
2: {'--container-padding-inline-end': spacingVars['--spacing-2']},
|
|
396
|
+
3: {'--container-padding-inline-end': spacingVars['--spacing-3']},
|
|
397
|
+
4: {'--container-padding-inline-end': spacingVars['--spacing-4']},
|
|
398
|
+
5: {'--container-padding-inline-end': spacingVars['--spacing-5']},
|
|
399
|
+
6: {'--container-padding-inline-end': spacingVars['--spacing-6']},
|
|
400
|
+
8: {'--container-padding-inline-end': spacingVars['--spacing-8']},
|
|
401
|
+
10: {'--container-padding-inline-end': spacingVars['--spacing-10']},
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Block-start-only padding override styles.
|
|
406
|
+
* Use when a component needs to override the block-start (top) edge
|
|
407
|
+
* independently of block-end — e.g. a section that sits under a sticky
|
|
408
|
+
* header and needs less padding above than below.
|
|
409
|
+
*/
|
|
410
|
+
export const paddingBlockStartStyles = stylex.create({
|
|
411
|
+
0: {paddingBlockStart: spacingVars['--spacing-0']},
|
|
412
|
+
0.5: {paddingBlockStart: spacingVars['--spacing-0-5']},
|
|
413
|
+
1: {paddingBlockStart: spacingVars['--spacing-1']},
|
|
414
|
+
1.5: {paddingBlockStart: spacingVars['--spacing-1-5']},
|
|
415
|
+
2: {paddingBlockStart: spacingVars['--spacing-2']},
|
|
416
|
+
3: {paddingBlockStart: spacingVars['--spacing-3']},
|
|
417
|
+
4: {paddingBlockStart: spacingVars['--spacing-4']},
|
|
418
|
+
5: {paddingBlockStart: spacingVars['--spacing-5']},
|
|
419
|
+
6: {paddingBlockStart: spacingVars['--spacing-6']},
|
|
420
|
+
8: {paddingBlockStart: spacingVars['--spacing-8']},
|
|
421
|
+
10: {paddingBlockStart: spacingVars['--spacing-10']},
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Block-end-only padding override styles.
|
|
426
|
+
* The block-end counterpart of paddingBlockStartStyles.
|
|
427
|
+
*/
|
|
428
|
+
export const paddingBlockEndStyles = stylex.create({
|
|
429
|
+
0: {paddingBlockEnd: spacingVars['--spacing-0']},
|
|
430
|
+
0.5: {paddingBlockEnd: spacingVars['--spacing-0-5']},
|
|
431
|
+
1: {paddingBlockEnd: spacingVars['--spacing-1']},
|
|
432
|
+
1.5: {paddingBlockEnd: spacingVars['--spacing-1-5']},
|
|
433
|
+
2: {paddingBlockEnd: spacingVars['--spacing-2']},
|
|
434
|
+
3: {paddingBlockEnd: spacingVars['--spacing-3']},
|
|
435
|
+
4: {paddingBlockEnd: spacingVars['--spacing-4']},
|
|
436
|
+
5: {paddingBlockEnd: spacingVars['--spacing-5']},
|
|
437
|
+
6: {paddingBlockEnd: spacingVars['--spacing-6']},
|
|
438
|
+
8: {paddingBlockEnd: spacingVars['--spacing-8']},
|
|
439
|
+
10: {paddingBlockEnd: spacingVars['--spacing-10']},
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Propagation styles for `--_section-padding-propagated`.
|
|
330
444
|
* When a parent section sets explicit padding, this propagates the value
|
|
331
445
|
* through the CSS custom property cascade so nested sections that use
|
|
332
446
|
* useThemeDefault inherit the parent's padding instead of the theme default.
|
|
447
|
+
*
|
|
448
|
+
* This is deliberately NOT the public `--astryx-section-padding` token. The
|
|
449
|
+
* two carry different authority: the public token is the THEME's section
|
|
450
|
+
* padding, set once at the theme root, while this one is one ancestor
|
|
451
|
+
* Section's padding, propagated down the tree. An overlay has to drop the
|
|
452
|
+
* inherited value at its boundary (see {@link overlayPaddingReset}) without
|
|
453
|
+
* dropping the theme's — impossible while both live under one name.
|
|
454
|
+
* `container.stylex.ts` reads this ahead of the public token, so a propagated
|
|
455
|
+
* value still wins over the theme for nested sections, as before.
|
|
333
456
|
*/
|
|
334
457
|
export const sectionPaddingPropagationStyles = stylex.create({
|
|
335
|
-
0: {'--
|
|
336
|
-
0.5: {'--
|
|
337
|
-
1: {'--
|
|
338
|
-
1.5: {'--
|
|
339
|
-
2: {'--
|
|
340
|
-
3: {'--
|
|
341
|
-
4: {'--
|
|
342
|
-
5: {'--
|
|
343
|
-
6: {'--
|
|
344
|
-
8: {'--
|
|
345
|
-
10: {'--
|
|
458
|
+
0: {'--_section-padding-propagated': spacingVars['--spacing-0']},
|
|
459
|
+
0.5: {'--_section-padding-propagated': spacingVars['--spacing-0-5']},
|
|
460
|
+
1: {'--_section-padding-propagated': spacingVars['--spacing-1']},
|
|
461
|
+
1.5: {'--_section-padding-propagated': spacingVars['--spacing-1-5']},
|
|
462
|
+
2: {'--_section-padding-propagated': spacingVars['--spacing-2']},
|
|
463
|
+
3: {'--_section-padding-propagated': spacingVars['--spacing-3']},
|
|
464
|
+
4: {'--_section-padding-propagated': spacingVars['--spacing-4']},
|
|
465
|
+
5: {'--_section-padding-propagated': spacingVars['--spacing-5']},
|
|
466
|
+
6: {'--_section-padding-propagated': spacingVars['--spacing-6']},
|
|
467
|
+
8: {'--_section-padding-propagated': spacingVars['--spacing-8']},
|
|
468
|
+
10: {'--_section-padding-propagated': spacingVars['--spacing-10']},
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Padding-variable reset for overlay roots (Dialog, BottomSheet, Drawer,
|
|
473
|
+
* MobileNav, Lightbox, and every layer surface).
|
|
474
|
+
*
|
|
475
|
+
* ## Why an overlay needs this
|
|
476
|
+
*
|
|
477
|
+
* The container padding system talks to descendants through inherited custom
|
|
478
|
+
* properties: a padded container announces its padding, and children read the
|
|
479
|
+
* value either to apply it or to cancel it with a negative margin
|
|
480
|
+
* (`Section`, `Divider`, `Layout`, `Table`).
|
|
481
|
+
*
|
|
482
|
+
* Inheritance follows the DOM, but an overlay leaves its parent's visual box —
|
|
483
|
+
* a fixed/top-layer `<dialog>` is a DOM descendant of the padded page while
|
|
484
|
+
* being nowhere near it on screen. It inherits values describing padding that
|
|
485
|
+
* is not there, and its content compensates against phantom space: a `Section`
|
|
486
|
+
* inside a 640px sheet rendered 672px wide and hung off both edges (#5208).
|
|
487
|
+
*
|
|
488
|
+
* Two families leak, and they need opposite treatments:
|
|
489
|
+
*
|
|
490
|
+
* - `--container-padding-*` -> `0px`. Descendants SUBTRACT these (bleed
|
|
491
|
+
* margins). The overlay root has no padding of its own to escape, so the
|
|
492
|
+
* honest answer is zero. Nested containers that do set padding (a Dialog's
|
|
493
|
+
* content wrapper) re-announce their own values below this point, so
|
|
494
|
+
* legitimate edge-to-edge bleed inside the overlay is unaffected.
|
|
495
|
+
* - `--layout-padding-*` and `--_section-padding-propagated` -> `initial`.
|
|
496
|
+
* Descendants ADD these, so zeroing them would strip padding rather than
|
|
497
|
+
* restore it. `initial` makes each guaranteed-invalid, so readers fall
|
|
498
|
+
* through their own `var(…, fallback)` chain and land on the theme default —
|
|
499
|
+
* which is what an overlay at the top of the tree should show.
|
|
500
|
+
*
|
|
501
|
+
* `initial` is also why propagation moved off `--astryx-section-padding`: that
|
|
502
|
+
* name is public theme surface, set at the theme root, and making it invalid
|
|
503
|
+
* here would blank the theme's own section padding inside every overlay.
|
|
504
|
+
*
|
|
505
|
+
* Apply on the overlay's outermost styled element.
|
|
506
|
+
*
|
|
507
|
+
* @example
|
|
508
|
+
* ```
|
|
509
|
+
* <dialog {...stylex.props(styles.dialog, overlayPaddingReset.reset)} />
|
|
510
|
+
* ```
|
|
511
|
+
*/
|
|
512
|
+
export const overlayPaddingReset = stylex.create({
|
|
513
|
+
reset: {
|
|
514
|
+
// Subtracted by descendants — the overlay root has no padding to escape.
|
|
515
|
+
'--container-padding-inline-start': '0px',
|
|
516
|
+
'--container-padding-inline-end': '0px',
|
|
517
|
+
'--container-padding-block-start': '0px',
|
|
518
|
+
'--container-padding-block-end': '0px',
|
|
519
|
+
// Added by descendants — fall through to each reader's own default.
|
|
520
|
+
'--layout-padding-outer-x': 'initial',
|
|
521
|
+
'--layout-padding-outer-y': 'initial',
|
|
522
|
+
'--layout-padding-inner-x': 'initial',
|
|
523
|
+
'--layout-padding-inner-y': 'initial',
|
|
524
|
+
'--_section-padding-propagated': 'initial',
|
|
525
|
+
},
|
|
346
526
|
});
|
|
@@ -36,6 +36,7 @@ import {mergeProps, mergeRefs, rtlStyles} from '../utils';
|
|
|
36
36
|
import type {BaseProps} from '../BaseProps';
|
|
37
37
|
import {themeProps} from '../utils/themeProps';
|
|
38
38
|
import {focusOutlineStyles} from '../utils/focusOutline.stylex';
|
|
39
|
+
import {overlayPaddingReset} from '../Layout/padding.stylex';
|
|
39
40
|
import {useTranslator} from '../i18n';
|
|
40
41
|
|
|
41
42
|
/**
|
|
@@ -588,7 +589,7 @@ export function Lightbox({
|
|
|
588
589
|
aria-label={currentItem.alt || t('@astryx.lightbox.mediaViewer')}
|
|
589
590
|
{...mergeProps(
|
|
590
591
|
themeProps('lightbox'),
|
|
591
|
-
stylex.props(styles.dialog, xstyle),
|
|
592
|
+
stylex.props(styles.dialog, overlayPaddingReset.reset, xstyle),
|
|
592
593
|
className,
|
|
593
594
|
style,
|
|
594
595
|
)}
|