@sableui/react 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +189 -0
  3. package/CONTRIBUTING.md +1 -1
  4. package/THIRD_PARTY_NOTICES.md +11 -0
  5. package/bin/sable-lint.mjs +2 -1
  6. package/bin/sable.mjs +3 -2
  7. package/dist/{_contract-Cn3lUpih.d.ts → _contract-C2M1SjBf.d.ts} +20 -2
  8. package/dist/blocks/index.js +21 -53
  9. package/dist/{chunk-CCUDFLU3.js → chunk-7QSDYBXO.js} +652 -38
  10. package/dist/{chunk-FBSL2LZQ.js → chunk-EDXLM7YL.js} +11 -30
  11. package/dist/chunk-FKZXAFIY.js +12 -0
  12. package/dist/{chunk-OQACYT2D.js → chunk-NETUFI34.js} +23 -1
  13. package/dist/{chunk-NGBDP3BM.js → chunk-QJ6FWTUG.js} +1 -1
  14. package/dist/{chunk-D2ETQBHV.js → chunk-VVW4UCDI.js} +5 -5
  15. package/dist/{chunk-TH563WLW.js → chunk-XAZGMY73.js} +10 -3
  16. package/dist/foundations/index.js +6 -0
  17. package/dist/icon/index.js +2 -2
  18. package/dist/icon-sets/brands.d.ts +0 -27
  19. package/dist/icon-sets/brands.js +7 -1
  20. package/dist/icon-sets/reicon.js +1 -1
  21. package/dist/index.d.ts +164 -23
  22. package/dist/index.js +116 -29
  23. package/dist/ios/index.d.ts +6 -1
  24. package/dist/ios/index.js +4 -3
  25. package/dist/ios/styles.css +9 -0
  26. package/dist/patterns/index.js +24 -30
  27. package/dist/presets/index.d.ts +108 -5
  28. package/dist/presets/index.js +239 -6
  29. package/dist/styles.css +57 -0
  30. package/dist/{theme-provider-CGeiusgu.d.ts → theme-provider-kQszHYji.d.ts} +1 -1
  31. package/dist/themes/atelier/atelier.css +31 -3
  32. package/dist/themes/atelier/index.d.ts +1 -1
  33. package/dist/themes/ember/ember.css +38 -7
  34. package/dist/themes/ember/index.d.ts +1 -1
  35. package/dist/themes/index.d.ts +2 -2
  36. package/dist/themes/meridian/index.d.ts +1 -1
  37. package/dist/themes/meridian/meridian.css +33 -4
  38. package/dist/themes/poppy/index.d.ts +1 -1
  39. package/dist/themes/poppy/poppy.css +28 -0
  40. package/dist/themes/prism/index.d.ts +1 -1
  41. package/dist/themes/prism/prism.css +26 -0
  42. package/dist/themes/sable/index.d.ts +1 -1
  43. package/dist/themes/sable/sable.css +24 -11
  44. package/dist/themes/verdant/index.d.ts +1 -1
  45. package/dist/themes/verdant/verdant.css +34 -4
  46. package/llms/blocks/danger-zone-block.md +1 -1
  47. package/llms/blocks/event-card-block.md +1 -1
  48. package/llms/blocks/feedback-form-block.md +1 -1
  49. package/llms/blocks/invite-team-block.md +1 -1
  50. package/llms/blocks/media-player-block.md +3 -16
  51. package/llms/blocks/notification-list-block.md +3 -3
  52. package/llms/blocks/product-card-block.md +3 -17
  53. package/llms/blocks/profile-card-block.md +4 -17
  54. package/llms/blocks/profile-form-block.md +2 -2
  55. package/llms/blocks/team-members-block.md +1 -1
  56. package/llms/blocks/testimonial-block.md +1 -1
  57. package/llms/components/avatar.md +13 -1
  58. package/llms/components/card.md +1 -1
  59. package/llms/components/gradient-art.md +80 -0
  60. package/llms/components/sheet.md +1 -1
  61. package/llms/components/tabs.md +1 -1
  62. package/llms/components/toast.md +12 -1
  63. package/llms/foundations/accessibility.md +1 -0
  64. package/llms/patterns/auth-page.md +5 -19
  65. package/llms/patterns/brand-landing-page.md +1 -1
  66. package/llms/patterns/chat-panel.md +1 -1
  67. package/llms/patterns/dashboard-page.md +4 -4
  68. package/llms/patterns/feed-page.md +4 -4
  69. package/llms/patterns/landing-page.md +1 -1
  70. package/llms/patterns/list-detail-page.md +3 -2
  71. package/llms/patterns/settings-page.md +3 -3
  72. package/llms/reference/token-intent.md +9 -1
  73. package/llms/tasks/auditing-an-app.md +6 -0
  74. package/llms/tasks/building-an-ios-prototype.md +3 -1
  75. package/llms/tasks/converting-an-app.md +1 -1
  76. package/llms/tasks/creating-a-preset.md +24 -0
  77. package/llms/tasks/reviewing-a-design.md +9 -0
  78. package/llms/tasks/using-presets.md +6 -1
  79. package/llms-full.txt +214 -106
  80. package/llms.txt +4 -3
  81. package/package.json +9 -7
  82. package/registry.json +310 -32
  83. package/scripts/design-presets.mjs +27 -4
  84. package/scripts/grade.mjs +2 -1
  85. package/scripts/label-contrast.mjs +138 -0
  86. package/scripts/lint-rules.mjs +23 -2
  87. package/skills/sable/SKILL.md +3 -1
  88. package/targets/ios.json +18 -2
  89. package/third-party/paper-shaders-LICENSE.txt +201 -0
  90. package/third-party/paper-shaders-NOTICE.txt +5 -0
package/dist/index.js CHANGED
@@ -1,17 +1,19 @@
1
- export { DENSITY_TOKENS, MOTION_TOKENS, RADIUS_TOKENS, SEMANTIC_TOKENS, TYPE_OVERLINE_TOKENS, TYPE_REFINEMENT_TOKENS, TYPE_SCALE_TOKENS, TYPE_UI_TOKENS, WORKSPACE_SURFACE_TOKENS } from './chunk-OQACYT2D.js';
1
+ export { ART_TOKENS, DENSITY_TOKENS, MOTION_TOKENS, RADIUS_TOKENS, SEMANTIC_TOKENS, TYPE_OVERLINE_TOKENS, TYPE_REFINEMENT_TOKENS, TYPE_SCALE_TOKENS, TYPE_UI_TOKENS, WORKSPACE_SURFACE_TOKENS } from './chunk-NETUFI34.js';
2
2
  export { Phone, phoneMeta } from './chunk-KFZ43RKU.js';
3
3
  import './chunk-NEQNXI2G.js';
4
- export { AppHeader, AppShell, BottomNav, BottomNavItem, Browser, ChatComposer, DataTable, EmptyState, Marker, MessageScroller, Meter, MeterIndicator, MeterLabel, MeterTrack, MeterValue, NotificationBadge, PageHeader, Presence, RelativeTime, Reveal, SearchInput, SettingsMenu, SettingsRow, SideNav, SideNavGroup, SideNavItem, Sidebar, SidebarFooter, SidebarHeader, SidebarItem, SidebarNav, Skeleton, StreamingText, Tabs, TabsPanel as TabsContent, TabsList, TabsPanel, TabsTrigger, TextReveal, Toolbar, ToolbarButton, ToolbarGroup, ToolbarInput, ToolbarLink, ToolbarSeparator, ViewTransitionName, appHeaderMeta, appShellMeta, bottomNavMeta, browserMeta, chatComposerMeta, dataTableMeta, emptyStateMeta, markerMeta, messageScrollerMeta, meterIndicatorVariants, meterMeta, meterTrackVariants, notificationBadgeMeta, notificationCountVariants, notificationDotVariants, pageHeaderMeta, relativeTimeMeta, searchInputMeta, settingsMenuMeta, sideNavMeta, sidebarMeta, skeletonMeta, startViewTransition, streamingTextMeta, supportsViewTransitions, tabsMeta, toolbarGroupVariants, toolbarMeta, toolbarSeparatorVariants, toolbarVariants, useInView, useSidebar } from './chunk-D2ETQBHV.js';
5
- import { SELECTION_CARD_CHECKED, CartesianChart, resolveSeries, chartFormatters, categoryText, numberValue, niceTicks, ChartFrame, polar, riseTransition, stagger, pathStyle, morphTransition, ChartLegend, RADIO_DOT, RADIO_RING, SELECTION_CARD_TILE_HEAD, SELECTION_CARD_GLYPH, SELECTION_CARD_SHELL, SELECTION_CARD_LAYOUT, CheckboxMark, CHECK_BOX, SEGMENTED_STEP, SEGMENTED_ITEM, SEGMENTED_TRACK, ToggleGroup, Toggle, approxTextWidth, ChartTooltipContent } from './chunk-FBSL2LZQ.js';
6
- export { Accordion, AccordionItem, AccordionPanel, AccordionTrigger, AreaChart, BarChart, CHART_SERIES_COUNT, Checkbox, CommandMenu, CommandMenuGroup, CommandMenuItem, CommandMenuPanel, CommandMenuTrigger, DateTile, Kbd, KbdGroup, OtpField, PieChart, RadialChart, SEGMENTED_BAR_TONES, Scroller, SegmentedBar, Slider, SliderControl, SliderIndicator, SliderRoot, SliderThumb, SliderTrack, SliderValue, Sparkline, Stepper, StepperItem, Toggle, ToggleGroup, Toggle as ToggleGroupItem, accordionMeta, areaChartMeta, barChartMeta, chartColor, toneColor as chartToneColor, checkboxMeta, commandMenuMeta, dateTileMeta, kbdMeta, otpFieldMeta, pieChartMeta, radialChartMeta, segmentedBarMeta, segmentedBarSegmentVariants, segmentedBarVariants, sliderMeta, sparklineMeta, stepperConnectorVariants, stepperIndicatorVariants, stepperMeta, toggleMeta, useCommandMenuShortcut } from './chunk-FBSL2LZQ.js';
7
- import { withPortalThemeScope, FIELD_SHELL_XS, useTypeTier, useDensity, FIELD_SHELL, MOBILE_FIELD_TIER, useMotion, HighlightGlide, useAnchoredDensity, anchoredScroll, useIsomorphicLayoutEffect, mergeRefs, buttonVariants, FIELD_INVALID, Select, SelectTrigger, SelectContent, SelectItem, Button, Spinner, Badge, anchoredListScroll, useResizeObserver, MENU_ITEM_DESTRUCTIVE, DensityProvider, Input, Textarea, Progress } from './chunk-CCUDFLU3.js';
8
- export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogTitle, AlertDialogTrigger, Attachment, Avatar, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, AvatarRoot, BADGE_APPEARANCES, BADGE_TONES, Badge, Bubble, BubbleReaction, BubbleReactions, Button, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardList, CardTitle, Code, CodeBlock, CodeHighlightProvider, Density, DensityProvider, DestructiveActionModal, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Entity, Field, Form, Input, Label, Menu, MenuCheckboxItem, MenuContent, MenuGroup, MenuGroupLabel, MenuItem, MenuPortal, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuSubmenu, MenuSubmenuTrigger, MenuTrigger, Message, MotionProvider, OverflowMenu, Pill, Progress, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue, Select, SelectContent, SelectGroup, SelectGroupLabel, SelectItem, SelectPortal, SelectSeparator, SelectTrigger, SelectValue, Separator, SimpleTooltip, Spinner, StatusDot, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Textarea, Tooltip, TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipTrigger, attachmentMeta, avatarGroupVariants, avatarMeta, avatarVariants, badgeMeta, badgeVariants, bubbleMeta, buttonMeta, buttonVariants, cardMeta, codeBlockMeta, codeMeta, destructiveActionModalMeta, dialogMeta, entityMeta, formMeta, inputMeta, labelMeta, menuMeta, messageMeta, overflowMenuMeta, pillVariants, progressMeta, progressTrackVariants, selectMeta, separatorMeta, spinnerMeta, statusDotMeta, statusDotVariants, switchMeta, tableMeta, textareaMeta, tooltipMeta, useAnchoredDensity, useCopy, useDensity, useMotion, useReducedMotion, useScrollActivity, useTypeTier } from './chunk-CCUDFLU3.js';
4
+ export { AppHeader, AppShell, BottomNav, BottomNavItem, Browser, ChatComposer, DataTable, EmptyState, Marker, MessageScroller, Meter, MeterIndicator, MeterLabel, MeterTrack, MeterValue, NotificationBadge, PageHeader, Presence, RelativeTime, Reveal, SearchInput, SettingsMenu, SettingsRow, SideNav, SideNavGroup, SideNavItem, Sidebar, SidebarFooter, SidebarHeader, SidebarItem, SidebarNav, Skeleton, StreamingText, Tabs, TabsPanel as TabsContent, TabsList, TabsPanel, TabsTrigger, TextReveal, Toolbar, ToolbarButton, ToolbarGroup, ToolbarInput, ToolbarLink, ToolbarSeparator, ViewTransitionName, appHeaderMeta, appShellMeta, bottomNavMeta, browserMeta, chatComposerMeta, dataTableMeta, emptyStateMeta, markerMeta, messageScrollerMeta, meterIndicatorVariants, meterMeta, meterTrackVariants, notificationBadgeMeta, notificationCountVariants, notificationDotVariants, pageHeaderMeta, relativeTimeMeta, searchInputMeta, settingsMenuMeta, sideNavMeta, sidebarMeta, skeletonMeta, startViewTransition, streamingTextMeta, supportsViewTransitions, tabsMeta, toolbarGroupVariants, toolbarMeta, toolbarSeparatorVariants, toolbarVariants, useInView, useSidebar } from './chunk-VVW4UCDI.js';
5
+ import { SELECTION_CARD_CHECKED, CartesianChart, resolveSeries, chartFormatters, categoryText, numberValue, niceTicks, ChartFrame, polar, riseTransition, stagger, pathStyle, morphTransition, ChartLegend, RADIO_DOT, RADIO_RING, SELECTION_CARD_TILE_HEAD, SELECTION_CARD_GLYPH, SELECTION_CARD_SHELL, SELECTION_CARD_LAYOUT, CheckboxMark, CHECK_BOX, SEGMENTED_STEP, SEGMENTED_ITEM, SEGMENTED_TRACK, ToggleGroup, Toggle, approxTextWidth, ChartTooltipContent } from './chunk-EDXLM7YL.js';
6
+ export { Accordion, AccordionItem, AccordionPanel, AccordionTrigger, AreaChart, BarChart, CHART_SERIES_COUNT, Checkbox, CommandMenu, CommandMenuGroup, CommandMenuItem, CommandMenuPanel, CommandMenuTrigger, DateTile, Kbd, KbdGroup, OtpField, PieChart, RadialChart, SEGMENTED_BAR_TONES, Scroller, SegmentedBar, Slider, SliderControl, SliderIndicator, SliderRoot, SliderThumb, SliderTrack, SliderValue, Sparkline, Stepper, StepperItem, Toggle, ToggleGroup, Toggle as ToggleGroupItem, accordionMeta, areaChartMeta, barChartMeta, chartColor, toneColor as chartToneColor, checkboxMeta, commandMenuMeta, dateTileMeta, kbdMeta, otpFieldMeta, pieChartMeta, radialChartMeta, segmentedBarMeta, segmentedBarSegmentVariants, segmentedBarVariants, sliderMeta, sparklineMeta, stepperConnectorVariants, stepperIndicatorVariants, stepperMeta, toggleMeta, useCommandMenuShortcut } from './chunk-EDXLM7YL.js';
7
+ import { withPortalThemeScope, FIELD_SHELL_XS, useTypeTier, useDensity, FIELD_SHELL, MOBILE_FIELD_TIER, useMotion, HighlightGlide, useAnchoredDensity, anchoredScroll, useIsomorphicLayoutEffect, mergeRefs, buttonVariants, FIELD_INVALID, Select, SelectTrigger, SelectContent, SelectItem, Button, Spinner, Badge, anchoredListScroll, useResizeObserver, MENU_ITEM_DESTRUCTIVE, DensityProvider, Input, Textarea, Progress } from './chunk-7QSDYBXO.js';
8
+ export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogTitle, AlertDialogTrigger, Attachment, Avatar, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, AvatarRoot, BADGE_APPEARANCES, BADGE_TONES, Badge, Bubble, BubbleReaction, BubbleReactions, Button, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardList, CardTitle, Code, CodeBlock, CodeHighlightProvider, Density, DensityProvider, DestructiveActionModal, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Entity, Field, Form, GradientArt, Input, Label, Menu, MenuCheckboxItem, MenuContent, MenuGroup, MenuGroupLabel, MenuItem, MenuPortal, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuSubmenu, MenuSubmenuTrigger, MenuTrigger, Message, MotionProvider, OverflowMenu, Pill, Progress, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue, Select, SelectContent, SelectGroup, SelectGroupLabel, SelectItem, SelectPortal, SelectSeparator, SelectTrigger, SelectValue, Separator, SimpleTooltip, Spinner, StatusDot, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Textarea, Tooltip, TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipTrigger, attachmentMeta, avatarGroupVariants, avatarMeta, avatarVariants, badgeMeta, badgeVariants, bubbleMeta, buttonMeta, buttonVariants, cardMeta, codeBlockMeta, codeMeta, destructiveActionModalMeta, dialogMeta, entityMeta, formMeta, gradientArtMeta, inputMeta, labelMeta, menuMeta, messageMeta, overflowMenuMeta, pillVariants, progressMeta, progressTrackVariants, selectMeta, separatorMeta, spinnerMeta, statusDotMeta, statusDotVariants, switchMeta, tableMeta, textareaMeta, tooltipMeta, useAnchoredDensity, useCopy, useDensity, useMotion, useReducedMotion, useScrollActivity, useTypeTier } from './chunk-7QSDYBXO.js';
9
+ import { PresentationProvider, usePresentation, StackedActionsContext } from './chunk-FKZXAFIY.js';
10
+ export { PresentationProvider, usePresentation } from './chunk-FKZXAFIY.js';
9
11
  export { AspectBox, Bleed, Center, Col, Columns, Grid, GridOverlay, Page, Region, Row, SafeArea, Spacer, SplitPane, Stack } from './chunk-3IWZYBGH.js';
10
12
  import { cn } from './chunk-SRQWQUTW.js';
11
13
  export { cn } from './chunk-SRQWQUTW.js';
12
- import { Icon } from './chunk-NGBDP3BM.js';
13
- export { Icon, IconProvider, composeIconSets, useIconSet } from './chunk-NGBDP3BM.js';
14
- export { reiconIconSet as fallbackIconSet, reiconIconNames, reiconIconSet } from './chunk-TH563WLW.js';
14
+ import { Icon } from './chunk-QJ6FWTUG.js';
15
+ export { Icon, IconProvider, composeIconSets, useIconSet } from './chunk-QJ6FWTUG.js';
16
+ export { reiconIconSet as fallbackIconSet, reiconIconNames, reiconIconSet } from './chunk-XAZGMY73.js';
15
17
  import { featuredThemeManifests, defaultThemeId } from './chunk-EFLC4NA3.js';
16
18
  export { DEFAULT_THEME_ID, SABLE_COLOR_STORAGE_KEY, SABLE_THEME_ATTRIBUTE, SABLE_THEME_STORAGE_KEY, SableThemeProvider, applySableColorMode, applySableTheme, defaultThemeId, getThemeManifest, isThemeId, themeIds, themeManifestById, themeManifests, useSableTheme } from './chunk-EFLC4NA3.js';
17
19
  import './chunk-7MG4SHYX.js';
@@ -429,6 +431,7 @@ var COMPONENT_TAXONOMY = {
429
431
  a player, and it sits with the other media now. */
430
432
  Browser: ["Media & mockups", "page"],
431
433
  Carousel: ["Media & mockups", "page"],
434
+ GradientArt: ["Media & mockups", "either"],
432
435
  Marquee: ["Media & mockups", "page"],
433
436
  Phone: ["Media & mockups", "page"],
434
437
  Video: ["Media & mockups", "page"]
@@ -2427,7 +2430,7 @@ function PopoverContent({
2427
2430
  className
2428
2431
  ),
2429
2432
  ...props,
2430
- children
2433
+ children: /* @__PURE__ */ jsx(PresentationProvider, { value: "page", children })
2431
2434
  }
2432
2435
  )
2433
2436
  }
@@ -2660,7 +2663,7 @@ function SheetContent({
2660
2663
  initialFocus: initialFocus === void 0 ? (type) => type === "touch" ? popupRef.current : true : initialFocus,
2661
2664
  className: cn(sheetVariants({ side }), className),
2662
2665
  ...props,
2663
- children: /* @__PURE__ */ jsx(Drawer.Content, { className: "contents", children })
2666
+ children: /* @__PURE__ */ jsx(Drawer.Content, { className: "contents", children: /* @__PURE__ */ jsx(PresentationProvider, { value: resolvedSide === "bottom" ? "sheet" : "page", children }) })
2664
2667
  }
2665
2668
  ) })
2666
2669
  ] });
@@ -2686,12 +2689,19 @@ function SheetDescription({ className, ...props }) {
2686
2689
  function SheetHeader({ className, ...props }) {
2687
2690
  return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-1.5", className), ...props });
2688
2691
  }
2689
- function SheetFooter({ className, ...props }) {
2692
+ function SheetFooter({ className, children, ...props }) {
2693
+ const stacked = usePresentation() === "sheet";
2690
2694
  return /* @__PURE__ */ jsx(
2691
2695
  "div",
2692
2696
  {
2693
- className: cn("mt-auto flex items-center justify-end gap-2", className),
2694
- ...props
2697
+ "data-actions": stacked ? "stack" : "row",
2698
+ className: cn(
2699
+ "mt-auto flex items-center justify-end gap-2",
2700
+ className,
2701
+ stacked && "w-full max-w-sm flex-col-reverse items-stretch justify-start self-center"
2702
+ ),
2703
+ ...props,
2704
+ children: stacked ? /* @__PURE__ */ jsx(StackedActionsContext.Provider, { value: true, children }) : children
2695
2705
  }
2696
2706
  );
2697
2707
  }
@@ -2814,7 +2824,7 @@ var sheetMeta = {
2814
2824
  {
2815
2825
  name: "SheetFooter",
2816
2826
  type: 'ComponentProps<"div">',
2817
- description: "Bottom row for actions, pinned after the scrollable body."
2827
+ description: "Bottom row for actions, pinned after the scrollable body. In a bottom sheet it stacks: full width, the primary on top, every button at the cta height."
2818
2828
  }
2819
2829
  ],
2820
2830
  variants: {
@@ -3512,7 +3522,43 @@ var ENTER_MOTION = {
3512
3522
  "bottom-center": "motion-slide-up",
3513
3523
  "bottom-right": "motion-slide-left"
3514
3524
  };
3515
- var ToastPositionContext = createContext("top-right");
3525
+ var STACKED_ROOT = [
3526
+ // design-lint-disable-next-line raw-z-index -- orders the cards inside the viewport's own stacking context (it is fixed at z-(--z-toast)); not a page layer
3527
+ "absolute inset-x-0 z-[calc(100-var(--toast-index))] select-none",
3528
+ "[--toast-gap:--spacing(2)] [--toast-peek:--spacing(3)]",
3529
+ "[--toast-scale:max(0,1-var(--toast-index)*0.05)]",
3530
+ "[--toast-h:var(--toast-frontmost-height,var(--toast-height))]",
3531
+ "h-(--toast-h) data-expanded:h-(--toast-height)",
3532
+ // Collapsed: shrink about the anchored edge, then lift a peek per card.
3533
+ "[transform:translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)+var(--toast-dir)*(var(--toast-index)*var(--toast-peek)+(1-var(--toast-scale))*var(--toast-h))))_scale(var(--toast-scale))]",
3534
+ // Fanned out: Base UI's offset is the heights in front of it; add the gaps.
3535
+ "data-expanded:[transform:translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)+var(--toast-dir)*(var(--toast-offset-y)+var(--toast-index)*var(--toast-gap))))]",
3536
+ // Arrive from the anchored edge and leave the same way, unless swiped or
3537
+ // pushed out by the limit, which only fade.
3538
+ "data-starting-style:[translate:0_calc(var(--toast-dir)*-100%)] data-starting-style:opacity-0",
3539
+ "[&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[translate:0_calc(var(--toast-dir)*-100%)]",
3540
+ "data-ending-style:opacity-0 data-limited:opacity-0",
3541
+ // Fanned out, bridges the gap to the next card, so the pointer stays on the
3542
+ // stack and the list does not collapse under it.
3543
+ "after:absolute after:inset-x-0 after:h-[calc(var(--toast-gap)+1px)] not-data-expanded:after:hidden",
3544
+ // Collapsed, the deck lifts as one: cards resting on each other barely shade
3545
+ // each other. A full shadow on every card stacked a slab per card, and a
3546
+ // theme with hard offset shadows (Poppy's reach 12px, past the 12px peek)
3547
+ // painted the front card's slab over the cards behind it. So the front card
3548
+ // steps down to shadow-md and the cards behind to shadow-sm; fanned out,
3549
+ // each is a toast again and takes the full step back.
3550
+ "not-data-expanded:shadow-md not-data-expanded:has-[>[data-behind]]:shadow-sm",
3551
+ "transition-[transform,translate,opacity,height,box-shadow] duration-(--motion-duration-slow) ease-emphasized"
3552
+ ].join(" ");
3553
+ var STACKED_EDGE = {
3554
+ top: "top-0 origin-top [--toast-dir:1] after:top-full",
3555
+ bottom: "bottom-0 origin-bottom [--toast-dir:-1] after:bottom-full"
3556
+ };
3557
+ var edgeOf = (position) => position.startsWith("top") ? "top" : "bottom";
3558
+ var ToastViewportContext = createContext({
3559
+ position: "top-right",
3560
+ stacked: false
3561
+ });
3516
3562
  function persistsByDefault(type, options) {
3517
3563
  return type === "loading" || type === "error" || options?.actionProps !== void 0;
3518
3564
  }
@@ -3548,13 +3594,16 @@ var ToastPortal = withPortalThemeScope(Toast.Portal);
3548
3594
  function ToastViewport({
3549
3595
  className,
3550
3596
  position = "top-right",
3597
+ stacked = false,
3551
3598
  ...props
3552
3599
  }) {
3553
- return /* @__PURE__ */ jsx(ToastPositionContext.Provider, { value: position, children: /* @__PURE__ */ jsx(ToastPortal, { children: /* @__PURE__ */ jsx(
3600
+ return /* @__PURE__ */ jsx(ToastViewportContext.Provider, { value: { position, stacked }, children: /* @__PURE__ */ jsx(ToastPortal, { children: /* @__PURE__ */ jsx(
3554
3601
  Toast.Viewport,
3555
3602
  {
3556
3603
  className: cn(
3557
- "fixed z-(--z-toast) flex w-95 max-w-[90vw] flex-col gap-2 outline-none",
3604
+ "fixed z-(--z-toast) w-95 max-w-[90vw] outline-none",
3605
+ // Stacked toasts are positioned against the viewport, not laid out in it.
3606
+ !stacked && "flex flex-col gap-2",
3558
3607
  POSITION[position],
3559
3608
  className
3560
3609
  ),
@@ -3563,13 +3612,27 @@ function ToastViewport({
3563
3612
  ) }) });
3564
3613
  }
3565
3614
  function ToastRoot({ className, ...props }) {
3566
- const position = useContext(ToastPositionContext);
3615
+ const { position, stacked } = useContext(ToastViewportContext);
3567
3616
  return /* @__PURE__ */ jsx(
3568
3617
  Toast.Root,
3569
3618
  {
3570
3619
  className: cn(
3571
3620
  "flex w-full gap-3 rounded-md border border-border-floating bg-popover p-4 text-popover-foreground shadow-xl",
3572
- ENTER_MOTION[position],
3621
+ stacked ? [STACKED_ROOT, STACKED_EDGE[edgeOf(position)]] : ENTER_MOTION[position],
3622
+ className
3623
+ ),
3624
+ ...props
3625
+ }
3626
+ );
3627
+ }
3628
+ function ToastContent({ className, ...props }) {
3629
+ const { stacked } = useContext(ToastViewportContext);
3630
+ return /* @__PURE__ */ jsx(
3631
+ Toast.Content,
3632
+ {
3633
+ className: cn(
3634
+ "flex min-w-0 flex-1 gap-3",
3635
+ stacked && "transition-opacity duration-(--motion-duration-base) ease-standard data-behind:not-data-expanded:pointer-events-none data-behind:not-data-expanded:opacity-0",
3573
3636
  className
3574
3637
  ),
3575
3638
  ...props
@@ -3619,6 +3682,7 @@ function ToastProvider({
3619
3682
  limit,
3620
3683
  closeIcon,
3621
3684
  position,
3685
+ stacked,
3622
3686
  viewportClassName
3623
3687
  }) {
3624
3688
  return /* @__PURE__ */ jsxs(Toast.Provider, { timeout, limit, toastManager, children: [
@@ -3628,6 +3692,7 @@ function ToastProvider({
3628
3692
  {
3629
3693
  closeIcon,
3630
3694
  position,
3695
+ stacked,
3631
3696
  viewportClassName
3632
3697
  }
3633
3698
  )
@@ -3642,12 +3707,13 @@ var TYPE_ACCENT = {
3642
3707
  function ToastList({
3643
3708
  closeIcon,
3644
3709
  position,
3710
+ stacked,
3645
3711
  viewportClassName
3646
3712
  }) {
3647
3713
  const { toasts } = useToast();
3648
- return /* @__PURE__ */ jsx(ToastViewport, { position, className: viewportClassName, children: toasts.map((item) => {
3714
+ return /* @__PURE__ */ jsx(ToastViewport, { position, stacked, className: viewportClassName, children: toasts.map((item) => {
3649
3715
  const accent = item.type ? TYPE_ACCENT[item.type] : void 0;
3650
- return /* @__PURE__ */ jsxs(ToastRoot, { toast: item, children: [
3716
+ return /* @__PURE__ */ jsx(ToastRoot, { toast: item, children: /* @__PURE__ */ jsxs(ToastContent, { children: [
3651
3717
  item.type === "loading" ? /* @__PURE__ */ jsx(
3652
3718
  Spinner,
3653
3719
  {
@@ -3667,7 +3733,7 @@ function ToastList({
3667
3733
  ] }),
3668
3734
  /* @__PURE__ */ jsx(ToastAction, { className: "self-center" }),
3669
3735
  /* @__PURE__ */ jsx(ToastClose, { children: closeIcon ?? /* @__PURE__ */ jsx(Icon, { name: "xmark", className: "text-sm" }) })
3670
- ] }, item.id);
3736
+ ] }) }, item.id);
3671
3737
  }) });
3672
3738
  }
3673
3739
 
@@ -3753,7 +3819,7 @@ var toastMeta = {
3753
3819
  props: [
3754
3820
  {
3755
3821
  name: "ToastProvider",
3756
- type: "{ children, timeout?, limit?, closeIcon?, position?, viewportClassName? }",
3822
+ type: "{ children, timeout?, limit?, closeIcon?, position?, stacked?, viewportClassName? }",
3757
3823
  default: "\u2014",
3758
3824
  description: "Wraps Base UI Toast.Provider and renders the themed Viewport + toast list. Mount once near the app root, above any caller of useToast()."
3759
3825
  },
@@ -3763,6 +3829,12 @@ var toastMeta = {
3763
3829
  default: '"top-right"',
3764
3830
  description: "Screen anchor for the toast stack."
3765
3831
  },
3832
+ {
3833
+ name: "stacked",
3834
+ type: "boolean",
3835
+ default: "false",
3836
+ description: "Stack the toasts like a deck of cards, the newest in front and the older ones peeking out behind it, a step smaller, instead of listing them one under another. Hovering or focusing the stack fans it out into the list. Use it when an app can raise several toasts in a row, so they don't take over the corner of the page."
3837
+ },
3766
3838
  {
3767
3839
  name: "viewportClassName",
3768
3840
  type: "string",
@@ -3811,6 +3883,11 @@ var toastMeta = {
3811
3883
  type: "Base UI Toast.Root props + className (requires the `toast` object)",
3812
3884
  description: "A single toast surface. Animates enter/leave via data-[starting-style]/data-[ending-style]; swipe-to-dismiss is wired by Base UI."
3813
3885
  },
3886
+ {
3887
+ name: "ToastContent",
3888
+ type: "Base UI Toast.Content props + className",
3889
+ description: "The toast's contents as one row. In a stacked viewport it fades on the cards behind the front one and returns when the stack fans out. Wrap a hand-composed toast's parts in it so a stacked viewport can hide them."
3890
+ },
3814
3891
  {
3815
3892
  name: "ToastTitle",
3816
3893
  type: "Base UI Toast.Title props + className",
@@ -3866,6 +3943,12 @@ var toastMeta = {
3866
3943
  part: "ToastRoot",
3867
3944
  why: "Leaving the same way it entered keeps the stack legible when several dismiss at once; toasts that fade in place leave the remaining ones jumping to fill gaps with no visible cause."
3868
3945
  },
3946
+ {
3947
+ slot: "transition",
3948
+ recipe: "custom",
3949
+ part: "ToastRoot (stacked)",
3950
+ why: "A stacked toast arrives from the anchored edge in front of the others, which step back and shrink to make room; hovering fans the deck out into the list. Moving every card, rather than snapping them, shows that the new one went on top and the old ones are still there."
3951
+ },
3869
3952
  {
3870
3953
  slot: "activity",
3871
3954
  recipe: "none",
@@ -3902,6 +3985,10 @@ var toastMeta = {
3902
3985
  label: "Undo action",
3903
3986
  code: 'toast.message("Post archived", { actionProps: { children: "Undo", onClick: () => restorePost() } })'
3904
3987
  },
3988
+ {
3989
+ label: "Stacked",
3990
+ code: '<ToastProvider stacked position="bottom-right">{children}</ToastProvider>'
3991
+ },
3905
3992
  {
3906
3993
  label: "Provider with app chrome",
3907
3994
  code: '<ToastProvider position="bottom-right" limit={3}><AppShell><Region max="feed"><Button onClick={() => toast.success("Saved")}>Save</Button></Region></AppShell></ToastProvider>'
@@ -4181,7 +4268,7 @@ function ComboboxChips({
4181
4268
  Combobox$1.Chip,
4182
4269
  {
4183
4270
  render: /* @__PURE__ */ jsx(Badge, { appearance: "soft", size: "sm" }),
4184
- className: "pe-0.5 outline-none focus-visible:ring-2 focus-visible:ring-ring",
4271
+ className: "gap-0.5 pe-0.5 outline-none focus-visible:ring-2 focus-visible:ring-ring",
4185
4272
  children: [
4186
4273
  label,
4187
4274
  /* @__PURE__ */ jsx(
@@ -4192,7 +4279,7 @@ function ComboboxChips({
4192
4279
  {
4193
4280
  variant: "ghost",
4194
4281
  size: "icon-xs",
4195
- className: "-my-1"
4282
+ className: cn("-my-1 size-5 [--button-icon:0.875rem]", hitTargetMin)
4196
4283
  }
4197
4284
  ),
4198
4285
  "aria-label": `Remove ${label}`,
@@ -8034,7 +8121,7 @@ function ColorField({
8034
8121
  "aria-hidden": true,
8035
8122
  className: (
8036
8123
  // design-lint-disable-next-line raw-black-white -- handle over arbitrary user colour; no token can guarantee contrast
8037
- "absolute size-3 -translate-x-1/2 -translate-y-1/2 rounded-full ring-2 ring-white ring-inset shadow-sm"
8124
+ "absolute size-3 -translate-x-1/2 -translate-y-1/2 rounded-full ring-2 ring-white ring-inset shadow-(--knob-shadow)"
8038
8125
  ),
8039
8126
  style: {
8040
8127
  left: `${picker.hsv.s * 100}%`,
@@ -11260,6 +11347,6 @@ var carouselMeta = {
11260
11347
  };
11261
11348
 
11262
11349
  // src/index.ts
11263
- var SABLE_UI_VERSION = "0.4.0";
11350
+ var SABLE_UI_VERSION = "0.6.0";
11264
11351
 
11265
- export { Banner, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator, Breadcrumbs, COMPONENT_GROUPS, COMPONENT_TAXONOMY, Calendar, Carousel, CheckboxCard, CheckboxGroup, Collapsible, CollapsibleIndicator, CollapsiblePanel, CollapsibleTrigger, ColorField, Combobox, ComboboxChips, ComboboxClear, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxPortal, ComboboxValue, ComboboxVirtualList, ContextCard, ContextCardArrow, ContextCardContent, ContextCardPortal, ContextCardTrigger, ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuGroupLabel, ContextMenuItem, ContextMenuPortal, ContextMenuSeparator, ContextMenuTrigger, DatePicker, Feedback, Fieldset, FieldsetContent, FieldsetDescription, FieldsetFooter, FieldsetLegend, FileDropzone, GlidingHighlight, InlineStatus, LineChart, Marquee, MiddleTruncate, Note, NumberField, PageLoader, Pagination, Panel, PanelGroup, PanelResizer, PanelSection, Popover, PopoverArrow, PopoverClose, PopoverContent, PopoverDescription, PopoverPortal, PopoverTitle, PopoverTrigger, PropertyPair, PropertyRow, RadarChart, Radio, RadioCard, RadioGroup, SABLE_UI_VERSION, STATUS_TONES, STATUS_TONE_ICON, ScrubField, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetPortal, SheetTitle, SheetTrigger, ShowMore, StatusBar, StatusBarGroup, StatusBarSeparator, TRANSPARENT, ThemeSelector, ThemeSwitcher, ThinkingOrb, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastRoot, ToastTitle, ToastViewport, Tree, TreeAddRow, TreeEmpty, TreeRow, TreeSection, Video, Workspace, WorkspaceBar, WorkspaceCanvas, bannerMeta, bannerVariants, breadcrumbsMeta, calendarMeta, carouselMeta, checkboxCardMeta, collapsibleMeta, colorFieldMeta, comboboxMeta, componentGuidance, componentLabel, componentSlug, componentsInGroup, contextCardMeta, contextMenuMeta, datePickerMeta, feedbackMeta, fieldsetMeta, fileDropzoneMeta, fileDropzoneVariants, formatFileSize, formatHex, glidingHighlightMeta, hsvToRgb, hueColor, inlineStatusMeta, isTransparent, lineChartMeta, marqueeMeta, middleTruncateMeta, noteMeta, noteVariants, numberFieldMeta, pageLoaderMeta, paginationMeta, panelGroupMeta, panelSectionMeta, parseHex, pillMeta, popoverMeta, radarChartMeta, radioCardMeta, radioMeta, rgbToHsv, scrollerMeta, scrubFieldMeta, sheetMeta, sheetVariants, showMoreMeta, statusBarMeta, themeSelectorMeta, themeSwitcherMeta, thinkingOrbMeta, toast, toastMeta, treeIndent, treeMeta, useComboboxFilteredItems, usePanelWidth, useToast, useToastManager, videoMeta, workspaceMeta };
11352
+ export { Banner, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator, Breadcrumbs, COMPONENT_GROUPS, COMPONENT_TAXONOMY, Calendar, Carousel, CheckboxCard, CheckboxGroup, Collapsible, CollapsibleIndicator, CollapsiblePanel, CollapsibleTrigger, ColorField, Combobox, ComboboxChips, ComboboxClear, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxPortal, ComboboxValue, ComboboxVirtualList, ContextCard, ContextCardArrow, ContextCardContent, ContextCardPortal, ContextCardTrigger, ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuGroupLabel, ContextMenuItem, ContextMenuPortal, ContextMenuSeparator, ContextMenuTrigger, DatePicker, Feedback, Fieldset, FieldsetContent, FieldsetDescription, FieldsetFooter, FieldsetLegend, FileDropzone, GlidingHighlight, InlineStatus, LineChart, Marquee, MiddleTruncate, Note, NumberField, PageLoader, Pagination, Panel, PanelGroup, PanelResizer, PanelSection, Popover, PopoverArrow, PopoverClose, PopoverContent, PopoverDescription, PopoverPortal, PopoverTitle, PopoverTrigger, PropertyPair, PropertyRow, RadarChart, Radio, RadioCard, RadioGroup, SABLE_UI_VERSION, STATUS_TONES, STATUS_TONE_ICON, ScrubField, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetPortal, SheetTitle, SheetTrigger, ShowMore, StatusBar, StatusBarGroup, StatusBarSeparator, TRANSPARENT, ThemeSelector, ThemeSwitcher, ThinkingOrb, ToastAction, ToastClose, ToastContent, ToastDescription, ToastProvider, ToastRoot, ToastTitle, ToastViewport, Tree, TreeAddRow, TreeEmpty, TreeRow, TreeSection, Video, Workspace, WorkspaceBar, WorkspaceCanvas, bannerMeta, bannerVariants, breadcrumbsMeta, calendarMeta, carouselMeta, checkboxCardMeta, collapsibleMeta, colorFieldMeta, comboboxMeta, componentGuidance, componentLabel, componentSlug, componentsInGroup, contextCardMeta, contextMenuMeta, datePickerMeta, feedbackMeta, fieldsetMeta, fileDropzoneMeta, fileDropzoneVariants, formatFileSize, formatHex, glidingHighlightMeta, hsvToRgb, hueColor, inlineStatusMeta, isTransparent, lineChartMeta, marqueeMeta, middleTruncateMeta, noteMeta, noteVariants, numberFieldMeta, pageLoaderMeta, paginationMeta, panelGroupMeta, panelSectionMeta, parseHex, pillMeta, popoverMeta, radarChartMeta, radioCardMeta, radioMeta, rgbToHsv, scrollerMeta, scrubFieldMeta, sheetMeta, sheetVariants, showMoreMeta, statusBarMeta, themeSelectorMeta, themeSwitcherMeta, thinkingOrbMeta, toast, toastMeta, treeIndent, treeMeta, useComboboxFilteredItems, usePanelWidth, useToast, useToastManager, videoMeta, workspaceMeta };
@@ -56,14 +56,19 @@ declare function NavigationStack({ children, active, label }: {
56
56
  * An iOS 26 sheet. At the medium detent it floats inset from the screen edges in
57
57
  * Liquid Glass; at the large detent it is opaque and meets the bottom edge. The
58
58
  * header is a glass close button and a centered inline title.
59
+ *
60
+ * `background="opaque"` keeps the medium sheet's floating shape but fills it
61
+ * solid, like SwiftUI's `.presentationBackground`: for a form, whose fields
62
+ * would otherwise sit on whatever the glass is blurring.
59
63
  * Browser dialog owns focus trapping, Escape, inert background, and restoration.
60
64
  */
61
- declare function IosSheet({ open, onOpenChange, title, children, detent }: {
65
+ declare function IosSheet({ open, onOpenChange, title, children, detent, background }: {
62
66
  open: boolean;
63
67
  onOpenChange: (open: boolean) => void;
64
68
  title: string;
65
69
  children: ReactNode;
66
70
  detent?: 'medium' | 'large';
71
+ background?: 'glass' | 'opaque';
67
72
  }): react.JSX.Element;
68
73
 
69
74
  /** A screen: the scrolling page under the navigation bar. Its content is Sable. */
package/dist/ios/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { StatusIcons } from '../chunk-NEQNXI2G.js';
2
+ import { PresentationProvider } from '../chunk-FKZXAFIY.js';
2
3
  import { App, Sheet, Button, Glass, Page, NavbarBackLink, TabbarLink, Navbar, Tabbar } from 'konsta/react';
3
4
  import { createContext, useEffect, useContext, useState, useRef, useId } from 'react';
4
5
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -209,7 +210,7 @@ function NavigationStack({ children, active = true, label }) {
209
210
  }
210
211
  ) });
211
212
  }
212
- function IosSheet({ open, onOpenChange, title, children, detent = "medium" }) {
213
+ function IosSheet({ open, onOpenChange, title, children, detent = "medium", background = "glass" }) {
213
214
  const dialog = useRef(null);
214
215
  const titleId = useId();
215
216
  const [shown, setShown] = useState(false);
@@ -246,7 +247,7 @@ function IosSheet({ open, onOpenChange, title, children, detent = "medium" }) {
246
247
  onClick: (event) => {
247
248
  if (event.target === event.currentTarget) onOpenChange(false);
248
249
  },
249
- children: /* @__PURE__ */ jsxs(Sheet, { opened: shown, backdrop: false, className: "ios-sheet", "data-detent": expanded ? "large" : "medium", style: { height: expanded ? "90%" : "56%" }, children: [
250
+ children: /* @__PURE__ */ jsxs(Sheet, { opened: shown, backdrop: false, className: "ios-sheet", "data-detent": expanded ? "large" : "medium", "data-background": background, style: { height: expanded ? "90%" : "56%" }, children: [
250
251
  /* @__PURE__ */ jsx(
251
252
  Button,
252
253
  {
@@ -280,7 +281,7 @@ function IosSheet({ open, onOpenChange, title, children, detent = "medium" }) {
280
281
  /* @__PURE__ */ jsx(Glass, { className: "ios-sheet-close", children: /* @__PURE__ */ jsx(Button, { inline: true, rounded: true, clear: true, className: "ios-icon-action", "aria-label": "Close", onClick: () => onOpenChange(false), children: /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", viewBox: "0 0 16 16", width: "16", height: "16", children: /* @__PURE__ */ jsx("path", { d: "M3.5 3.5l9 9m0-9l-9 9", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", fill: "none" }) }) }) }),
281
282
  /* @__PURE__ */ jsx("h2", { id: titleId, tabIndex: -1, children: title })
282
283
  ] }),
283
- /* @__PURE__ */ jsx("div", { className: "ios-sheet-content", children })
284
+ /* @__PURE__ */ jsx("div", { className: "ios-sheet-content", children: /* @__PURE__ */ jsx(PresentationProvider, { value: "sheet", children }) })
284
285
  ] })
285
286
  }
286
287
  );
@@ -87,6 +87,8 @@
87
87
  box-shadow: inset 0 .75px .5px rgb(255 255 255 / .6), 0 8px 40px color-mix(in srgb, var(--ios-ink) 14%, transparent);
88
88
  }
89
89
  .ios-prototype.dark .ios-sheet[data-detent='medium'], .dark .ios-sheet[data-detent='medium'] { box-shadow: inset 0 .75px .5px rgb(255 255 255 / .25), 0 8px 40px rgb(0 0 0 / .4); }
90
+ /* Opaque: the same floating shape, filled solid (presentationBackground). */
91
+ .ios-sheet[data-detent='medium'][data-background='opaque'] { background: var(--ios-canvas); -webkit-backdrop-filter: none; backdrop-filter: none; }
90
92
  .ios-sheet-grabber { display: flex; margin-inline: auto; width: 80px; touch-action: none; }
91
93
  .ios-grabber-mark { width: 36px; height: 5px; border-radius: 4px; background: var(--ios-secondary); }
92
94
  /* A glass close button, a centered inline title, and an empty column that keeps it centered. */
@@ -97,6 +99,13 @@
97
99
  flat surface only smears pale patches into the rim. Keep the fill and highlights. */
98
100
  .ios-prototype .ios-sheet .k-glass { -webkit-backdrop-filter: none; backdrop-filter: none; }
99
101
  .ios-sheet-content { height: calc(100% - 88px); overflow-y: auto; scrollbar-width: none; padding: 16px 20px; }
102
+ /* A stacked action bar sits at the sheet's bottom: every plain box between the content
103
+ and the bar becomes a column that fills the height, so the bar's margin-top: auto has
104
+ room to push into. A <form> or a grid keeps its own layout (a form's fields are often
105
+ a grid), and the bar inside it follows the content, as it would in a tall form anyway. */
106
+ .ios-sheet-content:has([data-actions='stack']),
107
+ .ios-sheet-content :has([data-actions='stack']):not(form, .grid, [role='group']) { display: flex; flex-direction: column; justify-content: flex-start; align-items: stretch; }
108
+ .ios-sheet-content :has([data-actions='stack']):not(form, .grid, [role='group']) { flex: 1 0 auto; }
100
109
  .ios-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
101
110
  @keyframes ios-route-enter { from { opacity: .7; transform: translateX(28px); } to { opacity: 1; transform: translateX(0); } }
102
111
  @keyframes ios-route-back { from { opacity: .7; transform: translateX(-16px); } to { opacity: 1; transform: translateX(0); } }
@@ -1,23 +1,13 @@
1
- import { TextReveal, Reveal, MessageScroller, Marker, Toolbar, ToolbarButton, StreamingText, ChatComposer, SettingsMenu, SettingsRow, AppShell, PageHeader, DataTable, Meter, RelativeTime, Sidebar, SidebarHeader, SidebarNav, SidebarItem, NotificationBadge, SidebarFooter, BottomNav, BottomNavItem, AppHeader, Tabs, TabsList, TabsTrigger, TabsPanel, Skeleton, Browser, MeterLabel, MeterValue, MeterTrack, SearchInput, EmptyState, SideNav, SideNavItem } from '../chunk-D2ETQBHV.js';
2
- import { Form, Field, Input, Button, Separator, Card, CardContent, Badge, Entity, Avatar, StatusDot, CardHeader, CardTitle, CardDescription, CardAction, Message, Bubble, CodeBlock, SimpleTooltip, Attachment, CardFooter, MenuRadioGroup, MenuRadioItem, CardList, OverflowMenu, MenuItem, MenuSeparator, Textarea, Code, Select, SelectTrigger, SelectContent, SelectItem, DestructiveActionModal, Switch } from '../chunk-CCUDFLU3.js';
1
+ import { TextReveal, Reveal, MessageScroller, Marker, Toolbar, ToolbarButton, StreamingText, ChatComposer, SettingsMenu, SettingsRow, AppShell, PageHeader, DataTable, Meter, RelativeTime, Sidebar, SidebarHeader, SidebarNav, SidebarItem, NotificationBadge, SidebarFooter, BottomNav, BottomNavItem, AppHeader, Tabs, TabsList, TabsTrigger, TabsPanel, Skeleton, Browser, MeterLabel, MeterValue, MeterTrack, SearchInput, EmptyState, SideNav, SideNavItem } from '../chunk-VVW4UCDI.js';
2
+ import { Form, Field, Input, Button, Separator, GradientArt, Card, CardContent, Badge, Entity, Avatar, StatusDot, CardHeader, CardTitle, CardDescription, CardAction, Message, Bubble, CodeBlock, SimpleTooltip, Attachment, CardFooter, MenuRadioGroup, MenuRadioItem, CardList, OverflowMenu, MenuItem, MenuSeparator, Textarea, Code, Select, SelectTrigger, SelectContent, SelectItem, DestructiveActionModal, Switch } from '../chunk-7QSDYBXO.js';
3
+ import '../chunk-FKZXAFIY.js';
3
4
  import { Region, Stack, Row, Grid, Page, Columns, Col, AspectBox } from '../chunk-3IWZYBGH.js';
4
5
  import '../chunk-SRQWQUTW.js';
5
- import { Icon } from '../chunk-NGBDP3BM.js';
6
- import '../chunk-TH563WLW.js';
6
+ import { Icon } from '../chunk-QJ6FWTUG.js';
7
+ import '../chunk-XAZGMY73.js';
7
8
  import { useState, useRef, useEffect } from 'react';
8
9
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
9
10
 
10
- var artwork = [
11
- // design-lint-disable-next-line inline-color -- relative colour derived from the theme's own --tone token, so it follows every look
12
- "radial-gradient(in oklab at 18% 22%, oklch(from var(--tone-info) clamp(0.5, calc(l + 0.16), 0.9) max(calc(c * 1.25), 0.1) h), transparent 58%)",
13
- // design-lint-disable-next-line inline-color -- relative colour derived from the theme's own --tone token, so it follows every look
14
- "radial-gradient(in oklab at 82% 18%, oklch(from var(--tone-collectible) clamp(0.5, calc(l + 0.16), 0.9) max(calc(c * 1.25), 0.1) h), transparent 55%)",
15
- // design-lint-disable-next-line inline-color -- relative colour derived from the theme's own --tone token, so it follows every look
16
- "radial-gradient(in oklab at 70% 88%, oklch(from var(--tone-edition) clamp(0.5, calc(l + 0.16), 0.9) max(calc(c * 1.25), 0.1) h), transparent 60%)",
17
- // design-lint-disable-next-line inline-color -- relative colour derived from the theme's own --tone token, so it follows every look
18
- "radial-gradient(in oklab at 12% 92%, oklch(from var(--tone-standard) clamp(0.5, calc(l + 0.16), 0.9) max(calc(c * 1.25), 0.1) h), transparent 55%)",
19
- "var(--primary)"
20
- ].join(", ");
21
11
  function AuthPage() {
22
12
  const [pending2, setPending] = useState(false);
23
13
  const [errors, setErrors] = useState({});
@@ -76,14 +66,14 @@ function AuthPage() {
76
66
  "."
77
67
  ] })
78
68
  ] }) }),
79
- /* @__PURE__ */ jsx("aside", { "aria-label": "Featured release", className: "hidden p-3 lg:flex", children: /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col justify-end rounded-xl p-8", style: { background: artwork }, children: /* @__PURE__ */ jsx(Card, { className: "max-w-md", children: /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
69
+ /* @__PURE__ */ jsx("aside", { "aria-label": "Featured release", className: "hidden p-3 lg:flex", children: /* @__PURE__ */ jsx(GradientArt, { seed: "Untitled (gold rush)", className: "flex flex-1 flex-col justify-end rounded-xl p-8", children: /* @__PURE__ */ jsx(Card, { className: "max-w-md", children: /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
80
70
  /* @__PURE__ */ jsx(Badge, { tone: "edition", className: "self-start", children: "Edition of 50" }),
81
71
  /* @__PURE__ */ jsx("p", { className: "text-title-lg", children: "\u201CEvery edition is a conversation with whoever holds it next.\u201D" }),
82
72
  /* @__PURE__ */ jsx(
83
73
  Entity,
84
74
  {
85
75
  className: "p-0",
86
- leading: /* @__PURE__ */ jsx(Avatar, { fallback: "MO" }),
76
+ leading: /* @__PURE__ */ jsx(Avatar, { variant: "art", fallback: "MO" }),
87
77
  title: "Mara Okafor",
88
78
  subtitle: "Untitled (gold rush), 2026"
89
79
  }
@@ -353,7 +343,7 @@ function BrandLandingPage() {
353
343
  /* @__PURE__ */ jsx("blockquote", { className: "text-balance text-heading-3 sm:text-heading-2", children: "\u201CWe used to chase approvals across four tools. Now every request has an owner, a deadline, and a record, and our auditors stopped asking for screenshots.\u201D" })
354
344
  ] }),
355
345
  /* @__PURE__ */ jsxs("figcaption", { className: "flex items-center gap-3", children: [
356
- /* @__PURE__ */ jsx(Avatar, { size: "lg", fallback: "MO" }),
346
+ /* @__PURE__ */ jsx(Avatar, { variant: "art", size: "lg", fallback: "MO" }),
357
347
  /* @__PURE__ */ jsxs("div", { children: [
358
348
  /* @__PURE__ */ jsx("p", { className: "text-title-sm", children: "Maya Okafor" }),
359
349
  /* @__PURE__ */ jsx("p", { className: "text-body-sm text-muted-foreground", children: "Head of operations, Fielddesk" })
@@ -486,6 +476,7 @@ function ChatPanel() {
486
476
  const assistant = /* @__PURE__ */ jsx(
487
477
  Avatar,
488
478
  {
479
+ variant: "art",
489
480
  size: "sm",
490
481
  alt: "Assistant",
491
482
  fallback: /* @__PURE__ */ jsx(Icon, { name: "sparkles", className: "text-base" })
@@ -711,7 +702,7 @@ function DashboardPage() {
711
702
  /* @__PURE__ */ jsx(Icon, { name: "gem", variant: "solid", className: "text-xl" }),
712
703
  /* @__PURE__ */ jsx("span", { className: "text-title-sm", children: "Atelier" })
713
704
  ] }),
714
- actions: /* @__PURE__ */ jsx(Avatar, { size: "sm", fallback: "AL", alt: "Ada Lovelace" })
705
+ actions: /* @__PURE__ */ jsx(Avatar, { variant: "art", size: "sm", fallback: "AL", alt: "Ada Lovelace" })
715
706
  }
716
707
  ),
717
708
  bottomNav: /* @__PURE__ */ jsxs(BottomNav, { "aria-label": "Primary", children: [
@@ -745,7 +736,7 @@ function DashboardPage() {
745
736
  Entity,
746
737
  {
747
738
  className: "[--entity-py:0]",
748
- leading: /* @__PURE__ */ jsx(Avatar, { size: "sm", fallback: "AL", alt: "" }),
739
+ leading: /* @__PURE__ */ jsx(Avatar, { variant: "art", size: "sm", fallback: "AL", alt: "" }),
749
740
  title: "Ada Lovelace",
750
741
  subtitle: "@ada",
751
742
  action: /* @__PURE__ */ jsxs(OverflowMenu, { label: "Account", size: "icon-sm", children: [
@@ -890,7 +881,7 @@ function DashboardPage() {
890
881
  /* @__PURE__ */ jsx(CardList, { children: collectors.map((person) => /* @__PURE__ */ jsx(
891
882
  Entity,
892
883
  {
893
- leading: /* @__PURE__ */ jsx(Avatar, { size: "sm", fallback: person.initials, alt: "" }),
884
+ leading: /* @__PURE__ */ jsx(Avatar, { variant: "art", size: "sm", fallback: person.initials, alt: "" }),
894
885
  title: person.name,
895
886
  subtitle: `${person.handle} \xB7 ${person.pieces} pieces`,
896
887
  action: /* @__PURE__ */ jsx("span", { className: "text-mono-sm", children: usd.format(person.spent) })
@@ -929,7 +920,7 @@ function DashboardPage() {
929
920
  /* @__PURE__ */ jsx(CardList, { children: activity.map((item) => /* @__PURE__ */ jsx(
930
921
  Entity,
931
922
  {
932
- leading: /* @__PURE__ */ jsx(Avatar, { size: "sm", fallback: item.initials, alt: "" }),
923
+ leading: /* @__PURE__ */ jsx(Avatar, { variant: "art", size: "sm", fallback: item.initials, alt: "" }),
933
924
  title: item.who,
934
925
  subtitle: item.what,
935
926
  action: /* @__PURE__ */ jsx(RelativeTime, { date: Date.now() - item.when, className: "text-caption text-muted-foreground" })
@@ -1019,7 +1010,7 @@ var renderPost = (post) => /* @__PURE__ */ jsx("article", { children: /* @__PURE
1019
1010
  /* @__PURE__ */ jsx(CardList, { children: /* @__PURE__ */ jsx(
1020
1011
  Entity,
1021
1012
  {
1022
- leading: /* @__PURE__ */ jsx(Avatar, { fallback: post.initials, alt: post.author }),
1013
+ leading: /* @__PURE__ */ jsx(Avatar, { variant: "art", fallback: post.initials, alt: post.author }),
1023
1014
  title: post.author,
1024
1015
  subtitle: `${post.handle} \xB7 ${post.time}`,
1025
1016
  action: /* @__PURE__ */ jsxs(OverflowMenu, { label: `Post options for ${post.author}`, size: "icon-sm", children: [
@@ -1082,7 +1073,7 @@ function FeedPage() {
1082
1073
  /* @__PURE__ */ jsxs(Stack, { gap: 3, className: "min-w-0 max-w-(--region-feed) flex-1", children: [
1083
1074
  /* @__PURE__ */ jsx(PageHeader, { title: "Home" }),
1084
1075
  /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs(Row, { gap: 1.5, align: "start", children: [
1085
- /* @__PURE__ */ jsx(Avatar, { fallback: "AL", alt: "Ada Lovelace" }),
1076
+ /* @__PURE__ */ jsx(Avatar, { variant: "art", fallback: "AL", alt: "Ada Lovelace" }),
1086
1077
  /* @__PURE__ */ jsxs(Stack, { gap: 1.5, className: "min-w-0 flex-1", children: [
1087
1078
  /* @__PURE__ */ jsx(
1088
1079
  Textarea,
@@ -1131,7 +1122,7 @@ function FeedPage() {
1131
1122
  /* @__PURE__ */ jsx(CardList, { children: suggestions.map((person) => /* @__PURE__ */ jsx(
1132
1123
  Entity,
1133
1124
  {
1134
- leading: /* @__PURE__ */ jsx(Avatar, { fallback: person.initials, alt: person.name }),
1125
+ leading: /* @__PURE__ */ jsx(Avatar, { variant: "art", fallback: person.initials, alt: person.name }),
1135
1126
  title: person.name,
1136
1127
  subtitle: person.handle,
1137
1128
  action: /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", "aria-label": `Follow ${person.name}`, children: "Follow" })
@@ -1144,7 +1135,7 @@ function FeedPage() {
1144
1135
  /* @__PURE__ */ jsx(CardList, { children: upcoming2.map((drop) => /* @__PURE__ */ jsx(
1145
1136
  Entity,
1146
1137
  {
1147
- leading: /* @__PURE__ */ jsx(Avatar, { fallback: drop.initials, alt: drop.artist }),
1138
+ leading: /* @__PURE__ */ jsx(Avatar, { variant: "art", fallback: drop.initials, alt: drop.artist }),
1148
1139
  title: drop.title,
1149
1140
  subtitle: `${drop.artist} \xB7 ${drop.date}`,
1150
1141
  action: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": `Remind me about ${drop.title}`, children: /* @__PURE__ */ jsx(Icon, { name: "bell" }) })
@@ -1394,7 +1385,7 @@ function LandingPage() {
1394
1385
  /* @__PURE__ */ jsx(CardList, { children: deploys.map((deploy) => /* @__PURE__ */ jsx(
1395
1386
  Entity,
1396
1387
  {
1397
- leading: /* @__PURE__ */ jsx(Avatar, { size: "sm", fallback: deploy.initials, alt: deploy.name }),
1388
+ leading: /* @__PURE__ */ jsx(Avatar, { variant: "art", size: "sm", fallback: deploy.initials, alt: deploy.name }),
1398
1389
  title: deploy.title,
1399
1390
  subtitle: deploy.meta,
1400
1391
  action: /* @__PURE__ */ jsx(Badge, { appearance: "plain", tone: deploy.tone, dot: true, pulse: deploy.pulse, children: deploy.status })
@@ -1721,6 +1712,8 @@ function ListDetailPage() {
1721
1712
  leading: /* @__PURE__ */ jsx(
1722
1713
  Avatar,
1723
1714
  {
1715
+ variant: "art",
1716
+ seed: m.name,
1724
1717
  fallback: m.pending ? /* @__PURE__ */ jsx(Icon, { name: "mail", className: "size-5" }) : m.initials,
1725
1718
  status: m.lastActive === "Online now" ? /* @__PURE__ */ jsx(StatusDot, { tone: "success" }) : void 0,
1726
1719
  "aria-hidden": true
@@ -1773,6 +1766,7 @@ function ListDetailPage() {
1773
1766
  /* @__PURE__ */ jsx(
1774
1767
  Avatar,
1775
1768
  {
1769
+ variant: "art",
1776
1770
  size: "lg",
1777
1771
  fallback: selected.pending ? /* @__PURE__ */ jsx(Icon, { name: "mail", className: "size-6" }) : selected.initials,
1778
1772
  status: selected.lastActive === "Online now" ? /* @__PURE__ */ jsx(StatusDot, { tone: "success" }) : void 0,
@@ -1928,7 +1922,7 @@ function SettingsPage() {
1928
1922
  /* @__PURE__ */ jsx(Icon, { name: "gem", variant: "solid", className: "text-xl" }),
1929
1923
  /* @__PURE__ */ jsx("span", { className: "text-title-sm", children: "Atelier" })
1930
1924
  ] }),
1931
- actions: /* @__PURE__ */ jsx(Avatar, { size: "sm", fallback: "AL", alt: "Ada Lovelace" })
1925
+ actions: /* @__PURE__ */ jsx(Avatar, { variant: "art", size: "sm", fallback: "AL", alt: "Ada Lovelace" })
1932
1926
  }
1933
1927
  ),
1934
1928
  bottomNav: /* @__PURE__ */ jsxs(BottomNav, { "aria-label": "Primary", children: [
@@ -1962,7 +1956,7 @@ function SettingsPage() {
1962
1956
  Entity,
1963
1957
  {
1964
1958
  className: "[--entity-py:0]",
1965
- leading: /* @__PURE__ */ jsx(Avatar, { size: "sm", fallback: "AL", alt: "" }),
1959
+ leading: /* @__PURE__ */ jsx(Avatar, { variant: "art", size: "sm", fallback: "AL", alt: "" }),
1966
1960
  title: "Ada Lovelace",
1967
1961
  subtitle: "@ada",
1968
1962
  action: /* @__PURE__ */ jsxs(OverflowMenu, { label: "Account", size: "icon-sm", children: [
@@ -2003,7 +1997,7 @@ function SettingsPage() {
2003
1997
  /* @__PURE__ */ jsxs(Form, { onSubmit: (event) => event.preventDefault(), className: "gap-0", children: [
2004
1998
  /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
2005
1999
  /* @__PURE__ */ jsxs(Row, { gap: 2, children: [
2006
- /* @__PURE__ */ jsx(Avatar, { size: "lg", fallback: "AL", alt: "Ada Lovelace" }),
2000
+ /* @__PURE__ */ jsx(Avatar, { variant: "art", size: "lg", fallback: "AL", alt: "Ada Lovelace" }),
2007
2001
  /* @__PURE__ */ jsxs(Stack, { gap: 0.5, align: "start", children: [
2008
2002
  /* @__PURE__ */ jsxs(Row, { gap: 1, children: [
2009
2003
  /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", children: "Upload photo" }),