@cube-dev/ui-kit 0.0.0-canary-d8e2a5f → 0.0.0-canary-d03ae24
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 +1 -1
- package/dist/CHANGELOG.md +19 -0
- package/dist/README.md +1 -1
- package/dist/_internal/hooks/use-chained-callback.js +1 -1
- package/dist/_internal/hooks/use-debounced-value.js +1 -1
- package/dist/_internal/hooks/use-deprecation-warning.js +1 -1
- package/dist/_internal/hooks/use-event.js +1 -1
- package/dist/_internal/hooks/use-is-first-render.js +1 -1
- package/dist/_internal/hooks/use-sync-ref.js +1 -1
- package/dist/_internal/hooks/use-timer/timer.js +1 -1
- package/dist/_internal/hooks/use-timer/use-timer.js +1 -1
- package/dist/_internal/hooks/use-warn.js +1 -1
- package/dist/components/Block.js +1 -1
- package/dist/components/CollectionItem.js +1 -1
- package/dist/components/GlobalStyles.js +1 -1
- package/dist/components/GridProvider.js +1 -1
- package/dist/components/HiddenInput.js +1 -1
- package/dist/components/Root.js +1 -1
- package/dist/components/actions/Action/Action.js +1 -1
- package/dist/components/actions/Banner/Banner.js +1 -1
- package/dist/components/actions/Button/Button.js +1 -1
- package/dist/components/actions/ButtonGroup/ButtonGroup.js +1 -1
- package/dist/components/actions/ButtonSplit/ButtonSplit.js +1 -1
- package/dist/components/actions/ButtonSplit/context.js +1 -1
- package/dist/components/actions/CommandMenu/CommandMenu.js +1 -1
- package/dist/components/actions/CommandMenu/styled.js +1 -1
- package/dist/components/actions/ItemAction/ItemAction.js +1 -1
- package/dist/components/actions/ItemActionContext.js +1 -1
- package/dist/components/actions/ItemButton/ItemButton.js +1 -1
- package/dist/components/actions/Link/Link.js +1 -1
- package/dist/components/actions/Menu/Menu.js +1 -1
- package/dist/components/actions/Menu/MenuItem.js +1 -1
- package/dist/components/actions/Menu/MenuSection.js +1 -1
- package/dist/components/actions/Menu/MenuTrigger.js +1 -1
- package/dist/components/actions/Menu/SubMenuTrigger.js +1 -1
- package/dist/components/actions/Menu/SubmenuTriggerContext.js +1 -1
- package/dist/components/actions/Menu/context.js +1 -1
- package/dist/components/actions/Menu/styled.js +1 -1
- package/dist/components/actions/index.js +1 -1
- package/dist/components/actions/use-action.js +1 -1
- package/dist/components/actions/use-anchored-menu.js +1 -1
- package/dist/components/actions/use-context-menu.js +1 -1
- package/dist/components/content/ActiveZone/ActiveZone.js +1 -1
- package/dist/components/content/Alert/Alert.js +1 -1
- package/dist/components/content/Alert/use-alert.js +1 -1
- package/dist/components/content/Avatar/Avatar.js +1 -1
- package/dist/components/content/Badge/Badge.js +1 -1
- package/dist/components/content/Card/Card.js +1 -1
- package/dist/components/content/Content.js +1 -1
- package/dist/components/content/CopyPasteBlock/CopyPasteBlock.js +1 -1
- package/dist/components/content/CopySnippet/CopySnippet.js +1 -1
- package/dist/components/content/Disclosure/Disclosure.js +1 -1
- package/dist/components/content/Divider.js +1 -1
- package/dist/components/content/Footer.js +1 -1
- package/dist/components/content/Header.js +1 -1
- package/dist/components/content/HotKeys/HotKeys.js +1 -1
- package/dist/components/content/InlineInput/InlineInput.js +1 -1
- package/dist/components/content/Item/Item.js +1 -1
- package/dist/components/content/ItemBadge/ItemBadge.js +1 -1
- package/dist/components/content/ItemCard/ItemCard.js +1 -1
- package/dist/components/content/Layout/GridLayout.js +1 -1
- package/dist/components/content/Layout/Layout.js +1 -1
- package/dist/components/content/Layout/LayoutBlock.js +1 -1
- package/dist/components/content/Layout/LayoutCenter.js +1 -1
- package/dist/components/content/Layout/LayoutContainer.js +1 -1
- package/dist/components/content/Layout/LayoutContent.js +1 -1
- package/dist/components/content/Layout/LayoutContext.js +1 -1
- package/dist/components/content/Layout/LayoutFlex.js +1 -1
- package/dist/components/content/Layout/LayoutFooter.js +1 -1
- package/dist/components/content/Layout/LayoutGrid.js +1 -1
- package/dist/components/content/Layout/LayoutHeader.js +1 -1
- package/dist/components/content/Layout/LayoutPane.js +1 -1
- package/dist/components/content/Layout/LayoutPanel.js +1 -1
- package/dist/components/content/Layout/LayoutPanelHeader.js +1 -1
- package/dist/components/content/Layout/LayoutToolbar.js +1 -1
- package/dist/components/content/Layout/hooks/useTinyScrollbar.js +1 -1
- package/dist/components/content/Layout/index.js +1 -1
- package/dist/components/content/Layout/utils.js +1 -1
- package/dist/components/content/Paragraph.js +1 -1
- package/dist/components/content/Placeholder/Placeholder.js +1 -1
- package/dist/components/content/PrismCode/PrismCode.js +1 -1
- package/dist/components/content/PrismCode/prismSetup.js +1 -1
- package/dist/components/content/PrismDiffCode/PrismDiffCode.js +1 -1
- package/dist/components/content/Result/Result.js +1 -1
- package/dist/components/content/Skeleton/Skeleton.js +1 -1
- package/dist/components/content/Tag/Tag.js +1 -1
- package/dist/components/content/Text.d.ts +7 -7
- package/dist/components/content/Text.js +1 -1
- package/dist/components/content/TextItem/TextItem.js +1 -1
- package/dist/components/content/Title.js +1 -1
- package/dist/components/content/Tree/Tree.js +1 -1
- package/dist/components/content/Tree/TreeNode.js +1 -1
- package/dist/components/content/Tree/styled.js +1 -1
- package/dist/components/content/Tree/tree-index.js +1 -1
- package/dist/components/content/Tree/use-checkbox-tree.js +1 -1
- package/dist/components/content/Tree/use-load-data.js +1 -1
- package/dist/components/content/highlightText.js +1 -1
- package/dist/components/content/use-auto-tooltip.js +1 -1
- package/dist/components/fields/Checkbox/Checkbox.js +1 -1
- package/dist/components/fields/Checkbox/CheckboxGroup.js +1 -1
- package/dist/components/fields/Checkbox/context.js +1 -1
- package/dist/components/fields/ComboBox/ComboBox.js +1 -1
- package/dist/components/fields/CommandTextArea/CommandTextArea.js +1 -1
- package/dist/components/fields/CommandTextArea/caretPosition.js +1 -1
- package/dist/components/fields/CommandTextArea/useCaretAnchor.js +1 -1
- package/dist/components/fields/DatePicker/DateInput.js +1 -1
- package/dist/components/fields/DatePicker/DateInputBase.js +1 -1
- package/dist/components/fields/DatePicker/DatePicker.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerButton.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerElement.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerInput.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerSegment.js +1 -1
- package/dist/components/fields/DatePicker/DateRangePicker.js +1 -1
- package/dist/components/fields/DatePicker/DateRangeSeparatedPicker.js +1 -1
- package/dist/components/fields/DatePicker/TimeInput.js +1 -1
- package/dist/components/fields/DatePicker/intl.js +1 -1
- package/dist/components/fields/DatePicker/parseDate.js +1 -1
- package/dist/components/fields/DatePicker/props.js +1 -1
- package/dist/components/fields/DatePicker/utils.js +1 -1
- package/dist/components/fields/FileInput/FileInput.js +1 -1
- package/dist/components/fields/FilterListBox/FilterListBox.js +1 -1
- package/dist/components/fields/FilterPicker/FilterPicker.js +1 -1
- package/dist/components/fields/Input/Input.js +1 -1
- package/dist/components/fields/ListBox/DraggableListBox.js +1 -1
- package/dist/components/fields/ListBox/ListBox.js +1 -1
- package/dist/components/fields/ListBoxPopover/ListBoxPopover.js +1 -1
- package/dist/components/fields/ListBoxPopover/listNavigation.js +1 -1
- package/dist/components/fields/ListBoxPopover/useCompositeFocus.js +1 -1
- package/dist/components/fields/NumberInput/NumberInput.js +1 -1
- package/dist/components/fields/NumberInput/StepButton.js +1 -1
- package/dist/components/fields/PasswordInput/PasswordInput.js +1 -1
- package/dist/components/fields/Picker/Picker.js +1 -1
- package/dist/components/fields/RadioGroup/Radio.js +1 -1
- package/dist/components/fields/RadioGroup/RadioGroup.js +1 -1
- package/dist/components/fields/RadioGroup/context.js +1 -1
- package/dist/components/fields/SearchInput/SearchInput.js +1 -1
- package/dist/components/fields/Select/Select.js +1 -1
- package/dist/components/fields/Slider/Gradation.js +1 -1
- package/dist/components/fields/Slider/HueSlider.js +1 -1
- package/dist/components/fields/Slider/RangeSlider.js +1 -1
- package/dist/components/fields/Slider/Slider.js +1 -1
- package/dist/components/fields/Slider/SliderBase.js +1 -1
- package/dist/components/fields/Slider/SliderThumb.js +1 -1
- package/dist/components/fields/Slider/SliderTrack.js +1 -1
- package/dist/components/fields/Slider/elements.js +1 -1
- package/dist/components/fields/Slider/index.js +1 -1
- package/dist/components/fields/Switch/Switch.js +1 -1
- package/dist/components/fields/TextArea/TextArea.js +1 -1
- package/dist/components/fields/TextInput/TextInput.js +1 -1
- package/dist/components/fields/TextInput/TextInputBase.js +1 -1
- package/dist/components/fields/TextInputMapper/TextInputMapper.js +1 -1
- package/dist/components/form/FieldWrapper/FieldWrapper.js +1 -1
- package/dist/components/form/FieldWrapper/extract-field-wrapper-props.js +1 -1
- package/dist/components/form/Form/Field.js +1 -1
- package/dist/components/form/Form/Form.js +1 -1
- package/dist/components/form/Form/ResetButton/ResetButton.js +1 -1
- package/dist/components/form/Form/SubmitButton/SubmitButton.js +1 -1
- package/dist/components/form/Form/SubmitError.js +1 -1
- package/dist/components/form/Form/index.js +1 -1
- package/dist/components/form/Form/use-field/use-field-props.js +1 -1
- package/dist/components/form/Form/use-field/use-field.js +1 -1
- package/dist/components/form/Form/use-form.js +1 -1
- package/dist/components/form/Form/validation.js +1 -1
- package/dist/components/form/Label.js +1 -1
- package/dist/components/form/wrapper.js +1 -1
- package/dist/components/helpers/DisplayTransition/DisplayTransition.js +1 -1
- package/dist/components/helpers/IconSwitch/IconSwitch.js +1 -1
- package/dist/components/layout/Board/Board.js +1 -1
- package/dist/components/layout/Board/BoardProvider.js +1 -1
- package/dist/components/layout/Board/BoardResponsive.js +1 -1
- package/dist/components/layout/Board/Widget.js +1 -1
- package/dist/components/layout/Board/WidgetHost.js +1 -1
- package/dist/components/layout/Board/board-context.js +1 -1
- package/dist/components/layout/Board/board-store.js +1 -1
- package/dist/components/layout/Board/grid-core/calculate.js +1 -1
- package/dist/components/layout/Board/grid-core/collision.js +1 -1
- package/dist/components/layout/Board/grid-core/compactors.js +1 -1
- package/dist/components/layout/Board/grid-core/constraints.js +1 -1
- package/dist/components/layout/Board/grid-core/layout.js +1 -1
- package/dist/components/layout/Board/grid-core/sort.js +1 -1
- package/dist/components/layout/Board/index.js +1 -1
- package/dist/components/layout/Board/responsive-utils.js +1 -1
- package/dist/components/layout/Board/use-board-layout.js +1 -1
- package/dist/components/layout/Board/use-board-registry.js +1 -1
- package/dist/components/layout/Flex.js +1 -1
- package/dist/components/layout/Flow.js +1 -1
- package/dist/components/layout/Grid.js +1 -1
- package/dist/components/layout/Panel.js +1 -1
- package/dist/components/layout/Prefix.js +1 -1
- package/dist/components/layout/ResizablePanel.js +1 -1
- package/dist/components/layout/Space.js +1 -1
- package/dist/components/layout/Suffix.js +1 -1
- package/dist/components/navigation/Tabs/DraggableTabList.js +1 -1
- package/dist/components/navigation/Tabs/TabButton.js +1 -1
- package/dist/components/navigation/Tabs/TabDropIndicator.js +1 -1
- package/dist/components/navigation/Tabs/TabPanel.js +1 -1
- package/dist/components/navigation/Tabs/TabPicker.js +1 -1
- package/dist/components/navigation/Tabs/Tabs.js +1 -1
- package/dist/components/navigation/Tabs/TabsAction.js +1 -1
- package/dist/components/navigation/Tabs/TabsContext.js +1 -1
- package/dist/components/navigation/Tabs/popover-placement.js +1 -1
- package/dist/components/navigation/Tabs/styled.js +1 -1
- package/dist/components/navigation/Tabs/types.js +1 -1
- package/dist/components/navigation/Tabs/use-tab-editing.js +1 -1
- package/dist/components/navigation/Tabs/use-tab-indicator.js +1 -1
- package/dist/components/organisms/FileTabs/FileTabs.js +1 -1
- package/dist/components/organisms/StatsCard/StatsCard.js +1 -1
- package/dist/components/other/Calendar/Calendar.js +1 -1
- package/dist/components/other/Calendar/CalendarCell.js +1 -1
- package/dist/components/other/Calendar/CalendarGrid.js +1 -1
- package/dist/components/other/Calendar/RangeCalendar.js +1 -1
- package/dist/components/other/CloudLogo/CloudLogo.js +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialog.js +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialogApiProvider.js +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialogZone.js +1 -1
- package/dist/components/overlays/Dialog/Dialog.js +1 -1
- package/dist/components/overlays/Dialog/DialogContainer.js +1 -1
- package/dist/components/overlays/Dialog/DialogForm.js +1 -1
- package/dist/components/overlays/Dialog/DialogTrigger.js +1 -1
- package/dist/components/overlays/Dialog/context.js +1 -1
- package/dist/components/overlays/Dialog/use-dialog-container.js +1 -1
- package/dist/components/overlays/Modal/Modal.js +1 -1
- package/dist/components/overlays/Modal/OpenTransitionContext.js +1 -1
- package/dist/components/overlays/Modal/Overlay.js +1 -1
- package/dist/components/overlays/Modal/Popover.js +1 -1
- package/dist/components/overlays/Modal/Tray.js +1 -1
- package/dist/components/overlays/Modal/Underlay.js +1 -1
- package/dist/components/overlays/Notifications/Notification.js +1 -1
- package/dist/components/overlays/Notifications/NotificationAction.js +1 -1
- package/dist/components/overlays/Notifications/NotificationCard.js +1 -1
- package/dist/components/overlays/Notifications/NotificationContext.js +1 -1
- package/dist/components/overlays/Notifications/NotificationItem.js +1 -1
- package/dist/components/overlays/Notifications/OverlayContainer.js +1 -1
- package/dist/components/overlays/Notifications/OverlayProvider.js +1 -1
- package/dist/components/overlays/Notifications/PersistentNotificationsList.js +1 -1
- package/dist/components/overlays/Notifications/dismissed-storage.js +1 -1
- package/dist/components/overlays/Notifications/format-relative-time.js +1 -1
- package/dist/components/overlays/Notifications/index.js +1 -1
- package/dist/components/overlays/Notifications/use-notification-state.js +1 -1
- package/dist/components/overlays/Notifications/use-notifications.js +1 -1
- package/dist/components/overlays/Notifications/use-overlay-timers.js +1 -1
- package/dist/components/overlays/Notifications/use-persistent-notifications.js +1 -1
- package/dist/components/overlays/Notifications/use-persistent-state.js +1 -1
- package/dist/components/overlays/Notifications/use-toast-state.js +1 -1
- package/dist/components/overlays/Toast/ToastItem.js +1 -1
- package/dist/components/overlays/Toast/index.js +1 -1
- package/dist/components/overlays/Toast/useProgressToast.js +1 -1
- package/dist/components/overlays/Toast/useToast.js +1 -1
- package/dist/components/overlays/Tooltip/Tooltip.js +1 -1
- package/dist/components/overlays/Tooltip/TooltipProvider.js +1 -1
- package/dist/components/overlays/Tooltip/TooltipTrigger.js +1 -1
- package/dist/components/overlays/Tooltip/context.js +1 -1
- package/dist/components/portal/Portal.js +1 -1
- package/dist/components/portal/PortalProvider.js +1 -1
- package/dist/components/portal/usePortal.js +1 -1
- package/dist/components/shared/DraggableCollection.js +1 -1
- package/dist/components/shared/InvalidIcon.js +1 -1
- package/dist/components/shared/ValidIcon.js +1 -1
- package/dist/components/status/LoadingAnimation/LoadingAnimation.js +1 -1
- package/dist/components/status/Spin/Cube.js +1 -1
- package/dist/components/status/Spin/InternalSpinner.js +1 -1
- package/dist/components/status/Spin/Spin.js +1 -1
- package/dist/components/status/Spin/SpinsContainer.js +1 -1
- package/dist/data/item-themes.js +1 -1
- package/dist/data/themes.js +1 -1
- package/dist/icons/AdjustmentsHorizontalIcon.js +1 -1
- package/dist/icons/AdjustmentsIcon.js +1 -1
- package/dist/icons/AiIcon.js +1 -1
- package/dist/icons/AreaChartIcon.js +1 -1
- package/dist/icons/BackwardIcon.js +1 -1
- package/dist/icons/BarChartIcon.js +1 -1
- package/dist/icons/BellFilledIcon.js +1 -1
- package/dist/icons/BellIcon.js +1 -1
- package/dist/icons/BooleanIcon.js +1 -1
- package/dist/icons/CalendarEditIcon.js +1 -1
- package/dist/icons/CalendarIcon.js +1 -1
- package/dist/icons/CaretDownIcon.js +1 -1
- package/dist/icons/CaretUpIcon.js +1 -1
- package/dist/icons/ChartAreaStackedIcon.js +1 -1
- package/dist/icons/ChartAreaStackedPercentageIcon.js +1 -1
- package/dist/icons/ChartBarGroupedHorizontalIcon.js +1 -1
- package/dist/icons/ChartBarGroupedIcon.js +1 -1
- package/dist/icons/ChartBarHorizontalIcon.js +1 -1
- package/dist/icons/ChartBarLineIcon.js +1 -1
- package/dist/icons/ChartBarStackedHorizontalIcon.js +1 -1
- package/dist/icons/ChartBarStackedIcon.js +1 -1
- package/dist/icons/ChartBarStackedPercentageHorizontalIcon.js +1 -1
- package/dist/icons/ChartBarStackedPercentageIcon.js +1 -1
- package/dist/icons/ChartBoxPlot2Icon.js +1 -1
- package/dist/icons/ChartBoxPlotIcon.js +1 -1
- package/dist/icons/ChartBubbleIcon.js +1 -1
- package/dist/icons/ChartDonut2Icon.js +1 -1
- package/dist/icons/ChartFunnelIcon.js +1 -1
- package/dist/icons/ChartHeatmapIcon.js +1 -1
- package/dist/icons/ChartKPIIcon.js +1 -1
- package/dist/icons/ChartPie2Icon.js +1 -1
- package/dist/icons/ChartScatterIcon.js +1 -1
- package/dist/icons/CheckCircleFilledIcon.js +1 -1
- package/dist/icons/CheckCircleIcon.js +1 -1
- package/dist/icons/CheckIcon.js +1 -1
- package/dist/icons/CircleFilledIcon.js +1 -1
- package/dist/icons/ClearIcon.js +1 -1
- package/dist/icons/CloseCircleFilledIcon.js +1 -1
- package/dist/icons/CloseCircleIcon.js +1 -1
- package/dist/icons/CloseIcon.js +1 -1
- package/dist/icons/CodeIcon.js +1 -1
- package/dist/icons/ColumnTotalIcon.js +1 -1
- package/dist/icons/CopyIcon.js +1 -1
- package/dist/icons/CountIcon.js +1 -1
- package/dist/icons/CubeIcon.js +1 -1
- package/dist/icons/CubePauseIcon.js +1 -1
- package/dist/icons/CubePlayIcon.js +1 -1
- package/dist/icons/CurrencyDollarIcon.js +1 -1
- package/dist/icons/DangerIcon.js +1 -1
- package/dist/icons/DashboardIcon.js +1 -1
- package/dist/icons/DatabaseIcon.js +1 -1
- package/dist/icons/DecimalDecreaseIcon.js +1 -1
- package/dist/icons/DecimalIncreaseIcon.js +1 -1
- package/dist/icons/DirectionIcon.js +1 -1
- package/dist/icons/DonutIcon.js +1 -1
- package/dist/icons/DownIcon.js +1 -1
- package/dist/icons/EditIcon.js +1 -1
- package/dist/icons/ExclamationCircleFilledIcon.js +1 -1
- package/dist/icons/ExclamationCircleIcon.js +1 -1
- package/dist/icons/ExclamationIcon.js +1 -1
- package/dist/icons/EyeIcon.js +1 -1
- package/dist/icons/EyeInvisibleIcon.js +1 -1
- package/dist/icons/FilterIcon.js +1 -1
- package/dist/icons/FolderFilledIcon.js +1 -1
- package/dist/icons/FolderIcon.js +1 -1
- package/dist/icons/FolderOpenFilledIcon.js +1 -1
- package/dist/icons/FolderOpenIcon.js +1 -1
- package/dist/icons/ForwardIcon.js +1 -1
- package/dist/icons/GripVerticalIcon.js +1 -1
- package/dist/icons/HierarchyIcon.js +1 -1
- package/dist/icons/HierarchyOpenIcon.js +1 -1
- package/dist/icons/Icon.js +1 -1
- package/dist/icons/InfoCircleIcon.js +1 -1
- package/dist/icons/InfoIcon.js +1 -1
- package/dist/icons/KeyIcon.js +1 -1
- package/dist/icons/LeftIcon.js +1 -1
- package/dist/icons/LineChartIcon.js +1 -1
- package/dist/icons/LoadingIcon.js +1 -1
- package/dist/icons/LockFilledIcon.js +1 -1
- package/dist/icons/LockIcon.js +1 -1
- package/dist/icons/MoreIcon.js +1 -1
- package/dist/icons/NotAllowedIcon.js +1 -1
- package/dist/icons/Number123Icon.js +1 -1
- package/dist/icons/NumberIcon.js +1 -1
- package/dist/icons/PauseCircleFilledIcon.js +1 -1
- package/dist/icons/PauseCircleIcon.js +1 -1
- package/dist/icons/PauseIcon.js +1 -1
- package/dist/icons/PercentageIcon.js +1 -1
- package/dist/icons/PieChartIcon.js +1 -1
- package/dist/icons/PlayCircleIcon.js +1 -1
- package/dist/icons/PlayIcon.js +1 -1
- package/dist/icons/PlusIcon.js +1 -1
- package/dist/icons/ProgressBarIcon.js +1 -1
- package/dist/icons/ReloadIcon.js +1 -1
- package/dist/icons/ReportIcon.js +1 -1
- package/dist/icons/ReturnIcon.js +1 -1
- package/dist/icons/RightIcon.js +1 -1
- package/dist/icons/RowTotalsIcon.js +1 -1
- package/dist/icons/SchemeIcon.js +1 -1
- package/dist/icons/SearchIcon.js +1 -1
- package/dist/icons/SemanticQueryIcon.js +1 -1
- package/dist/icons/SettingsIcon.js +1 -1
- package/dist/icons/ShieldFilledIcon.js +1 -1
- package/dist/icons/ShieldIcon.js +1 -1
- package/dist/icons/SlashIcon.js +1 -1
- package/dist/icons/SparklesIcon.js +1 -1
- package/dist/icons/SqlIcon.js +1 -1
- package/dist/icons/StatsIcon.js +1 -1
- package/dist/icons/StopIcon.js +1 -1
- package/dist/icons/StringIcon.js +1 -1
- package/dist/icons/SubtotalsIcon.js +1 -1
- package/dist/icons/SwitchIcon.js +1 -1
- package/dist/icons/TableIcon.js +1 -1
- package/dist/icons/ThumbsDownIcon.js +1 -1
- package/dist/icons/ThumbsUpIcon.js +1 -1
- package/dist/icons/ThunderboltCrossedIcon.js +1 -1
- package/dist/icons/ThunderboltFilledIcon.js +1 -1
- package/dist/icons/ThunderboltIcon.js +1 -1
- package/dist/icons/TimeIcon.js +1 -1
- package/dist/icons/TrashIcon.js +1 -1
- package/dist/icons/UnlockIcon.js +1 -1
- package/dist/icons/UpIcon.js +1 -1
- package/dist/icons/UserGroupIcon.js +1 -1
- package/dist/icons/UserIcon.js +1 -1
- package/dist/icons/UserLockIcon.js +1 -1
- package/dist/icons/ViewIcon.js +1 -1
- package/dist/icons/WarningFilledIcon.js +1 -1
- package/dist/icons/WarningIcon.js +1 -1
- package/dist/icons/wrap-icon.js +1 -1
- package/dist/index.js +1 -1
- package/dist/provider.js +1 -1
- package/dist/providers/TrackingProvider.js +1 -1
- package/dist/providers/navigationAdapter.default.js +1 -1
- package/dist/tokens/base.js +1 -1
- package/dist/tokens/colors.js +1 -2
- package/dist/tokens/colors.js.map +1 -1
- package/dist/tokens/index.js +1 -1
- package/dist/tokens/layout.js +1 -1
- package/dist/tokens/palette.js +105 -105
- package/dist/tokens/palette.js.map +1 -1
- package/dist/tokens/shadows.js +1 -1
- package/dist/tokens/sizes.js +1 -1
- package/dist/tokens/spacing.js +1 -1
- package/dist/tokens/typography.js +1 -1
- package/dist/utils/ResizeSensor.js +1 -1
- package/dist/utils/is-dev-env.js +1 -1
- package/dist/utils/modules.js +1 -1
- package/dist/utils/promise.js +1 -1
- package/dist/utils/raf.js +1 -1
- package/dist/utils/random.js +1 -1
- package/dist/utils/range.js +1 -1
- package/dist/utils/react/RenderCache.js +1 -1
- package/dist/utils/react/Slots.js +1 -1
- package/dist/utils/react/chain.js +1 -1
- package/dist/utils/react/forwardRefWithGenerics.js +1 -1
- package/dist/utils/react/index.js +1 -1
- package/dist/utils/react/interactions.js +1 -1
- package/dist/utils/react/isTextOnly.js +1 -1
- package/dist/utils/react/mapProps.js +1 -1
- package/dist/utils/react/mergeProps.js +1 -1
- package/dist/utils/react/nullableValue.js +1 -1
- package/dist/utils/react/resolveIcon.js +1 -1
- package/dist/utils/react/sharedStore.js +1 -1
- package/dist/utils/react/useCombinedRefs.js +1 -1
- package/dist/utils/react/useControlledFocusVisible.js +1 -1
- package/dist/utils/react/useEventBus.js +1 -1
- package/dist/utils/react/useId.js +1 -1
- package/dist/utils/react/useIsDarwin.js +1 -1
- package/dist/utils/react/useKeySymbols.js +1 -1
- package/dist/utils/react/useLayoutEffect.js +1 -1
- package/dist/utils/react/useLocalStorage.js +1 -1
- package/dist/utils/react/useMergeStyles.js +1 -1
- package/dist/utils/react/usePopoverSync.js +1 -1
- package/dist/utils/react/useQaProps.js +1 -1
- package/dist/utils/react/useViewportSize.js +1 -1
- package/dist/utils/react/wrapNodeIfPlain.js +1 -1
- package/dist/utils/selection.js +1 -1
- package/dist/utils/styles.js +1 -1
- package/dist/utils/tree.js +1 -1
- package/dist/utils/warnings.js +1 -1
- package/dist/version.js +3 -3
- package/docs/glaze/api.md +510 -150
- package/docs/glaze/methodology.md +438 -213
- package/docs/glaze/migration.md +152 -14
- package/docs/glaze/okhst.md +308 -0
- package/package.json +4 -4
package/docs/glaze/api.md
CHANGED
|
@@ -39,7 +39,7 @@ const d = glaze.fromRgb(122, 77, 191);
|
|
|
39
39
|
const e = glaze.from(a.export());
|
|
40
40
|
|
|
41
41
|
// Per-theme config override:
|
|
42
|
-
const rawTheme = glaze(280, 80, {
|
|
42
|
+
const rawTheme = glaze(280, 80, { lightTone: false, darkTone: false });
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
The optional `config` parameter is a `GlazeConfigOverride` — see [Per-instance config override](#per-instance-config-override).
|
|
@@ -72,15 +72,15 @@ A `GlazeTheme` exposes:
|
|
|
72
72
|
### `theme.colors(defs)`
|
|
73
73
|
|
|
74
74
|
```ts
|
|
75
|
-
theme.colors({ surface: {
|
|
76
|
-
theme.colors({ text: {
|
|
75
|
+
theme.colors({ surface: { tone: 97 } });
|
|
76
|
+
theme.colors({ text: { tone: 30 } });
|
|
77
77
|
// Both 'surface' and 'text' are now defined.
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
### `theme.color(name) / theme.color(name, def)`
|
|
81
81
|
|
|
82
82
|
```ts
|
|
83
|
-
theme.color('surface', {
|
|
83
|
+
theme.color('surface', { tone: 97, saturation: 0.75 }); // set
|
|
84
84
|
const def = theme.color('surface'); // get
|
|
85
85
|
```
|
|
86
86
|
|
|
@@ -91,11 +91,11 @@ Creates a new theme inheriting all color definitions, optionally replacing the h
|
|
|
91
91
|
```ts
|
|
92
92
|
const danger = primary.extend({
|
|
93
93
|
hue: 23,
|
|
94
|
-
colors: { 'accent-fill': {
|
|
94
|
+
colors: { 'accent-fill': { tone: 48, mode: 'fixed' } },
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
-
// Inherit parent's config override and
|
|
98
|
-
const highSat = base.extend({ config: {
|
|
97
|
+
// Inherit parent's config override and widen the dark window further:
|
|
98
|
+
const highSat = base.extend({ config: { darkTone: [10, 100] } });
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
`GlazeExtendOptions`:
|
|
@@ -115,14 +115,14 @@ Flat token map grouped by scheme variant.
|
|
|
115
115
|
|
|
116
116
|
```ts
|
|
117
117
|
theme.tokens()
|
|
118
|
-
// → { light: { surface: '
|
|
118
|
+
// → { light: { surface: 'oklch(...)' }, dark: { surface: 'oklch(...)' } }
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
`GlazeJsonOptions`:
|
|
122
122
|
|
|
123
123
|
| Option | Default | Description |
|
|
124
124
|
|---|---|---|
|
|
125
|
-
| `format` | `'
|
|
125
|
+
| `format` | `'oklch'` | Output color format. One of `'rgb' \| 'hsl' \| 'oklch'`. `'okhsl'` and `'okhst'` throw — use `tasty()` for those. |
|
|
126
126
|
| `modes` | `{ dark: true, highContrast: false }` (or global config) | Which scheme variants to include. |
|
|
127
127
|
|
|
128
128
|
### `theme.tasty(options?)`
|
|
@@ -141,10 +141,12 @@ theme.tasty()
|
|
|
141
141
|
|
|
142
142
|
| Option | Default | Description |
|
|
143
143
|
|---|---|---|
|
|
144
|
-
| `format` | `'okhsl'` | Output color format. |
|
|
144
|
+
| `format` | `'okhsl'` | Output color format. `'okhsl'` and `'okhst'` are supported here (Tasty-only spaces). |
|
|
145
145
|
| `modes` | global config | Which scheme variants to include. |
|
|
146
146
|
| `states.dark` | `'@dark'` (or global config) | State alias for dark mode tokens. |
|
|
147
147
|
| `states.highContrast` | `'@high-contrast'` (or global config) | State alias for high-contrast tokens. |
|
|
148
|
+
| `splitHue` | `false` | Emit hue as a separate custom property (`$name-hue` token + `var()` in `oklch` values). Requires `format: 'oklch'` and every color to be pastel. |
|
|
149
|
+
| `name` | `'theme'` | Base name for the theme-level hue var (`$theme-hue` / `--theme-hue`). Palette export auto-derives this from the theme name. |
|
|
148
150
|
| `prefix` | (palette only) | See [Palette](#palette). |
|
|
149
151
|
|
|
150
152
|
When both `dark` and `highContrast` modes are enabled, dark high-contrast variants are emitted under the combined key `<dark> & <highContrast>` (e.g. `'@dark & @high-contrast'`).
|
|
@@ -156,8 +158,8 @@ Per-color JSON map.
|
|
|
156
158
|
```ts
|
|
157
159
|
theme.json()
|
|
158
160
|
// → {
|
|
159
|
-
// surface: { light: '
|
|
160
|
-
// text: { light: '
|
|
161
|
+
// surface: { light: 'oklch(...)', dark: 'oklch(...)' },
|
|
162
|
+
// text: { light: 'oklch(...)', dark: 'oklch(...)' },
|
|
161
163
|
// }
|
|
162
164
|
```
|
|
163
165
|
|
|
@@ -181,11 +183,137 @@ theme.css();
|
|
|
181
183
|
|
|
182
184
|
| Option | Default | Description |
|
|
183
185
|
|---|---|---|
|
|
184
|
-
| `format` | `'rgb'` | Output color format. |
|
|
186
|
+
| `format` | `'rgb'` | Output color format. `'okhsl'` and `'okhst'` throw — use `tasty()` for those. |
|
|
185
187
|
| `suffix` | `'-color'` | Suffix appended to each CSS property name. Pass `''` for bare property names. |
|
|
188
|
+
| `splitHue` | `false` | Emit hue as a separate `--*-hue` custom property referenced via `var()` in `oklch` color values. Requires `format: 'oklch'` and every color to be pastel. Shadow/mix colors stay inline (blended hue; they do not follow `--hue` rotation). |
|
|
189
|
+
| `name` | `'theme'` | Base name for the theme-level hue var (`--theme-hue`). Palette export auto-derives this from the theme name. |
|
|
186
190
|
|
|
187
191
|
`GlazeCssResult` always contains all four keys (`light`, `dark`, `lightContrast`, `darkContrast`); empty if no colors are defined for that variant.
|
|
188
192
|
|
|
193
|
+
### `theme.dtcg(options?)`
|
|
194
|
+
|
|
195
|
+
W3C [Design Tokens Format Module (2025.10)](https://www.designtokens.org/) documents — the vendor-neutral JSON format consumed by Figma, Tokens Studio, Style Dictionary v4+, Terrazzo, Penpot, and every DTCG-compatible tool. Returns one spec-conformant token tree per scheme variant.
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
theme.dtcg()
|
|
199
|
+
// → {
|
|
200
|
+
// light: {
|
|
201
|
+
// surface: {
|
|
202
|
+
// $type: 'color',
|
|
203
|
+
// $value: { colorSpace: 'srgb', components: [0.96, 0.94, 0.98], hex: '#f5f0fa' },
|
|
204
|
+
// },
|
|
205
|
+
// },
|
|
206
|
+
// dark: {
|
|
207
|
+
// surface: {
|
|
208
|
+
// $type: 'color',
|
|
209
|
+
// $value: { colorSpace: 'srgb', components: [0.16, 0.14, 0.2], hex: '#292333' },
|
|
210
|
+
// },
|
|
211
|
+
// },
|
|
212
|
+
// }
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Write each document to its own `.tokens.json` file — one file per scheme is the most tool-compatible convention (one per Style Dictionary theme / Tokens Studio set / Figma variable mode).
|
|
216
|
+
|
|
217
|
+
`GlazeDtcgOptions`:
|
|
218
|
+
|
|
219
|
+
| Option | Default | Description |
|
|
220
|
+
|---|---|---|
|
|
221
|
+
| `colorSpace` | `'srgb'` | Color space for `$value`. `'srgb'` emits gamma sRGB `components` (0–1) plus a `hex` hint — universally understood. `'oklch'` emits `[L, C, H]` components with no hex — Glaze-native, wide-gamut. |
|
|
222
|
+
| `modes` | global config | Which scheme variants to include. `light` is always present. |
|
|
223
|
+
|
|
224
|
+
`alpha` is included on `$value` only when the color's opacity is below 1. `$type` is always `'color'`.
|
|
225
|
+
|
|
226
|
+
### `theme.dtcgResolver(options?)`
|
|
227
|
+
|
|
228
|
+
A single W3C [DTCG Resolver-Module](https://www.designtokens.org/) document describing **every scheme variant in one file** — an alternative to `dtcg()`'s per-scheme files for tools that resolve sets + modifiers (e.g. Dispersa). The light document becomes `sets.base.sources[0]` (the default context); each other variant becomes a context override on a single `scheme` modifier.
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
theme.dtcgResolver({ modes: { highContrast: true } })
|
|
232
|
+
// → {
|
|
233
|
+
// version: '2025.10',
|
|
234
|
+
// sets: {
|
|
235
|
+
// base: {
|
|
236
|
+
// sources: [
|
|
237
|
+
// {
|
|
238
|
+
// surface: {
|
|
239
|
+
// $type: 'color',
|
|
240
|
+
// $value: { colorSpace: 'srgb', components: [0.96, 0.94, 0.98], hex: '#f5f0fa' },
|
|
241
|
+
// },
|
|
242
|
+
// },
|
|
243
|
+
// ],
|
|
244
|
+
// },
|
|
245
|
+
// },
|
|
246
|
+
// modifiers: {
|
|
247
|
+
// scheme: {
|
|
248
|
+
// default: 'light',
|
|
249
|
+
// contexts: {
|
|
250
|
+
// light: [],
|
|
251
|
+
// dark: [
|
|
252
|
+
// {
|
|
253
|
+
// surface: {
|
|
254
|
+
// $type: 'color',
|
|
255
|
+
// $value: { colorSpace: 'srgb', components: [0.16, 0.14, 0.2], hex: '#292333' },
|
|
256
|
+
// },
|
|
257
|
+
// },
|
|
258
|
+
// ],
|
|
259
|
+
// lightContrast: [ /* … */ ],
|
|
260
|
+
// darkContrast: [ /* … */ ],
|
|
261
|
+
// },
|
|
262
|
+
// },
|
|
263
|
+
// },
|
|
264
|
+
// resolutionOrder: [
|
|
265
|
+
// { $ref: '#/sets/base' },
|
|
266
|
+
// { $ref: '#/modifiers/scheme' },
|
|
267
|
+
// ],
|
|
268
|
+
// }
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Why one modifier with four contexts.** Glaze resolves `darkContrast` independently — it is not `dark` + `lightContrast` layered. The resolver model composes modifiers additively (last in `resolutionOrder` wins on conflict), so two independent modifiers (`scheme` × `contrast`) would produce wrong values for the dark + high-contrast permutation. One `scheme` modifier with a context per variant keeps every resolved value exact. Choose `dtcgResolver()` when you want single-file theming and feed it to a resolver tool; choose `dtcg()` for maximum per-file tool compatibility.
|
|
272
|
+
|
|
273
|
+
`GlazeDtcgResolverOptions` (extends `GlazeDtcgOptions`, so `modes` and `colorSpace` pass through):
|
|
274
|
+
|
|
275
|
+
| Option | Default | Description |
|
|
276
|
+
|---|---|---|
|
|
277
|
+
| `colorSpace` | `'srgb'` | Same as `dtcg()` — flows through to every source and context. |
|
|
278
|
+
| `modes` | global config | Which scheme variants to emit as contexts. `light` is always present (the default); absent variants are omitted. |
|
|
279
|
+
| `setName` | `'base'` | Name of the single set holding the default (light) token tree. |
|
|
280
|
+
| `modifierName` | `'scheme'` | Name of the modifier describing the scheme axis. |
|
|
281
|
+
| `contextNames` | identity | Override the four context names (`light` / `dark` / `lightContrast` / `darkContrast`) — e.g. `{ dark: 'night' }`. |
|
|
282
|
+
| `version` | `'2025.10'` | Resolver document version. |
|
|
283
|
+
|
|
284
|
+
### `theme.tailwind(options?)`
|
|
285
|
+
|
|
286
|
+
A Tailwind CSS v4 `@theme` block (light baseline) plus dark / high-contrast overrides under configurable selectors. Returns a single ready-to-paste CSS string. The `--color-*` namespace auto-generates `bg-*` / `text-*` / `border-*` utilities.
|
|
287
|
+
|
|
288
|
+
```css
|
|
289
|
+
@theme {
|
|
290
|
+
--color-surface: oklch(0.96 0.01 280);
|
|
291
|
+
--color-text: oklch(0.3 0.05 280);
|
|
292
|
+
}
|
|
293
|
+
.dark {
|
|
294
|
+
--color-surface: oklch(0.16 0.01 280);
|
|
295
|
+
--color-text: oklch(0.85 0.05 280);
|
|
296
|
+
}
|
|
297
|
+
.high-contrast {
|
|
298
|
+
--color-surface: oklch(0.98 0.01 280);
|
|
299
|
+
--color-text: oklch(0.1 0.05 280);
|
|
300
|
+
}
|
|
301
|
+
.dark.high-contrast {
|
|
302
|
+
--color-surface: oklch(0.05 0.01 280);
|
|
303
|
+
--color-text: oklch(0.95 0.05 280);
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
`GlazeTailwindOptions`:
|
|
308
|
+
|
|
309
|
+
| Option | Default | Description |
|
|
310
|
+
|---|---|---|
|
|
311
|
+
| `format` | `'oklch'` | Output color format for the values. |
|
|
312
|
+
| `namespace` | `'color-'` | CSS custom property namespace, forming `--<namespace><name>` (e.g. `--color-surface`). Named `namespace` to avoid clashing with the palette theme-prefix option. |
|
|
313
|
+
| `darkSelector` | `'.dark'` | Selector wrapping the dark overrides. Pass an at-rule like `'@media (prefers-color-scheme: dark)'` to drive dark mode from the OS preference (it nests `:root` automatically). |
|
|
314
|
+
| `highContrastSelector` | `'.high-contrast'` | Selector wrapping the light high-contrast overrides. The combined dark + high-contrast block uses `${darkSelector}${highContrastSelector}` (e.g. `.dark.high-contrast`). |
|
|
315
|
+
| `modes` | global config | Which scheme variants to include. The `@theme` block (light) is always emitted when colors exist. |
|
|
316
|
+
|
|
189
317
|
### `theme.export()`
|
|
190
318
|
|
|
191
319
|
```ts
|
|
@@ -211,61 +339,182 @@ type ColorDef = RegularColorDef | ShadowColorDef | MixColorDef;
|
|
|
211
339
|
|
|
212
340
|
| Field | Type | Description |
|
|
213
341
|
|---|---|---|
|
|
214
|
-
| `
|
|
342
|
+
| `tone` | `HCPair<ToneValue>` | Number = absolute (0–100, contrast-uniform). `'+N'`/`'-N'` = relative to base's tone (requires `base`). `'max'`/`'min'` = forced to the scheme's tone extreme (no `base`). Optional HC pair `[normal, hc]`. |
|
|
215
343
|
| `saturation` | `number` | Saturation factor applied to the seed saturation (0–1). Default: `1`. |
|
|
216
344
|
| `hue` | `number \| RelativeValue` | Number = absolute (0–360). String (`'+N'`/`'-N'`) = relative to the **theme seed hue** (never to a base color). |
|
|
217
345
|
| `base` | `string` | Name of another color in the same theme — makes this a *dependent* color. |
|
|
218
|
-
| `contrast` | `HCPair<
|
|
346
|
+
| `contrast` | `HCPair<ContrastSpec>` | Contrast floor against `base`. Requires `base`. See [`contrast`](#contrast-floor). |
|
|
219
347
|
| `mode` | `'auto' \| 'fixed' \| 'static'` | Adaptation mode. Default: `'auto'`. See [Adaptation modes](#adaptation-modes). |
|
|
348
|
+
| `autoFlip` | `boolean` | Flip out-of-bounds results (relative `tone` overshoot / unmet `contrast`) to the opposite side instead of clamping. Default: the global `autoFlip` (`true`). See [`autoFlip`](#autoflip). |
|
|
220
349
|
| `opacity` | `number` | Fixed alpha 0–1. Output includes alpha in the CSS value. Combining with `contrast` is not recommended (a `console.warn` is emitted). |
|
|
350
|
+
| `pastel` | `boolean` | Per-color override for the hue-independent "safe" chroma limit used in OKHSL↔sRGB conversions (luminance, contrast solving, output formatting). Falls through to the global / per-theme `pastel` config when omitted. Default: unset. See [Per-color `pastel`](#per-color-pastel). |
|
|
351
|
+
| `role` | `RoleInput` | Semantic role against `base` (`'text'` / `'surface'` / `'border'` or an alias). Fixes APCA contrast polarity. Resolved via: explicit `role` → name inference → opposite of the base's role → `'text'`. See [Roles](#roles). |
|
|
221
352
|
| `inherit` | `boolean` | Whether this color is inherited by child themes via `extend()`. Default: `true`. Set to `false` to make the color local to the current theme. |
|
|
222
353
|
|
|
223
|
-
####
|
|
354
|
+
#### Tone values
|
|
355
|
+
|
|
356
|
+
`tone` (0–100) replaces OKHSL lightness with a contrast-uniform axis — equal tone steps give equal WCAG contrast. See [`docs/okhst.md`](okhst.md) for the math. (To port old `lightness` values, see [migration.md](migration.md).)
|
|
224
357
|
|
|
225
358
|
| Form | Example | Meaning |
|
|
226
359
|
|---|---|---|
|
|
227
|
-
| Number (absolute) | `
|
|
228
|
-
| String (relative) | `
|
|
229
|
-
|
|
|
360
|
+
| Number (absolute) | `tone: 45` | Absolute tone 0–100. |
|
|
361
|
+
| String (relative) | `tone: '-52'` | Relative to base color's tone (requires `base`). |
|
|
362
|
+
| Extreme | `tone: 'max'` / `'min'` | Force to the scheme's highest (`'max'` = 100) or lowest (`'min'` = 0) tone. No `base` needed. |
|
|
363
|
+
| HC pair | `tone: ['-7', '-20']` | `[normal, high-contrast]`. A single value applies to both. |
|
|
364
|
+
|
|
365
|
+
**Absolute tone** on a dependent color (`base` set) positions the color independently. In dark mode it is tone-mapped (inverted + windowed) on its own. The `contrast` solver acts as a safety net.
|
|
366
|
+
|
|
367
|
+
**Relative tone** applies a signed delta to the base color's resolved tone. Because tone is contrast-uniform, a fixed delta yields a fixed contrast step. In dark mode with `mode: 'auto'`, the offset is anchored to the base's per-scheme tone. If `base + delta` falls outside `[0, 100]`, the result is clamped to the boundary, or — with `autoFlip` (default on) — mirrored to the other side of the base.
|
|
230
368
|
|
|
231
|
-
**
|
|
369
|
+
**Extreme tone** (`'max'` / `'min'`) forces the color to the scheme's tone extreme without a contrast hack or a magic number. `'max'` resolves to author tone 100 and `'min'` to 0; both flow through scheme mapping like an absolute tone, so under `mode: 'auto'` they invert in dark (`'max'` is lightest in light, darkest in dark). Use `mode: 'static'` to pin the same extreme across schemes, or `mode: 'fixed'` to keep the same end without inverting. No `base` required.
|
|
232
370
|
|
|
233
|
-
|
|
371
|
+
A dependent color with `base` but no `tone` inherits the base's tone (equivalent to a delta of 0).
|
|
234
372
|
|
|
235
|
-
|
|
373
|
+
#### `autoFlip`
|
|
236
374
|
|
|
237
|
-
|
|
375
|
+
`autoFlip` governs what happens when a result would fall outside its valid range:
|
|
376
|
+
|
|
377
|
+
- **Relative `tone` overshoot:** when `base ± delta` exceeds `[0, 100]`, `autoFlip` mirrors the delta to the other side of the base (e.g. `'+30'` becomes `'-30'`) instead of clamping to the boundary.
|
|
378
|
+
- **`contrast` direction:** when the requested tone direction can't meet the floor, `autoFlip` lets the solver try the opposite side (the same behavior as the global `autoFlip`).
|
|
379
|
+
|
|
380
|
+
`autoFlip` defaults to the global `autoFlip` (`true`). Set `autoFlip: false` on a color to clamp instead of mirror — useful when you want a relative offset to stay on the authored side of the base, or to keep an unmet contrast pinned to one direction's extreme.
|
|
381
|
+
|
|
382
|
+
#### `contrast` (floor)
|
|
238
383
|
|
|
239
384
|
```ts
|
|
240
|
-
type
|
|
385
|
+
type ContrastPreset = 'AA' | 'AAA' | 'AA-large' | 'AAA-large';
|
|
386
|
+
type ContrastSpec =
|
|
387
|
+
| number // bare WCAG ratio
|
|
388
|
+
| ContrastPreset // named WCAG preset
|
|
389
|
+
| { wcag: HCPair<number | ContrastPreset> }
|
|
390
|
+
| { apca: HCPair<number> }; // APCA Lc target
|
|
241
391
|
```
|
|
242
392
|
|
|
243
|
-
| Preset |
|
|
393
|
+
| Preset | WCAG ratio |
|
|
244
394
|
|---|---|
|
|
245
395
|
| `'AA-large'` | 3 |
|
|
246
396
|
| `'AA'` | 4.5 |
|
|
247
397
|
| `'AAA-large'` | 4.5 |
|
|
248
398
|
| `'AAA'` | 7 |
|
|
249
399
|
|
|
250
|
-
|
|
400
|
+
A bare number or preset means **WCAG**. Use `{ wcag }` / `{ apca }` to pick the metric explicitly. The `[normal, highContrast]` pair may live at the outer level (`[4.5, 7]`, `[{ wcag: 4.5 }, { wcag: 7 }]`) or inside the metric (`{ wcag: [4.5, 7] }`, `{ apca: [45, 60] }`).
|
|
401
|
+
|
|
402
|
+
```ts
|
|
403
|
+
contrast: 4.5 // WCAG 4.5
|
|
404
|
+
contrast: 'AAA' // WCAG 7
|
|
405
|
+
contrast: { wcag: 6 } // WCAG 6
|
|
406
|
+
contrast: { wcag: [4.5, 7] } // WCAG 4.5 normal / 7 high-contrast (explicit)
|
|
407
|
+
contrast: { apca: 60 } // APCA Lc 60 normal / 75 high-contrast (auto)
|
|
408
|
+
contrast: { apca: [45, 60] } // APCA Lc 45 normal / 60 high-contrast (explicit)
|
|
409
|
+
contrast: { apca: 'content' } // APCA preset -> Lc 60 normal / 75 high-contrast (auto)
|
|
410
|
+
contrast: { apca: ['content', 'body'] } // Lc 60 normal / 75 high-contrast (explicit)
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
**WCAG HC auto-promotion:** a bare WCAG preset (no `[normal, hc]` pair at either
|
|
414
|
+
the outer `contrast` or inner `wcag` level) is automatically promoted to its
|
|
415
|
+
spec-defined "Enhanced" successor in high-contrast mode — `AA` → `AAA` (4.5 → 7)
|
|
416
|
+
and `AA-large` → `AAA-large` (3 → 4.5), per WCAG SC 1.4.3 → 1.4.6. `AAA` and
|
|
417
|
+
`AAA-large` are already the top WCAG tier and are left unchanged; bare numeric
|
|
418
|
+
targets have no successor tier and are also left unchanged. An explicit HC value
|
|
419
|
+
via either pair overrides and skips the promotion.
|
|
420
|
+
|
|
421
|
+
**APCA Enhanced Level (HC auto-boost):** a bare APCA scalar (no `[normal, hc]`
|
|
422
|
+
pair at either the outer `contrast` or inner `apca` level) is automatically
|
|
423
|
+
boosted by **+15 Lc** in high-contrast mode, the APCA analog of WCAG's
|
|
424
|
+
AAA-over-AA step. On by default; an explicit HC value via either pair
|
|
425
|
+
overrides it and skips the boost. The enhanced target is clamped to 106 Lc.
|
|
426
|
+
For large/bold text (where APCA caps contrast at Lc 90 to avoid glare), pass
|
|
427
|
+
an explicit HC pair to hold that ceiling — see
|
|
428
|
+
[`docs/okhst.md`](okhst.md) §Enhanced Level.
|
|
429
|
+
|
|
430
|
+
APCA preset keywords (Bronze Simple Mode conformance levels, role-independent):
|
|
431
|
+
`'preferred'` (Lc 90), `'body'` (75), `'content'` (60, ~AA), `'large'` (45, ~3:1),
|
|
432
|
+
`'non-text'` (30), `'min'` (15, point of invisibility). See
|
|
433
|
+
[`docs/okhst.md`](okhst.md) §APCA.
|
|
251
434
|
|
|
252
|
-
|
|
435
|
+
The floor is applied independently per scheme — if the `tone` already satisfies it the tone is kept, otherwise the solver searches in tone (contrast-uniform → a closed-form WCAG seed and fast convergence) until the target is met.
|
|
253
436
|
|
|
254
|
-
|
|
437
|
+
By default, the solver crosses to the opposite side of the base color when the requested tone direction cannot satisfy the floor. This is controlled per-color by [`autoFlip`](#autoflip) (which defaults to the global `autoFlip`). Set `glaze.configure({ autoFlip: false })` — or `autoFlip: false` on a single color — to keep strict directionality: unmet colors pin to that direction's 0 or 100 tone extreme instead of falling back to the original requested value.
|
|
438
|
+
|
|
439
|
+
**Full tone spectrum in HC mode:** in high-contrast variants the `lightTone` and `darkTone` window constraints are bypassed entirely (the window is forced to `[0, 100]`). Colors can reach the full range, maximizing perceivable contrast.
|
|
440
|
+
|
|
441
|
+
**Chromatic drift (verification):** tone is contrast-uniform for grays. A chromatic swatch at a given tone shares its OKHSL lightness with the equivalent gray but drifts in real luminance, so a contrast-floored color may land slightly under its gray-tone expectation. Glaze measures the resolved result against the base and emits a deduped advisory `console.warn` when it drifts below the target. See [`docs/okhst.md`](okhst.md) §Verification.
|
|
255
442
|
|
|
256
443
|
#### Per-color hue override
|
|
257
444
|
|
|
258
445
|
```ts
|
|
259
446
|
const theme = glaze(280, 80);
|
|
260
447
|
theme.colors({
|
|
261
|
-
surface: {
|
|
262
|
-
gradientEnd: {
|
|
263
|
-
warning: {
|
|
448
|
+
surface: { tone: 97 },
|
|
449
|
+
gradientEnd: { tone: 90, hue: '+20' }, // 280 + 20 = 300
|
|
450
|
+
warning: { tone: 60, hue: 40 }, // absolute
|
|
264
451
|
});
|
|
265
452
|
```
|
|
266
453
|
|
|
267
454
|
Relative hue is always relative to the **theme seed hue**, not to a base color.
|
|
268
455
|
|
|
456
|
+
#### Per-color `pastel`
|
|
457
|
+
|
|
458
|
+
`pastel: true` on a single color def overrides the global / per-theme `pastel` config for that color only. It toggles the hue-independent "safe" chroma limit used in every OKHSL↔sRGB conversion that touches this color: luminance calculations during contrast solving, gamut clamping during sRGB blend / mix edges, and output formatting. The effective flag is carried on the resolved variant (`ResolvedColorVariant.pastel`) so formatting matches the gamut mapping applied during resolution.
|
|
459
|
+
|
|
460
|
+
```ts
|
|
461
|
+
const theme = glaze(280, 80);
|
|
462
|
+
theme.colors({
|
|
463
|
+
plain: { tone: 50, saturation: 1 },
|
|
464
|
+
soft: { tone: 50, saturation: 1, pastel: true },
|
|
465
|
+
});
|
|
466
|
+
// theme.resolve().get('soft')!.light.pastel === true
|
|
467
|
+
// theme.css().light contains different rgb() triples for `--plain` and `--soft`
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Omit the field to inherit the global / per-theme `pastel` config — useful for keeping the default behavior while opting a single accent into the pastel gamut.
|
|
471
|
+
|
|
472
|
+
The flag is part of the def object, so `extend()` copies it through to child themes alongside the rest of the def. Override it again on the child to flip a single color back:
|
|
473
|
+
|
|
474
|
+
```ts
|
|
475
|
+
const parent = glaze(280, 80);
|
|
476
|
+
parent.colors({ soft: { tone: 50, saturation: 1, pastel: true } });
|
|
477
|
+
|
|
478
|
+
const child = parent.extend({
|
|
479
|
+
colors: { soft: { tone: 50, saturation: 1, pastel: false } },
|
|
480
|
+
});
|
|
481
|
+
// child.resolve().get('soft')!.light.pastel === false
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
> **Note:** Per-color `pastel` is also supported on `ShadowColorDef` and `MixColorDef` (see the tables above). For shadows the math itself happens in OKHSL space, so the flag mainly controls the gamut-mapped output formatting and any luminance verification for that variant.
|
|
485
|
+
>
|
|
486
|
+
> Standalone `glaze.color()` tokens accept the same `pastel` field on both the structured (`GlazeColorInput`) and value-shorthand (`GlazeColorOverrides`) forms, and it survives the `export()` / `glaze.colorFrom()` round-trip.
|
|
487
|
+
|
|
488
|
+
#### Roles
|
|
489
|
+
|
|
490
|
+
A color's `role` describes how it is used against its `base` and fixes **APCA contrast polarity** — which side is the foreground vs the background. APCA is asymmetric (`|apca(a,b)| ≠ |apca(b,a)|`), so the role picks the correct argument order; WCAG is symmetric and unaffected.
|
|
491
|
+
|
|
492
|
+
| Role | Polarity | Use | Aliases (name inference) |
|
|
493
|
+
|---|---|---|---|
|
|
494
|
+
| `'text'` | fg | Text / icons / foreground content | `text`, `fg`, `foreground`, `content`, `ink`, `label`, `stroke` |
|
|
495
|
+
| `'border'` | fg | Non-text spot elements (borders, dividers, outlines) | `border`, `divider`, `outline`, `separator`, `hairline`, `rule` |
|
|
496
|
+
| `'surface'` | bg | Backgrounds / fills | `surface`, `bg`, `background`, `fill`, `canvas`, `paper`, `layer` |
|
|
497
|
+
|
|
498
|
+
Resolution chain (per color):
|
|
499
|
+
|
|
500
|
+
1. Explicit `role` (normalized from an alias) wins.
|
|
501
|
+
2. Else, when `inferRole` is enabled (default), infer from the color name — the **last** recognized token wins (`button-text` → `text`, `input-bg` → `surface`, `card-outline` → `border`).
|
|
502
|
+
3. Else, the opposite of the base's role (a `surface` base ⇒ this is `text`).
|
|
503
|
+
4. Else, `'text'` (foreground) — i.e. the base is treated as the background.
|
|
504
|
+
|
|
505
|
+
```ts
|
|
506
|
+
const theme = glaze(280, 60);
|
|
507
|
+
theme.colors({
|
|
508
|
+
surface: { tone: 90 },
|
|
509
|
+
text: { base: 'surface', contrast: { apca: 'content' } }, // inferred text
|
|
510
|
+
border: { base: 'surface', tone: '-10' }, // inferred border
|
|
511
|
+
});
|
|
512
|
+
// role fixes APCA polarity; set `pastel: true` explicitly if a border
|
|
513
|
+
// needs the hue-independent safe chroma limit.
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
Disable name inference with `glaze.configure({ inferRole: false })` (the base-opposite and foreground-default fallbacks still apply).
|
|
517
|
+
|
|
269
518
|
### `ShadowColorDef`
|
|
270
519
|
|
|
271
520
|
| Field | Type | Description |
|
|
@@ -275,6 +524,7 @@ Relative hue is always relative to the **theme seed hue**, not to a base color.
|
|
|
275
524
|
| `fg` | `string` | Optional foreground color name for tinting and intensity modulation. Must reference a non-shadow color. Omit for an achromatic shadow at full user-specified intensity. |
|
|
276
525
|
| `intensity` | `HCPair<number>` | Shadow intensity, 0–100. Supports HC pairs. |
|
|
277
526
|
| `tuning` | `ShadowTuning` | Per-color tuning overrides. Merged field-by-field with the global `shadowTuning`. |
|
|
527
|
+
| `pastel` | `boolean` | Per-color `pastel` override. See [Per-color `pastel`](#per-color-pastel). |
|
|
278
528
|
| `inherit` | `boolean` | Inheritance flag, default `true`. |
|
|
279
529
|
|
|
280
530
|
See [Shadows](#shadows) below for the algorithm and tuning details.
|
|
@@ -289,7 +539,9 @@ See [Shadows](#shadows) below for the algorithm and tuning details.
|
|
|
289
539
|
| `value` | `HCPair<number>` | Mix ratio 0–100 (0 = pure base, 100 = pure target). In `'transparent'` blend, this becomes the target's opacity. Supports HC pairs. |
|
|
290
540
|
| `blend` | `'opaque' \| 'transparent'` | Default `'opaque'`. |
|
|
291
541
|
| `space` | `'okhsl' \| 'srgb'` | Interpolation space for opaque blending. Default `'okhsl'`. Ignored for `'transparent'` (always composites in linear sRGB). |
|
|
292
|
-
| `contrast` | `HCPair<
|
|
542
|
+
| `contrast` | `HCPair<ContrastSpec>` | Optional contrast floor against `base` (WCAG or APCA — see [`contrast`](#contrast-floor)). The solver adjusts the mix ratio (opaque) or opacity (transparent). |
|
|
543
|
+
| `pastel` | `boolean` | Per-color `pastel` override. See [Per-color `pastel`](#per-color-pastel). |
|
|
544
|
+
| `role` | `RoleInput` | Semantic role of the mixed result against `base`. Same semantics as `RegularColorDef.role` (see [Roles](#roles)). |
|
|
293
545
|
| `inherit` | `boolean` | Inheritance flag, default `true`. |
|
|
294
546
|
|
|
295
547
|
See [Mix colors](#mix-colors) below.
|
|
@@ -312,10 +564,10 @@ glaze.color(color: GlazeFromInput | GlazeColorInput | GlazeColorValue, config?:
|
|
|
312
564
|
|
|
313
565
|
| Shape | Example | Notes |
|
|
314
566
|
|---|---|---|
|
|
315
|
-
| **Bare string** | `'#26fcb2'` | Hex or CSS color function (`rgb()`, `hsl()`, `okhsl()`, `oklch()`). |
|
|
316
|
-
| **Value object** | `{ h: 152, s: 0.95, l: 0.74 }` | OKHSL, `{ r, g, b }` (sRGB 0–255), or `{ l, c, h }` (OKLCh). |
|
|
567
|
+
| **Bare string** | `'#26fcb2'` | Hex or CSS color function (`rgb()`, `hsl()`, `okhsl()`, `okhst()`, `oklch()`). |
|
|
568
|
+
| **Value object** | `{ h: 152, s: 0.95, l: 0.74 }` | OKHSL, OKHST (`{ h, s, t }`), `{ r, g, b }` (sRGB 0–255), or `{ l, c, h }` (OKLCh). |
|
|
317
569
|
| **`{ from, ...overrides }`** | `{ from: '#1a1a2e', base: bg, contrast: 'AA' }` | Value + color overrides in one object. |
|
|
318
|
-
| **Structured** | `{ hue: 152, saturation: 95,
|
|
570
|
+
| **Structured** | `{ hue: 152, saturation: 95, tone: 74 }` | Full theme-style token (hue/saturation in 0–100, tone in 0–100). |
|
|
319
571
|
|
|
320
572
|
`GlazeColorValue` (bare string or value-object forms) accepts:
|
|
321
573
|
|
|
@@ -325,23 +577,28 @@ glaze.color(color: GlazeFromInput | GlazeColorInput | GlazeColorValue, config?:
|
|
|
325
577
|
| `rgb()` | `'rgb(38 252 178)'`, `'rgb(38 252 178 / 0.8)'` | Modern space syntax. Alpha dropped with warning. |
|
|
326
578
|
| `hsl()` | `'hsl(152 97% 57%)'` | Modern space syntax. Alpha dropped with warning. |
|
|
327
579
|
| `okhsl()` | `'okhsl(152 95% 74%)'` | Glaze's own emit format. Alpha dropped with warning. |
|
|
580
|
+
| `okhst()` | `'okhst(152 95% 70%)'` | OKHST tone input (third value is tone 0–100). **Input only** — never emitted. Alpha dropped with warning. |
|
|
328
581
|
| `oklch()` | `'oklch(0.85 0.18 152)'` | Glaze's own emit format. Alpha dropped with warning. |
|
|
329
|
-
| `OkhslColor` object | `{ h: 152, s: 0.95, l: 0.74 }` |
|
|
582
|
+
| `OkhslColor` object | `{ h: 152, s: 0.95, l: 0.74 }` | OKHSL shape (h: 0–360, s/l: 0–1). Passing 0–100 for `s`/`l` throws with a hint to use the structured form. |
|
|
583
|
+
| `OkhstColor` object | `{ h: 152, s: 0.95, t: 0.70 }` | OKHST shape (h: 0–360, s/t: 0–1). The `t` key disambiguates it from `{ h, s, l }`. **Input only.** |
|
|
330
584
|
| `RgbColor` object | `{ r: 38, g: 252, b: 178 }` | sRGB 0–255. RGB tuple `[r, g, b]` is not supported — use this object form. |
|
|
331
585
|
| `OklchColor` object | `{ l: 0.85, c: 0.18, h: 152 }` | OKLCh (L/C: 0–1, H: degrees), same semantics as `oklch()` strings. |
|
|
332
586
|
|
|
333
|
-
`GlazeColorInput` (structured form) is `{ hue, saturation,
|
|
587
|
+
`GlazeColorInput` (structured form) is `{ hue, saturation, tone, ... }`:
|
|
334
588
|
|
|
335
589
|
| Field | Type | Description |
|
|
336
590
|
|---|---|---|
|
|
337
591
|
| `hue` | `number` | 0–360. |
|
|
338
592
|
| `saturation` | `number` | 0–100. |
|
|
339
|
-
| `
|
|
593
|
+
| `tone` | `HCPair<number \| ExtremeValue>` | 0–100 (contrast-uniform) or `'max'`/`'min'`, optional HC pair. |
|
|
340
594
|
| `saturationFactor` | `number` | Multiplier on the seed (0–1). Default: `1`. |
|
|
341
595
|
| `mode` | `AdaptationMode` | Default: `'auto'`. |
|
|
596
|
+
| `autoFlip` | `boolean` | Flip out-of-bounds results instead of clamping. Default: global `autoFlip`. |
|
|
342
597
|
| `opacity` | `number` | Fixed alpha 0–1. |
|
|
343
598
|
| `base` | `GlazeColorToken \| GlazeColorValue` | Optional dependency. See [Pairing colors](#pairing-colors). |
|
|
344
|
-
| `contrast` | `HCPair<
|
|
599
|
+
| `contrast` | `HCPair<ContrastSpec>` | Contrast floor against `base` (WCAG or APCA). Without `base`, anchored to the literal seed. |
|
|
600
|
+
| `pastel` | `boolean` | Per-color `pastel` override. Falls through to the global / per-theme `pastel` config when omitted. See [Per-color `pastel`](#per-color-pastel). |
|
|
601
|
+
| `role` | `RoleInput` | Semantic role against `base` / the seed (see [Roles](#roles)). Fixes APCA polarity. |
|
|
345
602
|
| `name` | `string` | Debug label for warnings; doesn't change output keys. Reserved names (`'value'`, `'seed'`, `'externalBase'`) are rejected. |
|
|
346
603
|
|
|
347
604
|
`GlazeFromInput` (from form) is `{ from: GlazeColorValue, ...colorOverrides }`:
|
|
@@ -351,12 +608,15 @@ glaze.color(color: GlazeFromInput | GlazeColorInput | GlazeColorValue, config?:
|
|
|
351
608
|
| `from` | **Required.** The source color value — same forms as `GlazeColorValue`. |
|
|
352
609
|
| `hue` | Number (absolute 0–360) or `'+N'`/`'-N'` (relative to seed, never to `base`). |
|
|
353
610
|
| `saturation` | Override seed saturation (0–100). |
|
|
354
|
-
| `
|
|
611
|
+
| `tone` | Number (absolute 0–100), `'+N'`/`'-N'`, or `'max'`/`'min'`. Without `base`, relative anchors to the seed; with `base`, anchors to `base`'s tone per scheme. |
|
|
355
612
|
| `saturationFactor` | Multiplier on the seed (0–1). |
|
|
356
613
|
| `mode` | `'auto'` (default) / `'fixed'` / `'static'`. |
|
|
357
|
-
| `
|
|
614
|
+
| `autoFlip` | Flip out-of-bounds results instead of clamping. Default: global `autoFlip`. |
|
|
615
|
+
| `contrast` | Contrast floor (WCAG or APCA). Without `base`, anchored to the literal seed; with `base`, solved per scheme. |
|
|
358
616
|
| `base` | `GlazeColorToken` or raw `GlazeColorValue`. See [Pairing colors](#pairing-colors). |
|
|
359
617
|
| `opacity` | Fixed alpha 0–1. Combining with `contrast` is not recommended — `console.warn` is emitted. |
|
|
618
|
+
| `pastel` | Per-color `pastel` override. Falls through to the global / per-theme `pastel` config when omitted. See [Per-color `pastel`](#per-color-pastel). |
|
|
619
|
+
| `role` | Semantic role against `base` / the seed (see [Roles](#roles)). Fixes APCA polarity. |
|
|
360
620
|
| `name` | Debug label only — surfaces in warnings/errors. Does not change output keys. |
|
|
361
621
|
|
|
362
622
|
Named CSS colors (`'red'`, `'blueviolet'`) are not supported.
|
|
@@ -366,10 +626,10 @@ Named CSS colors (`'red'`, `'blueviolet'`) are not supported.
|
|
|
366
626
|
Every input form defaults to `mode: 'auto'` so the resolved token adapts between light and dark like an ordinary theme color. The config snapshot taken at create time differs by input form:
|
|
367
627
|
|
|
368
628
|
- **Value-shorthand** (bare strings, value objects, and `{ from, ...overrides }`):
|
|
369
|
-
- Light variant preserves the input
|
|
370
|
-
- All other config fields (`
|
|
371
|
-
- **Structured input** (`{ hue, saturation,
|
|
372
|
-
- Both
|
|
629
|
+
- Light variant preserves the input tone exactly (`lightTone: false`).
|
|
630
|
+
- All other config fields (`darkTone`, `darkDesaturation`, `autoFlip`) snapshot from `globalConfig` at create time.
|
|
631
|
+
- **Structured input** (`{ hue, saturation, tone, ... }`):
|
|
632
|
+
- Both tone windows snapshot from `globalConfig` at create time (same as a theme color).
|
|
373
633
|
- All fields are **snapshotted at color-creation time** — later `glaze.configure()` calls don't retroactively change existing tokens.
|
|
374
634
|
|
|
375
635
|
```ts
|
|
@@ -379,11 +639,14 @@ glaze.color('#26fcb2')
|
|
|
379
639
|
// Value-object — same behavior
|
|
380
640
|
glaze.color({ h: 152, s: 0.95, l: 0.74 })
|
|
381
641
|
|
|
642
|
+
// OKHST value-object — tone axis
|
|
643
|
+
glaze.color({ h: 152, s: 0.95, t: 0.70 })
|
|
644
|
+
|
|
382
645
|
// From form — value + color overrides
|
|
383
646
|
glaze.color({ from: '#1a1a2e', hue: '+20', contrast: 'AA' })
|
|
384
647
|
|
|
385
|
-
// Structured form — explicit hue/saturation/
|
|
386
|
-
glaze.color({ hue: 152, saturation: 95,
|
|
648
|
+
// Structured form — explicit hue/saturation/tone (0–100)
|
|
649
|
+
glaze.color({ hue: 152, saturation: 95, tone: 74 })
|
|
387
650
|
```
|
|
388
651
|
|
|
389
652
|
### Token methods
|
|
@@ -394,43 +657,45 @@ A `GlazeColorToken` exposes:
|
|
|
394
657
|
|---|---|
|
|
395
658
|
| `token.resolve()` | Resolve as a `ResolvedColor` (light/dark/lightContrast/darkContrast variants). |
|
|
396
659
|
| `token.token(options?)` | Flat token map (no color-name key). Options: `format`, `modes`, `states`. |
|
|
397
|
-
| `token.tasty(options?)` | Tasty state map (no color-name key). Same options as `token.token`. |
|
|
660
|
+
| `token.tasty(options?)` | [Tasty](https://tasty.style) state map (no color-name key). Same options as `token.token`. |
|
|
398
661
|
| `token.json(options?)` | JSON map (no color-name key). Options: `format`, `modes`. |
|
|
399
662
|
| `token.css({ name, format?, suffix? })` | CSS custom property declarations grouped by scheme variant. `name` is **required** and becomes the variable identifier (`'brand'` → `--brand-color`). Defaults: `format: 'rgb'`, `suffix: '-color'` (matches `theme.css`). |
|
|
663
|
+
| `token.dtcg(options?)` | DTCG color tokens, one per scheme variant (no color-name key). Each entry is a full `{ $type: 'color', $value }` token. Options: `colorSpace` (`'srgb'` \| `'oklch'`), `modes`. |
|
|
664
|
+
| `token.dtcgResolver({ name, ... })` | A single DTCG Resolver-Module document for this color, keyed by `name` across all scheme variants. `name` is **required**. Same options as `theme.dtcgResolver()` plus `name`. |
|
|
665
|
+
| `token.tailwind({ name, ... })` | Tailwind v4 `@theme` block + dark / high-contrast overrides for this color. `name` is **required** (forms `--color-<name>`). Same options as `theme.tailwind()` plus `name`. |
|
|
400
666
|
| `token.export()` | JSON-safe snapshot — pass to `glaze.colorFrom(...)` to rehydrate. |
|
|
401
667
|
|
|
402
668
|
### Per-instance config override
|
|
403
669
|
|
|
404
|
-
The optional `config` second argument (`GlazeConfigOverride`) overrides the resolve-relevant global config fields for a single token or theme. Fields that are omitted fall through to the live global config at create time (and are snapshotted).
|
|
670
|
+
The optional `config` second argument (`GlazeConfigOverride`) overrides the resolve-relevant global config fields for a single token or theme. Fields that are omitted fall through to the live global config at create time (and are snapshotted). A tone window can be `[lo, hi]`, `{ lo, hi, eps }`, or `false` (disable clamping).
|
|
405
671
|
|
|
406
672
|
`GlazeConfigOverride`:
|
|
407
673
|
|
|
408
674
|
| Field | Default (from global) | Description |
|
|
409
675
|
|---|---|---|
|
|
410
|
-
| `
|
|
411
|
-
| `
|
|
676
|
+
| `lightTone` | `[10, 100]` | Light tone window: `[lo, hi]`, `{ lo, hi, eps }`, or `false` (disable clamping). |
|
|
677
|
+
| `darkTone` | `[15, 95]` | Dark tone window: `[lo, hi]`, `{ lo, hi, eps }`, or `false` (disable clamping). |
|
|
412
678
|
| `darkDesaturation` | `0.1` | Saturation reduction in dark scheme (0–1). |
|
|
413
|
-
| `
|
|
414
|
-
| `autoFlip` | `true` | When solving `contrast`, allow the solver to switch lightness direction if the requested side can't meet the target. |
|
|
679
|
+
| `autoFlip` | `true` | Default for each color's `autoFlip`: when solving `contrast` (or applying a relative `tone` that overshoots), allow crossing to the opposite side instead of clamping. |
|
|
415
680
|
| `shadowTuning` | `undefined` | Default shadow tuning (meaningful for themes; harmless on color tokens). |
|
|
416
681
|
|
|
417
682
|
Config overrides apply to both `glaze.color()` tokens and `glaze()` themes:
|
|
418
683
|
|
|
419
684
|
```ts
|
|
420
|
-
// Standalone color — preserve raw
|
|
421
|
-
glaze.color('#26fcb2', {
|
|
685
|
+
// Standalone color — preserve raw tone in both schemes
|
|
686
|
+
glaze.color('#26fcb2', { darkTone: false })
|
|
422
687
|
|
|
423
688
|
// Restore the #000 → white dark flip (full dark range)
|
|
424
689
|
glaze.color('#000000', {
|
|
425
|
-
|
|
426
|
-
|
|
690
|
+
lightTone: false,
|
|
691
|
+
darkTone: [15, 100],
|
|
427
692
|
})
|
|
428
693
|
|
|
429
694
|
// Structured form with config override
|
|
430
|
-
glaze.color({ hue: 152, saturation: 95,
|
|
695
|
+
glaze.color({ hue: 152, saturation: 95, tone: 74 }, { darkTone: false })
|
|
431
696
|
|
|
432
697
|
// Theme with config override
|
|
433
|
-
const rawTheme = glaze(280, 80, {
|
|
698
|
+
const rawTheme = glaze(280, 80, { lightTone: false })
|
|
434
699
|
```
|
|
435
700
|
|
|
436
701
|
The override is **snapshotted at create time** so later `glaze.configure()` calls don't change already-created tokens or themes (for non-overridden fields, the snapshot captured the global value at creation time; for themes, non-overridden fields are re-read from the live global at resolve time — see [Theme config override](#theme-config-override)).
|
|
@@ -443,17 +708,18 @@ When a theme is created with a `GlazeConfigOverride`, the override is **merged o
|
|
|
443
708
|
- Fields you didn't override still react to later `glaze.configure()` calls.
|
|
444
709
|
|
|
445
710
|
```ts
|
|
446
|
-
const t = glaze(280, 80, {
|
|
447
|
-
t.colors({ text: {
|
|
448
|
-
// text.light
|
|
711
|
+
const t = glaze(280, 80, { lightTone: [0, 50] });
|
|
712
|
+
t.colors({ text: { tone: 50, saturation: 1 } });
|
|
713
|
+
// text.light lands inside the [0, 50] window — always, regardless of
|
|
714
|
+
// global lightTone changes.
|
|
449
715
|
// text.dark.s reacts to glaze.configure({ darkDesaturation }) since it's not overridden.
|
|
450
716
|
```
|
|
451
717
|
|
|
452
718
|
`extend` inherits the parent's override and shallow-merges the child's:
|
|
453
719
|
|
|
454
720
|
```ts
|
|
455
|
-
const child = t.extend({ config: {
|
|
456
|
-
// child:
|
|
721
|
+
const child = t.extend({ config: { darkTone: false } });
|
|
722
|
+
// child: lightTone { lo: 0, hi: 50 } (inherited) + darkTone: false (added)
|
|
457
723
|
```
|
|
458
724
|
|
|
459
725
|
`theme.export()` includes `config`; `glaze.from(data)` restores it.
|
|
@@ -473,7 +739,7 @@ Both value-form and structured-form tokens round-trip.
|
|
|
473
739
|
|
|
474
740
|
### Pairing colors
|
|
475
741
|
|
|
476
|
-
Set `base` to anchor a standalone color to another standalone color or raw value. The
|
|
742
|
+
Set `base` to anchor a standalone color to another standalone color or raw value. The contrast solver and relative `tone` offsets switch their anchor from the literal seed to the base's resolved variant per scheme — so the same text color automatically lands at AA against its background in light, dark, and high-contrast modes.
|
|
477
743
|
|
|
478
744
|
```ts
|
|
479
745
|
const bg = glaze.color('#1a1a2e');
|
|
@@ -481,10 +747,10 @@ const bg = glaze.color('#1a1a2e');
|
|
|
481
747
|
// Text guaranteed AA against `bg` in every scheme.
|
|
482
748
|
const text = glaze.color({ from: '#ffffff', base: bg, contrast: 'AA' });
|
|
483
749
|
|
|
484
|
-
// Border 8
|
|
750
|
+
// Border 8 tone units lighter than `bg` in each scheme.
|
|
485
751
|
const border = glaze.color({ from: '#000000',
|
|
486
752
|
base: bg,
|
|
487
|
-
|
|
753
|
+
tone: '+8',
|
|
488
754
|
mode: 'fixed',
|
|
489
755
|
});
|
|
490
756
|
|
|
@@ -495,11 +761,11 @@ const text2 = glaze.color({ from: '#ffffff', base: '#1a1a2e', contrast: 'AA' });
|
|
|
495
761
|
Behavior with `base`:
|
|
496
762
|
|
|
497
763
|
- `contrast` is solved per scheme against `base`'s resolved variant (light / dark / lightContrast / darkContrast).
|
|
498
|
-
- Relative `
|
|
764
|
+
- Relative `tone: '+N'` / `'-N'` is anchored to `base`'s tone per scheme (matches theme behavior).
|
|
499
765
|
- Relative `hue: '+N'` / `'-N'` still anchors to the **seed** (the value passed to `glaze.color()`), not the base.
|
|
500
766
|
- `mode` works as a per-pair knob.
|
|
501
767
|
- The base token's `.resolve()` is called lazily on the first resolve of the dependent and the result is captured by reference; later mutations to the base don't apply.
|
|
502
|
-
- **Structured bases are resolved at full range for linking math**: when a value/`from` color links to a base created via the structured form, the contrast/
|
|
768
|
+
- **Structured bases are resolved at full range for linking math**: when a value/`from` color links to a base created via the structured form, the contrast/tone anchor uses the raw input tone (not the windowed output). This ensures the anchor matches what you intended, not what the light window remapped it to. The base's own `.resolve()` output is unaffected.
|
|
503
769
|
- When the contrast target is physically unreachable, `glaze` emits a single `console.warn` per `(name, scheme, target)` triple and returns the closest passing variant. Use the `name` override to make the warning identifiable.
|
|
504
770
|
|
|
505
771
|
Chains compose:
|
|
@@ -522,8 +788,8 @@ The `name` override appears in `console.warn` / Error messages but **does not**
|
|
|
522
788
|
|
|
523
789
|
```ts
|
|
524
790
|
theme.colors({
|
|
525
|
-
surface: {
|
|
526
|
-
text: { base: 'surface',
|
|
791
|
+
surface: { tone: 95 },
|
|
792
|
+
text: { base: 'surface', tone: '-52', contrast: 'AAA' },
|
|
527
793
|
|
|
528
794
|
'shadow-sm': { type: 'shadow', bg: 'surface', fg: 'text', intensity: 5 },
|
|
529
795
|
'shadow-md': { type: 'shadow', bg: 'surface', fg: 'text', intensity: 10 },
|
|
@@ -616,7 +882,7 @@ For a simple fixed-alpha color (no shadow algorithm), use `opacity` on a regular
|
|
|
616
882
|
|
|
617
883
|
```ts
|
|
618
884
|
theme.colors({
|
|
619
|
-
overlay: {
|
|
885
|
+
overlay: { tone: 0, opacity: 0.5 },
|
|
620
886
|
});
|
|
621
887
|
// → 'oklch(0 0 0 / 0.5)'
|
|
622
888
|
```
|
|
@@ -631,8 +897,8 @@ Produces a solid color by interpolating between `base` and `target`:
|
|
|
631
897
|
|
|
632
898
|
```ts
|
|
633
899
|
theme.colors({
|
|
634
|
-
surface: {
|
|
635
|
-
accent: {
|
|
900
|
+
surface: { tone: 95 },
|
|
901
|
+
accent: { tone: 30 },
|
|
636
902
|
tint: { type: 'mix', base: 'surface', target: 'accent', value: 30 },
|
|
637
903
|
});
|
|
638
904
|
```
|
|
@@ -647,8 +913,8 @@ Produces the target color with controlled opacity — useful for hover overlays:
|
|
|
647
913
|
|
|
648
914
|
```ts
|
|
649
915
|
theme.colors({
|
|
650
|
-
surface: {
|
|
651
|
-
black: {
|
|
916
|
+
surface: { tone: 95 },
|
|
917
|
+
black: { tone: 0, saturation: 0 },
|
|
652
918
|
hover: {
|
|
653
919
|
type: 'mix', base: 'surface', target: 'black',
|
|
654
920
|
value: 8, blend: 'transparent',
|
|
@@ -695,8 +961,8 @@ Mix colors can reference other mix colors:
|
|
|
695
961
|
|
|
696
962
|
```ts
|
|
697
963
|
theme.colors({
|
|
698
|
-
white: {
|
|
699
|
-
black: {
|
|
964
|
+
white: { tone: 100, saturation: 0 },
|
|
965
|
+
black: { tone: 0, saturation: 0 },
|
|
700
966
|
gray: { type: 'mix', base: 'white', target: 'black', value: 50, space: 'srgb' },
|
|
701
967
|
lightGray: { type: 'mix', base: 'white', target: 'gray', value: 50, space: 'srgb' },
|
|
702
968
|
});
|
|
@@ -845,6 +1111,56 @@ const stylesheet = `
|
|
|
845
1111
|
`palette.css()` accepts the same `GlazeCssOptions` as `theme.css()` plus `GlazePaletteExportOptions`.
|
|
846
1112
|
It does not accept `modes`; all four result fields are always returned.
|
|
847
1113
|
|
|
1114
|
+
### `palette.dtcg()`
|
|
1115
|
+
|
|
1116
|
+
DTCG export for a palette. Prefix defaults to `true` and the palette-level `primary` is honored (the primary theme's tokens are duplicated without prefix as aliases).
|
|
1117
|
+
|
|
1118
|
+
```ts
|
|
1119
|
+
palette.dtcg()
|
|
1120
|
+
// → {
|
|
1121
|
+
// light: {
|
|
1122
|
+
// 'primary-surface': { $type: 'color', $value: { ... } },
|
|
1123
|
+
// 'surface': { $type: 'color', $value: { ... } }, // unprefixed alias
|
|
1124
|
+
// 'danger-surface': { $type: 'color', $value: { ... } },
|
|
1125
|
+
// },
|
|
1126
|
+
// dark: { ... },
|
|
1127
|
+
// }
|
|
1128
|
+
```
|
|
1129
|
+
|
|
1130
|
+
Accepts `GlazeDtcgOptions` plus `GlazePaletteExportOptions`.
|
|
1131
|
+
|
|
1132
|
+
### `palette.dtcgResolver()`
|
|
1133
|
+
|
|
1134
|
+
Resolver-Module export for a palette. Same as `theme.dtcgResolver()` but merges every theme (with prefix / `primary` aliasing) into the single `sets.base` source and each `scheme` context. Prefix defaults to `true`; the palette-level `primary` is honored.
|
|
1135
|
+
|
|
1136
|
+
```ts
|
|
1137
|
+
palette.dtcgResolver()
|
|
1138
|
+
// → {
|
|
1139
|
+
// version: '2025.10',
|
|
1140
|
+
// sets: { base: { sources: [ { 'primary-surface': {…}, 'surface': {…}, 'danger-surface': {…} } ] } },
|
|
1141
|
+
// modifiers: { scheme: { default: 'light', contexts: { light: [], dark: [ {…} ] } } },
|
|
1142
|
+
// resolutionOrder: [ { $ref: '#/sets/base' }, { $ref: '#/modifiers/scheme' } ],
|
|
1143
|
+
// }
|
|
1144
|
+
```
|
|
1145
|
+
|
|
1146
|
+
Accepts `GlazeDtcgResolverOptions` plus `GlazePaletteExportOptions`.
|
|
1147
|
+
|
|
1148
|
+
### `palette.tailwind()`
|
|
1149
|
+
|
|
1150
|
+
Tailwind export for a palette. All themes are merged into a single `@theme` block (plus dark / high-contrast overrides), so each color is reachable as a Tailwind utility. Prefix defaults to `true`.
|
|
1151
|
+
|
|
1152
|
+
```ts
|
|
1153
|
+
const css = palette.tailwind();
|
|
1154
|
+
// @theme {
|
|
1155
|
+
// --color-primary-surface: oklch(...);
|
|
1156
|
+
// --color-surface: oklch(...); /* unprefixed alias */
|
|
1157
|
+
// --color-danger-surface: oklch(...);
|
|
1158
|
+
// }
|
|
1159
|
+
// .dark { ... }
|
|
1160
|
+
```
|
|
1161
|
+
|
|
1162
|
+
Accepts `GlazeTailwindOptions` plus `GlazePaletteExportOptions`. The palette `prefix` option (theme prefixing) is separate from `GlazeTailwindOptions.namespace` (the `--color-*` CSS namespace).
|
|
1163
|
+
|
|
848
1164
|
---
|
|
849
1165
|
|
|
850
1166
|
## Output formats
|
|
@@ -853,21 +1169,40 @@ Control the color format with the `format` option on any export method:
|
|
|
853
1169
|
|
|
854
1170
|
| Format | Output (alpha = 1) | Output (alpha < 1) | Notes |
|
|
855
1171
|
|---|---|---|---|
|
|
856
|
-
| `'okhsl'` (default for
|
|
857
|
-
| `'
|
|
1172
|
+
| `'okhsl'` (default for `tasty()`) | `okhsl(H S% L%)` | `okhsl(H S% L% / A)` | Glaze's native format, not a CSS function. **Tasty-only** (`tasty()`, `token()`, `.tasty()`). |
|
|
1173
|
+
| `'okhst'` | `okhst(H S% T%)` | `okhst(H S% T% / A)` | OKHST tone axis. **Tasty-only** — same restriction as `okhsl`. |
|
|
1174
|
+
| `'oklch'` (default for `tokens()` / `json()`) | `oklch(L C H)` | `oklch(L C H / A)` | OKLab-based LCH. Native CSS. Required for `splitHue`. |
|
|
1175
|
+
| `'rgb'` (default for `css()`) | `rgb(R G B)` | `rgb(R G B / A)` | Rounded integers, modern space syntax. |
|
|
858
1176
|
| `'hsl'` | `hsl(H S% L%)` | `hsl(H S% L% / A)` | Modern space syntax. |
|
|
859
|
-
| `'oklch'` | `oklch(L C H)` | `oklch(L C H / A)` | OKLab-based LCH. |
|
|
860
1177
|
|
|
861
1178
|
```ts
|
|
862
|
-
theme.tokens(); // '
|
|
1179
|
+
theme.tokens(); // 'oklch(0.965 0.0123 280)' (default)
|
|
863
1180
|
theme.tokens({ format: 'rgb' }); // 'rgb(244 240 250)'
|
|
864
|
-
theme.
|
|
865
|
-
theme.
|
|
1181
|
+
theme.tasty(); // 'okhsl(280 60% 97%)' (default)
|
|
1182
|
+
theme.tasty({ format: 'okhst' }); // 'okhst(280 60% 97%)'
|
|
866
1183
|
```
|
|
867
1184
|
|
|
868
1185
|
All numeric output strips trailing zeros for cleaner CSS (e.g. `95` not `95.0`).
|
|
869
1186
|
|
|
870
|
-
The `format` option works on
|
|
1187
|
+
The `format` option works on CSS-string exports: `theme.tokens()`, `theme.tasty()`, `theme.json()`, `theme.css()`, `theme.tailwind()`, the same on `palette`, and on `token.token()` / `.tasty()` / `.json()` / `.css()` / `.tailwind()`. **`okhsl` and `okhst` throw on non-Tasty exports** (`tokens`, `json`, `css`, `tailwind`) — they are not native CSS color spaces.
|
|
1188
|
+
|
|
1189
|
+
### Hue channel splitting (`splitHue`)
|
|
1190
|
+
|
|
1191
|
+
On `theme.css()`, `theme.tasty()`, `palette.css()`, `palette.tasty()`, and standalone `color.css()` with `format: 'oklch'`, set `splitHue: true` to emit hue as its own custom property so consumers can re-skin at runtime:
|
|
1192
|
+
|
|
1193
|
+
```css
|
|
1194
|
+
/* theme.css({ format: 'oklch', splitHue: true, name: 'brand' }) */
|
|
1195
|
+
--brand-hue: 240;
|
|
1196
|
+
--accent-hue: calc(var(--brand-hue) + 20);
|
|
1197
|
+
--surface-color: oklch(0.52 0.06 var(--brand-hue));
|
|
1198
|
+
--accent-color: oklch(0.62 0.03 var(--accent-hue));
|
|
1199
|
+
```
|
|
1200
|
+
|
|
1201
|
+
**Requirements:** every exported color must be pastel (`pastel: true` globally or per-color). Pastel mode bounds chroma by the hue-independent safe chroma at each lightness, so emitted `C` stays in sRGB for any rotated hue. Non-pastel palettes throw rather than emit values that would clip under rotation.
|
|
1202
|
+
|
|
1203
|
+
**Limitations:** `oklch` only (native CSS `var()` in the hue slot). Shadow and mix colors stay inline (blended hue). Standalone `.token()` / `.tasty()` do not support `splitHue` (return shape cannot carry the `$name-hue` declaration).
|
|
1204
|
+
|
|
1205
|
+
`theme.dtcg()` / `theme.dtcgResolver()` / `palette.dtcg()` / `palette.dtcgResolver()` ignore `format` — DTCG emits structured `$value` objects, not CSS strings. Use the `colorSpace` option (`'srgb'` or `'oklch'`) to pick the color representation instead.
|
|
871
1206
|
|
|
872
1207
|
---
|
|
873
1208
|
|
|
@@ -877,78 +1212,66 @@ The `format` option works on every export: `theme.tokens()`, `theme.tasty()`, `t
|
|
|
877
1212
|
|
|
878
1213
|
| Mode | Behavior |
|
|
879
1214
|
|---|---|
|
|
880
|
-
| `'auto'` (default) | Full adaptation.
|
|
881
|
-
| `'fixed'` | Color stays recognizable.
|
|
882
|
-
| `'static'` | No adaptation. Same
|
|
1215
|
+
| `'auto'` (default) | Full adaptation. Dark is a single tone inversion (`100 − t`) remapped into the dark window. High-contrast uses the full range. |
|
|
1216
|
+
| `'fixed'` | Color stays recognizable. Tone is *mapped* (not inverted) into the dark window. Use for brand buttons, CTAs, status banners. |
|
|
1217
|
+
| `'static'` | No adaptation. Same tone in every scheme. |
|
|
883
1218
|
|
|
884
|
-
### How relative
|
|
1219
|
+
### How relative tone adapts
|
|
885
1220
|
|
|
886
|
-
**`auto`** —
|
|
1221
|
+
**`auto`** — the offset is anchored to the base's per-scheme tone:
|
|
887
1222
|
|
|
888
1223
|
```
|
|
889
|
-
Light: surface
|
|
890
|
-
Dark: surface inverts to
|
|
891
|
-
|
|
1224
|
+
Light: surface tone=97, text tone='-52' → tone 45 (dark text on light bg)
|
|
1225
|
+
Dark: surface inverts to a low tone; the '-52' offset re-anchors to the
|
|
1226
|
+
base's light tone and maps into the dark window (light text on dark bg)
|
|
892
1227
|
```
|
|
893
1228
|
|
|
894
|
-
**`fixed`** —
|
|
1229
|
+
**`fixed`** — tone is mapped (not inverted), relative sign preserved:
|
|
895
1230
|
|
|
896
1231
|
```
|
|
897
|
-
Light: accent-fill
|
|
898
|
-
Dark: accent-fill maps
|
|
1232
|
+
Light: accent-fill tone=52, accent-text tone='+20' → lighter than the fill
|
|
1233
|
+
Dark: accent-fill maps into the dark window, sign preserved
|
|
899
1234
|
```
|
|
900
1235
|
|
|
901
|
-
|
|
1236
|
+
Offsets that would push past `[0, 100]` clamp to the boundary, or — with `autoFlip` (default on) — mirror to the other side of the base. Set `autoFlip: false` to keep the authored side and clamp instead.
|
|
1237
|
+
|
|
1238
|
+
**`static`** — no adaptation, same tone in every scheme.
|
|
902
1239
|
|
|
903
1240
|
---
|
|
904
1241
|
|
|
905
1242
|
## Light / dark scheme mapping
|
|
906
1243
|
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
Absolute lightness values (root colors and dependent colors with absolute lightness) are mapped linearly within the configured `lightLightness` window:
|
|
1244
|
+
The mapping is now a single tone pipeline; there is no Möbius curve. See [`docs/okhst.md`](okhst.md) for the full math and the calibrated default constants.
|
|
910
1245
|
|
|
911
|
-
|
|
912
|
-
const [lo, hi] = lightLightness; // default: [10, 100]
|
|
913
|
-
const mappedL = (lightness * (hi - lo)) / 100 + lo;
|
|
914
|
-
```
|
|
1246
|
+
### Light scheme
|
|
915
1247
|
|
|
916
|
-
|
|
1248
|
+
An authored tone (0–100) is remapped into the `lightTone` window. The window's `lo`/`hi` are OKHSL-lightness endpoints (0–100); the tone is positioned within the window's tone interval and converted to a final OKHSL lightness. `static` mode and HC variants use the full range.
|
|
917
1249
|
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
1250
|
+
```
|
|
1251
|
+
window = lightTone // default [10, 100]
|
|
1252
|
+
finalTone = remap(authorTone, window)
|
|
1253
|
+
finalL = fromTone(finalTone) // OKHSL lightness
|
|
1254
|
+
```
|
|
923
1255
|
|
|
924
|
-
### Dark scheme
|
|
1256
|
+
### Dark scheme
|
|
925
1257
|
|
|
926
|
-
**`auto`** —
|
|
1258
|
+
**`auto`** — invert the tone, then remap into the dark window:
|
|
927
1259
|
|
|
928
|
-
```
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
// darkCurve default: 0.5
|
|
1260
|
+
```
|
|
1261
|
+
window = darkTone // default [15, 95]
|
|
1262
|
+
inverted = 100 - authorTone
|
|
1263
|
+
finalTone = remap(inverted, window)
|
|
933
1264
|
```
|
|
934
1265
|
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
Unlike a power curve, the Möbius transformation provides **proportional expansion** — small and large deltas are scaled by similar ratios, preserving the visual hierarchy of the light theme.
|
|
1266
|
+
Because tone is contrast-uniform, the inversion preserves contrast steps without a fitted curve — the asymmetry between light and dark lives entirely in the two windows' `(lo, hi, eps)` scalars (`eps` defaults to the reference `0.05`).
|
|
938
1267
|
|
|
939
|
-
**`fixed`** —
|
|
1268
|
+
**`fixed`** — remap into the dark window without inversion:
|
|
940
1269
|
|
|
941
|
-
```
|
|
942
|
-
|
|
1270
|
+
```
|
|
1271
|
+
finalTone = remap(authorTone, darkTone)
|
|
943
1272
|
```
|
|
944
1273
|
|
|
945
|
-
|
|
946
|
-
|---|---|---|---|---|
|
|
947
|
-
| surface (L=97) | 97 | 19.7 | 17.4 | 92.6 |
|
|
948
|
-
| accent-fill (L=52) | 52 | 66.9 | 53.4 | 56.6 |
|
|
949
|
-
| accent-text (L=100) | 100 | 15 | 15 | 95 |
|
|
950
|
-
|
|
951
|
-
In high-contrast variants the `darkLightness` window is bypassed — `auto` uses the Möbius curve over the full `[0, 100]` range, `fixed` uses identity.
|
|
1274
|
+
In high-contrast variants both windows are bypassed (forced to the full `[0, 100]` range): `auto` still inverts, `fixed`/`static` do not.
|
|
952
1275
|
|
|
953
1276
|
### Dark scheme — saturation
|
|
954
1277
|
|
|
@@ -966,10 +1289,9 @@ S_dark = S_light * (1 - darkDesaturation) // default: 0.1
|
|
|
966
1289
|
|
|
967
1290
|
```ts
|
|
968
1291
|
glaze.configure({
|
|
969
|
-
|
|
970
|
-
|
|
1292
|
+
lightTone: [10, 100], // [lo, hi]; or { lo, hi, eps } / false to disable clamping
|
|
1293
|
+
darkTone: [15, 95], // [lo, hi]; or { lo, hi, eps } / false to disable clamping
|
|
971
1294
|
darkDesaturation: 0.1,
|
|
972
|
-
darkCurve: 0.5, // or [normal, hc] pair
|
|
973
1295
|
states: {
|
|
974
1296
|
dark: '@dark',
|
|
975
1297
|
highContrast: '@high-contrast',
|
|
@@ -985,20 +1307,23 @@ glaze.configure({
|
|
|
985
1307
|
});
|
|
986
1308
|
```
|
|
987
1309
|
|
|
1310
|
+
A `ToneWindow` is `[lo, hi]` (OKHSL-lightness endpoints, reference eps — the common form), `{ lo, hi, eps }` (advanced: explicit per-mode render eps), or `false` to disable clamping (full range `[0, 100]` at the reference eps). `false` removes the *boundaries*, not the contrast-uniform tone curve.
|
|
1311
|
+
|
|
988
1312
|
`GlazeConfig`:
|
|
989
1313
|
|
|
990
1314
|
| Field | Default | Description |
|
|
991
1315
|
|---|---|---|
|
|
992
|
-
| `
|
|
993
|
-
| `
|
|
1316
|
+
| `lightTone` | `[10, 100]` | Light scheme tone window: `[lo, hi]`, `{ lo, hi, eps }`, or `false` to disable clamping. Bypassed in HC. |
|
|
1317
|
+
| `darkTone` | `[15, 95]` | Dark scheme tone window: `[lo, hi]`, `{ lo, hi, eps }`, or `false` to disable clamping. Bypassed in HC. |
|
|
994
1318
|
| `darkDesaturation` | `0.1` | Saturation reduction in dark scheme (0–1). |
|
|
995
|
-
| `darkCurve` | `0.5` | Möbius beta for dark `auto`-inversion (0–1). Accepts `[normal, hc]` pair. |
|
|
996
1319
|
| `states.dark` | `'@dark'` | State alias for dark mode tokens (Tasty export). |
|
|
997
1320
|
| `states.highContrast` | `'@high-contrast'` | State alias for HC tokens. |
|
|
998
1321
|
| `modes.dark` | `true` | Include dark variants in exports. |
|
|
999
1322
|
| `modes.highContrast` | `false` | Include HC variants. |
|
|
1000
1323
|
| `shadowTuning` | `undefined` | Default tuning for all shadow colors. Per-color tuning merges field-by-field. |
|
|
1001
|
-
| `autoFlip` | `true` | When solving `contrast
|
|
1324
|
+
| `autoFlip` | `true` | Default for each color's `autoFlip`. When solving `contrast` (or applying a relative `tone` that overshoots `[0, 100]`), allow crossing to the opposite side instead of clamping. With `false`, only the requested direction is considered; unmet contrasts pin the tone to that direction's extreme (and emit a warning) and overshooting offsets clamp to the boundary. Override per color via [`autoFlip`](#autoflip). |
|
|
1325
|
+
| `pastel` | `false` | Hue-independent "safe" chroma limit across all colors so scaling saturation never exceeds the sRGB boundary at any hue for the given lightness. Override per color via [`pastel`](#per-color-pastel). |
|
|
1326
|
+
| `inferRole` | `true` | Infer each color's [`role`](#roles) from its name when no explicit `role` is set. Set to `false` to opt out of name-based inference (the base-opposite and foreground-default fallbacks still apply). |
|
|
1002
1327
|
|
|
1003
1328
|
| Method | Description |
|
|
1004
1329
|
|---|---|
|
|
@@ -1039,10 +1364,12 @@ Resolution priority (highest first):
|
|
|
1039
1364
|
| Condition | Behavior |
|
|
1040
1365
|
|---|---|
|
|
1041
1366
|
| `contrast` without `base` in a **theme** color | Validation error |
|
|
1042
|
-
| Relative `
|
|
1367
|
+
| Relative `tone` without `base` in a **theme** color | Validation error |
|
|
1043
1368
|
| `contrast` without `base` in `glaze.color()` | Anchors against the literal seed (no error) |
|
|
1044
|
-
| Relative `
|
|
1045
|
-
| `
|
|
1369
|
+
| Relative `tone` without `base` in `glaze.color()` | Anchors against the literal seed (no error) |
|
|
1370
|
+
| Relative `tone` overshoots `[0, 100]` | Mirror to the other side of the base (`autoFlip` on, default), or clamp to the boundary (`autoFlip` off) |
|
|
1371
|
+
| `tone` resolves outside 0–100 | Clamp silently |
|
|
1372
|
+
| `'max'` / `'min'` without `base` | Allowed — resolves to the scheme's tone extreme (root color) |
|
|
1046
1373
|
| `saturation` outside 0–1 | Clamp silently |
|
|
1047
1374
|
| Circular `base` references | Validation error |
|
|
1048
1375
|
| `base` references non-existent name | Validation error |
|
|
@@ -1112,35 +1439,68 @@ formatOklch(280, 60, 95); // 'oklch(0.95 ... 280)'
|
|
|
1112
1439
|
|
|
1113
1440
|
To attach an alpha component, use `glaze.format(variant, format)` on a `ResolvedColorVariant` (which carries the `alpha` channel) instead of these raw writers.
|
|
1114
1441
|
|
|
1442
|
+
### OKHST tone utilities
|
|
1443
|
+
|
|
1444
|
+
```ts
|
|
1445
|
+
import {
|
|
1446
|
+
toTone,
|
|
1447
|
+
fromTone,
|
|
1448
|
+
toneFromY,
|
|
1449
|
+
yFromTone,
|
|
1450
|
+
okhstToOkhsl,
|
|
1451
|
+
okhslToOkhst,
|
|
1452
|
+
variantToOkhsl,
|
|
1453
|
+
REF_EPS,
|
|
1454
|
+
} from '@tenphi/glaze';
|
|
1455
|
+
```
|
|
1456
|
+
|
|
1457
|
+
| Function | Description |
|
|
1458
|
+
|---|---|
|
|
1459
|
+
| `toTone(l, eps?)` | OKHSL lightness (0–1) → tone (0–100). Defaults to `REF_EPS`. |
|
|
1460
|
+
| `fromTone(t, eps?)` | Tone (0–100) → OKHSL lightness (0–1). Inverse of `toTone`. |
|
|
1461
|
+
| `toneFromY(y, eps?)` / `yFromTone(t, eps?)` | Same transfer in luminance space (0–1). |
|
|
1462
|
+
| `okhstToOkhsl({ h, s, t })` | OKHST → OKHSL (`{ h, s, l }`). |
|
|
1463
|
+
| `okhslToOkhst({ h, s, l })` | OKHSL → OKHST (`{ h, s, t }`). |
|
|
1464
|
+
| `variantToOkhsl(variant)` | `ResolvedColorVariant` (stores `t`) → `{ h, s, l, alpha }` for rendering. |
|
|
1465
|
+
| `REF_EPS` | Reference epsilon (`0.05`) for the canonical tone axis. |
|
|
1466
|
+
|
|
1467
|
+
`ResolvedColorVariant` now stores `{ h, s, t, alpha }` (tone, not lightness). Use `variantToOkhsl(variant).l` to recover OKHSL lightness. See [`docs/okhst.md`](okhst.md) for the full model.
|
|
1468
|
+
|
|
1115
1469
|
### Contrast solver
|
|
1116
1470
|
|
|
1117
1471
|
```ts
|
|
1118
1472
|
import {
|
|
1119
|
-
|
|
1473
|
+
findToneForContrast,
|
|
1120
1474
|
findValueForMixContrast,
|
|
1475
|
+
resolveContrastForMode,
|
|
1121
1476
|
resolveMinContrast,
|
|
1477
|
+
apcaContrast,
|
|
1122
1478
|
} from '@tenphi/glaze';
|
|
1123
1479
|
```
|
|
1124
1480
|
|
|
1125
1481
|
| Function | Description |
|
|
1126
1482
|
|---|---|
|
|
1127
|
-
| `
|
|
1483
|
+
| `findToneForContrast(opts)` | Binary-search for the tone (0–1) that meets a contrast floor (WCAG or APCA) against a base color. Returns `{ tone, contrast, met, branch, flipped? }`. |
|
|
1128
1484
|
| `findValueForMixContrast(opts)` | Same, but searches for a mix `value` (0–1) that meets a contrast floor between a base and a target. |
|
|
1129
|
-
| `
|
|
1485
|
+
| `resolveContrastForMode(spec, isHC, polarity?, outerExplicitHC?)` | Resolves a `ContrastSpec` to `{ metric: 'wcag' \| 'apca', target }` for the requested mode (picks the normal or HC entry of any pair). In HC, applies the metric's auto-enhancement unless `outerExplicitHC` is set or the inner metric pair carries an explicit HC value: APCA +15 Lc (clamped to 106); WCAG AA → AAA / AA-large → AAA-large (AAA-family and bare numbers unchanged). |
|
|
1486
|
+
| `resolveMinContrast(value)` | Resolves a `MinContrast` (WCAG preset or number) to a numeric ratio. |
|
|
1487
|
+
| `apcaContrast(yText, yBg)` | APCA Lc magnitude (0–106) for two relative luminances. |
|
|
1488
|
+
|
|
1489
|
+
Exported constants: `APCA_PRESETS`, `APCA_HC_ENHANCEMENT` (`15`, the Enhanced Level delta), `APCA_MAX_LC` (`106`).
|
|
1130
1490
|
|
|
1131
|
-
`
|
|
1491
|
+
`findToneForContrast` options:
|
|
1132
1492
|
|
|
1133
1493
|
| Option | Default | Description |
|
|
1134
1494
|
|---|---|---|
|
|
1135
1495
|
| `hue` | — | Candidate hue (0–360). |
|
|
1136
1496
|
| `saturation` | — | Candidate saturation (0–1). |
|
|
1137
|
-
| `
|
|
1497
|
+
| `preferredTone` | — | Preferred candidate tone (0–1). Kept if it already meets the target. |
|
|
1138
1498
|
| `baseLinearRgb` | — | Base color as linear sRGB tuple. |
|
|
1139
|
-
| `contrast` | — |
|
|
1140
|
-
| `
|
|
1499
|
+
| `contrast` | — | `ResolvedContrast` (`{ metric, target }`). |
|
|
1500
|
+
| `toneRange` | `[0, 1]` | Search bounds in tone. |
|
|
1141
1501
|
| `epsilon` | `1e-4` | Convergence threshold. |
|
|
1142
|
-
| `maxIterations` | `
|
|
1143
|
-
| `initialDirection` | higher-contrast side | Direction to search first (`'lighter'` or `'darker'`).
|
|
1502
|
+
| `maxIterations` | `18` | Max binary-search iterations per branch. |
|
|
1503
|
+
| `initialDirection` | higher-contrast side | Direction to search first (`'lighter'` or `'darker'`). |
|
|
1144
1504
|
| `flip` | `false` | When `true`, try the opposite direction if the initial one doesn't meet the target. When `false`, only the initial direction is searched — unmet contrasts pin the result to that direction's extreme. |
|
|
1145
1505
|
|
|
1146
|
-
Result: `{
|
|
1506
|
+
Result: `{ tone, contrast, met, branch: 'lighter' | 'darker' | 'preferred', flipped? }`. `flipped: true` indicates the initial direction failed and the opposite direction satisfied the target.
|