@sixthshift/design-system 0.5.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.
- package/README.md +132 -87
- package/dist/components/Badge/Badge.d.ts +2 -2
- package/dist/components/Badge/Badge.js +2 -2
- package/dist/components/Button/Button.d.ts +1 -1
- package/dist/components/Button/Button.js +1 -1
- package/dist/components/Calendar/Calendar.d.ts.map +1 -1
- package/dist/components/Calendar/Calendar.js +1 -0
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Calendar/CalendarView.d.ts +0 -11
- package/dist/components/Calendar/CalendarView.d.ts.map +1 -1
- package/dist/components/Calendar/CalendarView.js +1 -0
- package/dist/components/Calendar/CalendarView.js.map +1 -1
- package/dist/components/Calendar/calendar.hooks.d.ts.map +1 -1
- package/dist/components/Calendar/calendar.hooks.js +1 -0
- package/dist/components/Calendar/calendar.hooks.js.map +1 -1
- package/dist/components/Card/Card.d.ts +2 -2
- package/dist/components/Card/Card.d.ts.map +1 -1
- package/dist/components/Card/Card.js +3 -2
- package/dist/components/Card/Card.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/Checkbox.js +1 -0
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/CheckboxGroup/CheckboxGroup.d.ts.map +1 -1
- package/dist/components/CheckboxGroup/CheckboxGroup.js +1 -0
- package/dist/components/CheckboxGroup/CheckboxGroup.js.map +1 -1
- package/dist/components/Code/Editor/Editor.d.ts.map +1 -1
- package/dist/components/Code/Editor/Editor.js +1 -0
- package/dist/components/Code/Editor/Editor.js.map +1 -1
- package/dist/components/Code/Workspace/StatusBar.d.ts.map +1 -1
- package/dist/components/Code/Workspace/StatusBar.js +1 -0
- package/dist/components/Code/Workspace/StatusBar.js.map +1 -1
- package/dist/components/Code/Workspace/Toolbar.d.ts.map +1 -1
- package/dist/components/Code/Workspace/Toolbar.js +1 -0
- package/dist/components/Code/Workspace/Toolbar.js.map +1 -1
- package/dist/components/Code/Workspace/Workspace.d.ts.map +1 -1
- package/dist/components/Code/Workspace/Workspace.js +1 -0
- package/dist/components/Code/Workspace/Workspace.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts.map +1 -1
- package/dist/components/DatePicker/DatePicker.js +5 -0
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/DatePicker/DateSegments.d.ts.map +1 -1
- package/dist/components/DatePicker/DateSegments.js +1 -0
- package/dist/components/DatePicker/DateSegments.js.map +1 -1
- package/dist/components/DatePicker/datepicker.hooks.d.ts.map +1 -1
- package/dist/components/DatePicker/datepicker.hooks.js +1 -0
- package/dist/components/DatePicker/datepicker.hooks.js.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.js +1 -0
- package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.js +5 -0
- package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
- package/dist/components/DateTimePicker/DateTimeSegments.d.ts.map +1 -1
- package/dist/components/DateTimePicker/DateTimeSegments.js +1 -0
- package/dist/components/DateTimePicker/DateTimeSegments.js.map +1 -1
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.d.ts.map +1 -1
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js +5 -0
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js.map +1 -1
- package/dist/components/FormField/FormField.d.ts +31 -10
- package/dist/components/FormField/FormField.d.ts.map +1 -1
- package/dist/components/FormField/FormField.js +46 -17
- package/dist/components/FormField/FormField.js.map +1 -1
- package/dist/components/FormField/index.d.ts +2 -2
- package/dist/components/FormField/index.d.ts.map +1 -1
- package/dist/components/FormField/index.js +1 -1
- package/dist/components/FormField/index.js.map +1 -1
- package/dist/components/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/components/HoverCard/HoverCard.js +1 -0
- package/dist/components/HoverCard/HoverCard.js.map +1 -1
- package/dist/components/HoverCard/components/HoverCardContent.d.ts.map +1 -1
- package/dist/components/HoverCard/components/HoverCardContent.js +1 -0
- package/dist/components/HoverCard/components/HoverCardContent.js.map +1 -1
- package/dist/components/HoverCard/components/HoverCardContext.d.ts.map +1 -1
- package/dist/components/HoverCard/components/HoverCardContext.js +1 -0
- package/dist/components/HoverCard/components/HoverCardContext.js.map +1 -1
- package/dist/components/HoverCard/components/HoverCardTrigger.d.ts.map +1 -1
- package/dist/components/HoverCard/components/HoverCardTrigger.js +1 -0
- package/dist/components/HoverCard/components/HoverCardTrigger.js.map +1 -1
- package/dist/components/Message/Message.d.ts +1 -1
- package/dist/components/Message/Message.js +1 -1
- package/dist/components/Modal/Modal.d.ts +14 -9
- package/dist/components/Modal/Modal.d.ts.map +1 -1
- package/dist/components/Modal/Modal.js +42 -20
- package/dist/components/Modal/Modal.js.map +1 -1
- package/dist/components/Modal/components/ModalContext.d.ts.map +1 -1
- package/dist/components/Modal/components/ModalContext.js +1 -0
- package/dist/components/Modal/components/ModalContext.js.map +1 -1
- package/dist/components/Modal/components/ModalHeader.d.ts.map +1 -1
- package/dist/components/Modal/components/ModalHeader.js +1 -0
- package/dist/components/Modal/components/ModalHeader.js.map +1 -1
- package/dist/components/Popover/Popover.d.ts.map +1 -1
- package/dist/components/Popover/Popover.js +5 -0
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Popover/components/PopoverBody.d.ts.map +1 -1
- package/dist/components/Popover/components/PopoverBody.js +1 -0
- package/dist/components/Popover/components/PopoverBody.js.map +1 -1
- package/dist/components/Popover/components/PopoverClose.d.ts.map +1 -1
- package/dist/components/Popover/components/PopoverClose.js +1 -0
- package/dist/components/Popover/components/PopoverClose.js.map +1 -1
- package/dist/components/Popover/components/PopoverContext.d.ts.map +1 -1
- package/dist/components/Popover/components/PopoverContext.js +1 -0
- package/dist/components/Popover/components/PopoverContext.js.map +1 -1
- package/dist/components/Popover/components/PopoverTrigger.d.ts.map +1 -1
- package/dist/components/Popover/components/PopoverTrigger.js +1 -0
- package/dist/components/Popover/components/PopoverTrigger.js.map +1 -1
- package/dist/components/RadioButton/RadioButton.d.ts.map +1 -1
- package/dist/components/RadioButton/RadioButton.js +1 -0
- package/dist/components/RadioButton/RadioButton.js.map +1 -1
- package/dist/components/RadioButtonGroup/RadioButtonGroup.d.ts.map +1 -1
- package/dist/components/RadioButtonGroup/RadioButtonGroup.js +1 -0
- package/dist/components/RadioButtonGroup/RadioButtonGroup.js.map +1 -1
- package/dist/components/SearchInput/SearchInput.d.ts +10 -7
- package/dist/components/SearchInput/SearchInput.d.ts.map +1 -1
- package/dist/components/SearchInput/SearchInput.js +11 -6
- package/dist/components/SearchInput/SearchInput.js.map +1 -1
- package/dist/components/Select/Select.d.ts +6 -0
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.js +9 -3
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Select/SelectDropdown.d.ts.map +1 -1
- package/dist/components/Select/SelectDropdown.js +1 -0
- package/dist/components/Select/SelectDropdown.js.map +1 -1
- package/dist/components/Select/SelectTrigger.d.ts.map +1 -1
- package/dist/components/Select/SelectTrigger.js +5 -1
- package/dist/components/Select/SelectTrigger.js.map +1 -1
- package/dist/components/Select/useSelectKeyboard.d.ts.map +1 -1
- package/dist/components/Select/useSelectKeyboard.js +1 -0
- package/dist/components/Select/useSelectKeyboard.js.map +1 -1
- package/dist/components/Sheet/Sheet.d.ts.map +1 -1
- package/dist/components/Sheet/Sheet.js +23 -9
- package/dist/components/Sheet/Sheet.js.map +1 -1
- package/dist/components/Sheet/components/SheetContext.d.ts.map +1 -1
- package/dist/components/Sheet/components/SheetContext.js +1 -0
- package/dist/components/Sheet/components/SheetContext.js.map +1 -1
- package/dist/components/Sheet/components/SheetHeader.d.ts.map +1 -1
- package/dist/components/Sheet/components/SheetHeader.js +1 -0
- package/dist/components/Sheet/components/SheetHeader.js.map +1 -1
- package/dist/components/Spinner/Spinner.d.ts +2 -2
- package/dist/components/Spinner/Spinner.js +2 -2
- package/dist/components/Switch/Switch.d.ts.map +1 -1
- package/dist/components/Switch/Switch.js +1 -0
- package/dist/components/Switch/Switch.js.map +1 -1
- package/dist/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/components/Tabs/Tabs.js +1 -0
- package/dist/components/Tabs/Tabs.js.map +1 -1
- package/dist/components/Tabs/components/TabsContext.d.ts.map +1 -1
- package/dist/components/Tabs/components/TabsContext.js +1 -0
- package/dist/components/Tabs/components/TabsContext.js.map +1 -1
- package/dist/components/Tabs/components/TabsList.d.ts.map +1 -1
- package/dist/components/Tabs/components/TabsList.js +1 -0
- package/dist/components/Tabs/components/TabsList.js.map +1 -1
- package/dist/components/Tabs/components/TabsPanels.d.ts.map +1 -1
- package/dist/components/Tabs/components/TabsPanels.js +1 -0
- package/dist/components/Tabs/components/TabsPanels.js.map +1 -1
- package/dist/components/Tabs/components/TabsTrigger.d.ts.map +1 -1
- package/dist/components/Tabs/components/TabsTrigger.js +2 -1
- package/dist/components/Tabs/components/TabsTrigger.js.map +1 -1
- package/dist/components/TagChip/TagChip.d.ts.map +1 -1
- package/dist/components/TagChip/TagChip.js +1 -0
- package/dist/components/TagChip/TagChip.js.map +1 -1
- package/dist/components/TagInput/TagInput.d.ts +8 -2
- package/dist/components/TagInput/TagInput.d.ts.map +1 -1
- package/dist/components/TagInput/TagInput.js +8 -5
- package/dist/components/TagInput/TagInput.js.map +1 -1
- package/dist/components/Textarea/Textarea.d.ts +21 -5
- package/dist/components/Textarea/Textarea.d.ts.map +1 -1
- package/dist/components/Textarea/Textarea.js +31 -5
- package/dist/components/Textarea/Textarea.js.map +1 -1
- package/dist/components/TimePicker/PeriodSelector.d.ts.map +1 -1
- package/dist/components/TimePicker/PeriodSelector.js +1 -0
- package/dist/components/TimePicker/PeriodSelector.js.map +1 -1
- package/dist/components/TimePicker/TimeColumn.d.ts.map +1 -1
- package/dist/components/TimePicker/TimeColumn.js +1 -0
- package/dist/components/TimePicker/TimeColumn.js.map +1 -1
- package/dist/components/TimePicker/TimePicker.d.ts.map +1 -1
- package/dist/components/TimePicker/TimePicker.js +5 -0
- package/dist/components/TimePicker/TimePicker.js.map +1 -1
- package/dist/components/TimePicker/TimeSegments.d.ts.map +1 -1
- package/dist/components/TimePicker/TimeSegments.js +1 -0
- package/dist/components/TimePicker/TimeSegments.js.map +1 -1
- package/dist/components/Toast/Toast.d.ts +16 -2
- package/dist/components/Toast/Toast.d.ts.map +1 -1
- package/dist/components/Toast/Toast.js +16 -6
- package/dist/components/Toast/Toast.js.map +1 -1
- package/dist/components/Toggle/Toggle.d.ts +1 -1
- package/dist/components/Toggle/Toggle.d.ts.map +1 -1
- package/dist/components/Toggle/Toggle.js +2 -1
- package/dist/components/Toggle/Toggle.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupMultiple.d.ts +2 -0
- package/dist/components/ToggleGroup/ToggleGroupMultiple.d.ts.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupMultiple.js +4 -3
- package/dist/components/ToggleGroup/ToggleGroupMultiple.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupSingle.d.ts +2 -0
- package/dist/components/ToggleGroup/ToggleGroupSingle.d.ts.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupSingle.js +4 -3
- package/dist/components/ToggleGroup/ToggleGroupSingle.js.map +1 -1
- package/dist/components/ToggleGroup/toggleGroup.types.d.ts +7 -0
- package/dist/components/ToggleGroup/toggleGroup.types.d.ts.map +1 -1
- package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip/Tooltip.js +1 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/components/Tooltip/components/TooltipBody.d.ts.map +1 -1
- package/dist/components/Tooltip/components/TooltipBody.js +1 -0
- package/dist/components/Tooltip/components/TooltipBody.js.map +1 -1
- package/dist/components/Tooltip/components/TooltipContext.d.ts.map +1 -1
- package/dist/components/Tooltip/components/TooltipContext.js +1 -0
- package/dist/components/Tooltip/components/TooltipContext.js.map +1 -1
- package/dist/components/Tooltip/components/TooltipTrigger.d.ts.map +1 -1
- package/dist/components/Tooltip/components/TooltipTrigger.js +1 -0
- package/dist/components/Tooltip/components/TooltipTrigger.js.map +1 -1
- package/dist/hooks/useCollapsible.d.ts.map +1 -1
- package/dist/hooks/useCollapsible.js +1 -0
- package/dist/hooks/useCollapsible.js.map +1 -1
- package/dist/hooks/useControllableState.d.ts.map +1 -1
- package/dist/hooks/useControllableState.js +1 -0
- package/dist/hooks/useControllableState.js.map +1 -1
- package/dist/hooks/useDebouncedCallback.d.ts.map +1 -1
- package/dist/hooks/useDebouncedCallback.js +1 -0
- package/dist/hooks/useDebouncedCallback.js.map +1 -1
- package/dist/hooks/useDebouncedState.d.ts.map +1 -1
- package/dist/hooks/useDebouncedState.js +1 -0
- package/dist/hooks/useDebouncedState.js.map +1 -1
- package/dist/hooks/useDeviceFormFactor.d.ts.map +1 -1
- package/dist/hooks/useDeviceFormFactor.js +1 -0
- package/dist/hooks/useDeviceFormFactor.js.map +1 -1
- package/dist/hooks/useLocalStorage.d.ts.map +1 -1
- package/dist/hooks/useLocalStorage.js +1 -0
- package/dist/hooks/useLocalStorage.js.map +1 -1
- package/dist/hooks/useMergedFloatingRef.d.ts.map +1 -1
- package/dist/hooks/useMergedFloatingRef.js +1 -0
- package/dist/hooks/useMergedFloatingRef.js.map +1 -1
- package/dist/hooks/usePresence.d.ts.map +1 -1
- package/dist/hooks/usePresence.js +1 -0
- package/dist/hooks/usePresence.js.map +1 -1
- package/dist/hooks/useStack.d.ts.map +1 -1
- package/dist/hooks/useStack.js +34 -10
- package/dist/hooks/useStack.js.map +1 -1
- package/dist/hooks/useTheme.d.ts.map +1 -1
- package/dist/hooks/useTheme.js +1 -0
- package/dist/hooks/useTheme.js.map +1 -1
- package/dist/internal/PickerField.d.ts.map +1 -1
- package/dist/internal/PickerField.js +1 -0
- package/dist/internal/PickerField.js.map +1 -1
- package/dist/internal/SegmentedField.d.ts.map +1 -1
- package/dist/internal/SegmentedField.js +1 -0
- package/dist/internal/SegmentedField.js.map +1 -1
- package/dist/internal/escapeLayers.d.ts +12 -0
- package/dist/internal/escapeLayers.d.ts.map +1 -0
- package/dist/internal/escapeLayers.js +48 -0
- package/dist/internal/escapeLayers.js.map +1 -0
- package/dist/lib/ErrorBoundary.d.ts.map +1 -1
- package/dist/lib/ErrorBoundary.js +1 -0
- package/dist/lib/ErrorBoundary.js.map +1 -1
- package/dist/lib/contexts/ComponentsContext/ComponentsContext.d.ts.map +1 -1
- package/dist/lib/contexts/ComponentsContext/ComponentsContext.js +1 -0
- package/dist/lib/contexts/ComponentsContext/ComponentsContext.js.map +1 -1
- package/dist/lib/contexts/OverlayContext/OverlayContext.d.ts +9 -4
- package/dist/lib/contexts/OverlayContext/OverlayContext.d.ts.map +1 -1
- package/dist/lib/contexts/OverlayContext/OverlayContext.js +25 -12
- package/dist/lib/contexts/OverlayContext/OverlayContext.js.map +1 -1
- package/dist/lib/contexts/OverlayContext/ToastStack.d.ts +20 -0
- package/dist/lib/contexts/OverlayContext/ToastStack.d.ts.map +1 -0
- package/dist/lib/contexts/OverlayContext/ToastStack.js +45 -0
- package/dist/lib/contexts/OverlayContext/ToastStack.js.map +1 -0
- package/dist/lib/contexts/OverlayContext/hooks/useModal.d.ts.map +1 -1
- package/dist/lib/contexts/OverlayContext/hooks/useModal.js +1 -0
- package/dist/lib/contexts/OverlayContext/hooks/useModal.js.map +1 -1
- package/dist/lib/contexts/OverlayContext/hooks/useToast.d.ts +27 -10
- package/dist/lib/contexts/OverlayContext/hooks/useToast.d.ts.map +1 -1
- package/dist/lib/contexts/OverlayContext/hooks/useToast.js +31 -49
- package/dist/lib/contexts/OverlayContext/hooks/useToast.js.map +1 -1
- package/dist/lib/contexts/OverlayContext/index.d.ts +2 -0
- package/dist/lib/contexts/OverlayContext/index.d.ts.map +1 -1
- package/dist/lib/contexts/OverlayContext/index.js +2 -0
- package/dist/lib/contexts/OverlayContext/index.js.map +1 -1
- package/dist/lib/contexts/OverlayContext/toastStore.d.ts +68 -0
- package/dist/lib/contexts/OverlayContext/toastStore.d.ts.map +1 -0
- package/dist/lib/contexts/OverlayContext/toastStore.js +69 -0
- package/dist/lib/contexts/OverlayContext/toastStore.js.map +1 -0
- package/dist/lib/withErrorBoundary.d.ts.map +1 -1
- package/dist/lib/withErrorBoundary.js +1 -0
- package/dist/lib/withErrorBoundary.js.map +1 -1
- package/dist/lib/withSuspenseAndErrorBoundary.d.ts.map +1 -1
- package/dist/lib/withSuspenseAndErrorBoundary.js +1 -0
- package/dist/lib/withSuspenseAndErrorBoundary.js.map +1 -1
- package/dist/{theme/schema.d.ts → theming/vocabulary.d.ts} +4 -4
- package/dist/theming/vocabulary.d.ts.map +1 -0
- package/dist/{theme/schema.js → theming/vocabulary.js} +4 -4
- package/dist/theming/vocabulary.js.map +1 -0
- package/package.json +18 -6
- package/src/components/Badge/Badge.tsx +2 -2
- package/src/components/Button/Button.tsx +1 -1
- package/src/{theme/recipes/button.css → components/Button/button.recipe.css} +2 -2
- package/src/components/Calendar/Calendar.tsx +2 -0
- package/src/components/Calendar/CalendarView.tsx +2 -0
- package/src/components/Calendar/calendar.hooks.ts +2 -0
- package/src/components/Card/Card.tsx +4 -2
- package/src/components/Checkbox/Checkbox.tsx +2 -0
- package/src/components/CheckboxGroup/CheckboxGroup.tsx +2 -0
- package/src/components/Code/Editor/Editor.tsx +2 -0
- package/src/components/Code/Workspace/StatusBar.tsx +2 -0
- package/src/components/Code/Workspace/Toolbar.tsx +2 -0
- package/src/components/Code/Workspace/Workspace.tsx +2 -0
- package/src/components/DatePicker/DatePicker.tsx +7 -0
- package/src/components/DatePicker/DateSegments.tsx +2 -0
- package/src/components/DatePicker/datepicker.hooks.ts +2 -0
- package/src/components/DateRangePicker/DateRangePicker.tsx +2 -0
- package/src/components/DateTimePicker/DateTimePicker.tsx +7 -1
- package/src/components/DateTimePicker/DateTimeSegments.tsx +2 -0
- package/src/components/DateTimeRangePicker/DateTimeRangePicker.tsx +7 -1
- package/src/components/FormField/FormField.tsx +94 -42
- package/src/components/FormField/index.ts +2 -2
- package/src/components/HoverCard/HoverCard.tsx +2 -0
- package/src/components/HoverCard/components/HoverCardContent.tsx +2 -0
- package/src/components/HoverCard/components/HoverCardContext.tsx +2 -0
- package/src/components/HoverCard/components/HoverCardTrigger.tsx +2 -0
- package/src/components/Message/Message.tsx +1 -1
- package/src/components/Modal/Modal.tsx +77 -51
- package/src/components/Modal/components/ModalContext.tsx +2 -0
- package/src/components/Modal/components/ModalHeader.tsx +2 -0
- package/src/components/Popover/Popover.tsx +7 -0
- package/src/components/Popover/components/PopoverBody.tsx +2 -0
- package/src/components/Popover/components/PopoverClose.tsx +2 -0
- package/src/components/Popover/components/PopoverContext.tsx +2 -0
- package/src/components/Popover/components/PopoverTrigger.tsx +2 -0
- package/src/components/RadioButton/RadioButton.tsx +2 -0
- package/src/components/RadioButtonGroup/RadioButtonGroup.tsx +2 -0
- package/src/components/SearchInput/SearchInput.tsx +15 -8
- package/src/components/Select/Select.tsx +24 -1
- package/src/components/Select/SelectDropdown.tsx +2 -0
- package/src/components/Select/SelectTrigger.tsx +5 -0
- package/src/components/Select/useSelectKeyboard.ts +2 -0
- package/src/components/Sheet/Sheet.tsx +49 -34
- package/src/components/Sheet/components/SheetContext.tsx +2 -0
- package/src/components/Sheet/components/SheetHeader.tsx +2 -0
- package/src/components/Spinner/Spinner.tsx +2 -2
- package/src/components/Switch/Switch.tsx +2 -0
- package/src/components/Tabs/Tabs.tsx +2 -0
- package/src/components/Tabs/components/TabsContext.tsx +2 -0
- package/src/components/Tabs/components/TabsList.tsx +2 -0
- package/src/components/Tabs/components/TabsPanels.tsx +2 -0
- package/src/components/Tabs/components/TabsTrigger.tsx +3 -1
- package/src/{theme/recipes/tabs.css → components/Tabs/tabs.recipe.css} +1 -1
- package/src/components/TagChip/TagChip.tsx +2 -0
- package/src/components/TagInput/TagInput.tsx +15 -6
- package/src/components/Textarea/Textarea.tsx +42 -6
- package/src/{theme/recipes/textarea.css → components/Textarea/textarea.recipe.css} +1 -1
- package/src/components/TimePicker/PeriodSelector.tsx +2 -0
- package/src/components/TimePicker/TimeColumn.tsx +2 -0
- package/src/components/TimePicker/TimePicker.tsx +7 -0
- package/src/components/TimePicker/TimeSegments.tsx +2 -0
- package/src/components/Toast/Toast.tsx +22 -6
- package/src/components/Toggle/Toggle.tsx +3 -1
- package/src/components/ToggleGroup/ToggleGroupMultiple.tsx +6 -0
- package/src/components/ToggleGroup/ToggleGroupSingle.tsx +6 -0
- package/src/components/ToggleGroup/toggleGroup.types.ts +7 -0
- package/src/components/Tooltip/Tooltip.tsx +2 -0
- package/src/components/Tooltip/components/TooltipBody.tsx +2 -0
- package/src/components/Tooltip/components/TooltipContext.tsx +2 -0
- package/src/components/Tooltip/components/TooltipTrigger.tsx +2 -0
- package/src/hooks/useCollapsible.ts +2 -0
- package/src/hooks/useControllableState.ts +2 -0
- package/src/hooks/useDebouncedCallback.ts +2 -0
- package/src/hooks/useDebouncedState.ts +2 -0
- package/src/hooks/useDeviceFormFactor.ts +2 -0
- package/src/hooks/useLocalStorage.ts +2 -0
- package/src/hooks/useMergedFloatingRef.ts +2 -0
- package/src/hooks/usePresence.ts +2 -0
- package/src/hooks/useStack.ts +35 -12
- package/src/hooks/useTheme.ts +2 -0
- package/src/internal/PickerField.tsx +2 -0
- package/src/internal/SegmentedField.tsx +2 -0
- package/src/internal/escapeLayers.ts +53 -0
- package/src/lib/ErrorBoundary.tsx +2 -0
- package/src/lib/contexts/ComponentsContext/ComponentsContext.tsx +2 -0
- package/src/lib/contexts/OverlayContext/OverlayContext.tsx +42 -26
- package/src/lib/contexts/OverlayContext/ToastStack.tsx +71 -0
- package/src/lib/contexts/OverlayContext/hooks/useModal.tsx +2 -0
- package/src/lib/contexts/OverlayContext/hooks/useToast.ts +30 -73
- package/src/lib/contexts/OverlayContext/index.ts +2 -0
- package/src/lib/contexts/OverlayContext/toastStore.ts +138 -0
- package/src/lib/withErrorBoundary.tsx +2 -0
- package/src/lib/withSuspenseAndErrorBoundary.tsx +2 -0
- package/src/theme/linen/index.css +11 -0
- package/src/theme/linen/palette.css +87 -0
- package/src/theme/linen/theme.css +371 -0
- package/src/theming/tailwind.css +356 -0
- package/src/{theme/schema.ts → theming/vocabulary.ts} +3 -3
- package/dist/theme/index.d.ts +0 -9
- package/dist/theme/index.d.ts.map +0 -1
- package/dist/theme/index.js +0 -8
- package/dist/theme/index.js.map +0 -1
- package/dist/theme/schema.d.ts.map +0 -1
- package/dist/theme/schema.js.map +0 -1
- package/src/theme/index.ts +0 -39
- package/src/theme/recipes/index.css +0 -28
- package/src/theme/tokens.css +0 -824
- /package/src/{theme/recipes/badge.css → components/Badge/badge.recipe.css} +0 -0
- /package/src/{theme/recipes/card.css → components/Card/card.recipe.css} +0 -0
- /package/src/{theme/recipes/checkbox.css → components/Checkbox/checkbox.recipe.css} +0 -0
- /package/src/{theme/recipes/field.css → components/Field/field.recipe.css} +0 -0
- /package/src/{theme/recipes/input.css → components/Input/input.recipe.css} +0 -0
- /package/src/{theme/recipes/message.css → components/Message/message.recipe.css} +0 -0
- /package/src/{theme/recipes/modal.css → components/Modal/modal.recipe.css} +0 -0
- /package/src/{theme/recipes/radio-button.css → components/RadioButton/radio-button.recipe.css} +0 -0
- /package/src/{theme/recipes/search-input.css → components/SearchInput/search-input.recipe.css} +0 -0
- /package/src/{theme/recipes/select.css → components/Select/select.recipe.css} +0 -0
- /package/src/{theme/recipes/sheet.css → components/Sheet/sheet.recipe.css} +0 -0
- /package/src/{theme/recipes/spinner.css → components/Spinner/spinner.recipe.css} +0 -0
- /package/src/{theme/recipes/switch.css → components/Switch/switch.recipe.css} +0 -0
- /package/src/{theme/recipes/tag-chip.css → components/TagChip/tag-chip.recipe.css} +0 -0
- /package/src/{theme/recipes/toggle.css → components/Toggle/toggle.recipe.css} +0 -0
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* or intent the library never shipped.
|
|
9
9
|
*
|
|
10
10
|
* The grammar is `--button-{context}[-{state}]` — the same `context` and
|
|
11
|
-
* `state` words the semantic layer uses (src/
|
|
11
|
+
* `state` words the semantic layer uses (src/theming/vocabulary.ts). Note what is
|
|
12
12
|
* deliberately *absent*: intent and weight never appear in a token name. They
|
|
13
13
|
* select, via the `data-` attributes below. Putting them in the name
|
|
14
14
|
* (`--button-bg-danger`) would restore the combinatorial explosion this layer
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
--button-fg: var(--fg-on-brand);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
/* `neutral` means *no colour family* — the grey
|
|
50
|
+
/* `neutral` means *no colour family* — the grey ramp. It used to resolve to
|
|
51
51
|
the brand fill, which made `intent="neutral"` mean one thing on Button and
|
|
52
52
|
another on Badge and Message, where it was already grey. Button
|
|
53
53
|
was the outlier; this is the cell that ends that. A brand-coloured button
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { useCallback, useMemo } from "react";
|
|
2
4
|
import { addDays, formatDateMediumYear, isPlainDate, isSameDay, isSameMonth, startOfMonth, startOfWeek, Temporal, today } from "../../date-time";
|
|
3
5
|
import type { DateRangeValue, DateSelectionState, DisabledDateMatcher, SelectionMode } from "./calendar.types";
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { cn } from "@sixthshift/design-system/utils";
|
|
2
4
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
5
|
import * as React from "react";
|
|
@@ -6,7 +8,7 @@ import * as React from "react";
|
|
|
6
8
|
* Geometry only, plus the five `--card-*` component tokens.
|
|
7
9
|
*
|
|
8
10
|
* Every colour reads a `--card-*` token whose value is decided by
|
|
9
|
-
* src/
|
|
11
|
+
* src/components/Card/card.recipe.css. `size` stays here: it is pure geometry
|
|
10
12
|
* (padding, header gap, corner radius), not colour, so it has no reason to
|
|
11
13
|
* move — the same split Message.tsx documents.
|
|
12
14
|
*
|
|
@@ -108,7 +110,7 @@ export type CardProps = Omit<React.HTMLAttributes<HTMLDivElement>, "title"> &
|
|
|
108
110
|
* `role="button"`, `tabIndex={0}`, and both Enter and Space activate it, not
|
|
109
111
|
* just a pointer click. Omit `onClick` for a purely presentational card.
|
|
110
112
|
*
|
|
111
|
-
* Colour reads `--card-*` component tokens (src/
|
|
113
|
+
* Colour reads `--card-*` component tokens (src/components/Card/card.recipe.css) —
|
|
112
114
|
* the same seam Button and Badge use — so a consumer can re-point them
|
|
113
115
|
* without a release.
|
|
114
116
|
*/
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { autoUpdate, FloatingPortal, flip, offset, shift, useClick, useDismiss, useFloating, useInteractions } from "@floating-ui/react";
|
|
2
4
|
import { useControllableState } from "@sixthshift/design-system/hooks";
|
|
3
5
|
import { cn } from "@sixthshift/design-system/utils";
|
|
@@ -19,6 +21,7 @@ import {
|
|
|
19
21
|
toISODateRange,
|
|
20
22
|
} from "../../date-time";
|
|
21
23
|
import { PickerField } from "../../internal";
|
|
24
|
+
import { useEscapeLayer } from "../../internal/escapeLayers";
|
|
22
25
|
import { CalendarView } from "../Calendar/CalendarView";
|
|
23
26
|
import { isDateDisabled } from "../Calendar/calendar.hooks";
|
|
24
27
|
import type { PresetOption } from "../Calendar/calendar.types";
|
|
@@ -236,6 +239,10 @@ export const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>((pro
|
|
|
236
239
|
|
|
237
240
|
const click = useClick(context);
|
|
238
241
|
const dismiss = useDismiss(context);
|
|
242
|
+
|
|
243
|
+
// While open, an Escape press closes this picker's popover and must not
|
|
244
|
+
// also close a Modal/Sheet it is rendered inside.
|
|
245
|
+
useEscapeLayer(open);
|
|
239
246
|
const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss]);
|
|
240
247
|
|
|
241
248
|
// IDs for accessibility
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { autoUpdate, FloatingPortal, flip, offset, shift, useClick, useDismiss, useFloating, useInteractions } from "@floating-ui/react";
|
|
2
4
|
import { useControllableState } from "@sixthshift/design-system/hooks";
|
|
3
5
|
import { cn } from "@sixthshift/design-system/utils";
|
|
@@ -13,8 +15,8 @@ import {
|
|
|
13
15
|
today,
|
|
14
16
|
toISOInstantOrUndefined,
|
|
15
17
|
} from "../../date-time";
|
|
16
|
-
|
|
17
18
|
import { PickerField } from "../../internal";
|
|
19
|
+
import { useEscapeLayer } from "../../internal/escapeLayers";
|
|
18
20
|
import { Button } from "../Button";
|
|
19
21
|
import { CalendarView } from "../Calendar/CalendarView";
|
|
20
22
|
import { isDateDisabled } from "../Calendar/calendar.hooks";
|
|
@@ -251,6 +253,10 @@ export const DateTimePicker = React.forwardRef<HTMLDivElement, DateTimePickerPro
|
|
|
251
253
|
|
|
252
254
|
const click = useClick(context);
|
|
253
255
|
const dismiss = useDismiss(context);
|
|
256
|
+
|
|
257
|
+
// While open, an Escape press closes this picker's popover and must not
|
|
258
|
+
// also close a Modal/Sheet it is rendered inside.
|
|
259
|
+
useEscapeLayer(open);
|
|
254
260
|
const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss]);
|
|
255
261
|
|
|
256
262
|
// IDs for accessibility
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { autoUpdate, FloatingPortal, flip, offset, shift, useClick, useDismiss, useFloating, useInteractions } from "@floating-ui/react";
|
|
2
4
|
import { useControllableState } from "@sixthshift/design-system/hooks";
|
|
3
5
|
import { cn } from "@sixthshift/design-system/utils";
|
|
@@ -16,8 +18,8 @@ import {
|
|
|
16
18
|
toISOInstant,
|
|
17
19
|
toISOInstantRange,
|
|
18
20
|
} from "../../date-time";
|
|
19
|
-
|
|
20
21
|
import { PickerField } from "../../internal";
|
|
22
|
+
import { useEscapeLayer } from "../../internal/escapeLayers";
|
|
21
23
|
import { Button } from "../Button";
|
|
22
24
|
import { CalendarView } from "../Calendar/CalendarView";
|
|
23
25
|
import { isDateDisabled } from "../Calendar/calendar.hooks";
|
|
@@ -412,6 +414,10 @@ export const DateTimeRangePicker = React.forwardRef<HTMLDivElement, DateTimeRang
|
|
|
412
414
|
|
|
413
415
|
const click = useClick(context);
|
|
414
416
|
const dismiss = useDismiss(context);
|
|
417
|
+
|
|
418
|
+
// While open, an Escape press closes this picker's popover and must not
|
|
419
|
+
// also close a Modal/Sheet it is rendered inside.
|
|
420
|
+
useEscapeLayer(open);
|
|
415
421
|
const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss]);
|
|
416
422
|
|
|
417
423
|
// IDs for accessibility
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { Label } from "@sixthshift/design-system/label";
|
|
2
4
|
import { Message } from "@sixthshift/design-system/message";
|
|
3
5
|
import { Muted } from "@sixthshift/design-system/muted";
|
|
@@ -10,61 +12,111 @@ export type FormFieldFeedback = {
|
|
|
10
12
|
};
|
|
11
13
|
|
|
12
14
|
export type FormFieldProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
13
|
-
label:
|
|
14
|
-
description?:
|
|
15
|
+
label: React.ReactNode;
|
|
16
|
+
description?: React.ReactNode;
|
|
15
17
|
feedback?: FormFieldFeedback;
|
|
16
18
|
required?: boolean;
|
|
17
19
|
};
|
|
18
20
|
|
|
21
|
+
/** What FormField knows about the control it wraps — see `useFormField`. */
|
|
22
|
+
export type FormFieldContextValue = {
|
|
23
|
+
/** The id the control should carry, and the label's `htmlFor` target. */
|
|
24
|
+
id: string;
|
|
25
|
+
/** Space-separated ids of the description/feedback texts, for `aria-describedby`. `undefined` when there are none. */
|
|
26
|
+
describedBy: string | undefined;
|
|
27
|
+
/** True when `feedback.intent` is `"danger"` — the control should set `aria-invalid`. */
|
|
28
|
+
invalid: boolean;
|
|
29
|
+
/** Mirrors the `required` prop, for `aria-required`/`required` on the control. */
|
|
30
|
+
required: boolean;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const FormFieldContext = React.createContext<FormFieldContextValue | null>(null);
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The wiring `FormField` provides to whatever control it wraps: `id`,
|
|
37
|
+
* `describedBy`, `invalid`, `required`. Direct element children get these
|
|
38
|
+
* cloned on automatically; a control nested deeper — inside a wrapper div, a
|
|
39
|
+
* render prop, a custom composite — can call this instead and apply them
|
|
40
|
+
* itself. Returns `null` outside a `FormField`.
|
|
41
|
+
*/
|
|
42
|
+
export const useFormField = () => React.useContext(FormFieldContext);
|
|
43
|
+
|
|
19
44
|
/**
|
|
20
45
|
* Wraps a form control with a label, optional description, and optional
|
|
21
46
|
* validation feedback — the composition point for `Input`, `Textarea`,
|
|
22
47
|
* `Select` and similar controls inside a form.
|
|
23
48
|
*
|
|
24
|
-
* Generates an `id` (or uses the one passed in) and
|
|
25
|
-
* `aria-describedby` (pointing at the description and/or feedback text)
|
|
26
|
-
* `aria-invalid` (when `feedback.intent` is `"danger"`)
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
49
|
+
* Generates an `id` (or uses the one passed in) and wires it, plus
|
|
50
|
+
* `aria-describedby` (pointing at the description and/or feedback text),
|
|
51
|
+
* `aria-invalid` (when `feedback.intent` is `"danger"`) and `aria-required`
|
|
52
|
+
* (when `required`), onto the first element child. A child's own attributes
|
|
53
|
+
* win: an explicit `id` is kept (and becomes the label's `htmlFor` target),
|
|
54
|
+
* an existing `aria-describedby` is merged with FormField's rather than
|
|
55
|
+
* replaced. Controls that aren't the first element child can self-wire via
|
|
56
|
+
* `useFormField`.
|
|
30
57
|
*
|
|
31
58
|
* Distinct from `Field`, which displays a read-only label/value pair rather
|
|
32
59
|
* than wrapping an interactive control.
|
|
33
60
|
*/
|
|
34
|
-
const FormField = React.forwardRef<HTMLDivElement, FormFieldProps>(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
const FormField = React.forwardRef<HTMLDivElement, FormFieldProps>(
|
|
62
|
+
({ className, label, description, feedback, required = false, children, id, ...props }, ref) => {
|
|
63
|
+
const generatedId = React.useId();
|
|
64
|
+
const fieldId = id ?? generatedId;
|
|
65
|
+
|
|
66
|
+
// The label must point at the id the control actually carries: when the
|
|
67
|
+
// (first element) child brings its own id, that id wins over ours.
|
|
68
|
+
const childArray = React.Children.toArray(children);
|
|
69
|
+
const firstElementIndex = childArray.findIndex((child) => React.isValidElement(child));
|
|
70
|
+
const firstElement = firstElementIndex === -1 ? null : (childArray[firstElementIndex] as React.ReactElement<React.HTMLAttributes<HTMLElement>>);
|
|
71
|
+
const controlId = firstElement?.props.id ?? fieldId;
|
|
72
|
+
|
|
73
|
+
const descriptionId = description ? `${fieldId}-description` : undefined;
|
|
74
|
+
const feedbackId = feedback ? `${fieldId}-feedback` : undefined;
|
|
75
|
+
const invalid = feedback?.intent === "danger";
|
|
76
|
+
|
|
77
|
+
const contextValue = React.useMemo<FormFieldContextValue>(
|
|
78
|
+
() => ({
|
|
79
|
+
id: controlId,
|
|
80
|
+
describedBy: cn(descriptionId, feedbackId) || undefined,
|
|
81
|
+
invalid,
|
|
82
|
+
required,
|
|
83
|
+
}),
|
|
84
|
+
[controlId, descriptionId, feedbackId, invalid, required]
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const wiredChildren = childArray.map((child, index) => {
|
|
88
|
+
if (index !== firstElementIndex || !React.isValidElement(child)) return child;
|
|
89
|
+
const childProps = child.props as React.HTMLAttributes<HTMLElement>;
|
|
90
|
+
return React.cloneElement(child, {
|
|
91
|
+
id: controlId,
|
|
92
|
+
// The child's own describedby (a tooltip, an external hint) is kept and
|
|
93
|
+
// FormField's ids are appended, rather than overwritten.
|
|
94
|
+
"aria-describedby": cn(childProps["aria-describedby"], descriptionId, feedbackId) || undefined,
|
|
95
|
+
"aria-invalid": childProps["aria-invalid"] ?? (invalid ? true : undefined),
|
|
96
|
+
"aria-required": childProps["aria-required"] ?? (required ? true : undefined),
|
|
97
|
+
} as React.HTMLAttributes<HTMLElement>);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<div ref={ref} className={cn("flex flex-col gap-1.5", className)} {...props}>
|
|
102
|
+
<Label htmlFor={controlId}>
|
|
103
|
+
{label}
|
|
104
|
+
{required && <span className="ml-0.5 text-fg-danger">*</span>}
|
|
105
|
+
</Label>
|
|
106
|
+
|
|
107
|
+
{description && <Muted id={descriptionId}>{description}</Muted>}
|
|
108
|
+
|
|
109
|
+
<FormFieldContext.Provider value={contextValue}>{wiredChildren}</FormFieldContext.Provider>
|
|
110
|
+
|
|
111
|
+
{feedback && (
|
|
112
|
+
<Message id={feedbackId} intent={feedback.intent} size="sm">
|
|
113
|
+
{feedback.message}
|
|
114
|
+
</Message>
|
|
115
|
+
)}
|
|
116
|
+
</div>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
);
|
|
68
120
|
FormField.displayName = "FormField";
|
|
69
121
|
|
|
70
122
|
export { FormField };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type { FormFieldFeedback, FormFieldProps } from "./FormField";
|
|
2
|
-
export { FormField } from "./FormField";
|
|
1
|
+
export type { FormFieldContextValue, FormFieldFeedback, FormFieldProps } from "./FormField";
|
|
2
|
+
export { FormField, useFormField } from "./FormField";
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { autoUpdate, flip, offset, type Placement, safePolygon, shift, useDismiss, useFloating, useFocus, useHover, useInteractions } from "@floating-ui/react";
|
|
2
4
|
import { useControllableState } from "@sixthshift/design-system/hooks";
|
|
3
5
|
import type * as React from "react";
|
|
@@ -10,7 +10,7 @@ import { MessageTitle } from "./components/MessageTitle";
|
|
|
10
10
|
* Geometry only, plus the three `--message-*` component tokens.
|
|
11
11
|
*
|
|
12
12
|
* Every colour reads a `--message-*` component token whose value is decided by
|
|
13
|
-
* src/
|
|
13
|
+
* src/components/Message/message.recipe.css. That file is the mapping from `intent` to a
|
|
14
14
|
* semantic token — the layer that used to be the `intent` entry in `variants`
|
|
15
15
|
* here, compiled into class-name literals and unreachable from outside.
|
|
16
16
|
* `size` stays here: it is pure geometry (padding, gap, font-size), not
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { FloatingFocusManager, FloatingOverlay, FloatingPortal, useDismiss, useFloating, useInteractions, useRole } from "@floating-ui/react";
|
|
2
4
|
import { useMergedFloatingRef, usePresence } from "@sixthshift/design-system/hooks";
|
|
3
5
|
import { cn } from "@sixthshift/design-system/utils";
|
|
4
6
|
import { forwardRef, type HTMLAttributes, type ReactNode, useCallback, useContext, useEffect, useId, useMemo, useState } from "react";
|
|
7
|
+
import { hasOpenEscapeLayer, useEscapeDialog } from "../../internal/escapeLayers";
|
|
5
8
|
import { ModalBody, ModalContext, ModalFooter, ModalHeader } from "./components";
|
|
6
9
|
|
|
7
10
|
// =============================================================================
|
|
@@ -21,9 +24,11 @@ export type ModalProps = Pick<HTMLAttributes<HTMLDivElement>, "className" | "sty
|
|
|
21
24
|
/** Children - use Modal.Header, Modal.Body, Modal.Footer */
|
|
22
25
|
children: ReactNode;
|
|
23
26
|
/**
|
|
24
|
-
* When true (default), clicking outside
|
|
27
|
+
* When true (default), clicking outside — and, for a directly-mounted
|
|
28
|
+
* modal, pressing Escape — closes the modal.
|
|
25
29
|
* When false, the modal can only be closed programmatically.
|
|
26
|
-
* Note:
|
|
30
|
+
* Note: for modals opened via `useModal()`, Escape is handled by
|
|
31
|
+
* OverlayContext for proper stack ordering.
|
|
27
32
|
*/
|
|
28
33
|
dismissable?: boolean;
|
|
29
34
|
/** When true, shows a close (X) button in the modal header */
|
|
@@ -66,6 +71,9 @@ const ModalRoot = forwardRef<HTMLDivElement, ModalProps>(
|
|
|
66
71
|
) => {
|
|
67
72
|
// Prefer explicit prop over context (context is set by useModal's overlay system)
|
|
68
73
|
const contextValue = useContext(ModalContext);
|
|
74
|
+
// A context means useModal's stack owns this modal — and with it, Escape
|
|
75
|
+
// ordering. Without one the modal is mounted directly and handles its own.
|
|
76
|
+
const isStackManaged = contextValue != null;
|
|
69
77
|
// Context provides a parameterless onClose for programmatic modals; adapt to the boolean shape.
|
|
70
78
|
const handleDismiss = useCallback(() => {
|
|
71
79
|
if (onOpenChange) onOpenChange(false);
|
|
@@ -84,8 +92,12 @@ const ModalRoot = forwardRef<HTMLDivElement, ModalProps>(
|
|
|
84
92
|
|
|
85
93
|
const { refs, context } = useFloating({
|
|
86
94
|
open: true,
|
|
87
|
-
onOpenChange: (nextOpen) => {
|
|
88
|
-
if (
|
|
95
|
+
onOpenChange: (nextOpen, _event, reason) => {
|
|
96
|
+
if (nextOpen) return;
|
|
97
|
+
// A transient overlay (Select dropdown, Popover, picker) open above
|
|
98
|
+
// this modal consumes the Escape itself — don't also close the modal.
|
|
99
|
+
if (reason === "escape-key" && hasOpenEscapeLayer()) return;
|
|
100
|
+
handleClose();
|
|
89
101
|
},
|
|
90
102
|
});
|
|
91
103
|
|
|
@@ -93,8 +105,10 @@ const ModalRoot = forwardRef<HTMLDivElement, ModalProps>(
|
|
|
93
105
|
|
|
94
106
|
const dismiss = useDismiss(context, {
|
|
95
107
|
enabled: dismissable,
|
|
96
|
-
//
|
|
97
|
-
|
|
108
|
+
// Stack-managed modals leave Escape to OverlayContext, which closes
|
|
109
|
+
// topmost-first. A directly-mounted modal has no stack above it and
|
|
110
|
+
// handles its own Escape here.
|
|
111
|
+
escapeKey: !isStackManaged,
|
|
98
112
|
outsidePress: true,
|
|
99
113
|
outsidePressEvent: "mousedown",
|
|
100
114
|
});
|
|
@@ -119,52 +133,63 @@ const ModalRoot = forwardRef<HTMLDivElement, ModalProps>(
|
|
|
119
133
|
|
|
120
134
|
const modalContextValue = useMemo(() => ({ onClose: handleClose, closable, titleId, registerTitle }), [closable, handleClose, titleId, registerTitle]);
|
|
121
135
|
|
|
136
|
+
// While mounted (exit animation included), a non-modal Sheet underneath
|
|
137
|
+
// must leave Escape to this dialog.
|
|
138
|
+
useEscapeDialog(isMounted);
|
|
139
|
+
|
|
122
140
|
if (!isMounted) return null;
|
|
123
141
|
|
|
124
142
|
const isEntering = state === "entering";
|
|
125
143
|
const isExiting = state === "exiting";
|
|
126
144
|
|
|
127
145
|
return (
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
aria-labelledby={labelledBy}
|
|
139
|
-
aria-describedby={ariaDescribedBy}
|
|
140
|
-
tabIndex={-1}
|
|
141
|
-
data-state={state}
|
|
142
|
-
className={cn(
|
|
143
|
-
"modal fixed flex flex-col overflow-hidden outline-hidden",
|
|
144
|
-
"border-(color:--modal-border) rounded-xl border bg-(--modal-bg)",
|
|
145
|
-
// Size
|
|
146
|
-
sizeClasses[size],
|
|
147
|
-
// Cap height so ModalBody scrolls instead of overflowing the viewport
|
|
148
|
-
"max-h-[95%]",
|
|
149
|
-
// Mobile: slide up from bottom, full width
|
|
150
|
-
"max-sm:inset-x-0 max-sm:bottom-0 max-sm:rounded-b-none",
|
|
151
|
-
isEntering && "max-sm:animate-slide-up-in",
|
|
152
|
-
isExiting && "max-sm:animate-slide-up-out",
|
|
153
|
-
// Desktop: horizontal center + vertical alignment
|
|
154
|
-
"sm:left-1/2 sm:-translate-x-1/2",
|
|
155
|
-
align === "center" && "sm:top-1/2 sm:-translate-y-1/2",
|
|
156
|
-
align === "top" && "sm:top-[15vh]",
|
|
157
|
-
isEntering && "sm:animate-fade-in",
|
|
158
|
-
isExiting && "sm:animate-fade-out",
|
|
159
|
-
className
|
|
160
|
-
)}
|
|
161
|
-
style={style}
|
|
162
|
-
{...getFloatingProps({})}
|
|
146
|
+
// Self-portalled: `position: fixed` resolves against the nearest
|
|
147
|
+
// transformed/filtered ancestor, so a modal rendered in place inside a
|
|
148
|
+
// `transform` container would be positioned (and clipped) by it. Nested
|
|
149
|
+
// FloatingPortals attach to the parent portal's node, so a stack-managed
|
|
150
|
+
// modal stays inside the `OverlayProvider`'s custom `modal` root.
|
|
151
|
+
<FloatingPortal>
|
|
152
|
+
<FloatingFocusManager context={context} modal>
|
|
153
|
+
<FloatingOverlay
|
|
154
|
+
lockScroll
|
|
155
|
+
className={cn("modal-overlay fixed inset-0 z-modal bg-(--modal-overlay-bg)", isEntering && "animate-fade-in", isExiting && "animate-fade-out")}
|
|
163
156
|
>
|
|
164
|
-
<
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
157
|
+
<div
|
|
158
|
+
ref={mergedRef}
|
|
159
|
+
role="dialog"
|
|
160
|
+
aria-modal="true"
|
|
161
|
+
aria-label={ariaLabel}
|
|
162
|
+
aria-labelledby={labelledBy}
|
|
163
|
+
aria-describedby={ariaDescribedBy}
|
|
164
|
+
tabIndex={-1}
|
|
165
|
+
data-state={state}
|
|
166
|
+
className={cn(
|
|
167
|
+
"modal fixed flex flex-col overflow-hidden outline-hidden",
|
|
168
|
+
"border-(color:--modal-border) rounded-xl border bg-(--modal-bg)",
|
|
169
|
+
// Size
|
|
170
|
+
sizeClasses[size],
|
|
171
|
+
// Cap height so ModalBody scrolls instead of overflowing the viewport
|
|
172
|
+
"max-h-[95%]",
|
|
173
|
+
// Mobile: slide up from bottom, full width
|
|
174
|
+
"max-sm:inset-x-0 max-sm:bottom-0 max-sm:rounded-b-none",
|
|
175
|
+
isEntering && "max-sm:animate-slide-up-in",
|
|
176
|
+
isExiting && "max-sm:animate-slide-up-out",
|
|
177
|
+
// Desktop: horizontal center + vertical alignment
|
|
178
|
+
"sm:left-1/2 sm:-translate-x-1/2",
|
|
179
|
+
align === "center" && "sm:top-1/2 sm:-translate-y-1/2",
|
|
180
|
+
align === "top" && "sm:top-[15vh]",
|
|
181
|
+
isEntering && "sm:animate-fade-in",
|
|
182
|
+
isExiting && "sm:animate-fade-out",
|
|
183
|
+
className
|
|
184
|
+
)}
|
|
185
|
+
style={style}
|
|
186
|
+
{...getFloatingProps({})}
|
|
187
|
+
>
|
|
188
|
+
<ModalContext.Provider value={modalContextValue}>{children}</ModalContext.Provider>
|
|
189
|
+
</div>
|
|
190
|
+
</FloatingOverlay>
|
|
191
|
+
</FloatingFocusManager>
|
|
192
|
+
</FloatingPortal>
|
|
168
193
|
);
|
|
169
194
|
}
|
|
170
195
|
);
|
|
@@ -192,11 +217,12 @@ ModalRoot.displayName = "Modal";
|
|
|
192
217
|
* Modal is mount-driven — a parent (or `useModal`'s stack) decides whether it
|
|
193
218
|
* renders at all, so there's no `open` prop. `onOpenChange` still exists,
|
|
194
219
|
* firing only with `false` on dismissal, so every overlay in this library
|
|
195
|
-
* shares one open/close shape. Escape
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
* `
|
|
199
|
-
*
|
|
220
|
+
* shares one open/close shape. Escape closes the modal: a directly-mounted
|
|
221
|
+
* Modal handles it itself (via `useDismiss`, so `dismissable={false}` turns
|
|
222
|
+
* it off along with outside-press), while one opened through `useModal()`
|
|
223
|
+
* defers to `OverlayProvider`, which closes a stack of modals topmost-first.
|
|
224
|
+
* Either way, an Escape pressed while a transient overlay (Select dropdown,
|
|
225
|
+
* Popover, picker) is open above the modal closes only that overlay.
|
|
200
226
|
*
|
|
201
227
|
* Focus moves into the modal on mount and is trapped there
|
|
202
228
|
* (`FloatingFocusManager modal`) until it unmounts, then returns to whatever
|