@cube-dev/ui-kit 0.165.0 → 0.167.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -7
- package/dist/CHANGELOG.md +48 -0
- package/dist/README.md +4 -7
- 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 +4 -4
- package/dist/components/GlobalStyles.js.map +1 -1
- package/dist/components/GridProvider.js +1 -1
- package/dist/components/HiddenInput.js +1 -1
- package/dist/components/Root.js +1 -2
- package/dist/components/Root.js.map +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.d.ts +1 -0
- 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.d.ts +7 -3
- package/dist/components/actions/use-anchored-menu.js +17 -12
- package/dist/components/actions/use-anchored-menu.js.map +1 -1
- package/dist/components/actions/use-context-menu.d.ts +6 -3
- package/dist/components/actions/use-context-menu.js +25 -13
- package/dist/components/actions/use-context-menu.js.map +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/InfoBadge/InfoBadge.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.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/data/DataTable/DataTable.js +1 -1
- package/dist/components/data/ItemTable/ItemTable.js +1 -1
- package/dist/components/data/ItemTable/ItemTableBulkBar.js +1 -1
- package/dist/components/data/ItemTable/ItemTableDragPreview.js +1 -1
- package/dist/components/data/ItemTable/ItemTableFooter.js +1 -1
- package/dist/components/data/ItemTable/ItemTableToolbar.js +1 -1
- package/dist/components/data/TableBase/ColumnResizer.js +1 -1
- package/dist/components/data/TableBase/RowCollection.js +1 -1
- package/dist/components/data/TableBase/TableHeaderCell.js +1 -1
- package/dist/components/data/TableBase/TableRow.js +1 -1
- package/dist/components/data/TableBase/TableView.js +1 -1
- package/dist/components/data/TableBase/column-menu.js +1 -1
- package/dist/components/data/TableBase/column-tint.js +1 -1
- package/dist/components/data/TableBase/row-menu.js +1 -1
- package/dist/components/data/TableBase/styled.d.ts +2 -1
- package/dist/components/data/TableBase/styled.js +1 -1
- package/dist/components/data/TableBase/table-tree.js +1 -1
- package/dist/components/data/TableBase/types.js +1 -1
- package/dist/components/data/TableBase/use-cell-selection.d.ts +1 -0
- package/dist/components/data/TableBase/use-cell-selection.js +0 -0
- package/dist/components/data/TableBase/use-column-order.js +1 -1
- package/dist/components/data/TableBase/use-container-width.js +1 -1
- package/dist/components/data/TableBase/use-row-move-animation.js +1 -1
- package/dist/components/data/TableBase/use-scrollability.js +1 -1
- package/dist/components/data/TableBase/use-table-columns.js +1 -1
- package/dist/components/data/TableBase/use-table-search.js +1 -1
- package/dist/components/data/TableBase/use-table-selection.js +1 -1
- package/dist/components/data/TableBase/use-table-sort.js +1 -1
- package/dist/components/data/TableBase/use-table-sorts.js +1 -1
- package/dist/components/data/TableBase/use-table-storage.js +1 -1
- package/dist/components/data/TableBase/use-table-tree-state.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/ColorInput/ColorInput.js +1 -1
- package/dist/components/fields/ColorPicker/ColorPicker.js +1 -1
- package/dist/components/fields/ColorSwatch/ColorSwatch.js +1 -1
- package/dist/components/fields/ColorSwatchGroup/ColorSwatchGroup.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/MonthPicker.js +1 -1
- package/dist/components/fields/DatePicker/PeriodPicker.js +1 -1
- package/dist/components/fields/DatePicker/QuarterPicker.js +1 -1
- package/dist/components/fields/DatePicker/TimeInput.js +1 -1
- package/dist/components/fields/DatePicker/WeekPicker.js +1 -1
- package/dist/components/fields/DatePicker/YearPicker.js +1 -1
- package/dist/components/fields/DatePicker/parseDate.js +1 -1
- package/dist/components/fields/DatePicker/period.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/index.d.ts +1 -0
- package/dist/components/fields/ListBoxPopover/listNavigation.js +1 -1
- package/dist/components/fields/ListBoxPopover/useCompositeFocus.d.ts +2 -0
- 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/SearchComboBox/SearchComboBox.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/TextInput/useAutoSizeTextArea.js +1 -1
- package/dist/components/fields/TextInputMapper/TextInputMapper.js +1 -1
- package/dist/components/fields/color/ColorPanel.js +1 -1
- package/dist/components/fields/color/channels.js +1 -1
- package/dist/components/fields/color/color.js +1 -1
- package/dist/components/fields/color/context.js +1 -1
- package/dist/components/form/FieldWrapper/FieldWrapper.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/validation/ValidationIndicator.js +1 -1
- package/dist/components/form/validation/resolve-validation-props.js +1 -1
- package/dist/components/form/validation/use-validation-props.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.d.ts +33 -7
- package/dist/components/layout/Board/Board.js +29 -11
- package/dist/components/layout/Board/Board.js.map +1 -1
- package/dist/components/layout/Board/BoardProvider.js +1 -1
- package/dist/components/layout/Board/BoardResponsive.d.ts +6 -3
- package/dist/components/layout/Board/BoardResponsive.js +3 -3
- package/dist/components/layout/Board/BoardResponsive.js.map +1 -1
- package/dist/components/layout/Board/Widget.d.ts +38 -1
- package/dist/components/layout/Board/Widget.js +6 -2
- package/dist/components/layout/Board/Widget.js.map +1 -1
- package/dist/components/layout/Board/WidgetHost.js +69 -18
- package/dist/components/layout/Board/WidgetHost.js.map +1 -1
- package/dist/components/layout/Board/board-context.js +1 -1
- package/dist/components/layout/Board/board-context.js.map +1 -1
- package/dist/components/layout/Board/board-store.js +2 -2
- package/dist/components/layout/Board/board-store.js.map +1 -1
- package/dist/components/layout/Board/grid-core/calculate.js +1 -1
- package/dist/components/layout/Board/grid-core/collision-modes.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/group-move.js +1 -1
- package/dist/components/layout/Board/grid-core/layout.js +1 -1
- package/dist/components/layout/Board/grid-core/placement.d.ts +58 -0
- package/dist/components/layout/Board/grid-core/placement.js +153 -0
- package/dist/components/layout/Board/grid-core/placement.js.map +1 -0
- package/dist/components/layout/Board/grid-core/sort.js +1 -1
- package/dist/components/layout/Board/index.d.ts +3 -1
- package/dist/components/layout/Board/index.js +2 -1
- package/dist/components/layout/Board/index.js.map +1 -1
- package/dist/components/layout/Board/responsive-utils.js +1 -1
- package/dist/components/layout/Board/use-board-layout.d.ts +26 -0
- package/dist/components/layout/Board/use-board-layout.js +4 -4
- package/dist/components/layout/Board/use-board-layout.js.map +1 -1
- package/dist/components/layout/Board/use-board-registry.js +5 -56
- package/dist/components/layout/Board/use-board-registry.js.map +1 -1
- package/dist/components/layout/Board/use-board-select-modifier-key.js +1 -1
- package/dist/components/layout/Board/use-board-selection.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/Pagination/Pagination.js +1 -1
- package/dist/components/navigation/Pagination/use-pagination.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/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/CalendarHeader.js +1 -1
- package/dist/components/other/Calendar/CalendarPanel.js +1 -1
- package/dist/components/other/Calendar/PeriodCalendar.js +1 -1
- package/dist/components/other/Calendar/PeriodGrid.js +1 -1
- package/dist/components/other/Calendar/RangeCalendar.js +1 -1
- package/dist/components/other/Calendar/styled.js +1 -1
- package/dist/components/other/CubeLogo/CubeLogo.js +1 -1
- package/dist/components/other/NoDataIcon/NoDataIcon.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.d.ts +2 -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.d.ts +1 -0
- 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/Modal/types.d.ts +1 -0
- 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.d.ts +2 -0
- 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 +2 -1
- package/dist/components/overlays/Tooltip/Tooltip.js.map +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.d.ts +2 -0
- package/dist/components/portal/PortalProvider.js +1 -1
- package/dist/components/portal/index.d.ts +1 -0
- 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/eslint-plugin/defaults.generated.js +25 -1
- package/dist/eslint-plugin/defaults.generated.js.map +1 -1
- package/dist/eslint-plugin/index.js +1 -1
- package/dist/eslint-plugin/rules/no-redundant-default-prop.js +1 -1
- package/dist/i18n/I18nProvider.js +1 -1
- package/dist/i18n/createFormatter.js +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/instance.js +1 -1
- package/dist/i18n/locales/de-DE/uikit.js +1 -1
- package/dist/i18n/locales/en-US/uikit.js +1 -1
- package/dist/i18n/locales/es-ES/uikit.js +1 -1
- package/dist/i18n/locales/es-MX/uikit.js +1 -1
- package/dist/i18n/locales/fr-FR/uikit.js +1 -1
- package/dist/i18n/locales/it-IT/uikit.js +1 -1
- package/dist/i18n/locales/ja-JP/uikit.js +1 -1
- package/dist/i18n/locales/nb-NO/uikit.js +1 -1
- package/dist/i18n/locales/pt-BR/uikit.js +1 -1
- package/dist/i18n/locales/pt-PT/uikit.js +1 -1
- package/dist/i18n/locales/sv-SE/uikit.js +1 -1
- package/dist/i18n/locales/vi-VN/uikit.js +1 -1
- package/dist/i18n/locales.js +1 -1
- package/dist/i18n/useFormatter.js +1 -1
- package/dist/i18n/useI18n.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/ArrowNarrowDownIcon.js +1 -1
- package/dist/icons/ArrowNarrowUpIcon.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/PipetteIcon.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.d.ts +7 -3
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/probe/canonicalize.js +1 -1
- package/dist/probe/css.js +1 -1
- package/dist/probe/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/all-tokens.d.ts +10 -0
- package/dist/tokens/{index.js → all-tokens.js} +7 -25
- package/dist/tokens/all-tokens.js.map +1 -0
- package/dist/tokens/base.js +2 -1
- package/dist/tokens/base.js.map +1 -1
- package/dist/tokens/color-seed.js +1 -1
- package/dist/tokens/color-theme.js +1 -1
- package/dist/tokens/colors.js +1 -1
- package/dist/tokens/index.d.ts +3 -10
- package/dist/tokens/layout.js +1 -1
- package/dist/tokens/lazy-styles.js +1 -1
- package/dist/tokens/palette-config.js +1 -1
- package/dist/tokens/palette.js +1 -1
- package/dist/tokens/resolve.d.ts +113 -0
- package/dist/tokens/resolve.js +403 -0
- package/dist/tokens/resolve.js.map +1 -0
- 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/disabledProps.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/useBufferedValue.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.d.ts +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/Colors.md +16 -40
- package/docs/ComplexLayout.md +8 -0
- package/docs/CreateComponent.md +15 -8
- package/docs/Introduction.md +15 -36
- package/docs/RenderCache.md +8 -6
- package/docs/Theming.md +164 -497
- package/docs/Usage.md +129 -138
- package/docs/Utilities.md +2 -2
- package/docs/components/CollectionItem.md +1 -0
- package/docs/components/actions/Banner.md +1 -0
- package/docs/components/actions/Button.md +8 -36
- package/docs/components/actions/ButtonSplit.md +2 -0
- package/docs/components/actions/CommandMenu.md +8 -8
- package/docs/components/actions/ItemButton.md +6 -20
- package/docs/components/actions/Link.md +10 -5
- package/docs/components/actions/Menu.md +24 -11
- package/docs/components/actions/MenuTrigger.md +3 -12
- package/docs/components/actions/use-anchored-menu.md +5 -5
- package/docs/components/actions/use-context-menu.md +11 -7
- package/docs/components/content/Badge.md +3 -0
- package/docs/components/content/HotKeys.md +21 -14
- package/docs/components/content/InlineInput.md +14 -14
- package/docs/components/content/Item.md +25 -17
- package/docs/components/content/ItemCard.md +1 -0
- package/docs/components/content/Layout.md +12 -1
- package/docs/components/content/PrismCode.md +13 -18
- package/docs/components/content/Tag.md +1 -1
- package/docs/components/content/TextItem.md +5 -3
- package/docs/components/content/Tree.md +69 -154
- package/docs/components/data/DataTable.md +56 -168
- package/docs/components/data/ItemTable.md +182 -485
- package/docs/components/fields/Checkbox.md +2 -0
- package/docs/components/fields/ColorInput.md +38 -79
- package/docs/components/fields/ColorPicker.md +17 -39
- package/docs/components/fields/ColorSwatch.md +11 -30
- package/docs/components/fields/ColorSwatchGroup.md +18 -42
- package/docs/components/fields/ComboBox.md +13 -1
- package/docs/components/fields/CommandTextArea.md +10 -37
- package/docs/components/fields/DatePicker.md +3 -0
- package/docs/components/fields/FileInput.md +3 -0
- package/docs/components/fields/FilterListBox.md +34 -14
- package/docs/components/fields/FilterPicker.md +33 -16
- package/docs/components/fields/HueSlider.md +5 -5
- package/docs/components/fields/ListBox.md +35 -9
- package/docs/components/fields/NumberInput.md +3 -0
- package/docs/components/fields/PasswordInput.md +3 -0
- package/docs/components/fields/PeriodPicker.md +7 -17
- package/docs/components/fields/Picker.md +54 -29
- package/docs/components/fields/RadioGroup.md +13 -5
- package/docs/components/fields/SearchComboBox.md +3 -0
- package/docs/components/fields/SearchInput.md +4 -2
- package/docs/components/fields/Select.md +23 -13
- package/docs/components/fields/Switch.md +3 -0
- package/docs/components/fields/TextInput.md +3 -0
- package/docs/components/fields/TextInputMapper.md +1 -2
- package/docs/components/form/Field.md +5 -2
- package/docs/components/form/Form.md +5 -0
- package/docs/components/form/FormInstance.md +1 -1
- package/docs/components/helpers/DisplayTransition.md +10 -6
- package/docs/components/helpers/IconSwitch.md +1 -0
- package/docs/components/layout/Board.md +89 -193
- package/docs/components/navigation/Pagination.md +36 -75
- package/docs/components/navigation/Tabs.md +3 -15
- package/docs/components/other/Calendar.md +22 -39
- package/docs/components/other/CubeLogo.md +1 -1
- package/docs/components/overlays/Dialog.md +3 -0
- package/docs/components/overlays/DialogContainer.md +2 -0
- package/docs/components/overlays/DialogForm.md +6 -2
- package/docs/components/overlays/DialogTrigger.md +4 -2
- package/docs/components/overlays/Notifications.md +7 -0
- package/docs/components/overlays/Toast.md +12 -8
- package/docs/components/overlays/Tooltip.md +16 -0
- package/docs/components/overlays/UseDialogContainer.md +16 -10
- package/docs/components/status/LoadingAnimation.md +3 -9
- package/docs/tasty/configuration.md +195 -15
- package/docs/tasty/dsl.md +40 -5
- package/docs/tasty/injector.md +11 -0
- package/docs/tasty/methodology.md +1 -1
- package/docs/tasty/pipeline.md +1 -4
- package/docs/tasty/react-api.md +1 -1
- package/docs/tasty/styles.md +8 -1
- package/package.json +4 -4
- package/dist/tokens/index.js.map +0 -1
package/docs/Theming.md
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
# Theming
|
|
2
2
|
|
|
3
|
-
The whole palette is generated by [Glaze](https://github.com/tenphi/glaze) from a handful
|
|
4
|
-
of seeds, one per **zone**: the accent, the base, and each of the four status themes.
|
|
5
|
-
Those seeds are tunable at runtime — change one and every token re-resolves, in light,
|
|
6
|
-
dark, and high-contrast schemes at once.
|
|
3
|
+
The whole palette is generated by [Glaze](https://github.com/tenphi/glaze) from a handful of seeds, one per **zone**: the accent, the base, and each of the four status themes. Those seeds are tunable at runtime — change one and every token re-resolves, in light, dark, and high-contrast schemes at once.
|
|
7
4
|
|
|
8
|
-
Every zone takes the same seed, and it comes in two forms: a **color**, which is usually
|
|
9
|
-
what you actually have, or the **numbers** behind one. Never both — a zone is seeded one
|
|
10
|
-
way or the other. See [One seed, two ways to spell it](#one-seed-two-ways-to-spell-it).
|
|
5
|
+
Every zone takes the same seed, and it comes in two forms: a **color**, which is usually what you actually have, or the **numbers** behind one. Never both — a zone is seeded one way or the other. See [One seed, two ways to spell it](#one-seed-two-ways-to-spell-it).
|
|
11
6
|
|
|
12
7
|
```ts
|
|
13
8
|
import { setPaletteConfig } from '@cube-dev/ui-kit';
|
|
@@ -24,47 +19,39 @@ setPaletteConfig({
|
|
|
24
19
|
});
|
|
25
20
|
```
|
|
26
21
|
|
|
27
|
-
With no configuration set, the palette is exactly the one the kit ships — the
|
|
28
|
-
defaults below are the shipped seeds, and a snapshot test pins every resolved
|
|
29
|
-
value so this stays true.
|
|
22
|
+
With no configuration set, the palette is exactly the one the kit ships — the defaults below are the shipped seeds, and a snapshot test pins every resolved value so this stays true.
|
|
30
23
|
|
|
31
24
|
## What is tunable
|
|
32
25
|
|
|
33
26
|
Every zone below takes a `PaletteSeed`: either a color string, or `{ hue?, saturation? }`.
|
|
34
27
|
|
|
35
|
-
| Option
|
|
36
|
-
|
|
|
37
|
-
| `accent`
|
|
38
|
-
| `accent` as a color
|
|
39
|
-
| `accent.saturation`
|
|
40
|
-
| `base`
|
|
41
|
-
| `base` as a color
|
|
42
|
-
| `base.saturation`
|
|
43
|
-
| `themes.<status>`
|
|
44
|
-
| `themes.<status>` as a color | All three components, and its chroma **does** become the theme's seed — unlike the accent's. See [Status themes](#status-themes).
|
|
45
|
-
| `themes.code.saturation`
|
|
46
|
-
| `surfaceMode`
|
|
47
|
-
| `pastel`
|
|
48
|
-
| `contrastLevel`
|
|
28
|
+
| Option | Scope | Default |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| `accent` | The **accent** zone — the brand. Drives the `accent-*` family on every theme, `primary` / `purple` / `special`, and the brand-tinted `focus`, loading faces and disabled chip. | `{ hue: 280.3 }` |
|
|
31
|
+
| `accent` as a color | Contributes hue, chroma **and tone**, so the brand fill renders as the color you passed. Its chroma reaches the accent family through Glaze's `from`, not through the zone's seed. | unset |
|
|
32
|
+
| `accent.saturation` | Seed saturation (0–100) for the `default` theme, and the fallback every status theme inherits. Setting it **turns `pastel` off**, which is the path it belongs to. | `100` |
|
|
33
|
+
| `base` | The **base** zone — the neutral chrome: `surface` and its ladder, the `surface-text*` ramp, `border`, `placeholder`. Omit it and the zone follows the accent. | follows `accent` |
|
|
34
|
+
| `base` as a color | Contributes hue **and saturation**, clipped to 50; its tone is discarded. | unset |
|
|
35
|
+
| `base.saturation` | Seed saturation (0–100) of the base zone, on the same scale as the accent's. The shipped chrome is `12`. | `(accent's chroma) × 0.12` |
|
|
36
|
+
| `themes.<status>` | Seed for `success` / `danger` / `warning` / `note`. | `156.9` / `23.1` / `84.3` / `302.3` |
|
|
37
|
+
| `themes.<status>` as a color | All three components, and its chroma **does** become the theme's seed — unlike the accent's. See [Status themes](#status-themes). | unset |
|
|
38
|
+
| `themes.code.saturation` | Saturation for the `code-*` syntax family. Hues are fixed, it takes no color, and it does **not** inherit the accent's saturation nor track its default. | `80` |
|
|
39
|
+
| `surfaceMode` | Global. `'tinted'` moves the neutral surface ramp two tones off the end of the tone scale, which is what gives the base saturation room to reach the page surface. | `'neutral'` |
|
|
40
|
+
| `pastel` | Global. Relaxes the sRGB-safe chroma limit, and **pins the accent's saturation to 100**. Wins wherever both are set. Every theme except `code`. | `true` |
|
|
41
|
+
| `contrastLevel` | Global. `'auto'`, or a manual `0`–`100` level. | `'auto'` |
|
|
49
42
|
|
|
50
43
|
### The setter replaces
|
|
51
44
|
|
|
52
|
-
`setPaletteConfig()` works like `useState`, not like `glaze.configure()`: the
|
|
53
|
-
config you pass **is** the config, resolved against the shipped defaults. Nothing
|
|
54
|
-
accumulates, so removing a customization means removing it from the object:
|
|
45
|
+
`setPaletteConfig()` works like `useState`, not like `glaze.configure()`: the config you pass **is** the config, resolved against the shipped defaults. Nothing accumulates, so removing a customization means removing it from the object:
|
|
55
46
|
|
|
56
47
|
```ts
|
|
57
48
|
setPaletteConfig({ accent: { hue: 200 }, base: { hue: 60 } });
|
|
58
49
|
setPaletteConfig({ accent: { hue: 200 } }); // `base` is gone — follows accent again
|
|
59
50
|
```
|
|
60
51
|
|
|
61
|
-
That is what makes the config safe to keep in your own state and re-apply: the
|
|
62
|
-
same object twice does the same thing as once, and `<Root palette>` can un-set a
|
|
63
|
-
field by no longer passing it.
|
|
52
|
+
That is what makes the config safe to keep in your own state and re-apply: the same object twice does the same thing as once, and `<Root palette>` can un-set a field by no longer passing it.
|
|
64
53
|
|
|
65
|
-
To change one field of the config already in place — a slider in a settings UI —
|
|
66
|
-
pass an updater. It receives the config **as written**, sparse, so spreading it
|
|
67
|
-
preserves which fields are pinned and which still inherit:
|
|
54
|
+
To change one field of the config already in place — a slider in a settings UI — pass an updater. It receives the config **as written**, sparse, so spreading it preserves which fields are pinned and which still inherit:
|
|
68
55
|
|
|
69
56
|
```ts
|
|
70
57
|
// A zone holds ONE seed, so a one-field control spreads that seed too — writing a bare
|
|
@@ -81,8 +68,7 @@ setPaletteConfig((config) => ({
|
|
|
81
68
|
}));
|
|
82
69
|
```
|
|
83
70
|
|
|
84
|
-
`resetPaletteConfig()` drops all tuning at once — the same as
|
|
85
|
-
`setPaletteConfig({})`, just easier to read at a call site.
|
|
71
|
+
`resetPaletteConfig()` drops all tuning at once — the same as `setPaletteConfig({})`, just easier to read at a call site.
|
|
86
72
|
|
|
87
73
|
### One seed, two ways to spell it
|
|
88
74
|
|
|
@@ -92,14 +78,9 @@ Every zone takes the same `PaletteSeed`, and it comes in two forms:
|
|
|
92
78
|
type PaletteSeed = string | { hue?: number; saturation?: number };
|
|
93
79
|
```
|
|
94
80
|
|
|
95
|
-
A string is a color — anything Glaze parses: hex, `rgb()`, `hsl()`, `okhsl()`, `okhst()`,
|
|
96
|
-
`oklch()`. CSS color keywords (`rebeccapurple`) are not supported; an unparseable value
|
|
97
|
-
warns once and falls back to the numeric path.
|
|
81
|
+
A string is a color — anything Glaze parses: hex, `rgb()`, `hsl()`, `okhsl()`, `okhst()`, `oklch()`. CSS color keywords (`rebeccapurple`) are not supported; an unparseable value warns once and falls back to the numeric path.
|
|
98
82
|
|
|
99
|
-
**The union is the exclusivity.** A zone is seeded one way or the other — there is no
|
|
100
|
-
precedence rule to learn, and no way to write a hue that half-overrides a hex. A patch
|
|
101
|
-
that switches form therefore *replaces* rather than merges; layering happens within a
|
|
102
|
-
path:
|
|
83
|
+
**The union is the exclusivity.** A zone is seeded one way or the other — there is no precedence rule to learn, and no way to write a hue that half-overrides a hex. A patch that switches form therefore _replaces_ rather than merges; layering happens within a path:
|
|
103
84
|
|
|
104
85
|
```ts
|
|
105
86
|
setPaletteConfig({ accent: '#2F5BFF' });
|
|
@@ -109,54 +90,32 @@ setPaletteConfig((config) => ({ ...config, accent: { hue: 300 } }));
|
|
|
109
90
|
|
|
110
91
|
#### The zones
|
|
111
92
|
|
|
112
|
-
- **Accent** (`accent`) — the `accent-*` family on every theme, `primary` / `purple` /
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
- **
|
|
116
|
-
ramp, `border`, `placeholder`.
|
|
117
|
-
- **Status** (`themes.success` / `danger` / `warning` / `note`) — one seed each. See
|
|
118
|
-
[Status themes](#status-themes).
|
|
119
|
-
- **Syntax** (`themes.code`) — the exception: a saturation and nothing else. See
|
|
120
|
-
[The `code-*` family is the exception](#the-code--family-is-the-exception).
|
|
93
|
+
- **Accent** (`accent`) — the `accent-*` family on every theme, `primary` / `purple` / `special`, plus `focus`, the loading faces and the disabled chip. Its saturation is also the fallback every status theme inherits.
|
|
94
|
+
- **Base** (`base`) — the neutral chrome: `surface` and its ladder, the `surface-text*` ramp, `border`, `placeholder`.
|
|
95
|
+
- **Status** (`themes.success` / `danger` / `warning` / `note`) — one seed each. See [Status themes](#status-themes).
|
|
96
|
+
- **Syntax** (`themes.code`) — the exception: a saturation and nothing else. See [The `code-*` family is the exception](#the-code--family-is-the-exception).
|
|
121
97
|
|
|
122
|
-
Omit `base` and the chrome follows the accent, so out of the box the greys carry a faint
|
|
123
|
-
tint of the brand. Seed it to decouple them — a warm grey UI under a cool blue brand:
|
|
98
|
+
Omit `base` and the chrome follows the accent, so out of the box the greys carry a faint tint of the brand. Seed it to decouple them — a warm grey UI under a cool blue brand:
|
|
124
99
|
|
|
125
100
|
```ts
|
|
126
101
|
setPaletteConfig({ accent: { hue: 235 }, base: { hue: 60 } });
|
|
127
102
|
```
|
|
128
103
|
|
|
129
|
-
Only the `default` theme is affected. A colored theme's tinted `surface` deliberately
|
|
130
|
-
follows _its own_ hue, because a danger banner should read as red.
|
|
104
|
+
Only the `default` theme is affected. A colored theme's tinted `surface` deliberately follows _its own_ hue, because a danger banner should read as red.
|
|
131
105
|
|
|
132
106
|
#### What a color contributes, per zone
|
|
133
107
|
|
|
134
|
-
The same string means slightly different things by zone, and the differences are the
|
|
135
|
-
point:
|
|
108
|
+
The same string means slightly different things by zone, and the differences are the point:
|
|
136
109
|
|
|
137
110
|
```ts
|
|
138
111
|
setPaletteConfig({ accent: '#2F5BFF', base: '#7A7269' });
|
|
139
112
|
```
|
|
140
113
|
|
|
141
|
-
- **Accent** — hue, chroma **and tone**. The tone is what makes the brand fill actually
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
status themes.
|
|
147
|
-
- **Base** — hue and saturation; the **tone is discarded**, because the chrome's own
|
|
148
|
-
lightness ladder is the design. A base color says which way the greys lean and how far,
|
|
149
|
-
not how dark they are.
|
|
150
|
-
- **Status** — hue, chroma and tone, and its chroma **does** become that theme's seed.
|
|
151
|
-
Nothing inherits from a status theme, so there is nothing to re-chromatise, and moving
|
|
152
|
-
the seed is what keeps the banner in proportion to the button.
|
|
153
|
-
|
|
154
|
-
The base color's saturation is **clipped to 50**. Naming a base color says "the chrome
|
|
155
|
-
_is_ this color", so it lands near it rather than at the 12% share it would otherwise
|
|
156
|
-
inherit — but a fully saturated chrome stops being chrome, and the base colors begin to
|
|
157
|
-
converge above 25 anyway (see [Tinted surfaces](#tinted-surfaces)). The tuner's manual
|
|
158
|
-
slider shares the same ceiling, so the two routes agree on what the top of the range
|
|
159
|
-
means. A base **number** is not clipped: a number is the more specific instruction.
|
|
114
|
+
- **Accent** — hue, chroma **and tone**. The tone is what makes the brand fill actually _be_ your color. Without it the fill is authored as a fixed tone step off white, so every accent hue lands at roughly the same lightness — a yellow brand comes out olive. The chroma reaches the accent family through Glaze's `from` rather than through the zone's seed, which is what stops a brand from re-chromatising the chrome and all four status themes.
|
|
115
|
+
- **Base** — hue and saturation; the **tone is discarded**, because the chrome's own lightness ladder is the design. A base color says which way the greys lean and how far, not how dark they are.
|
|
116
|
+
- **Status** — hue, chroma and tone, and its chroma **does** become that theme's seed. Nothing inherits from a status theme, so there is nothing to re-chromatise, and moving the seed is what keeps the banner in proportion to the button.
|
|
117
|
+
|
|
118
|
+
The base color's saturation is **clipped to 50**. Naming a base color says "the chrome _is_ this color", so it lands near it rather than at the 12% share it would otherwise inherit — but a fully saturated chrome stops being chrome, and the base colors begin to converge above 25 anyway (see [Tinted surfaces](#tinted-surfaces)). The tuner's manual slider shares the same ceiling, so the two routes agree on what the top of the range means. A base **number** is not clipped: a number is the more specific instruction.
|
|
160
119
|
|
|
161
120
|
```ts
|
|
162
121
|
setPaletteConfig({ base: '#6e7076' }); // near-grey in, near-grey chrome out
|
|
@@ -166,104 +125,45 @@ setPaletteConfig({ base: { saturation: 100 }, pastel: false }); // 100 stays 100
|
|
|
166
125
|
|
|
167
126
|
### A color seed is a request
|
|
168
127
|
|
|
169
|
-
The palette renders the color you asked for, and moves it only as far as it has to. Two
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
looks right for the pair. In dark the page is near-black and the same number becomes a
|
|
187
|
-
demand that a filled shape reach text contrast against it — which nothing in the palette
|
|
188
|
-
meets, the shipped fill included. Since a floor can only lighten, the surplus flattened
|
|
189
|
-
the dark half of the tone axis onto a single value: every brand darker than the floor came
|
|
190
|
-
out the same colour. The page floor is now sized for a shape and the label is guaranteed
|
|
191
|
-
separately, by a cap on the seed's tone.
|
|
192
|
-
|
|
193
|
-
They are APCA rather than WCAG on purpose. A single WCAG ratio means two different
|
|
194
|
-
things depending on the scheme: measured across twelve hues, a fill sitting exactly at
|
|
195
|
-
3:1 comes out at Lc 56 in light but only Lc 23 in dark. That is why light brands kept
|
|
196
|
-
getting crushed while dark ones sailed through the same rule. **A consequence to state
|
|
197
|
-
plainly: the emitted fill can sit below WCAG 3:1.** `#0EA5E9` renders at 2.77:1 against
|
|
198
|
-
a white page and is correct there — the Lc is the guarantee, not the ratio.
|
|
199
|
-
|
|
200
|
-
High contrast does **not** escalate the page floor. It is a request for separation over
|
|
201
|
-
brand, but not for separation from the page: the same fill carries the label, and driving
|
|
202
|
-
it off the page drives the label off it. The shipped ladder makes the same trade and lands
|
|
203
|
-
the other side of it, ending up with *less* page separation in high contrast than in
|
|
204
|
-
normal, because it darkens the fill toward its label. What does escalate is the label cap,
|
|
205
|
-
which searches the high-contrast variants too.
|
|
206
|
-
|
|
207
|
-
**`pastel` caps chroma.** The flat, hue-independent ceiling is what makes pastel even
|
|
208
|
-
across hues, and it sits below where a saturated color would land, so under it a color
|
|
209
|
-
seed can never resolve to itself: `#EF4444` renders `#c47069`. Under pastel the color
|
|
210
|
-
contributes its hue and its tone; turn pastel off to get its chroma too.
|
|
211
|
-
|
|
212
|
-
All of it applies per zone. A status color answers to the same two constraints on its own
|
|
213
|
-
`#<theme>-accent-surface`, including the label cap — every `type="primary"` item on a
|
|
214
|
-
status theme paints `#white` on that fill too, so a pale `danger` color is pulled down
|
|
215
|
-
rather than shipped as a white label on white.
|
|
216
|
-
|
|
217
|
-
Read the result back from the tokens themselves — `#accent-surface` is the fill,
|
|
218
|
-
`#accent-text-soft` the rest link color — or watch the requested/resolved chips in the
|
|
219
|
-
[Theme builder](#theme-builder).
|
|
128
|
+
The palette renders the color you asked for, and moves it only as far as it has to. Two things can make it move.
|
|
129
|
+
|
|
130
|
+
First, **exactness is scoped to the light, normal-contrast variant.** That is the one that reproduces your color. Dark and high contrast adapt, as every other color in the palette does — they are different pages, and a brand pinned across all four would be less faithful, not more. What holds everywhere is the floor below.
|
|
131
|
+
|
|
132
|
+
**The fill answers to two constraints, and they are different sizes.** The `#white` label it carries needs **APCA Lc 45** — text strength, because it is text. The page it sits on needs only **Lc 25**, because a solid fill is a shape, not text, and Lc 25 is what the palette's own shipped fill achieves against a dark page. Both are floors rather than targets: a brand already past them is emitted exactly as given, and one that misses moves only as far as the nearer requires.
|
|
133
|
+
|
|
134
|
+
Sizing those two the same is a mistake worth naming, because this palette made it. In light `surface` **is** white, so one measurement is both constraints at once and Lc 45 looks right for the pair. In dark the page is near-black and the same number becomes a demand that a filled shape reach text contrast against it — which nothing in the palette meets, the shipped fill included. Since a floor can only lighten, the surplus flattened the dark half of the tone axis onto a single value: every brand darker than the floor came out the same colour. The page floor is now sized for a shape and the label is guaranteed separately, by a cap on the seed's tone.
|
|
135
|
+
|
|
136
|
+
They are APCA rather than WCAG on purpose. A single WCAG ratio means two different things depending on the scheme: measured across twelve hues, a fill sitting exactly at 3:1 comes out at Lc 56 in light but only Lc 23 in dark. That is why light brands kept getting crushed while dark ones sailed through the same rule. **A consequence to state plainly: the emitted fill can sit below WCAG 3:1.** `#0EA5E9` renders at 2.77:1 against a white page and is correct there — the Lc is the guarantee, not the ratio.
|
|
137
|
+
|
|
138
|
+
High contrast does **not** escalate the page floor. It is a request for separation over brand, but not for separation from the page: the same fill carries the label, and driving it off the page drives the label off it. The shipped ladder makes the same trade and lands the other side of it, ending up with _less_ page separation in high contrast than in normal, because it darkens the fill toward its label. What does escalate is the label cap, which searches the high-contrast variants too.
|
|
139
|
+
|
|
140
|
+
**`pastel` caps chroma.** The flat, hue-independent ceiling is what makes pastel even across hues, and it sits below where a saturated color would land, so under it a color seed can never resolve to itself: `#EF4444` renders `#c47069`. Under pastel the color contributes its hue and its tone; turn pastel off to get its chroma too.
|
|
141
|
+
|
|
142
|
+
All of it applies per zone. A status color answers to the same two constraints on its own `#<theme>-accent-surface`, including the label cap — every `type="primary"` item on a status theme paints `#white` on that fill too, so a pale `danger` color is pulled down rather than shipped as a white label on white.
|
|
143
|
+
|
|
144
|
+
Read the result back from the tokens themselves — `#accent-surface` is the fill, `#accent-text-soft` the rest link color — or watch the requested/resolved chips in the [Theme builder](#theme-builder).
|
|
220
145
|
|
|
221
146
|
### One saturation scale per theme
|
|
222
147
|
|
|
223
|
-
Saturation is _not_ split per token, deliberately: a zone's `saturation` is its theme's
|
|
224
|
-
**seed**, and every color's own `saturation` is a 0–1 factor of it. `surface` sits at
|
|
225
|
-
`0.12`, `border` at `0.175`, the text ramp at `0.2`, the accent family at ~`1.0`.
|
|
148
|
+
Saturation is _not_ split per token, deliberately: a zone's `saturation` is its theme's **seed**, and every color's own `saturation` is a 0–1 factor of it. `surface` sits at `0.12`, `border` at `0.175`, the text ramp at `0.2`, the accent family at ~`1.0`.
|
|
226
149
|
|
|
227
|
-
So a theme has one saturation _scale_, and everything on it keeps its proportions:
|
|
228
|
-
turning the seed down mutes the brand fills and the neutral tint together, in the ratios
|
|
229
|
-
the palette was designed around. That is the point — the relationship between a subtle
|
|
230
|
-
surface tint and a saturated accent is part of the design, not something to tune per
|
|
231
|
-
token. It is also why a status **color** takes over its theme's seed rather than reaching
|
|
232
|
-
only its fill: chroma arriving absolutely through `from` while the seed stayed put is
|
|
233
|
-
exactly how those ratios come apart.
|
|
150
|
+
So a theme has one saturation _scale_, and everything on it keeps its proportions: turning the seed down mutes the brand fills and the neutral tint together, in the ratios the palette was designed around. That is the point — the relationship between a subtle surface tint and a saturated accent is part of the design, not something to tune per token. It is also why a status **color** takes over its theme's seed rather than reaching only its fill: chroma arriving absolutely through `from` while the seed stayed put is exactly how those ratios come apart.
|
|
234
151
|
|
|
235
|
-
The one seam is the **base zone**, and it is the same seam its own hue opens: the chrome
|
|
236
|
-
is the one family whose job is _not_ to look like the brand. `base.saturation` gives it
|
|
237
|
-
its own seed, on the same 0–100 scale, so a vivid accent over near-grey chrome — or a
|
|
238
|
-
muted accent over visibly warm chrome — is one number rather than a choice between them:
|
|
152
|
+
The one seam is the **base zone**, and it is the same seam its own hue opens: the chrome is the one family whose job is _not_ to look like the brand. `base.saturation` gives it its own seed, on the same 0–100 scale, so a vivid accent over near-grey chrome — or a muted accent over visibly warm chrome — is one number rather than a choice between them:
|
|
239
153
|
|
|
240
154
|
```ts
|
|
241
155
|
setPaletteConfig({ accent: { saturation: 90 }, base: { saturation: 3 } });
|
|
242
156
|
```
|
|
243
157
|
|
|
244
|
-
Unset, it takes `0.12` — `surface`'s own factor — of whatever the accent zone carries:
|
|
245
|
-
its seed saturation, or an accent color's own chroma when one is set. So leaving it alone
|
|
246
|
-
reproduces the shipped palette exactly, a muted accent still mutes the chrome along with
|
|
247
|
-
everything else, and a near-grey brand hex leaves near-grey chrome rather than 12% of a
|
|
248
|
-
saturation nobody asked for. A base color overrides all of that with its own, clipped to
|
|
249
|
-
50.
|
|
158
|
+
Unset, it takes `0.12` — `surface`'s own factor — of whatever the accent zone carries: its seed saturation, or an accent color's own chroma when one is set. So leaving it alone reproduces the shipped palette exactly, a muted accent still mutes the chrome along with everything else, and a near-grey brand hex leaves near-grey chrome rather than 12% of a saturation nobody asked for. A base color overrides all of that with its own, clipped to 50.
|
|
250
159
|
|
|
251
|
-
**The shipped value is `12`** — a faint tint is what a neutral surface _is_ — so the
|
|
252
|
-
interesting range is the low end. The base colors keep their proportions to one another
|
|
253
|
-
until the highest of them (`0.475`, `surface-inverse`) hits the top of the scale, around
|
|
254
|
-
`25`; past that they converge.
|
|
160
|
+
**The shipped value is `12`** — a faint tint is what a neutral surface _is_ — so the interesting range is the low end. The base colors keep their proportions to one another until the highest of them (`0.475`, `surface-inverse`) hits the top of the scale, around `25`; past that they converge.
|
|
255
161
|
|
|
256
|
-
Note the asymmetry with the accent's saturation: writing the base's does **not** turn
|
|
257
|
-
`pastel` off. How much hue the chrome carries says nothing about which chroma space the
|
|
258
|
-
palette is in.
|
|
162
|
+
Note the asymmetry with the accent's saturation: writing the base's does **not** turn `pastel` off. How much hue the chrome carries says nothing about which chroma space the palette is in.
|
|
259
163
|
|
|
260
164
|
### Tinted surfaces
|
|
261
165
|
|
|
262
|
-
A neutral `surface` sits at the extreme of the tone scale — pure white in light,
|
|
263
|
-
the darkest step the dark tone window allows in dark. Chroma needs distance from
|
|
264
|
-
the extreme to exist at all, so on a light page `surface` is white whatever the base
|
|
265
|
-
saturation asks for. The base seed reaches `surface-2`…`surface-4`, `border`,
|
|
266
|
-
`placeholder` and the text ramp, and stops at the page itself.
|
|
166
|
+
A neutral `surface` sits at the extreme of the tone scale — pure white in light, the darkest step the dark tone window allows in dark. Chroma needs distance from the extreme to exist at all, so on a light page `surface` is white whatever the base saturation asks for. The base seed reaches `surface-2`…`surface-4`, `border`, `placeholder` and the text ramp, and stops at the page itself.
|
|
267
167
|
|
|
268
168
|
`surfaceMode: 'tinted'` moves the whole ramp two tones inward:
|
|
269
169
|
|
|
@@ -271,59 +171,26 @@ saturation asks for. The base seed reaches `surface-2`…`surface-4`, `border`,
|
|
|
271
171
|
setPaletteConfig({ surfaceMode: 'tinted', base: { saturation: 25 } });
|
|
272
172
|
```
|
|
273
173
|
|
|
274
|
-
Two tones is not a lightness change you would name — it is _room_. Everything below
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
tint's, from `getColorTheme()` — is authored as an offset from the page's rather
|
|
282
|
-
than as an absolute tone, and that offset is exactly the two tones `tinted` shifts
|
|
283
|
-
by. Anchored absolutely they would land on the page's own new tone and a `note`
|
|
284
|
-
banner would stop reading as a banner at all; anchored to the page they keep the
|
|
285
|
-
separation the offset was chosen for, in both schemes. They also pick up a little
|
|
286
|
-
more chroma there, being further from the extreme — so `tinted` makes a status
|
|
287
|
-
surface easier to see, not harder.
|
|
288
|
-
|
|
289
|
-
The tint stays subtle by construction. Near white the sRGB gamut has very little
|
|
290
|
-
chroma to give, so `tinted` buys a surface that reads as warm or cool rather than
|
|
291
|
-
one that reads as colored — which is the whole ask. For a genuinely colored panel,
|
|
292
|
-
reach for a status theme's `surface` instead.
|
|
293
|
-
|
|
294
|
-
All of which describes the `pastel: false` path. Under `pastel` there is still one seed
|
|
295
|
-
and it is pinned to `100`, because a flat chroma ceiling is the whole mechanism and a
|
|
296
|
-
second scale on top of it would only undo the evenness. So there are two paths:
|
|
174
|
+
Two tones is not a lightness change you would name — it is _room_. Everything below `surface` is positioned relative to it, so the ladder, the borders and the text ramp all follow, and the text's `['AA','AAA']` floors re-solve against the new background rather than drifting. The `code-*` family follows too: its mirrored `surface` exists to be the page, so it tracks both the tone and the base seed.
|
|
175
|
+
|
|
176
|
+
**The tinted surfaces move with it.** A status theme's `surface` — and a runtime tint's, from `getColorTheme()` — is authored as an offset from the page's rather than as an absolute tone, and that offset is exactly the two tones `tinted` shifts by. Anchored absolutely they would land on the page's own new tone and a `note` banner would stop reading as a banner at all; anchored to the page they keep the separation the offset was chosen for, in both schemes. They also pick up a little more chroma there, being further from the extreme — so `tinted` makes a status surface easier to see, not harder.
|
|
177
|
+
|
|
178
|
+
The tint stays subtle by construction. Near white the sRGB gamut has very little chroma to give, so `tinted` buys a surface that reads as warm or cool rather than one that reads as colored — which is the whole ask. For a genuinely colored panel, reach for a status theme's `surface` instead.
|
|
179
|
+
|
|
180
|
+
All of which describes the `pastel: false` path. Under `pastel` there is still one seed and it is pinned to `100`, because a flat chroma ceiling is the whole mechanism and a second scale on top of it would only undo the evenness. So there are two paths:
|
|
297
181
|
|
|
298
182
|
```ts
|
|
299
183
|
setPaletteConfig({ pastel: true }); // even across hues; saturation is 100, full stop
|
|
300
184
|
setPaletteConfig({ accent: { saturation: 65 } }); // your scale, per-hue ceiling
|
|
301
185
|
```
|
|
302
186
|
|
|
303
|
-
Note the second line does not mention `pastel`. **Setting the accent's `saturation` turns
|
|
304
|
-
pastel off**, because tuning a saturation is the non-pastel path by definition — so you
|
|
305
|
-
pick a path by asking for what you want from it, not by setting a flag first. A *color*
|
|
306
|
-
does not answer that question and does not turn pastel off: `accent: '#FFD400'` on its
|
|
307
|
-
own still resolves under the flat ceiling, contributing its hue and tone but not its
|
|
308
|
-
chroma.
|
|
187
|
+
Note the second line does not mention `pastel`. **Setting the accent's `saturation` turns pastel off**, because tuning a saturation is the non-pastel path by definition — so you pick a path by asking for what you want from it, not by setting a flag first. A _color_ does not answer that question and does not turn pastel off: `accent: '#FFD400'` on its own still resolves under the flat ceiling, contributing its hue and tone but not its chroma.
|
|
309
188
|
|
|
310
|
-
State `pastel` only to override that. It is the coarser of the two choices — a color
|
|
311
|
-
space rather than a value on one — so it wins wherever both are set, and a saturation it
|
|
312
|
-
shadows is ignored with a dev-mode warning. The number is **kept** rather than dropped,
|
|
313
|
-
though: it stays in the sparse config, so turning pastel back off restores it.
|
|
189
|
+
State `pastel` only to override that. It is the coarser of the two choices — a color space rather than a value on one — so it wins wherever both are set, and a saturation it shadows is ignored with a dev-mode warning. The number is **kept** rather than dropped, though: it stays in the sparse config, so turning pastel back off restores it.
|
|
314
190
|
|
|
315
191
|
### The `code-*` family is the exception
|
|
316
192
|
|
|
317
|
-
Syntax colors are their own theme with their own seed, so neither the brand hue nor
|
|
318
|
-
the palette saturation reaches them. Hues are absolute literals — a brand re-seeded
|
|
319
|
-
toward green would otherwise collide `code-string` with `code-number` (156°) — and
|
|
320
|
-
the saturation is fixed at `80` rather than inheriting, so muting the app cannot
|
|
321
|
-
wash out a code block. That `80` is its own constant (`DEFAULT_CODE_SATURATION`),
|
|
322
|
-
deliberately not the palette default it once shared a value with: the app seed moved
|
|
323
|
-
to `100` with the pastel palette and the syntax colors stayed put, which is the whole
|
|
324
|
-
point of them not inheriting. `pastel` skips them for the same reason: it lowers
|
|
325
|
-
the chroma ceiling far enough to take `code-keyword` from ~0.19 to ~0.07,
|
|
326
|
-
collapsing the spread that keeps the syntax hues apart.
|
|
193
|
+
Syntax colors are their own theme with their own seed, so neither the brand hue nor the palette saturation reaches them. Hues are absolute literals — a brand re-seeded toward green would otherwise collide `code-string` with `code-number` (156°) — and the saturation is fixed at `80` rather than inheriting, so muting the app cannot wash out a code block. That `80` is its own constant (`DEFAULT_CODE_SATURATION`), deliberately not the palette default it once shared a value with: the app seed moved to `100` with the pastel palette and the syntax colors stayed put, which is the whole point of them not inheriting. `pastel` skips them for the same reason: it lowers the chroma ceiling far enough to take `code-keyword` from ~0.19 to ~0.07, collapsing the spread that keeps the syntax hues apart.
|
|
327
194
|
|
|
328
195
|
So `themes.code.saturation` is the only thing that moves them. Tune it on its own:
|
|
329
196
|
|
|
@@ -331,21 +198,13 @@ So `themes.code.saturation` is the only thing that moves them. Tune it on its ow
|
|
|
331
198
|
setPaletteConfig({ themes: { code: { saturation: 60 } } });
|
|
332
199
|
```
|
|
333
200
|
|
|
334
|
-
They are still _adaptive_: each one is anchored to the real `surface` with an
|
|
335
|
-
`['AA','AAA']` floor, so they re-solve for light, dark and high contrast. Only hue
|
|
336
|
-
and saturation are pinned.
|
|
201
|
+
They are still _adaptive_: each one is anchored to the real `surface` with an `['AA','AAA']` floor, so they re-solve for light, dark and high contrast. Only hue and saturation are pinned.
|
|
337
202
|
|
|
338
|
-
That separate seed is also a hard requirement, not a preference: a Glaze colour can
|
|
339
|
-
never exceed its own theme seed, and four of these sit at factor `1.0`. Inside a
|
|
340
|
-
default theme seeded below `80` they simply could not hold their chroma — which is
|
|
341
|
-
also why the pinned seed is a floor to respect rather than a number to tidy up.
|
|
203
|
+
That separate seed is also a hard requirement, not a preference: a Glaze colour can never exceed its own theme seed, and four of these sit at factor `1.0`. Inside a default theme seeded below `80` they simply could not hold their chroma — which is also why the pinned seed is a floor to respect rather than a number to tidy up.
|
|
342
204
|
|
|
343
205
|
### Inherited vs pinned
|
|
344
206
|
|
|
345
|
-
Every zone's seed starts out **inheriting**: the base zone follows the accent until
|
|
346
|
-
something seeds it, and a status theme's saturation tracks the accent's. Moving the accent
|
|
347
|
-
hue therefore appears to move the base hue too — they are not linked, the base zone simply
|
|
348
|
-
has no value of its own yet.
|
|
207
|
+
Every zone's seed starts out **inheriting**: the base zone follows the accent until something seeds it, and a status theme's saturation tracks the accent's. Moving the accent hue therefore appears to move the base hue too — they are not linked, the base zone simply has no value of its own yet.
|
|
349
208
|
|
|
350
209
|
Writing a seed pins it; leaving it out of the config unpins it, so it inherits again:
|
|
351
210
|
|
|
@@ -358,9 +217,7 @@ setPaletteConfig({ accent: { hue: 235 } }); // base dropped — follows again
|
|
|
358
217
|
setPaletteConfig(({ base, ...config }) => config);
|
|
359
218
|
```
|
|
360
219
|
|
|
361
|
-
A zone is therefore **three-state**, and one field answers all three: absent and it
|
|
362
|
-
inherits, an object and it is pinned to numbers, a string and it is derived from a color.
|
|
363
|
-
A settings UI reads the sparse config to know which of its own controls is in charge:
|
|
220
|
+
A zone is therefore **three-state**, and one field answers all three: absent and it inherits, an object and it is pinned to numbers, a string and it is derived from a color. A settings UI reads the sparse config to know which of its own controls is in charge:
|
|
364
221
|
|
|
365
222
|
```ts
|
|
366
223
|
const input = getPaletteConfigInput();
|
|
@@ -368,233 +225,113 @@ const accentMode = typeof input.accent === 'string' ? 'color' : 'numbers';
|
|
|
368
225
|
const baseIsOwn = input.base !== undefined;
|
|
369
226
|
```
|
|
370
227
|
|
|
371
|
-
`base: {}` and no `base` at all resolve to the same colors, but they are not the same
|
|
372
|
-
config — one has a seed of its own that pins nothing, the other has no seed. The two read
|
|
373
|
-
back differently and both count as changes, because that distinction is exactly what a
|
|
374
|
-
**Follow accent / Own** control is.
|
|
228
|
+
`base: {}` and no `base` at all resolve to the same colors, but they are not the same config — one has a seed of its own that pins nothing, the other has no seed. The two read back differently and both count as changes, because that distinction is exactly what a **Follow accent / Own** control is.
|
|
375
229
|
|
|
376
|
-
Swapping one form for the other counts as a change even when the numbers agree — an
|
|
377
|
-
`accent: { hue: 45 }` replaced by a color that derives hue 45 resolves identically, but
|
|
378
|
-
the UI still has to re-render to move its mode control. So does replacing one unparseable
|
|
379
|
-
string with another, which is why the colors are compared by value rather than by
|
|
380
|
-
presence.
|
|
230
|
+
Swapping one form for the other counts as a change even when the numbers agree — an `accent: { hue: 45 }` replaced by a color that derives hue 45 resolves identically, but the UI still has to re-render to move its mode control. So does replacing one unparseable string with another, which is why the colors are compared by value rather than by presence.
|
|
381
231
|
|
|
382
|
-
An explicit `{ hue: undefined }` inside a seed is equivalent to omitting the field;
|
|
383
|
-
neither is a value.
|
|
232
|
+
An explicit `{ hue: undefined }` inside a seed is equivalent to omitting the field; neither is a value.
|
|
384
233
|
|
|
385
|
-
`getPaletteConfig()` resolves everything, which loses that distinction — it cannot tell
|
|
386
|
-
you whether `100` was chosen or inherited, and it always reports flat numbers whichever
|
|
387
|
-
way a zone was seeded. `getPaletteConfigInput()` returns the sparse config as set, which
|
|
388
|
-
is what a settings UI needs to render an inherited value as inherited and offer a way
|
|
389
|
-
back:
|
|
234
|
+
`getPaletteConfig()` resolves everything, which loses that distinction — it cannot tell you whether `100` was chosen or inherited, and it always reports flat numbers whichever way a zone was seeded. `getPaletteConfigInput()` returns the sparse config as set, which is what a settings UI needs to render an inherited value as inherited and offer a way back:
|
|
390
235
|
|
|
391
236
|
```ts
|
|
392
237
|
const seed = getPaletteConfigInput().base;
|
|
393
238
|
const pinnedHue = typeof seed === 'object' ? seed.hue : undefined;
|
|
394
239
|
```
|
|
395
240
|
|
|
396
|
-
Pinning a field to the value it already inherited resolves to the same colors but still
|
|
397
|
-
counts as a change, so a UI reading the sparse config re-renders. Re-applying an _already
|
|
398
|
-
pinned_ value is a true no-op and costs nothing.
|
|
241
|
+
Pinning a field to the value it already inherited resolves to the same colors but still counts as a change, so a UI reading the sparse config re-renders. Re-applying an _already pinned_ value is a true no-op and costs nothing.
|
|
399
242
|
|
|
400
243
|
## Palette playground
|
|
401
244
|
|
|
402
|
-
Drag the brand hue and watch the accent ramp, the neutral surfaces, the buttons,
|
|
403
|
-
the borders and the shadows move together. Nothing re-renders: every color in the
|
|
404
|
-
kit compiles to a CSS custom property, so re-seeding replaces a single rule on
|
|
405
|
-
`body` and the browser repaints.
|
|
245
|
+
Drag the brand hue and watch the accent ramp, the neutral surfaces, the buttons, the borders and the shadows move together. Nothing re-renders: every color in the kit compiles to a CSS custom property, so re-seeding replaces a single rule on `body` and the browser repaints.
|
|
406
246
|
|
|
407
247
|
Two things worth noticing while you tune:
|
|
408
248
|
|
|
409
|
-
- The **neutral** surfaces carry saturation factors of 0.10–0.175, so they read
|
|
410
|
-
|
|
411
|
-
legible — the solid accents hide it.
|
|
412
|
-
- The **syntax** colors do not move at all — they are their own theme with their
|
|
413
|
-
own seed, so neither the accent hue nor the saturation reaches them.
|
|
249
|
+
- The **neutral** surfaces carry saturation factors of 0.10–0.175, so they read as a faint tint of the brand hue. That is where the saturation seed is legible — the solid accents hide it.
|
|
250
|
+
- The **syntax** colors do not move at all — they are their own theme with their own seed, so neither the accent hue nor the saturation reaches them.
|
|
414
251
|
|
|
415
252
|
## Status themes
|
|
416
253
|
|
|
417
|
-
Each status theme is a Glaze `extend()` of the default theme with its own seed, so tuning
|
|
418
|
-
one moves only its own `#<theme>-*` family.
|
|
254
|
+
Each status theme is a Glaze `extend()` of the default theme with its own seed, so tuning one moves only its own `#<theme>-*` family.
|
|
419
255
|
|
|
420
|
-
That seed is a `PaletteSeed` like any other, so `danger` can be the red your product
|
|
421
|
-
already ships rather than a hue you reverse-engineered from it:
|
|
256
|
+
That seed is a `PaletteSeed` like any other, so `danger` can be the red your product already ships rather than a hue you reverse-engineered from it:
|
|
422
257
|
|
|
423
258
|
```ts
|
|
424
259
|
setPaletteConfig({ themes: { danger: '#b91c1c', success: { hue: 150 } } });
|
|
425
260
|
```
|
|
426
261
|
|
|
427
|
-
A status color behaves like the brand's in the ways that matter — the light,
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
color
|
|
434
|
-
raising it would re-chromatise every one of them. Nothing inherits from a status theme,
|
|
435
|
-
so there is nothing to protect — and moving the seed is what holds the rest of the theme
|
|
436
|
-
in proportion to the fill. The tinted banner surface, the border and the text ramp are
|
|
437
|
-
authored as factors of the seed (`0.2`, `0.3`, `0.25`), so with the seed left at `100`
|
|
438
|
-
beside a muted fill the banner would read as fully tinted under a washed-out button.
|
|
439
|
-
Moving it keeps the shipped `1.0 : 0.2 : 0.3 : 0.25` ratio exactly.
|
|
440
|
-
|
|
441
|
-
Two consequences worth stating. A vivid status color under a muted palette gives one
|
|
442
|
-
vivid theme beside muted siblings — that is the point of naming a color. And under
|
|
443
|
-
`pastel` the flat ceiling can hold the fill below the color's own chroma while the banner
|
|
444
|
-
still sits at `0.2` of it, so the ratio drifts slightly; turn pastel off for an exact
|
|
445
|
-
color, exactly as with the brand.
|
|
446
|
-
|
|
447
|
-
A muted seed *beside* an accent color is not expressible, because the zone is seeded one
|
|
448
|
-
way or the other: a color there leaves the inherited saturation at its default. Mute the
|
|
449
|
-
status themes individually if you want that.
|
|
262
|
+
A status color behaves like the brand's in the ways that matter — the light, normal-contrast fill reproduces it, dark and high contrast adapt, and the softened APCA floors apply instead of the white-anchored ladder's WCAG ones, including the cap that keeps the `#white` label on a `type="primary"` button readable.
|
|
263
|
+
|
|
264
|
+
**One thing is deliberately different: its chroma becomes the theme's seed.** An accent color's does not, because all four status themes inherit the accent's saturation and raising it would re-chromatise every one of them. Nothing inherits from a status theme, so there is nothing to protect — and moving the seed is what holds the rest of the theme in proportion to the fill. The tinted banner surface, the border and the text ramp are authored as factors of the seed (`0.2`, `0.3`, `0.25`), so with the seed left at `100` beside a muted fill the banner would read as fully tinted under a washed-out button. Moving it keeps the shipped `1.0 : 0.2 : 0.3 : 0.25` ratio exactly.
|
|
265
|
+
|
|
266
|
+
Two consequences worth stating. A vivid status color under a muted palette gives one vivid theme beside muted siblings — that is the point of naming a color. And under `pastel` the flat ceiling can hold the fill below the color's own chroma while the banner still sits at `0.2` of it, so the ratio drifts slightly; turn pastel off for an exact color, exactly as with the brand.
|
|
267
|
+
|
|
268
|
+
A muted seed _beside_ an accent color is not expressible, because the zone is seeded one way or the other: a color there leaves the inherited saturation at its default. Mute the status themes individually if you want that.
|
|
450
269
|
|
|
451
270
|
## Contrast level
|
|
452
271
|
|
|
453
|
-
By default contrast is a two-tier switch: normal colors plus a separate
|
|
454
|
-
high-contrast set, selected by `<html data-contrast="high">` or a
|
|
455
|
-
`prefers-contrast: more` preference.
|
|
272
|
+
By default contrast is a two-tier switch: normal colors plus a separate high-contrast set, selected by `<html data-contrast="high">` or a `prefers-contrast: more` preference.
|
|
456
273
|
|
|
457
|
-
A manual `contrastLevel` adds a 0–100 slider that positions the **normal** colors,
|
|
458
|
-
for a product that wants to offer its own contrast control. Level `0` is the
|
|
459
|
-
shipped palette and `100` is the high-contrast one, bit for bit, so the slider
|
|
460
|
-
interpolates between exactly what the two tiers already ship.
|
|
274
|
+
A manual `contrastLevel` adds a 0–100 slider that positions the **normal** colors, for a product that wants to offer its own contrast control. Level `0` is the shipped palette and `100` is the high-contrast one, bit for bit, so the slider interpolates between exactly what the two tiers already ship.
|
|
461
275
|
|
|
462
|
-
The two **compose**; the slider does not replace the switch. The high-contrast
|
|
463
|
-
tier stays the true high-contrast resolution at every level — identical to what
|
|
464
|
-
`'auto'` emits — so `data-contrast="high"` and `prefers-contrast: more` keep
|
|
465
|
-
working and escalate on top of wherever the slider has put the baseline.
|
|
276
|
+
The two **compose**; the slider does not replace the switch. The high-contrast tier stays the true high-contrast resolution at every level — identical to what `'auto'` emits — so `data-contrast="high"` and `prefers-contrast: more` keep working and escalate on top of wherever the slider has put the baseline.
|
|
466
277
|
|
|
467
|
-
The one exception is level `100`: there the normal colors already _are_ the
|
|
468
|
-
high-contrast ones, so a second tier would only duplicate them and a single
|
|
469
|
-
light/dark set is emitted.
|
|
278
|
+
The one exception is level `100`: there the normal colors already _are_ the high-contrast ones, so a second tier would only duplicate them and a single light/dark set is emitted.
|
|
470
279
|
|
|
471
|
-
Because level `0` reproduces `'auto'` exactly, tier included, shipping the slider
|
|
472
|
-
and defaulting it off costs a consumer nothing.
|
|
280
|
+
Because level `0` reproduces `'auto'` exactly, tier included, shipping the slider and defaulting it off costs a consumer nothing.
|
|
473
281
|
|
|
474
282
|
## Theme builder
|
|
475
283
|
|
|
476
|
-
The `Theme Builder` story puts the whole config behind controls and renders the
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
what it is named after: **Global** for the ones that govern both zones — `pastel`,
|
|
492
|
-
the accent saturation, `surfaceMode` and `contrastLevel` — then **Accent** and **Base** for
|
|
493
|
-
the ones that do not. `surfaceMode` files under Global despite moving the *base*
|
|
494
|
-
surfaces, because the status themes' tinted surfaces follow it too, and so does the
|
|
495
|
-
mirrored surface the syntax palette solves against.
|
|
496
|
-
|
|
497
|
-
Those headings are also why the field labels are bare. `Seeded by` and `Hue` appear
|
|
498
|
-
in both zones, and the heading above them is what says which — repeating it in
|
|
499
|
-
every label was two words of noise on every line of a narrow column.
|
|
500
|
-
|
|
501
|
-
The **contrast level** needs no on/off switch: level `0` and `'auto'` are
|
|
502
|
-
output-identical, tier included, so the slider at rest _is_ the shipped palette.
|
|
503
|
-
|
|
504
|
-
Status themes are four chips on one line rather than eight sliders. Each chip is a
|
|
505
|
-
`theme="current"` `Button` colored by its own theme with a
|
|
506
|
-
[ColorSwatch](./components/fields/ColorSwatch.md) of its accent, so the group answers
|
|
507
|
-
the question you actually have — do these four still read as four different
|
|
508
|
-
things — at a glance; press one to open its hue and saturation. The hue is not
|
|
509
|
-
printed on the chip: it belongs to the slider that sets it, and carrying it there
|
|
510
|
-
cost the whole row, since `success — 157°` is wide enough that four of them have
|
|
511
|
-
to stack.
|
|
512
|
-
|
|
513
|
-
**Reset**, **Export** and **JSON** sit at the top of the column, not the bottom.
|
|
514
|
-
The one button you reach for when an experiment goes wrong should not be behind
|
|
515
|
-
the controls that caused it. `Export` opens the config as a `setPaletteConfig()`
|
|
516
|
-
call to copy; `JSON` downloads `palette.json` on the press, with no intermediate
|
|
517
|
-
state worth a second click. Both carry the config _as written_ rather than the
|
|
518
|
-
resolved one, so an inherited `base` stays inherited instead of being frozen to
|
|
519
|
-
whatever the accent happened to be.
|
|
520
|
-
|
|
521
|
-
Every caveat on the panel is an **InfoBadge** beside the control it qualifies rather
|
|
522
|
-
than a paragraph under it. A tuner is a dense column of controls, and prose between
|
|
523
|
-
them pushes the next knob off the screen to explain something you need once.
|
|
284
|
+
The `Theme Builder` story puts the whole config behind controls and renders the result into a single region, with one line drawn through the middle of the page: **the left column is the theme, the two switches over the preview are the viewing conditions.** Everything on the left writes to the palette config and would ship with the product; **Light / Dark** and **Normal / High contrast** write nothing at all — the same theme renders in all four combinations, and moving between them is how you check a theme rather than how you change one.
|
|
285
|
+
|
|
286
|
+
Those two switches start on whatever the surrounding page is already showing and keep following it until you press one, after which they are yours. There is no `Auto` option to press: `Auto` means "follow the OS" — a _preference_ — and the preview resolves to flat token values, which can only express one concrete variant. Following is the default behaviour rather than a third choice.
|
|
287
|
+
|
|
288
|
+
On the theme side, the panel is grouped by **what a knob reaches** rather than by what it is named after: **Global** for the ones that govern both zones — `pastel`, the accent saturation, `surfaceMode` and `contrastLevel` — then **Accent** and **Base** for the ones that do not. `surfaceMode` files under Global despite moving the _base_ surfaces, because the status themes' tinted surfaces follow it too, and so does the mirrored surface the syntax palette solves against.
|
|
289
|
+
|
|
290
|
+
Those headings are also why the field labels are bare. `Seeded by` and `Hue` appear in both zones, and the heading above them is what says which — repeating it in every label was two words of noise on every line of a narrow column.
|
|
291
|
+
|
|
292
|
+
The **contrast level** needs no on/off switch: level `0` and `'auto'` are output-identical, tier included, so the slider at rest _is_ the shipped palette.
|
|
293
|
+
|
|
294
|
+
Status themes are four chips on one line rather than eight sliders. Each chip is a `theme="current"` `Button` colored by its own theme with a [ColorSwatch](./components/fields/ColorSwatch.md) of its accent, so the group answers the question you actually have — do these four still read as four different things — at a glance; press one to open its hue and saturation. The hue is not printed on the chip: it belongs to the slider that sets it, and carrying it there cost the whole row, since `success — 157°` is wide enough that four of them have to stack.
|
|
295
|
+
|
|
296
|
+
**Reset**, **Export** and **JSON** sit at the top of the column, not the bottom. The one button you reach for when an experiment goes wrong should not be behind the controls that caused it. `Export` opens the config as a `setPaletteConfig()` call to copy; `JSON` downloads `palette.json` on the press, with no intermediate state worth a second click. Both carry the config _as written_ rather than the resolved one, so an inherited `base` stays inherited instead of being frozen to whatever the accent happened to be.
|
|
297
|
+
|
|
298
|
+
Every caveat on the panel is an **InfoBadge** beside the control it qualifies rather than a paragraph under it. A tuner is a dense column of controls, and prose between them pushes the next knob off the screen to explain something you need once.
|
|
524
299
|
|
|
525
300
|
### Three states, one tab bar
|
|
526
301
|
|
|
527
|
-
An unlabelled tab bar spans the top of the panel, and everything below reads as the state
|
|
528
|
-
it has selected:
|
|
302
|
+
An unlabelled tab bar spans the top of the panel, and everything below reads as the state it has selected:
|
|
529
303
|
|
|
530
|
-
|
|
|
531
|
-
|
|
|
532
|
-
| **Accent**
|
|
533
|
-
| **Base**
|
|
534
|
-
| **Status**
|
|
535
|
-
| **Syntax**
|
|
304
|
+
| | **Pastel** | **Advanced** | **Color** |
|
|
305
|
+
| --- | --- | --- | --- |
|
|
306
|
+
| **Accent** | Hue | Hue + Saturation | Color (hue+chroma+tone) |
|
|
307
|
+
| **Base** | Hue, or _Follow accent_ | Hue + Saturation, or _Follow accent_ | Color, or _Follow accent_ |
|
|
308
|
+
| **Status** | Hue | Hue + Saturation | Color |
|
|
309
|
+
| **Syntax** | Saturation | Saturation | Saturation |
|
|
536
310
|
|
|
537
|
-
`Advanced` and `Color` are the **same chroma space** — the per-hue ceiling — and differ
|
|
538
|
-
only in what you hand it. `Pastel` is the other space, and it takes hues because a flat
|
|
539
|
-
ceiling has nothing to do with a color.
|
|
311
|
+
`Advanced` and `Color` are the **same chroma space** — the per-hue ceiling — and differ only in what you hand it. `Pastel` is the other space, and it takes hues because a flat ceiling has nothing to do with a color.
|
|
540
312
|
|
|
541
|
-
It began as two controls, a `pastel` switch and a per-zone **Seeded by**, which described
|
|
542
|
-
a 2×2 grid with one impossible cell: pastel cannot honour a color, so one of the two spent
|
|
543
|
-
its life disabled. Three tabs spend three buttons on the three reachable states, and make
|
|
544
|
-
Pastel → Color one press instead of two. The bar carries no label, because naming it would
|
|
545
|
-
mean finding a word for "the palette" — and both candidates, _Mode_ and _Surfaces_, are
|
|
546
|
-
spoken for further down.
|
|
313
|
+
It began as two controls, a `pastel` switch and a per-zone **Seeded by**, which described a 2×2 grid with one impossible cell: pastel cannot honour a color, so one of the two spent its life disabled. Three tabs spend three buttons on the three reachable states, and make Pastel → Color one press instead of two. The bar carries no label, because naming it would mean finding a word for "the palette" — and both candidates, _Mode_ and _Surfaces_, are spoken for further down.
|
|
547
314
|
|
|
548
315
|
Two rules follow from it:
|
|
549
316
|
|
|
550
|
-
- **`pastel` gates saturation.** It is one flat, hue-independent ceiling, which is what
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
therefore pins each zone at what its color derived and drops the hex — including on the
|
|
565
|
-
way to `Pastel`, which cannot honour a color at all. Status themes pin their **hue** only:
|
|
566
|
-
a saturation pinned on the way out would survive into `Pastel`, where it is inert but
|
|
567
|
-
still in effect, and that is not a state to manufacture on a tab press.
|
|
568
|
-
|
|
569
|
-
The two halves of the way *in* differ, and both are deliberate. The brand zones open on a
|
|
570
|
-
fixed sample hex, so the flip changes which control is in charge rather than reading the
|
|
571
|
-
page back to itself. The four status themes convert instead — each to the fill it is
|
|
572
|
-
already emitting — because four sample hexes would repaint every banner on a tab press,
|
|
573
|
-
and a status theme's identity is a *meaning* a sample color has no business overwriting.
|
|
574
|
-
Coming from `Advanced`, the same chroma space, that conversion lands the banner back where
|
|
575
|
-
it was; coming from `Pastel` the palette repaints regardless, since the tabs turn `pastel`
|
|
576
|
-
off and a change of chroma space is the one thing no hand-over can carry across.
|
|
577
|
-
|
|
578
|
-
In color mode the panel shows where the color actually landed — **Accent Fill** and
|
|
579
|
-
**Accent Text**, the two tokens the seed's tone reaches. The requested color is not
|
|
580
|
-
repeated beside them: the field above holds it, with a swatch of its own.
|
|
581
|
-
|
|
582
|
-
The **preset** buttons show which one is active, and stop showing it the moment you
|
|
583
|
-
touch a control. The setter replaces rather than merges, so a preset is either the
|
|
584
|
-
whole config or it is not the config at all; anything else would claim a theme is
|
|
585
|
-
still `Ocean` after you had re-seeded half of it.
|
|
586
|
-
|
|
587
|
-
The preview deliberately shows all three surface levels with their own text ramps
|
|
588
|
-
(`#surface-text`, `#surface-2-text`, `#surface-3-text`), because a theme that looks
|
|
589
|
-
fine on the page surface can fall apart two panels deep.
|
|
317
|
+
- **`pastel` gates saturation.** It is one flat, hue-independent ceiling, which is what makes the palette even across hues and what leaves nothing for a saturation scale to do. There is no saturation control in that state except the syntax one, which `pastel` never reaches.
|
|
318
|
+
- **A derived control is not shown.** Whatever a seed already supplies, its slider goes away rather than sitting on screen disabled. A disabled slider under a color seed is a read-out dressed as a control, and it cost two rows to repeat what the color field above it already said.
|
|
319
|
+
|
|
320
|
+
The base zone keeps its own **Follow accent | Own**, which is orthogonal to the tabs: it is about whether the chrome has a seed at all, not about how a seed is spelled.
|
|
321
|
+
|
|
322
|
+
Every transition hands the incoming controls the values the outgoing ones were displaying, so switching changes who is in charge without repainting on the way. Leaving `Color` therefore pins each zone at what its color derived and drops the hex — including on the way to `Pastel`, which cannot honour a color at all. Status themes pin their **hue** only: a saturation pinned on the way out would survive into `Pastel`, where it is inert but still in effect, and that is not a state to manufacture on a tab press.
|
|
323
|
+
|
|
324
|
+
The two halves of the way _in_ differ, and both are deliberate. The brand zones open on a fixed sample hex, so the flip changes which control is in charge rather than reading the page back to itself. The four status themes convert instead — each to the fill it is already emitting — because four sample hexes would repaint every banner on a tab press, and a status theme's identity is a _meaning_ a sample color has no business overwriting. Coming from `Advanced`, the same chroma space, that conversion lands the banner back where it was; coming from `Pastel` the palette repaints regardless, since the tabs turn `pastel` off and a change of chroma space is the one thing no hand-over can carry across.
|
|
325
|
+
|
|
326
|
+
In color mode the panel shows where the color actually landed — **Accent Fill** and **Accent Text**, the two tokens the seed's tone reaches. The requested color is not repeated beside them: the field above holds it, with a swatch of its own.
|
|
327
|
+
|
|
328
|
+
The **preset** buttons show which one is active, and stop showing it the moment you touch a control. The setter replaces rather than merges, so a preset is either the whole config or it is not the config at all; anything else would claim a theme is still `Ocean` after you had re-seeded half of it.
|
|
329
|
+
|
|
330
|
+
The preview deliberately shows all three surface levels with their own text ramps (`#surface-text`, `#surface-2-text`, `#surface-3-text`), because a theme that looks fine on the page surface can fall apart two panels deep.
|
|
590
331
|
|
|
591
332
|
## Previewing a theme in a region
|
|
592
333
|
|
|
593
|
-
`setPaletteConfig()` re-themes the whole document, which is no use for a theme
|
|
594
|
-
picker — you want several themes visible at once, or a dark preview inside a light
|
|
595
|
-
page. `renderColorTokens()` does that: it resolves the palette for **one** config
|
|
596
|
-
and **one** scheme and returns flat literal values, ready to apply to a subtree
|
|
597
|
-
through a tasty `tokens` prop.
|
|
334
|
+
`setPaletteConfig()` re-themes the whole document, which is no use for a theme picker — you want several themes visible at once, or a dark preview inside a light page. `renderColorTokens()` does that: it resolves the palette for **one** config and **one** scheme and returns flat literal values, ready to apply to a subtree through a tasty `tokens` prop.
|
|
598
335
|
|
|
599
336
|
```tsx
|
|
600
337
|
import { renderColorTokens, tasty } from '@cube-dev/ui-kit';
|
|
@@ -609,54 +346,27 @@ const preview = useMemo(
|
|
|
609
346
|
<Region tokens={preview}>…everything in here renders in that theme…</Region>;
|
|
610
347
|
```
|
|
611
348
|
|
|
612
|
-
The reason this needs its own API: the document palette emits **state maps**
|
|
613
|
-
(`{ '': …, '@dark': …, '@hc': … }`), so a page can only ever show one scheme at a
|
|
614
|
-
time — that is what `@dark` means. Collapsing the palette to a chosen scheme
|
|
615
|
-
removes the conditionality, so several themes can coexist.
|
|
349
|
+
The reason this needs its own API: the document palette emits **state maps** (`{ '': …, '@dark': …, '@hc': … }`), so a page can only ever show one scheme at a time — that is what `@dark` means. Collapsing the palette to a chosen scheme removes the conditionality, so several themes can coexist.
|
|
616
350
|
|
|
617
|
-
| Option
|
|
618
|
-
|
|
|
351
|
+
| Option | Meaning |
|
|
352
|
+
| --- | --- |
|
|
619
353
|
| every `PaletteConfig` field | merged over the **current** config, so `{ scheme: 'dark' }` previews the active theme in dark |
|
|
620
|
-
| `scheme`
|
|
621
|
-
| `highContrast`
|
|
354
|
+
| `scheme` | `'light'` (default) or `'dark'` |
|
|
355
|
+
| `highContrast` | resolve that scheme's high-contrast variant. Default `false` |
|
|
622
356
|
|
|
623
|
-
Nothing is applied globally — the live palette and the stored config are
|
|
624
|
-
untouched, so previews are safe to render anywhere.
|
|
357
|
+
Nothing is applied globally — the live palette and the stored config are untouched, so previews are safe to render anywhere.
|
|
625
358
|
|
|
626
|
-
Note the one place the merge/replace split matters: this call **layers** over the
|
|
627
|
-
live config, unlike `setPaletteConfig()`, which replaces. A preview means "the
|
|
628
|
-
theme in use, but in dark", so the fields it does not mention have to come from
|
|
629
|
-
the current palette rather than from the defaults. `resolvePaletteConfig()` layers
|
|
630
|
-
the same way.
|
|
359
|
+
Note the one place the merge/replace split matters: this call **layers** over the live config, unlike `setPaletteConfig()`, which replaces. A preview means "the theme in use, but in dark", so the fields it does not mention have to come from the current palette rather than from the defaults. `resolvePaletteConfig()` layers the same way.
|
|
631
360
|
|
|
632
361
|
Notes:
|
|
633
362
|
|
|
634
|
-
- Real components work inside a region. Every color in the kit compiles to a CSS
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
theme instead.
|
|
642
|
-
- Typography, spacing, sizes and layout are **not** included — nothing in their
|
|
643
|
-
values references a color, so the region inherits them from `<Root>`.
|
|
644
|
-
- `contrastLevel` works per region, so the whole 0–100 ramp can be shown at once —
|
|
645
|
-
something a document cannot do, since it is only ever at one level. Level `0`
|
|
646
|
-
reproduces the normal tier and `100` the high-contrast tier exactly, in both
|
|
647
|
-
schemes. `highContrast: true` still returns the genuine high-contrast
|
|
648
|
-
resolution at any level below `100`, because the level moves the baseline and
|
|
649
|
-
the tier escalates from where `'auto'` would put it; at `100` the two coincide
|
|
650
|
-
and it returns the same colors as the normal variant.
|
|
651
|
-
Note that tokens carrying a contrast _floor_ (most text) can sit still over part
|
|
652
|
-
of the ramp — the floor is solved, not approximated, so the value only moves once
|
|
653
|
-
the interpolated target does. Tokens positioned by a plain tone pair, like
|
|
654
|
-
`#border`, step at every level.
|
|
655
|
-
- Resolving a palette costs a few milliseconds. The last config is memoized, but
|
|
656
|
-
`useMemo` on the caller side if you drive it from state.
|
|
657
|
-
|
|
658
|
-
`renderPaletteTokens()` is the same thing without the aliases and companion
|
|
659
|
-
tokens, if you want only the Glaze palette.
|
|
363
|
+
- Real components work inside a region. Every color in the kit compiles to a CSS custom property, so overriding those properties on one element re-colors its whole subtree with no scheme attribute and no second `<Root>`.
|
|
364
|
+
- The legacy aliases come along **by reference** (`'#dark': '#surface-text'`), and so do the shadow tokens and scrollbar colors, whose values embed a palette color. Tasty re-declares them on the region so each `var()` resolves against the region's own values; resolving them up front would freeze them to the outer theme instead.
|
|
365
|
+
- Typography, spacing, sizes and layout are **not** included — nothing in their values references a color, so the region inherits them from `<Root>`.
|
|
366
|
+
- `contrastLevel` works per region, so the whole 0–100 ramp can be shown at once — something a document cannot do, since it is only ever at one level. Level `0` reproduces the normal tier and `100` the high-contrast tier exactly, in both schemes. `highContrast: true` still returns the genuine high-contrast resolution at any level below `100`, because the level moves the baseline and the tier escalates from where `'auto'` would put it; at `100` the two coincide and it returns the same colors as the normal variant. Note that tokens carrying a contrast _floor_ (most text) can sit still over part of the ramp — the floor is solved, not approximated, so the value only moves once the interpolated target does. Tokens positioned by a plain tone pair, like `#border`, step at every level.
|
|
367
|
+
- Resolving a palette costs a few milliseconds. The last config is memoized, but `useMemo` on the caller side if you drive it from state.
|
|
368
|
+
|
|
369
|
+
`renderPaletteTokens()` is the same thing without the aliases and companion tokens, if you want only the Glaze palette.
|
|
660
370
|
|
|
661
371
|
## Reading and reacting to the config
|
|
662
372
|
|
|
@@ -683,14 +393,11 @@ subscribePaletteConfig(() => {
|
|
|
683
393
|
});
|
|
684
394
|
```
|
|
685
395
|
|
|
686
|
-
`getPaletteConfig()` always returns the fully resolved form, so
|
|
687
|
-
`getPaletteConfig().themes.danger.saturation` is a number even if nobody ever set
|
|
688
|
-
it. `DEFAULT_PALETTE_CONFIG` is the shipped baseline in the same shape.
|
|
396
|
+
`getPaletteConfig()` always returns the fully resolved form, so `getPaletteConfig().themes.danger.saturation` is a number even if nobody ever set it. `DEFAULT_PALETTE_CONFIG` is the shipped baseline in the same shape.
|
|
689
397
|
|
|
690
398
|
## `<Root palette>`
|
|
691
399
|
|
|
692
|
-
`<Root>` accepts the same config as a prop, applied during render so the first
|
|
693
|
-
paint is already correct:
|
|
400
|
+
`<Root>` accepts the same config as a prop, applied during render so the first paint is already correct:
|
|
694
401
|
|
|
695
402
|
```tsx
|
|
696
403
|
<Root palette={{ accent: userBrandColor }}>
|
|
@@ -698,57 +405,24 @@ paint is already correct:
|
|
|
698
405
|
</Root>
|
|
699
406
|
```
|
|
700
407
|
|
|
701
|
-
Because the setter replaces, the prop describes the **whole** palette: drop a
|
|
702
|
-
field from the object and that customization goes away on the next render, which
|
|
703
|
-
is what you want from a declarative prop.
|
|
408
|
+
Because the setter replaces, the prop describes the **whole** palette: drop a field from the object and that customization goes away on the next render, which is what you want from a declarative prop.
|
|
704
409
|
|
|
705
|
-
Removing the prop entirely is the one thing that does _not_ reset the palette —
|
|
706
|
-
`<Root>` with no `palette` leaves whatever is configured alone, so that the common
|
|
707
|
-
case cannot clobber a host's imperative `setPaletteConfig()` call. Pass
|
|
708
|
-
`palette={{}}` if you do want the default.
|
|
410
|
+
Removing the prop entirely is the one thing that does _not_ reset the palette — `<Root>` with no `palette` leaves whatever is configured alone, so that the common case cannot clobber a host's imperative `setPaletteConfig()` call. Pass `palette={{}}` if you do want the default.
|
|
709
411
|
|
|
710
|
-
This is a convenience wrapper over `setPaletteConfig()`, not a separate scope.
|
|
711
|
-
**The palette is process-global** — Glaze's own config is, and so is the single
|
|
712
|
-
`body` rule the tokens are injected into. One palette per process, not per tree
|
|
713
|
-
and not per request:
|
|
412
|
+
This is a convenience wrapper over `setPaletteConfig()`, not a separate scope. **The palette is process-global** — Glaze's own config is, and so is the single `body` rule the tokens are injected into. One palette per process, not per tree and not per request:
|
|
714
413
|
|
|
715
414
|
- Two `<Root>`s with different `palette` props will fight over the same tokens.
|
|
716
|
-
- Under SSR, apply the palette in code that runs on **both** server and client.
|
|
717
|
-
A client-only `setPaletteConfig` disposes and replaces the server-rendered
|
|
718
|
-
token block on the first render, which is visible as a flash. Per-request
|
|
719
|
-
palettes are not supported.
|
|
415
|
+
- Under SSR, apply the palette in code that runs on **both** server and client. A client-only `setPaletteConfig` disposes and replaces the server-rendered token block on the first render, which is visible as a flash. Per-request palettes are not supported.
|
|
720
416
|
|
|
721
417
|
## Caveats
|
|
722
418
|
|
|
723
|
-
**`pastel` is a redesign, not a filter — in either direction.** It changes every
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
the
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
direction you flip.
|
|
731
|
-
|
|
732
|
-
It also owns the accent's `saturation` outright — pinned to `100`, so a number passed
|
|
733
|
-
_explicitly alongside_ it is inert and warned about (a number passed on its own turns
|
|
734
|
-
pastel off instead). And it caps a color seed short of itself: the ceiling sits below
|
|
735
|
-
where a saturated color lands, so `#EF4444` resolves to `#c47069`. Both are visible in the
|
|
736
|
-
[Theme builder](#theme-builder), the first as a disabled slider and the second as the
|
|
737
|
-
requested/resolved chips.
|
|
738
|
-
|
|
739
|
-
**Re-seeding costs about 10 ms.** Rebuilding the eight themes and re-solving
|
|
740
|
-
~156 tokens across four scheme variants is not free, though it is inside a frame.
|
|
741
|
-
A manual `contrastLevel` costs the same — it runs the same four passes — except
|
|
742
|
-
at level `100`, which skips the two high-contrast ones because the normal pass
|
|
743
|
-
already produced those values.
|
|
744
|
-
Setting the config to a value it already holds is free — it does not even bump
|
|
745
|
-
the version. If you are driving it from a slider, let the input coalesce to
|
|
746
|
-
frames (a pointer-driven `onChange` already does) rather than writing on every
|
|
747
|
-
event.
|
|
748
|
-
|
|
749
|
-
**If you call Glaze directly, tell the kit.** `glaze.configure({ darkTone })` and
|
|
750
|
-
friends invalidate Glaze's own caches, but the kit's token maps are memoized
|
|
751
|
-
against the palette config version:
|
|
419
|
+
**`pastel` is a redesign, not a filter — in either direction.** It changes every resolved color outside the `code-*` family, and the shipped palette is now pastel (`pastel: true`, seed `100`), so it is `pastel: false` that is the departure. The two spaces want different seeds: pastel equalizes the chroma ceiling across hues, where the non-pastel one is per-hue and lets warm hues run further. Flipping the flag alone therefore re-tunes nothing — a seed picked in one space lands somewhere else in the other, and the warm statuses move most. Re-tune the seeds alongside it, in whichever direction you flip.
|
|
420
|
+
|
|
421
|
+
It also owns the accent's `saturation` outright — pinned to `100`, so a number passed _explicitly alongside_ it is inert and warned about (a number passed on its own turns pastel off instead). And it caps a color seed short of itself: the ceiling sits below where a saturated color lands, so `#EF4444` resolves to `#c47069`. Both are visible in the [Theme builder](#theme-builder), the first as a disabled slider and the second as the requested/resolved chips.
|
|
422
|
+
|
|
423
|
+
**Re-seeding costs about 10 ms.** Rebuilding the eight themes and re-solving ~156 tokens across four scheme variants is not free, though it is inside a frame. A manual `contrastLevel` costs the same — it runs the same four passes — except at level `100`, which skips the two high-contrast ones because the normal pass already produced those values. Setting the config to a value it already holds is free — it does not even bump the version. If you are driving it from a slider, let the input coalesce to frames (a pointer-driven `onChange` already does) rather than writing on every event.
|
|
424
|
+
|
|
425
|
+
**If you call Glaze directly, tell the kit.** `glaze.configure({ darkTone })` and friends invalidate Glaze's own caches, but the kit's token maps are memoized against the palette config version:
|
|
752
426
|
|
|
753
427
|
```ts
|
|
754
428
|
import { glaze, invalidatePaletteTokens } from '@cube-dev/ui-kit';
|
|
@@ -757,18 +431,11 @@ glaze.configure({ darkDesaturation: 0.2 });
|
|
|
757
431
|
invalidatePaletteTokens(); // only needed once the kit is already mounted
|
|
758
432
|
```
|
|
759
433
|
|
|
760
|
-
`contrastLevel` is the one field the kit writes to Glaze's global config, and it
|
|
761
|
-
only ever does so if you asked for a level. A host that sets its own
|
|
762
|
-
`glaze.configure({ contrastLevel })` and never passes `contrastLevel` here keeps
|
|
763
|
-
it.
|
|
434
|
+
`contrastLevel` is the one field the kit writes to Glaze's global config, and it only ever does so if you asked for a level. A host that sets its own `glaze.configure({ contrastLevel })` and never passes `contrastLevel` here keeps it.
|
|
764
435
|
|
|
765
|
-
**Some things are not tunable at all.** Tasty locks its configuration on the
|
|
766
|
-
first style injection, so the `@dark` / `@hc` state definitions and the
|
|
767
|
-
`colorSpace` (both set in `Root`) are fixed for the lifetime of the page. Only
|
|
768
|
-
token _values_ stay mutable — which is all re-seeding needs.
|
|
436
|
+
**Some things are not tunable at all.** Tasty locks its configuration on the first style injection, so the `@dark` / `@hc` state definitions (set in `Root`) are fixed for the lifetime of the page. Only token _values_ stay mutable — which is all re-seeding needs.
|
|
769
437
|
|
|
770
438
|
## See also
|
|
771
439
|
|
|
772
|
-
- [Colors](./Colors.md) — how to pair surfaces with
|
|
773
|
-
foregrounds, and what each token family is for.
|
|
440
|
+
- [Colors](./Colors.md) — how to pair surfaces with foregrounds, and what each token family is for.
|
|
774
441
|
- [Usage](./Usage.md) — the full token reference.
|