@sableui/react 0.3.2 → 0.5.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 (59) hide show
  1. package/AGENTS.md +3 -3
  2. package/CHANGELOG.md +87 -0
  3. package/CONTRIBUTING.md +2 -2
  4. package/DESIGN.md +7 -7
  5. package/README.md +2 -2
  6. package/bin/sable-lint.mjs +0 -0
  7. package/bin/sable.mjs +4 -3
  8. package/dist/{_contract-BlKMR4eX.d.ts → _contract-Cn3lUpih.d.ts} +7 -7
  9. package/dist/blocks/index.js +4 -4
  10. package/dist/{chunk-YXBOYWBN.js → chunk-C4Z3CF54.js} +1 -1
  11. package/dist/{chunk-MXJX3NZI.js → chunk-EFLC4NA3.js} +4 -4
  12. package/dist/{chunk-EP55KSYA.js → chunk-EHH4MHO6.js} +6 -6
  13. package/dist/{chunk-FBSL2LZQ.js → chunk-GU3T7SBA.js} +11 -30
  14. package/dist/{chunk-NGBDP3BM.js → chunk-QJ6FWTUG.js} +1 -1
  15. package/dist/{chunk-CCUDFLU3.js → chunk-RCLKXF2N.js} +43 -9
  16. package/dist/{chunk-TH563WLW.js → chunk-XAZGMY73.js} +10 -3
  17. package/dist/{chunk-D2ETQBHV.js → chunk-ZBZMKOO7.js} +4 -4
  18. package/dist/icon/index.js +2 -2
  19. package/dist/icon-sets/brands.d.ts +0 -27
  20. package/dist/icon-sets/brands.js +7 -1
  21. package/dist/icon-sets/reicon.js +1 -1
  22. package/dist/index.d.ts +44 -19
  23. package/dist/index.js +104 -27
  24. package/dist/patterns/index.js +4 -4
  25. package/dist/presets/index.d.ts +1 -1
  26. package/dist/presets/index.js +1 -1
  27. package/dist/styles.css +19 -11
  28. package/dist/{theme-provider-CuYYxF0o.d.ts → theme-provider-CGeiusgu.d.ts} +3 -3
  29. package/dist/themes/atelier/index.d.ts +1 -1
  30. package/dist/themes/atelier/index.js +1 -1
  31. package/dist/themes/ember/ember.css +8 -5
  32. package/dist/themes/ember/index.d.ts +1 -1
  33. package/dist/themes/index.d.ts +3 -3
  34. package/dist/themes/index.js +3 -3
  35. package/dist/themes/meridian/index.d.ts +1 -1
  36. package/dist/themes/poppy/index.d.ts +1 -1
  37. package/dist/themes/poppy/poppy.css +1 -1
  38. package/dist/themes/prism/index.d.ts +1 -1
  39. package/dist/themes/sable/index.d.ts +9 -0
  40. package/dist/themes/sable/index.js +1 -0
  41. package/dist/themes/{base/base.css → sable/sable.css} +6 -6
  42. package/dist/themes/verdant/index.d.ts +1 -1
  43. package/dist/themes.css +3 -3
  44. package/llms/components/tabs.md +1 -1
  45. package/llms/components/theme-selector.md +1 -1
  46. package/llms/components/toast.md +12 -1
  47. package/llms/reference/token-intent.md +1 -1
  48. package/llms/tasks/building-a-page.md +1 -1
  49. package/llms/tasks/creating-a-preset.md +1 -1
  50. package/llms/tasks/designing-a-surface.md +1 -1
  51. package/llms-full.txt +19 -8
  52. package/llms.txt +2 -2
  53. package/package.json +5 -5
  54. package/registry.json +43 -14
  55. package/scripts/design-presets.mjs +1 -1
  56. package/scripts/grade.mjs +18 -5
  57. package/scripts/lint-rules.mjs +20 -1
  58. package/dist/themes/base/index.d.ts +0 -9
  59. package/dist/themes/base/index.js +0 -1
package/dist/index.js CHANGED
@@ -1,26 +1,26 @@
1
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';
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-ZBZMKOO7.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-GU3T7SBA.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-GU3T7SBA.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-RCLKXF2N.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-RCLKXF2N.js';
9
9
  export { AspectBox, Bleed, Center, Col, Columns, Grid, GridOverlay, Page, Region, Row, SafeArea, Spacer, SplitPane, Stack } from './chunk-3IWZYBGH.js';
10
10
  import { cn } from './chunk-SRQWQUTW.js';
11
11
  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';
15
- import { featuredThemeManifests, defaultThemeId } from './chunk-MXJX3NZI.js';
16
- 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-MXJX3NZI.js';
12
+ import { Icon } from './chunk-QJ6FWTUG.js';
13
+ export { Icon, IconProvider, composeIconSets, useIconSet } from './chunk-QJ6FWTUG.js';
14
+ export { reiconIconSet as fallbackIconSet, reiconIconNames, reiconIconSet } from './chunk-XAZGMY73.js';
15
+ import { featuredThemeManifests, defaultThemeId } from './chunk-EFLC4NA3.js';
16
+ 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
17
  import './chunk-7MG4SHYX.js';
18
18
  import './chunk-KO3NAEBF.js';
19
19
  import './chunk-L4IEIQQA.js';
20
- import './chunk-EP55KSYA.js';
20
+ import './chunk-EHH4MHO6.js';
21
21
  import './chunk-ADLLDWLW.js';
22
22
  import './chunk-K7RUHUGC.js';
23
- import './chunk-YXBOYWBN.js';
23
+ import './chunk-C4Z3CF54.js';
24
24
  import { NumberField as NumberField$1 } from '@base-ui/react/number-field';
25
25
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
26
26
  import { createContext, useId, useRef, useState, useEffect, useLayoutEffect, useContext, useMemo, useCallback, useSyncExternalStore, Children } from 'react';
@@ -3512,7 +3512,43 @@ var ENTER_MOTION = {
3512
3512
  "bottom-center": "motion-slide-up",
3513
3513
  "bottom-right": "motion-slide-left"
3514
3514
  };
3515
- var ToastPositionContext = createContext("top-right");
3515
+ var STACKED_ROOT = [
3516
+ // 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
3517
+ "absolute inset-x-0 z-[calc(100-var(--toast-index))] select-none",
3518
+ "[--toast-gap:--spacing(2)] [--toast-peek:--spacing(3)]",
3519
+ "[--toast-scale:max(0,1-var(--toast-index)*0.05)]",
3520
+ "[--toast-h:var(--toast-frontmost-height,var(--toast-height))]",
3521
+ "h-(--toast-h) data-expanded:h-(--toast-height)",
3522
+ // Collapsed: shrink about the anchored edge, then lift a peek per card.
3523
+ "[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))]",
3524
+ // Fanned out: Base UI's offset is the heights in front of it; add the gaps.
3525
+ "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))))]",
3526
+ // Arrive from the anchored edge and leave the same way, unless swiped or
3527
+ // pushed out by the limit, which only fade.
3528
+ "data-starting-style:[translate:0_calc(var(--toast-dir)*-100%)] data-starting-style:opacity-0",
3529
+ "[&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[translate:0_calc(var(--toast-dir)*-100%)]",
3530
+ "data-ending-style:opacity-0 data-limited:opacity-0",
3531
+ // Fanned out, bridges the gap to the next card, so the pointer stays on the
3532
+ // stack and the list does not collapse under it.
3533
+ "after:absolute after:inset-x-0 after:h-[calc(var(--toast-gap)+1px)] not-data-expanded:after:hidden",
3534
+ // Collapsed, the deck lifts as one: cards resting on each other barely shade
3535
+ // each other. A full shadow on every card stacked a slab per card, and a
3536
+ // theme with hard offset shadows (Poppy's reach 12px, past the 12px peek)
3537
+ // painted the front card's slab over the cards behind it. So the front card
3538
+ // steps down to shadow-md and the cards behind to shadow-sm; fanned out,
3539
+ // each is a toast again and takes the full step back.
3540
+ "not-data-expanded:shadow-md not-data-expanded:has-[>[data-behind]]:shadow-sm",
3541
+ "transition-[transform,translate,opacity,height,box-shadow] duration-(--motion-duration-slow) ease-emphasized"
3542
+ ].join(" ");
3543
+ var STACKED_EDGE = {
3544
+ top: "top-0 origin-top [--toast-dir:1] after:top-full",
3545
+ bottom: "bottom-0 origin-bottom [--toast-dir:-1] after:bottom-full"
3546
+ };
3547
+ var edgeOf = (position) => position.startsWith("top") ? "top" : "bottom";
3548
+ var ToastViewportContext = createContext({
3549
+ position: "top-right",
3550
+ stacked: false
3551
+ });
3516
3552
  function persistsByDefault(type, options) {
3517
3553
  return type === "loading" || type === "error" || options?.actionProps !== void 0;
3518
3554
  }
@@ -3548,13 +3584,16 @@ var ToastPortal = withPortalThemeScope(Toast.Portal);
3548
3584
  function ToastViewport({
3549
3585
  className,
3550
3586
  position = "top-right",
3587
+ stacked = false,
3551
3588
  ...props
3552
3589
  }) {
3553
- return /* @__PURE__ */ jsx(ToastPositionContext.Provider, { value: position, children: /* @__PURE__ */ jsx(ToastPortal, { children: /* @__PURE__ */ jsx(
3590
+ return /* @__PURE__ */ jsx(ToastViewportContext.Provider, { value: { position, stacked }, children: /* @__PURE__ */ jsx(ToastPortal, { children: /* @__PURE__ */ jsx(
3554
3591
  Toast.Viewport,
3555
3592
  {
3556
3593
  className: cn(
3557
- "fixed z-(--z-toast) flex w-95 max-w-[90vw] flex-col gap-2 outline-none",
3594
+ "fixed z-(--z-toast) w-95 max-w-[90vw] outline-none",
3595
+ // Stacked toasts are positioned against the viewport, not laid out in it.
3596
+ !stacked && "flex flex-col gap-2",
3558
3597
  POSITION[position],
3559
3598
  className
3560
3599
  ),
@@ -3563,13 +3602,27 @@ function ToastViewport({
3563
3602
  ) }) });
3564
3603
  }
3565
3604
  function ToastRoot({ className, ...props }) {
3566
- const position = useContext(ToastPositionContext);
3605
+ const { position, stacked } = useContext(ToastViewportContext);
3567
3606
  return /* @__PURE__ */ jsx(
3568
3607
  Toast.Root,
3569
3608
  {
3570
3609
  className: cn(
3571
3610
  "flex w-full gap-3 rounded-md border border-border-floating bg-popover p-4 text-popover-foreground shadow-xl",
3572
- ENTER_MOTION[position],
3611
+ stacked ? [STACKED_ROOT, STACKED_EDGE[edgeOf(position)]] : ENTER_MOTION[position],
3612
+ className
3613
+ ),
3614
+ ...props
3615
+ }
3616
+ );
3617
+ }
3618
+ function ToastContent({ className, ...props }) {
3619
+ const { stacked } = useContext(ToastViewportContext);
3620
+ return /* @__PURE__ */ jsx(
3621
+ Toast.Content,
3622
+ {
3623
+ className: cn(
3624
+ "flex min-w-0 flex-1 gap-3",
3625
+ 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
3626
  className
3574
3627
  ),
3575
3628
  ...props
@@ -3619,6 +3672,7 @@ function ToastProvider({
3619
3672
  limit,
3620
3673
  closeIcon,
3621
3674
  position,
3675
+ stacked,
3622
3676
  viewportClassName
3623
3677
  }) {
3624
3678
  return /* @__PURE__ */ jsxs(Toast.Provider, { timeout, limit, toastManager, children: [
@@ -3628,6 +3682,7 @@ function ToastProvider({
3628
3682
  {
3629
3683
  closeIcon,
3630
3684
  position,
3685
+ stacked,
3631
3686
  viewportClassName
3632
3687
  }
3633
3688
  )
@@ -3642,12 +3697,13 @@ var TYPE_ACCENT = {
3642
3697
  function ToastList({
3643
3698
  closeIcon,
3644
3699
  position,
3700
+ stacked,
3645
3701
  viewportClassName
3646
3702
  }) {
3647
3703
  const { toasts } = useToast();
3648
- return /* @__PURE__ */ jsx(ToastViewport, { position, className: viewportClassName, children: toasts.map((item) => {
3704
+ return /* @__PURE__ */ jsx(ToastViewport, { position, stacked, className: viewportClassName, children: toasts.map((item) => {
3649
3705
  const accent = item.type ? TYPE_ACCENT[item.type] : void 0;
3650
- return /* @__PURE__ */ jsxs(ToastRoot, { toast: item, children: [
3706
+ return /* @__PURE__ */ jsx(ToastRoot, { toast: item, children: /* @__PURE__ */ jsxs(ToastContent, { children: [
3651
3707
  item.type === "loading" ? /* @__PURE__ */ jsx(
3652
3708
  Spinner,
3653
3709
  {
@@ -3667,7 +3723,7 @@ function ToastList({
3667
3723
  ] }),
3668
3724
  /* @__PURE__ */ jsx(ToastAction, { className: "self-center" }),
3669
3725
  /* @__PURE__ */ jsx(ToastClose, { children: closeIcon ?? /* @__PURE__ */ jsx(Icon, { name: "xmark", className: "text-sm" }) })
3670
- ] }, item.id);
3726
+ ] }) }, item.id);
3671
3727
  }) });
3672
3728
  }
3673
3729
 
@@ -3753,7 +3809,7 @@ var toastMeta = {
3753
3809
  props: [
3754
3810
  {
3755
3811
  name: "ToastProvider",
3756
- type: "{ children, timeout?, limit?, closeIcon?, position?, viewportClassName? }",
3812
+ type: "{ children, timeout?, limit?, closeIcon?, position?, stacked?, viewportClassName? }",
3757
3813
  default: "\u2014",
3758
3814
  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
3815
  },
@@ -3763,6 +3819,12 @@ var toastMeta = {
3763
3819
  default: '"top-right"',
3764
3820
  description: "Screen anchor for the toast stack."
3765
3821
  },
3822
+ {
3823
+ name: "stacked",
3824
+ type: "boolean",
3825
+ default: "false",
3826
+ 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."
3827
+ },
3766
3828
  {
3767
3829
  name: "viewportClassName",
3768
3830
  type: "string",
@@ -3811,6 +3873,11 @@ var toastMeta = {
3811
3873
  type: "Base UI Toast.Root props + className (requires the `toast` object)",
3812
3874
  description: "A single toast surface. Animates enter/leave via data-[starting-style]/data-[ending-style]; swipe-to-dismiss is wired by Base UI."
3813
3875
  },
3876
+ {
3877
+ name: "ToastContent",
3878
+ type: "Base UI Toast.Content props + className",
3879
+ 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."
3880
+ },
3814
3881
  {
3815
3882
  name: "ToastTitle",
3816
3883
  type: "Base UI Toast.Title props + className",
@@ -3866,6 +3933,12 @@ var toastMeta = {
3866
3933
  part: "ToastRoot",
3867
3934
  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
3935
  },
3936
+ {
3937
+ slot: "transition",
3938
+ recipe: "custom",
3939
+ part: "ToastRoot (stacked)",
3940
+ 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."
3941
+ },
3869
3942
  {
3870
3943
  slot: "activity",
3871
3944
  recipe: "none",
@@ -3902,6 +3975,10 @@ var toastMeta = {
3902
3975
  label: "Undo action",
3903
3976
  code: 'toast.message("Post archived", { actionProps: { children: "Undo", onClick: () => restorePost() } })'
3904
3977
  },
3978
+ {
3979
+ label: "Stacked",
3980
+ code: '<ToastProvider stacked position="bottom-right">{children}</ToastProvider>'
3981
+ },
3905
3982
  {
3906
3983
  label: "Provider with app chrome",
3907
3984
  code: '<ToastProvider position="bottom-right" limit={3}><AppShell><Region max="feed"><Button onClick={() => toast.success("Saved")}>Save</Button></Region></AppShell></ToastProvider>'
@@ -4181,7 +4258,7 @@ function ComboboxChips({
4181
4258
  Combobox$1.Chip,
4182
4259
  {
4183
4260
  render: /* @__PURE__ */ jsx(Badge, { appearance: "soft", size: "sm" }),
4184
- className: "pe-0.5 outline-none focus-visible:ring-2 focus-visible:ring-ring",
4261
+ className: "gap-0.5 pe-0.5 outline-none focus-visible:ring-2 focus-visible:ring-ring",
4185
4262
  children: [
4186
4263
  label,
4187
4264
  /* @__PURE__ */ jsx(
@@ -4192,7 +4269,7 @@ function ComboboxChips({
4192
4269
  {
4193
4270
  variant: "ghost",
4194
4271
  size: "icon-xs",
4195
- className: "-my-1"
4272
+ className: cn("-my-1 size-5 [--button-icon:0.875rem]", hitTargetMin)
4196
4273
  }
4197
4274
  ),
4198
4275
  "aria-label": `Remove ${label}`,
@@ -8034,7 +8111,7 @@ function ColorField({
8034
8111
  "aria-hidden": true,
8035
8112
  className: (
8036
8113
  // 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"
8114
+ "absolute size-3 -translate-x-1/2 -translate-y-1/2 rounded-full ring-2 ring-white ring-inset shadow-(--knob-shadow)"
8038
8115
  ),
8039
8116
  style: {
8040
8117
  left: `${picker.hsv.s * 100}%`,
@@ -9358,7 +9435,7 @@ var themeSelectorMeta = {
9358
9435
  },
9359
9436
  {
9360
9437
  label: "Controlled",
9361
- code: 'const [themeId, setThemeId] = useState<ThemeId>("base")\n<ThemeSelector value={themeId} onValueChange={setThemeId} />'
9438
+ code: 'const [themeId, setThemeId] = useState<ThemeId>("sable")\n<ThemeSelector value={themeId} onValueChange={setThemeId} />'
9362
9439
  },
9363
9440
  {
9364
9441
  label: "In chrome \u2014 a popover or a docked panel",
@@ -11260,6 +11337,6 @@ var carouselMeta = {
11260
11337
  };
11261
11338
 
11262
11339
  // src/index.ts
11263
- var SABLE_UI_VERSION = "0.3.2";
11340
+ var SABLE_UI_VERSION = "0.5.0";
11264
11341
 
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 };
11342
+ 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 };
@@ -1,9 +1,9 @@
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-ZBZMKOO7.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-RCLKXF2N.js';
3
3
  import { Region, Stack, Row, Grid, Page, Columns, Col, AspectBox } from '../chunk-3IWZYBGH.js';
4
4
  import '../chunk-SRQWQUTW.js';
5
- import { Icon } from '../chunk-NGBDP3BM.js';
6
- import '../chunk-TH563WLW.js';
5
+ import { Icon } from '../chunk-QJ6FWTUG.js';
6
+ import '../chunk-XAZGMY73.js';
7
7
  import { useState, useRef, useEffect } from 'react';
8
8
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
9
9
 
@@ -1,4 +1,4 @@
1
- import { T as ThemeManifest } from '../_contract-BlKMR4eX.js';
1
+ import { T as ThemeManifest } from '../_contract-Cn3lUpih.js';
2
2
 
3
3
  /** The public theme vocabulary. Presets never need component overrides. */
4
4
  declare const PRESET_TOKEN_NAMES: readonly string[];
@@ -24,7 +24,7 @@ var PRESET_TOKEN_NAMES = [.../* @__PURE__ */ new Set([
24
24
  "theme-shadow-md",
25
25
  "theme-shadow-lg",
26
26
  "theme-shadow-xl",
27
- // Chart series colours: optional — a preset without them inherits Base's validated set.
27
+ // Chart series colours: optional — a preset without them inherits the Sable theme's validated set.
28
28
  "chart-1",
29
29
  "chart-2",
30
30
  "chart-3",
package/dist/styles.css CHANGED
@@ -12,7 +12,7 @@
12
12
  @utility set, and an @source directive so Tailwind scans the package.
13
13
  ========================================================================== */
14
14
 
15
- /* Base ONLY. It is the default theme, and it is also the layout floor:
15
+ /* The Sable theme ONLY. It is the default theme, and it is also the layout floor:
16
16
  `--page-inset`, the `--region-*` caps, `--rhythm-unit`, `--grid-*` and
17
17
  `--z-*` are declared here on a bare `:root`, so every other theme — bundled
18
18
  or app-owned — inherits them. Removing it does not save 18 KB, it silently
@@ -30,10 +30,10 @@
30
30
  @import "@sableui/react/themes.css";
31
31
 
32
32
  The failure mode if you forget: `data-sable-theme` is set, nothing matches,
33
- and the page renders as Base — no error, just the wrong theme. If a
33
+ and the page renders as the Sable theme — no error, just the wrong theme. If a
34
34
  theme selector looks like it does nothing, this import is the first thing
35
35
  to check. */
36
- @import "./themes/base/base.css";
36
+ @import "./themes/sable/sable.css";
37
37
 
38
38
  /* Scan the package for utility classes (path is relative to THIS file). Covers
39
39
  both workspace source (.ts/.tsx next to this file in src/) and the compiled
@@ -119,7 +119,7 @@
119
119
  /* Motion easings → ease-* utilities (ease-standard/decelerate/emphasized;
120
120
  `linear` is built-in). Durations stay raw CSS vars and are consumed via
121
121
  `duration-(--motion-duration-*)` so the --motion-scale kill-switch applies.
122
- See themes/base/base.css → Motion tokens, and DESIGN.md → Motion. */
122
+ See themes/sable/sable.css → Motion tokens, and DESIGN.md → Motion. */
123
123
  --ease-standard: var(--motion-ease-standard);
124
124
  --ease-decelerate: var(--motion-ease-decelerate);
125
125
  --ease-emphasized: var(--motion-ease-emphasized);
@@ -168,7 +168,7 @@
168
168
  dims what is behind it, per mode.
169
169
 
170
170
  `--overlay` is near-black in every theme and mode, which is right for a
171
- scrim. But a dark page is near-black too: Base's dark `--background` IS its
171
+ scrim. But a dark page is near-black too: the Sable theme's dark `--background` IS its
172
172
  `--overlay`, so a 50% scrim over it changed nothing, and with a dialog open
173
173
  the page's text stayed at nearly full strength — while foundations/surfaces
174
174
  calls the scrim "the primary depth cue" for a modal. Dark mode needs more of
@@ -322,11 +322,12 @@
322
322
  --panel-raised: var(--theme-panel-raised, color-mix(in oklch, var(--background) 94%, var(--foreground)));
323
323
 
324
324
  /* A compact control docked in a panel: the xs field rung and a field-style
325
- button. Inset to the canvas tone at rest, a panel step under the pointer.
326
- Named so a panel control states its role instead of borrowing the work
327
- surface's token and a fixed hover. */
328
- --panel-field: var(--theme-panel-field, var(--canvas));
329
- --panel-field-hover: var(--theme-panel-field-hover, var(--panel-raised));
325
+ button. Mixed from the panel it sits in, a further step under the pointer.
326
+ It used to borrow the canvas tone (3% ink), which measured 1.04:1 against
327
+ a dark panel: the field all but vanished. 9% is what a shipped inspector
328
+ settled on (1.15:1 dark, 1.25:1 light). */
329
+ --panel-field: var(--theme-panel-field, color-mix(in oklch, var(--panel) 91%, var(--panel-foreground)));
330
+ --panel-field-hover: var(--theme-panel-field-hover, color-mix(in oklch, var(--panel) 88%, var(--panel-foreground)));
330
331
 
331
332
  /* The structural edge. Alpha-based so it holds over any surface beneath it. */
332
333
  --hairline: var(--theme-hairline, color-mix(in oklch, transparent 93%, var(--foreground)));
@@ -344,6 +345,13 @@
344
345
  a dark track (well under 3:1). When ON the knob takes `--primary-foreground`,
345
346
  the ink every theme already tunes against its primary fill. */
346
347
  --switch-thumb: var(--theme-switch-thumb, oklch(99% 0.002 90));
348
+
349
+ /* The contact shadow under a knob: the Switch thumb, the Slider thumb, the
350
+ ColorField handle. NOT the elevation ladder. `shadow-sm` is a surface's
351
+ lift, and a theme or a Depth setting may make it a long offset (Poppy's
352
+ are hard 3–12px drops); on a 20px knob inside its track that drop escaped
353
+ the track. A knob only sits on its rail, so it keeps one small shadow. */
354
+ --knob-shadow: var(--theme-knob-shadow, 0 1px 2px 0 rgb(0 0 0 / 0.05));
347
355
  }
348
356
 
349
357
  /* ==========================================================================
@@ -1477,7 +1485,7 @@
1477
1485
 
1478
1486
  Motion is a first-class layer of Sable. Three ideas:
1479
1487
 
1480
- 1. TOKENS (themes/base/base.css): a duration ladder + semantic
1488
+ 1. TOKENS (themes/sable/sable.css): a duration ladder + semantic
1481
1489
  easings, every duration scaled by --motion-scale.
1482
1490
  2. RECIPES (below): named, reusable motion behaviours a component opts into
1483
1491
  with ONE class (e.g. `motion-pop`, `motion-press`) instead of hand-rolling
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { T as ThemeManifest } from './_contract-BlKMR4eX.js';
3
+ import { T as ThemeManifest } from './_contract-Cn3lUpih.js';
4
4
 
5
5
  declare const SABLE_THEME_ATTRIBUTE: "data-sable-theme";
6
6
  declare const DEFAULT_THEME_ID: string;
@@ -62,7 +62,7 @@ interface SableThemeProviderProps {
62
62
  preference?: SableThemePreference;
63
63
  /** Notified whenever setPreference/setColorPreference is called. */
64
64
  onPreferenceChange?: (preference: SableThemePreference) => void;
65
- /** Initial design theme when uncontrolled and no stored value exists. @default "base" */
65
+ /** Initial design theme when uncontrolled and no stored value exists. @default "sable" */
66
66
  defaultThemeId?: AnyThemeId;
67
67
  /** Controlled design theme id. */
68
68
  themeId?: AnyThemeId;
@@ -98,7 +98,7 @@ declare function applySableTheme(themeId: AnyThemeId, target?: HTMLElement | nul
98
98
  declare function SableThemeProvider({ children, defaultPreference, preference: controlledPreference, onPreferenceChange, defaultThemeId, themeId: controlledThemeId, onThemeIdChange, colorStorageKey, themeStorageKey, target, customThemes, }: SableThemeProviderProps): react.JSX.Element;
99
99
  /**
100
100
  * Reads Sable's active color preference and design theme. Safe without a
101
- * provider; mutators become no-ops and the default (Base, dark) is reported.
101
+ * provider; mutators become no-ops and the default (Sable, dark) is reported.
102
102
  */
103
103
  declare function useSableTheme(): SableThemeContextValue;
104
104
 
@@ -1,4 +1,4 @@
1
- import { T as ThemeManifest } from '../../_contract-BlKMR4eX.js';
1
+ import { T as ThemeManifest } from '../../_contract-Cn3lUpih.js';
2
2
 
3
3
  /**
4
4
  * Mono Editorial — a Sable theme. Concrete token values live in
@@ -1 +1 @@
1
- export { atelierTheme, atelier_default as default } from '../../chunk-YXBOYWBN.js';
1
+ export { atelierTheme, atelier_default as default } from '../../chunk-C4Z3CF54.js';
@@ -5,7 +5,7 @@
5
5
  --tone-edition, …), never any palette ramp directly. See themes/_contract.ts.
6
6
  ========================================================================== */
7
7
 
8
- /* Scoped only — never a bare `:root`. Base alone owns `:root` as the
8
+ /* Scoped only — never a bare `:root`. The Sable theme alone owns `:root` as the
9
9
  package default; a second theme claiming it leaks its tokens into every other
10
10
  theme, and `themes.test.ts` fails the build on it. */
11
11
  [data-sable-theme="ember"] {
@@ -238,8 +238,11 @@
238
238
  --input: oklch(33% 0.012 65);
239
239
  --control-border: oklch(55.6% 0.0084 67.7);
240
240
  --ring: oklch(65.2% 0.235 32.9);
241
- --primary: oklch(65.2% 0.235 32.9);
242
- --primary-foreground: oklch(14.1% 0.018 70.5);
241
+ /* The light-mode fill, not a brighter one: on the brighter fill WCAG preferred
242
+ dark ink (5.6:1), but it reads at APCA Lc 42 — muddy — against Lc 67 for
243
+ white. At 58% white clears both (4.8:1, Lc 76). */
244
+ --primary: oklch(58% 0.245 32.9);
245
+ --primary-foreground: oklch(100% 0 0);
243
246
  --secondary: oklch(26% 0.012 67.2); /* a step ABOVE the card, so a secondary Button reads on a card and on the page */
244
247
  --secondary-foreground: oklch(100% 0 0);
245
248
  --accent: oklch(29% 0.014 60);
@@ -264,8 +267,8 @@
264
267
  --overlay-foreground: oklch(100% 0 0);
265
268
  --sidebar: oklch(15.9% 0.016 65);
266
269
  --sidebar-foreground: oklch(100% 0 0);
267
- --sidebar-primary: oklch(65.2% 0.235 32.9);
268
- --sidebar-primary-foreground: oklch(14.1% 0.018 70.5);
270
+ --sidebar-primary: oklch(58% 0.245 32.9);
271
+ --sidebar-primary-foreground: oklch(100% 0 0);
269
272
  --sidebar-accent: oklch(22% 0.010 60);
270
273
  --sidebar-accent-foreground: oklch(100% 0 0);
271
274
  --sidebar-border: oklch(25.2% 0.012 67.2);
@@ -1,4 +1,4 @@
1
- import { T as ThemeManifest } from '../../_contract-BlKMR4eX.js';
1
+ import { T as ThemeManifest } from '../../_contract-Cn3lUpih.js';
2
2
 
3
3
  /**
4
4
  * Ember — a Sable theme. Concrete token values live in
@@ -1,10 +1,10 @@
1
- export { A as AnyThemeId, D as DEFAULT_THEME_ID, S as SABLE_COLOR_STORAGE_KEY, a as SABLE_THEME_ATTRIBUTE, b as SABLE_THEME_STORAGE_KEY, c as SableColorMode, d as SableThemeContextValue, e as SableThemePreference, f as SableThemeProvider, g as SableThemeProviderProps, T as ThemeId, h as applySableColorMode, i as applySableTheme, j as buildThemeManifestById, k as defaultThemeId, l as featuredThemeManifests, m as getThemeManifest, n as isKnownThemeId, o as isThemeId, t as themeIds, p as themeManifestById, q as themeManifests, u as useSableTheme } from '../theme-provider-CuYYxF0o.js';
1
+ export { A as AnyThemeId, D as DEFAULT_THEME_ID, S as SABLE_COLOR_STORAGE_KEY, a as SABLE_THEME_ATTRIBUTE, b as SABLE_THEME_STORAGE_KEY, c as SableColorMode, d as SableThemeContextValue, e as SableThemePreference, f as SableThemeProvider, g as SableThemeProviderProps, T as ThemeId, h as applySableColorMode, i as applySableTheme, j as buildThemeManifestById, k as defaultThemeId, l as featuredThemeManifests, m as getThemeManifest, n as isKnownThemeId, o as isThemeId, t as themeIds, p as themeManifestById, q as themeManifests, u as useSableTheme } from '../theme-provider-CGeiusgu.js';
2
2
  export { atelierTheme } from './atelier/index.js';
3
- export { baseTheme } from './base/index.js';
4
3
  export { default as emberTheme } from './ember/index.js';
5
4
  export { default as meridianTheme } from './meridian/index.js';
6
5
  export { default as poppyTheme } from './poppy/index.js';
7
6
  export { default as prismTheme } from './prism/index.js';
7
+ export { default as sableTheme } from './sable/index.js';
8
8
  export { default as verdantTheme } from './verdant/index.js';
9
9
  import 'react';
10
- import '../_contract-BlKMR4eX.js';
10
+ import '../_contract-Cn3lUpih.js';
@@ -1,8 +1,8 @@
1
- export { DEFAULT_THEME_ID, SABLE_COLOR_STORAGE_KEY, SABLE_THEME_ATTRIBUTE, SABLE_THEME_STORAGE_KEY, SableThemeProvider, applySableColorMode, applySableTheme, buildThemeManifestById, defaultThemeId, featuredThemeManifests, getThemeManifest, isKnownThemeId, isThemeId, themeIds, themeManifestById, themeManifests, useSableTheme } from '../chunk-MXJX3NZI.js';
1
+ export { DEFAULT_THEME_ID, SABLE_COLOR_STORAGE_KEY, SABLE_THEME_ATTRIBUTE, SABLE_THEME_STORAGE_KEY, SableThemeProvider, applySableColorMode, applySableTheme, buildThemeManifestById, defaultThemeId, featuredThemeManifests, getThemeManifest, isKnownThemeId, isThemeId, themeIds, themeManifestById, themeManifests, useSableTheme } from '../chunk-EFLC4NA3.js';
2
2
  export { prismTheme } from '../chunk-7MG4SHYX.js';
3
3
  export { verdantTheme } from '../chunk-KO3NAEBF.js';
4
4
  export { emberTheme } from '../chunk-L4IEIQQA.js';
5
- export { baseTheme } from '../chunk-EP55KSYA.js';
5
+ export { sableTheme } from '../chunk-EHH4MHO6.js';
6
6
  export { poppyTheme } from '../chunk-ADLLDWLW.js';
7
7
  export { meridianTheme } from '../chunk-K7RUHUGC.js';
8
- export { atelierTheme } from '../chunk-YXBOYWBN.js';
8
+ export { atelierTheme } from '../chunk-C4Z3CF54.js';
@@ -1,4 +1,4 @@
1
- import { T as ThemeManifest } from '../../_contract-BlKMR4eX.js';
1
+ import { T as ThemeManifest } from '../../_contract-Cn3lUpih.js';
2
2
 
3
3
  /**
4
4
  * Meridian — a Sable theme. Concrete token values live in
@@ -1,4 +1,4 @@
1
- import { T as ThemeManifest } from '../../_contract-BlKMR4eX.js';
1
+ import { T as ThemeManifest } from '../../_contract-Cn3lUpih.js';
2
2
 
3
3
  /** Original Sable preset; no third-party artwork or reference-site code. */
4
4
  declare const poppyTheme: ThemeManifest;
@@ -122,7 +122,7 @@
122
122
  --theme-button-radius: 12px;
123
123
  --button-radius: var(--theme-button-radius);
124
124
  /* Hard offsets the whole way up. Only sm and md were declared, so the
125
- default, lg and xl steps fell through to Base's soft blurs and one ladder
125
+ default, lg and xl steps fell through to the Sable theme's soft blurs and one ladder
126
126
  spoke two shadow languages. Offset doubles roughly per step. */
127
127
  --theme-shadow-sm: 3px 3px 0 oklch(32% 0.05 320 / 0.12);
128
128
  --theme-shadow: 4px 4px 0 oklch(32% 0.05 320 / 0.13);
@@ -1,4 +1,4 @@
1
- import { T as ThemeManifest } from '../../_contract-BlKMR4eX.js';
1
+ import { T as ThemeManifest } from '../../_contract-Cn3lUpih.js';
2
2
 
3
3
  /** Original Sable preset; no third-party artwork or reference-site code. */
4
4
  declare const prismTheme: ThemeManifest;
@@ -0,0 +1,9 @@
1
+ import { T as ThemeManifest } from '../../_contract-Cn3lUpih.js';
2
+
3
+ /**
4
+ * Sable — the default theme. Concrete token values live in
5
+ * `sable.css`; this manifest is the typed, machine-readable description.
6
+ */
7
+ declare const sableTheme: ThemeManifest;
8
+
9
+ export { sableTheme as default, sableTheme };
@@ -0,0 +1 @@
1
+ export { sable_default as default, sableTheme } from '../../chunk-EHH4MHO6.js';
@@ -1,5 +1,5 @@
1
1
  /* ==========================================================================
2
- Base — the default Sable theme.
2
+ Sable — the default theme.
3
3
 
4
4
  Dark-by-default, content-first, fluid product aesthetic. Palette authored in
5
5
  OKLCH (locked hue per ramp, perceptually-even lightness, sRGB-capped chroma).
@@ -14,7 +14,7 @@
14
14
  ========================================================================== */
15
15
 
16
16
  :root,
17
- [data-sable-theme="base"] {
17
+ [data-sable-theme="sable"] {
18
18
  /* Chart series colours — a categorical palette validated for colour-blind
19
19
  separation (adjacent pairs), a normal-vision floor, a lightness band and a
20
20
  chroma floor against this theme's surfaces. Charts take them in order
@@ -319,7 +319,7 @@
319
319
  font size. The docs app runs a 14px responsive root, so `56rem` rendered
320
320
  784px while claiming 896px and `80rem` rendered 1120px while claiming
321
321
  1280px — the default theme silently 12.5% under its own spec, in its own
322
- primary consumer. Every generated theme already declares px; Base was
322
+ primary consumer. Every generated theme already declares px; Sable was
323
323
  the only one that did not, which is the worst possible one to get wrong.
324
324
  The values below are DESIGN.md's table verbatim. */
325
325
  --region-form: 480px; /* narrow single-col forms, auth, dialogs */
@@ -382,11 +382,11 @@
382
382
  Semantic tokens — dark mode (the brand default)
383
383
  ========================================================================== */
384
384
  .dark,
385
- .dark[data-sable-theme="base"],
386
- [data-sable-theme="base"].dark,
385
+ .dark[data-sable-theme="sable"],
386
+ [data-sable-theme="sable"].dark,
387
387
  /* A preset-scoped subtree inside a dark page follows the page into dark mode;
388
388
  add `.light` to that subtree to pin it light. */
389
- .dark [data-sable-theme="base"]:not(.light) {
389
+ .dark [data-sable-theme="sable"]:not(.light) {
390
390
  /* The same eight hues, stepped for the dark band (L 0.48–0.67, >= 3:1 on
391
391
  the dark surfaces) and validated as a set — not a lightness flip. */
392
392
  --chart-1: oklch(62.21% 0.1612 255.05); /* #3987e5 */
@@ -1,4 +1,4 @@
1
- import { T as ThemeManifest } from '../../_contract-BlKMR4eX.js';
1
+ import { T as ThemeManifest } from '../../_contract-Cn3lUpih.js';
2
2
 
3
3
  /**
4
4
  * Verdant — a Sable theme. Concrete token values live in