@eocrm/design-system 0.0.0-stage → 0.6.18
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/AI-PRIMER.md +341 -0
- package/LICENSE +202 -0
- package/README.md +266 -2
- package/docs/components/Accordion.md +114 -0
- package/docs/components/AgentAvatar.md +58 -0
- package/docs/components/Alert.md +81 -0
- package/docs/components/AppLayout.md +70 -0
- package/docs/components/Avatar.md +49 -0
- package/docs/components/AvatarGroup.md +47 -0
- package/docs/components/Badge.md +60 -0
- package/docs/components/Banner.md +89 -0
- package/docs/components/BrandIcon.md +32 -0
- package/docs/components/Breadcrumb.md +72 -0
- package/docs/components/Button.md +107 -0
- package/docs/components/ButtonGroup.md +78 -0
- package/docs/components/Calendar.md +158 -0
- package/docs/components/Card.md +165 -0
- package/docs/components/CatalogPicker.md +83 -0
- package/docs/components/Chart.md +114 -0
- package/docs/components/ChatBubble.md +55 -0
- package/docs/components/ChatLauncher.md +97 -0
- package/docs/components/Checkbox.md +55 -0
- package/docs/components/CircularProgress.md +53 -0
- package/docs/components/Cluster.md +96 -0
- package/docs/components/Code.md +35 -0
- package/docs/components/CodeBlock.md +67 -0
- package/docs/components/ColorPicker.md +115 -0
- package/docs/components/ConfirmationPopover.md +70 -0
- package/docs/components/Constrain.md +39 -0
- package/docs/components/CurrencySelect.md +57 -0
- package/docs/components/CursorPagination.md +43 -0
- package/docs/components/DashboardCanvas.md +79 -0
- package/docs/components/DashboardWidget.md +131 -0
- package/docs/components/DataTable.md +88 -0
- package/docs/components/DatePicker.md +68 -0
- package/docs/components/DateRangePicker.md +71 -0
- package/docs/components/DateStrip.md +56 -0
- package/docs/components/DefinitionList.md +82 -0
- package/docs/components/Divider.md +57 -0
- package/docs/components/Dot.md +26 -0
- package/docs/components/Drawer.md +94 -0
- package/docs/components/DropdownMenu.md +299 -0
- package/docs/components/EmojiPicker.md +84 -0
- package/docs/components/EmptyState.md +55 -0
- package/docs/components/EntityChip.md +102 -0
- package/docs/components/ErrorState.md +72 -0
- package/docs/components/Field.md +91 -0
- package/docs/components/FileUpload.md +109 -0
- package/docs/components/FilterChip.md +88 -0
- package/docs/components/FlowCanvas.md +108 -0
- package/docs/components/FormRow.md +31 -0
- package/docs/components/FormSection.md +37 -0
- package/docs/components/Grid.md +103 -0
- package/docs/components/Highlight.md +75 -0
- package/docs/components/HighlightedText.md +50 -0
- package/docs/components/IconPicker.md +134 -0
- package/docs/components/IconTile.md +30 -0
- package/docs/components/Image.md +84 -0
- package/docs/components/ImageCrop.md +163 -0
- package/docs/components/Indent.md +31 -0
- package/docs/components/InlineDatePicker.md +58 -0
- package/docs/components/InlineDateRangePicker.md +57 -0
- package/docs/components/Input.md +54 -0
- package/docs/components/Kanban.md +122 -0
- package/docs/components/Kbd.md +41 -0
- package/docs/components/Lightbox.md +105 -0
- package/docs/components/Link.md +65 -0
- package/docs/components/LinkCard.md +41 -0
- package/docs/components/LiquidEditor.md +84 -0
- package/docs/components/List.md +68 -0
- package/docs/components/LiveRegion.md +29 -0
- package/docs/components/LocaleProvider.md +25 -0
- package/docs/components/Logo.md +41 -0
- package/docs/components/Masonry.md +48 -0
- package/docs/components/MediaTile.md +95 -0
- package/docs/components/Modal.md +107 -0
- package/docs/components/MoneyInput.md +62 -0
- package/docs/components/OptionsPicker.md +123 -0
- package/docs/components/OtpInput.md +65 -0
- package/docs/components/Page.md +35 -0
- package/docs/components/PageHeader.md +133 -0
- package/docs/components/Pagination.md +44 -0
- package/docs/components/Palette.md +32 -0
- package/docs/components/PasswordInput.md +45 -0
- package/docs/components/PasswordStrengthMeter.md +27 -0
- package/docs/components/PersonDisplay.md +153 -0
- package/docs/components/PhoneInput.md +54 -0
- package/docs/components/PillMenu.md +91 -0
- package/docs/components/Popover.md +127 -0
- package/docs/components/Progress.md +56 -0
- package/docs/components/QrCode.md +34 -0
- package/docs/components/Radio.md +37 -0
- package/docs/components/RadioGroup.md +56 -0
- package/docs/components/Rail.md +191 -0
- package/docs/components/RelativeDateInput.md +114 -0
- package/docs/components/RichText.md +44 -0
- package/docs/components/RichTextEditor.md +112 -0
- package/docs/components/Screen.md +37 -0
- package/docs/components/ScrollArea.md +39 -0
- package/docs/components/Select.md +131 -0
- package/docs/components/SettingRow.md +98 -0
- package/docs/components/Skeleton.md +68 -0
- package/docs/components/Slider.md +92 -0
- package/docs/components/SlotGrid.md +55 -0
- package/docs/components/SocialButton.md +31 -0
- package/docs/components/Sortable.md +127 -0
- package/docs/components/SortableGroup.md +52 -0
- package/docs/components/Sparkline.md +51 -0
- package/docs/components/Split.md +76 -0
- package/docs/components/Stack.md +59 -0
- package/docs/components/StagePath.md +66 -0
- package/docs/components/StatGroup.md +61 -0
- package/docs/components/StatTile.md +58 -0
- package/docs/components/Sticky.md +69 -0
- package/docs/components/Switch.md +89 -0
- package/docs/components/Table.md +184 -0
- package/docs/components/TableOfContents.md +76 -0
- package/docs/components/Tabs.md +94 -0
- package/docs/components/Text.md +63 -0
- package/docs/components/Textarea.md +59 -0
- package/docs/components/Thread.md +52 -0
- package/docs/components/TimeField.md +70 -0
- package/docs/components/Timeline.md +57 -0
- package/docs/components/Title.md +54 -0
- package/docs/components/ToastViewport.md +61 -0
- package/docs/components/Tooltip.md +63 -0
- package/docs/components/TopBar.md +214 -0
- package/docs/components/Tour.md +85 -0
- package/docs/components/TreeView.md +113 -0
- package/docs/components/VisuallyHidden.md +43 -0
- package/docs/components/WidgetPreview.md +54 -0
- package/docs/components/useBelowBreakpoint.md +11 -0
- package/docs/components/useMonth.md +18 -0
- package/docs/setup.md +51 -0
- package/docs/theming.md +95 -0
- package/docs/tokens.md +123 -0
- package/docs/transient-state.md +56 -0
- package/package.json +86 -4
- package/src/_meta/manifest.ts +293 -0
- package/src/app/AppProvider.tsx +78 -0
- package/src/app/index.ts +3 -0
- package/src/app/themeTokens.ts +95 -0
- package/src/calendar/dateMath.ts +114 -0
- package/src/calendar/formatters.ts +75 -0
- package/src/calendar/index.ts +39 -0
- package/src/calendar/types.ts +36 -0
- package/src/calendar/useAgenda.ts +70 -0
- package/src/calendar/useDay.ts +51 -0
- package/src/calendar/useMonth.ts +82 -0
- package/src/calendar/useWeek.ts +62 -0
- package/src/calendar/weekInfo.ts +83 -0
- package/src/components/Accordion/Accordion.module.scss +304 -0
- package/src/components/Accordion/Accordion.tokens.scss +64 -0
- package/src/components/Accordion/Accordion.tsx +272 -0
- package/src/components/Accordion/AccordionContent.tsx +36 -0
- package/src/components/Accordion/AccordionItem.tsx +66 -0
- package/src/components/Accordion/AccordionTrigger.tsx +121 -0
- package/src/components/Accordion/context.ts +47 -0
- package/src/components/Accordion/index.ts +14 -0
- package/src/components/Alert/Alert.module.scss +92 -0
- package/src/components/Alert/Alert.tokens.scss +60 -0
- package/src/components/Alert/Alert.tsx +136 -0
- package/src/components/Alert/index.ts +2 -0
- package/src/components/AppLayout/AppLayout.module.scss +130 -0
- package/src/components/AppLayout/AppLayout.tokens.scss +27 -0
- package/src/components/AppLayout/AppLayout.tsx +211 -0
- package/src/components/AppLayout/index.ts +2 -0
- package/src/components/Avatar/AgentAvatar.module.scss +117 -0
- package/src/components/Avatar/AgentAvatar.tsx +122 -0
- package/src/components/Avatar/Avatar.module.scss +181 -0
- package/src/components/Avatar/Avatar.tokens.scss +107 -0
- package/src/components/Avatar/Avatar.tsx +210 -0
- package/src/components/Avatar/AvatarGroup.module.scss +128 -0
- package/src/components/Avatar/AvatarGroup.tsx +119 -0
- package/src/components/Avatar/AvatarGroupContext.tsx +20 -0
- package/src/components/Avatar/index.ts +6 -0
- package/src/components/Badge/Badge.module.scss +124 -0
- package/src/components/Badge/Badge.tokens.scss +74 -0
- package/src/components/Badge/Badge.tsx +164 -0
- package/src/components/Badge/index.ts +2 -0
- package/src/components/Banner/Banner.module.scss +73 -0
- package/src/components/Banner/Banner.tokens.scss +51 -0
- package/src/components/Banner/Banner.tsx +138 -0
- package/src/components/Banner/index.ts +2 -0
- package/src/components/BrandIcon/BrandIcon.module.scss +5 -0
- package/src/components/BrandIcon/BrandIcon.tsx +99 -0
- package/src/components/BrandIcon/index.ts +2 -0
- package/src/components/Breadcrumb/Breadcrumb.module.scss +32 -0
- package/src/components/Breadcrumb/Breadcrumb.tokens.scss +9 -0
- package/src/components/Breadcrumb/Breadcrumb.tsx +146 -0
- package/src/components/Breadcrumb/index.ts +2 -0
- package/src/components/Button/Button.module.scss +167 -0
- package/src/components/Button/Button.tokens.scss +90 -0
- package/src/components/Button/Button.tsx +205 -0
- package/src/components/Button/index.ts +2 -0
- package/src/components/ButtonGroup/ButtonGroup.module.scss +134 -0
- package/src/components/ButtonGroup/ButtonGroup.tokens.scss +42 -0
- package/src/components/ButtonGroup/ButtonGroup.tsx +278 -0
- package/src/components/ButtonGroup/ButtonGroupItem.tsx +74 -0
- package/src/components/ButtonGroup/context.ts +45 -0
- package/src/components/ButtonGroup/index.ts +2 -0
- package/src/components/Calendar/AgendaView.module.scss +231 -0
- package/src/components/Calendar/AgendaView.tsx +214 -0
- package/src/components/Calendar/AllDayBand.module.scss +18 -0
- package/src/components/Calendar/AllDayBand.tsx +75 -0
- package/src/components/Calendar/Calendar.module.scss +23 -0
- package/src/components/Calendar/Calendar.tokens.scss +262 -0
- package/src/components/Calendar/Calendar.tsx +370 -0
- package/src/components/Calendar/DayCell.module.scss +30 -0
- package/src/components/Calendar/DayCell.tsx +50 -0
- package/src/components/Calendar/DayView.module.scss +10 -0
- package/src/components/Calendar/DayView.tsx +163 -0
- package/src/components/Calendar/EventChip.module.scss +171 -0
- package/src/components/Calendar/EventChip.tsx +115 -0
- package/src/components/Calendar/HourGrid.module.scss +123 -0
- package/src/components/Calendar/HourGrid.tsx +381 -0
- package/src/components/Calendar/MonthView.module.scss +99 -0
- package/src/components/Calendar/MonthView.tsx +296 -0
- package/src/components/Calendar/TimedEvent.module.scss +205 -0
- package/src/components/Calendar/TimedEvent.tsx +247 -0
- package/src/components/Calendar/ViewSwitcher.module.scss +3 -0
- package/src/components/Calendar/ViewSwitcher.tsx +47 -0
- package/src/components/Calendar/WeekView.module.scss +10 -0
- package/src/components/Calendar/WeekView.tsx +137 -0
- package/src/components/Calendar/eventColor.ts +60 -0
- package/src/components/Calendar/index.ts +18 -0
- package/src/components/Calendar/types.ts +451 -0
- package/src/components/Calendar/useEventDrag.ts +783 -0
- package/src/components/Calendar/utils.ts +622 -0
- package/src/components/Card/Card.module.scss +264 -0
- package/src/components/Card/Card.tokens.scss +55 -0
- package/src/components/Card/Card.tsx +170 -0
- package/src/components/Card/CardBody.tsx +45 -0
- package/src/components/Card/CardHeader.tsx +113 -0
- package/src/components/Card/CardList.tsx +24 -0
- package/src/components/Card/CardListRow.tsx +24 -0
- package/src/components/Card/index.ts +7 -0
- package/src/components/CatalogPicker/CatalogPicker.module.scss +193 -0
- package/src/components/CatalogPicker/CatalogPicker.tokens.scss +26 -0
- package/src/components/CatalogPicker/CatalogPicker.tsx +339 -0
- package/src/components/CatalogPicker/index.ts +2 -0
- package/src/components/Chart/Chart.module.scss +287 -0
- package/src/components/Chart/Chart.tokens.scss +63 -0
- package/src/components/Chart/Chart.tsx +607 -0
- package/src/components/Chart/ChartLegend.tsx +99 -0
- package/src/components/Chart/ChartTable.tsx +62 -0
- package/src/components/Chart/ChartTooltip.tsx +91 -0
- package/src/components/Chart/chartModel.ts +689 -0
- package/src/components/Chart/index.ts +2 -0
- package/src/components/ChatBubble/ChatBubble.module.scss +93 -0
- package/src/components/ChatBubble/ChatBubble.tokens.scss +17 -0
- package/src/components/ChatBubble/ChatBubble.tsx +61 -0
- package/src/components/ChatBubble/ChatBubbleList.tsx +27 -0
- package/src/components/ChatBubble/index.ts +3 -0
- package/src/components/ChatLauncher/ChatLauncher.module.scss +68 -0
- package/src/components/ChatLauncher/ChatLauncher.tokens.scss +27 -0
- package/src/components/ChatLauncher/ChatLauncher.tsx +202 -0
- package/src/components/ChatLauncher/index.ts +2 -0
- package/src/components/ChatLauncher/isAtBottom.ts +12 -0
- package/src/components/Checkbox/Checkbox.module.scss +147 -0
- package/src/components/Checkbox/Checkbox.tokens.scss +44 -0
- package/src/components/Checkbox/Checkbox.tsx +188 -0
- package/src/components/Checkbox/index.ts +2 -0
- package/src/components/CircularProgress/CircularProgress.module.scss +133 -0
- package/src/components/CircularProgress/CircularProgress.tokens.scss +40 -0
- package/src/components/CircularProgress/CircularProgress.tsx +139 -0
- package/src/components/CircularProgress/index.ts +7 -0
- package/src/components/Cluster/Cluster.module.scss +145 -0
- package/src/components/Cluster/Cluster.tokens.scss +11 -0
- package/src/components/Cluster/Cluster.tsx +215 -0
- package/src/components/Cluster/index.ts +2 -0
- package/src/components/Code/Code.module.scss +28 -0
- package/src/components/Code/Code.tokens.scss +15 -0
- package/src/components/Code/Code.tsx +44 -0
- package/src/components/Code/index.ts +2 -0
- package/src/components/CodeBlock/CodeBlock.module.scss +146 -0
- package/src/components/CodeBlock/CodeBlock.tokens.scss +27 -0
- package/src/components/CodeBlock/CodeBlock.tsx +274 -0
- package/src/components/CodeBlock/highlight.ts +179 -0
- package/src/components/CodeBlock/index.ts +8 -0
- package/src/components/CodeBlock/sampleSync.ts +42 -0
- package/src/components/ColorPicker/ColorPicker.module.scss +286 -0
- package/src/components/ColorPicker/ColorPicker.tokens.scss +60 -0
- package/src/components/ColorPicker/ColorPicker.tsx +367 -0
- package/src/components/ColorPicker/ColorPickerPanel.tsx +265 -0
- package/src/components/ColorPicker/SVSquare.tsx +189 -0
- package/src/components/ColorPicker/colorMath.ts +141 -0
- package/src/components/ColorPicker/index.ts +6 -0
- package/src/components/ConfirmationPopover/ConfirmationPopover.module.scss +39 -0
- package/src/components/ConfirmationPopover/ConfirmationPopover.tokens.scss +13 -0
- package/src/components/ConfirmationPopover/ConfirmationPopover.tsx +395 -0
- package/src/components/ConfirmationPopover/index.ts +2 -0
- package/src/components/Constrain/Constrain.module.scss +99 -0
- package/src/components/Constrain/Constrain.tsx +79 -0
- package/src/components/Constrain/index.ts +2 -0
- package/src/components/CurrencySelect/CurrencySelect.module.scss +7 -0
- package/src/components/CurrencySelect/CurrencySelect.tsx +167 -0
- package/src/components/CurrencySelect/index.ts +3 -0
- package/src/components/CursorPagination/CursorPagination.module.scss +69 -0
- package/src/components/CursorPagination/CursorPagination.tokens.scss +32 -0
- package/src/components/CursorPagination/CursorPagination.tsx +121 -0
- package/src/components/CursorPagination/index.ts +2 -0
- package/src/components/DashboardCanvas/DashboardCanvas.module.scss +360 -0
- package/src/components/DashboardCanvas/DashboardCanvas.tokens.scss +48 -0
- package/src/components/DashboardCanvas/DashboardCanvas.tsx +1270 -0
- package/src/components/DashboardCanvas/DashboardCanvasItem.tsx +140 -0
- package/src/components/DashboardCanvas/DashboardCanvasSection.tsx +174 -0
- package/src/components/DashboardCanvas/engine.ts +363 -0
- package/src/components/DashboardCanvas/index.ts +9 -0
- package/src/components/DashboardWidget/DashboardWidget.module.scss +100 -0
- package/src/components/DashboardWidget/DashboardWidget.tokens.scss +16 -0
- package/src/components/DashboardWidget/DashboardWidget.tsx +188 -0
- package/src/components/DashboardWidget/index.ts +7 -0
- package/src/components/DataTable/BodyRow.tsx +197 -0
- package/src/components/DataTable/ColumnVisibilityTrigger.module.scss +7 -0
- package/src/components/DataTable/ColumnVisibilityTrigger.tsx +105 -0
- package/src/components/DataTable/DataTable.module.scss +511 -0
- package/src/components/DataTable/DataTable.tokens.scss +80 -0
- package/src/components/DataTable/DataTable.tsx +734 -0
- package/src/components/DataTable/HeaderCell.module.scss +215 -0
- package/src/components/DataTable/HeaderCell.tsx +440 -0
- package/src/components/DataTable/columnShift.ts +117 -0
- package/src/components/DataTable/index.ts +23 -0
- package/src/components/DataTable/pinStyle.ts +47 -0
- package/src/components/DataTable/reorderColumns.ts +66 -0
- package/src/components/DataTable/types.ts +289 -0
- package/src/components/DataTable/useColumnDragShift.ts +216 -0
- package/src/components/DataTable/useDataTable.ts +372 -0
- package/src/components/DataTable/useResizeHandle.ts +97 -0
- package/src/components/DatePicker/DatePicker.module.scss +180 -0
- package/src/components/DatePicker/DatePicker.tokens.scss +152 -0
- package/src/components/DatePicker/DatePicker.tsx +664 -0
- package/src/components/DatePicker/DatePickerGrid.module.scss +172 -0
- package/src/components/DatePicker/DatePickerGrid.tsx +341 -0
- package/src/components/DatePicker/InlineDatePicker.module.scss +32 -0
- package/src/components/DatePicker/InlineDatePicker.tsx +201 -0
- package/src/components/DatePicker/index.ts +4 -0
- package/src/components/DatePicker/utils.ts +364 -0
- package/src/components/DateRangePicker/DateRangePicker.module.scss +237 -0
- package/src/components/DateRangePicker/DateRangePicker.tokens.scss +78 -0
- package/src/components/DateRangePicker/DateRangePicker.tsx +720 -0
- package/src/components/DateRangePicker/InlineDateRangePicker.module.scss +94 -0
- package/src/components/DateRangePicker/InlineDateRangePicker.tsx +376 -0
- package/src/components/DateRangePicker/index.ts +5 -0
- package/src/components/DateRangePicker/utils.ts +151 -0
- package/src/components/DateStrip/DateStrip.module.scss +78 -0
- package/src/components/DateStrip/DateStrip.tokens.scss +23 -0
- package/src/components/DateStrip/DateStrip.tsx +205 -0
- package/src/components/DateStrip/index.ts +2 -0
- package/src/components/DefinitionList/DefinitionList.module.scss +102 -0
- package/src/components/DefinitionList/DefinitionList.tokens.scss +29 -0
- package/src/components/DefinitionList/DefinitionList.tsx +198 -0
- package/src/components/DefinitionList/index.ts +9 -0
- package/src/components/Divider/Divider.module.scss +144 -0
- package/src/components/Divider/Divider.tokens.scss +21 -0
- package/src/components/Divider/Divider.tsx +103 -0
- package/src/components/Divider/index.ts +2 -0
- package/src/components/Dot/Dot.module.scss +40 -0
- package/src/components/Dot/Dot.tokens.scss +4 -0
- package/src/components/Dot/Dot.tsx +45 -0
- package/src/components/Dot/index.ts +2 -0
- package/src/components/Drawer/Body.tsx +23 -0
- package/src/components/Drawer/Close.tsx +35 -0
- package/src/components/Drawer/Content.tsx +93 -0
- package/src/components/Drawer/Drawer.module.scss +232 -0
- package/src/components/Drawer/Drawer.tokens.scss +38 -0
- package/src/components/Drawer/Drawer.tsx +23 -0
- package/src/components/Drawer/DrawerRoot.tsx +190 -0
- package/src/components/Drawer/Footer.tsx +24 -0
- package/src/components/Drawer/Header.tsx +64 -0
- package/src/components/Drawer/Overlay.tsx +82 -0
- package/src/components/Drawer/context.ts +44 -0
- package/src/components/Drawer/index.ts +12 -0
- package/src/components/Drawer/useDragToClose.ts +149 -0
- package/src/components/DropdownMenu/CheckboxItem.tsx +144 -0
- package/src/components/DropdownMenu/Content.tsx +419 -0
- package/src/components/DropdownMenu/DropdownMenu.module.scss +280 -0
- package/src/components/DropdownMenu/DropdownMenu.tokens.scss +88 -0
- package/src/components/DropdownMenu/DropdownMenu.tsx +43 -0
- package/src/components/DropdownMenu/Group.tsx +76 -0
- package/src/components/DropdownMenu/Item.tsx +148 -0
- package/src/components/DropdownMenu/ItemIndicator.tsx +30 -0
- package/src/components/DropdownMenu/Radio.tsx +178 -0
- package/src/components/DropdownMenu/Root.tsx +100 -0
- package/src/components/DropdownMenu/Sub.tsx +332 -0
- package/src/components/DropdownMenu/Trigger.tsx +76 -0
- package/src/components/DropdownMenu/context.ts +65 -0
- package/src/components/DropdownMenu/index.ts +20 -0
- package/src/components/EmojiPicker/EmojiPicker.module.scss +84 -0
- package/src/components/EmojiPicker/EmojiPicker.tokens.scss +24 -0
- package/src/components/EmojiPicker/EmojiPicker.tsx +341 -0
- package/src/components/EmojiPicker/emojiData.ts +245 -0
- package/src/components/EmojiPicker/index.ts +3 -0
- package/src/components/EmptyState/EmptyState.module.scss +102 -0
- package/src/components/EmptyState/EmptyState.tokens.scss +28 -0
- package/src/components/EmptyState/EmptyState.tsx +112 -0
- package/src/components/EmptyState/index.ts +7 -0
- package/src/components/EntityChip/EntityChip.module.scss +275 -0
- package/src/components/EntityChip/EntityChip.tokens.scss +66 -0
- package/src/components/EntityChip/EntityChip.tsx +649 -0
- package/src/components/EntityChip/index.ts +10 -0
- package/src/components/ErrorState/ErrorState.module.scss +105 -0
- package/src/components/ErrorState/ErrorState.tokens.scss +32 -0
- package/src/components/ErrorState/ErrorState.tsx +125 -0
- package/src/components/ErrorState/index.ts +8 -0
- package/src/components/Field/Field.module.scss +46 -0
- package/src/components/Field/Field.tsx +185 -0
- package/src/components/Field/index.ts +2 -0
- package/src/components/FileUpload/FileUpload.module.scss +187 -0
- package/src/components/FileUpload/FileUpload.tokens.scss +81 -0
- package/src/components/FileUpload/FileUpload.tsx +569 -0
- package/src/components/FileUpload/formatBytes.ts +34 -0
- package/src/components/FileUpload/iconForFile.ts +40 -0
- package/src/components/FileUpload/index.ts +2 -0
- package/src/components/FilterChip/FilterChip.module.scss +61 -0
- package/src/components/FilterChip/FilterChip.tokens.scss +25 -0
- package/src/components/FilterChip/FilterChip.tsx +208 -0
- package/src/components/FilterChip/index.ts +5 -0
- package/src/components/FlowCanvas/FlowCanvas.module.scss +329 -0
- package/src/components/FlowCanvas/FlowCanvas.tokens.scss +45 -0
- package/src/components/FlowCanvas/FlowCanvas.tsx +1867 -0
- package/src/components/FlowCanvas/FlowControls.tsx +46 -0
- package/src/components/FlowCanvas/FlowEdge.tsx +58 -0
- package/src/components/FlowCanvas/FlowNode.tsx +76 -0
- package/src/components/FlowCanvas/edgePath.ts +85 -0
- package/src/components/FlowCanvas/index.ts +4 -0
- package/src/components/FlowCanvas/layout.ts +148 -0
- package/src/components/FlowCanvas/spatialNav.ts +76 -0
- package/src/components/FlowCanvas/types.ts +59 -0
- package/src/components/FlowCanvas/useViewport.ts +122 -0
- package/src/components/FormRow/FormRow.module.scss +2 -0
- package/src/components/FormRow/FormRow.tsx +37 -0
- package/src/components/FormRow/index.ts +2 -0
- package/src/components/FormSection/FormSection.module.scss +24 -0
- package/src/components/FormSection/FormSection.tsx +46 -0
- package/src/components/FormSection/index.ts +2 -0
- package/src/components/Grid/Grid.module.scss +162 -0
- package/src/components/Grid/Grid.tokens.scss +13 -0
- package/src/components/Grid/Grid.tsx +226 -0
- package/src/components/Grid/GridItem.tsx +77 -0
- package/src/components/Grid/index.ts +11 -0
- package/src/components/Highlight/Highlight.module.scss +43 -0
- package/src/components/Highlight/Highlight.tokens.scss +35 -0
- package/src/components/Highlight/Highlight.tsx +164 -0
- package/src/components/Highlight/HighlightOverlay.tsx +100 -0
- package/src/components/Highlight/index.ts +2 -0
- package/src/components/HighlightedText/HighlightedText.module.scss +11 -0
- package/src/components/HighlightedText/HighlightedText.tokens.scss +9 -0
- package/src/components/HighlightedText/HighlightedText.tsx +50 -0
- package/src/components/HighlightedText/highlightRanges.ts +44 -0
- package/src/components/HighlightedText/index.ts +2 -0
- package/src/components/IconPicker/IconPicker.module.scss +175 -0
- package/src/components/IconPicker/IconPicker.tokens.scss +40 -0
- package/src/components/IconPicker/IconPicker.tsx +629 -0
- package/src/components/IconPicker/index.ts +9 -0
- package/src/components/IconTile/IconTile.module.scss +57 -0
- package/src/components/IconTile/IconTile.tokens.scss +16 -0
- package/src/components/IconTile/IconTile.tsx +91 -0
- package/src/components/IconTile/index.ts +2 -0
- package/src/components/Image/Image.module.scss +266 -0
- package/src/components/Image/Image.tokens.scss +55 -0
- package/src/components/Image/Image.tsx +342 -0
- package/src/components/Image/index.ts +2 -0
- package/src/components/ImageCrop/ImageCrop.module.scss +274 -0
- package/src/components/ImageCrop/ImageCrop.tokens.scss +33 -0
- package/src/components/ImageCrop/ImageCrop.tsx +542 -0
- package/src/components/ImageCrop/cropGeometry.ts +120 -0
- package/src/components/ImageCrop/extractCropBlob.ts +140 -0
- package/src/components/ImageCrop/index.ts +11 -0
- package/src/components/ImageCrop/useCropPreview.ts +161 -0
- package/src/components/Indent/Indent.module.scss +33 -0
- package/src/components/Indent/Indent.tokens.scss +10 -0
- package/src/components/Indent/Indent.tsx +46 -0
- package/src/components/Indent/index.ts +2 -0
- package/src/components/Input/Input.module.scss +99 -0
- package/src/components/Input/Input.tokens.scss +54 -0
- package/src/components/Input/Input.tsx +105 -0
- package/src/components/Input/Suggestions.tsx +260 -0
- package/src/components/Input/index.ts +2 -0
- package/src/components/Kanban/Kanban.module.scss +39 -0
- package/src/components/Kanban/Kanban.tokens.scss +15 -0
- package/src/components/Kanban/Kanban.tsx +951 -0
- package/src/components/Kanban/index.ts +7 -0
- package/src/components/Kbd/Kbd.module.scss +47 -0
- package/src/components/Kbd/Kbd.tokens.scss +26 -0
- package/src/components/Kbd/Kbd.tsx +73 -0
- package/src/components/Kbd/index.ts +2 -0
- package/src/components/Lightbox/Lightbox.module.scss +283 -0
- package/src/components/Lightbox/Lightbox.tokens.scss +36 -0
- package/src/components/Lightbox/Lightbox.tsx +506 -0
- package/src/components/Lightbox/index.ts +2 -0
- package/src/components/Link/Link.module.scss +78 -0
- package/src/components/Link/Link.tokens.scss +28 -0
- package/src/components/Link/Link.tsx +114 -0
- package/src/components/Link/index.ts +2 -0
- package/src/components/LinkCard/LinkCard.module.scss +92 -0
- package/src/components/LinkCard/LinkCard.tokens.scss +9 -0
- package/src/components/LinkCard/LinkCard.tsx +72 -0
- package/src/components/LinkCard/index.ts +2 -0
- package/src/components/LiquidEditor/AutocompleteMenu.tsx +133 -0
- package/src/components/LiquidEditor/HighlightLayer.tsx +53 -0
- package/src/components/LiquidEditor/InsertVariableMenu.tsx +81 -0
- package/src/components/LiquidEditor/LiquidEditor.module.scss +339 -0
- package/src/components/LiquidEditor/LiquidEditor.tokens.scss +81 -0
- package/src/components/LiquidEditor/LiquidEditor.tsx +412 -0
- package/src/components/LiquidEditor/PreviewPane.tsx +29 -0
- package/src/components/LiquidEditor/caretCoordinates.ts +97 -0
- package/src/components/LiquidEditor/index.ts +7 -0
- package/src/components/LiquidEditor/liquidFilters.ts +23 -0
- package/src/components/LiquidEditor/liquidTokenizer.ts +235 -0
- package/src/components/LiquidEditor/types.ts +101 -0
- package/src/components/LiquidEditor/useLiquidAutocomplete.ts +178 -0
- package/src/components/List/List.module.scss +105 -0
- package/src/components/List/List.tokens.scss +42 -0
- package/src/components/List/List.tsx +124 -0
- package/src/components/List/index.ts +9 -0
- package/src/components/LiveRegion/LiveRegion.module.scss +3 -0
- package/src/components/LiveRegion/LiveRegion.tsx +116 -0
- package/src/components/LiveRegion/index.ts +2 -0
- package/src/components/Logo/Logo.module.scss +139 -0
- package/src/components/Logo/Logo.tokens.scss +14 -0
- package/src/components/Logo/Logo.tsx +126 -0
- package/src/components/Logo/index.ts +2 -0
- package/src/components/Masonry/Masonry.module.scss +42 -0
- package/src/components/Masonry/Masonry.tokens.scss +8 -0
- package/src/components/Masonry/Masonry.tsx +136 -0
- package/src/components/Masonry/index.ts +2 -0
- package/src/components/Masonry/masonryUtils.ts +42 -0
- package/src/components/MediaTile/MediaTile.module.scss +183 -0
- package/src/components/MediaTile/MediaTile.tokens.scss +60 -0
- package/src/components/MediaTile/MediaTile.tsx +208 -0
- package/src/components/MediaTile/index.ts +8 -0
- package/src/components/Modal/Body.tsx +27 -0
- package/src/components/Modal/Close.tsx +45 -0
- package/src/components/Modal/Content.tsx +98 -0
- package/src/components/Modal/Footer.tsx +28 -0
- package/src/components/Modal/Header.tsx +51 -0
- package/src/components/Modal/Modal.module.scss +262 -0
- package/src/components/Modal/Modal.tokens.scss +50 -0
- package/src/components/Modal/Modal.tsx +23 -0
- package/src/components/Modal/ModalRoot.tsx +299 -0
- package/src/components/Modal/Overlay.tsx +101 -0
- package/src/components/Modal/context.ts +60 -0
- package/src/components/Modal/index.ts +11 -0
- package/src/components/MoneyInput/MoneyInput.module.scss +57 -0
- package/src/components/MoneyInput/MoneyInput.tsx +433 -0
- package/src/components/MoneyInput/index.ts +2 -0
- package/src/components/OptionsPicker/OptionsPicker.module.scss +216 -0
- package/src/components/OptionsPicker/OptionsPicker.tokens.scss +68 -0
- package/src/components/OptionsPicker/OptionsPicker.tsx +936 -0
- package/src/components/OptionsPicker/index.ts +9 -0
- package/src/components/OtpInput/OtpInput.module.scss +69 -0
- package/src/components/OtpInput/OtpInput.tokens.scss +45 -0
- package/src/components/OtpInput/OtpInput.tsx +368 -0
- package/src/components/OtpInput/index.ts +2 -0
- package/src/components/Page/Page.module.scss +30 -0
- package/src/components/Page/Page.tokens.scss +11 -0
- package/src/components/Page/Page.tsx +53 -0
- package/src/components/Page/index.ts +2 -0
- package/src/components/PageHeader/PageHeader.module.scss +197 -0
- package/src/components/PageHeader/PageHeader.tokens.scss +41 -0
- package/src/components/PageHeader/PageHeader.tsx +310 -0
- package/src/components/PageHeader/index.ts +20 -0
- package/src/components/Pagination/Pagination.module.scss +117 -0
- package/src/components/Pagination/Pagination.tokens.scss +54 -0
- package/src/components/Pagination/Pagination.tsx +165 -0
- package/src/components/Pagination/index.ts +4 -0
- package/src/components/Pagination/paginationRange.ts +72 -0
- package/src/components/PasswordInput/PasswordInput.module.scss +120 -0
- package/src/components/PasswordInput/PasswordInput.tokens.scss +44 -0
- package/src/components/PasswordInput/PasswordInput.tsx +210 -0
- package/src/components/PasswordInput/index.ts +2 -0
- package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.module.scss +80 -0
- package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tokens.scss +40 -0
- package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tsx +96 -0
- package/src/components/PasswordStrengthMeter/index.ts +2 -0
- package/src/components/PersonDisplay/PersonDisplay.module.scss +180 -0
- package/src/components/PersonDisplay/PersonDisplay.tokens.scss +35 -0
- package/src/components/PersonDisplay/PersonDisplay.tsx +420 -0
- package/src/components/PersonDisplay/index.ts +10 -0
- package/src/components/PhoneInput/PhoneInput.module.scss +23 -0
- package/src/components/PhoneInput/PhoneInput.tsx +271 -0
- package/src/components/PhoneInput/index.ts +4 -0
- package/src/components/PhoneInput/phone.ts +128 -0
- package/src/components/PillMenu/PillMenu.module.scss +117 -0
- package/src/components/PillMenu/PillMenu.tokens.scss +22 -0
- package/src/components/PillMenu/PillMenu.tsx +324 -0
- package/src/components/PillMenu/index.ts +2 -0
- package/src/components/Popover/Anchor.tsx +37 -0
- package/src/components/Popover/Close.tsx +45 -0
- package/src/components/Popover/Content.tsx +213 -0
- package/src/components/Popover/Heading.tsx +33 -0
- package/src/components/Popover/Popover.module.scss +177 -0
- package/src/components/Popover/Popover.tokens.scss +22 -0
- package/src/components/Popover/Popover.tsx +23 -0
- package/src/components/Popover/PopoverRoot.tsx +75 -0
- package/src/components/Popover/Trigger.tsx +86 -0
- package/src/components/Popover/context.ts +22 -0
- package/src/components/Popover/index.ts +7 -0
- package/src/components/Progress/Progress.module.scss +110 -0
- package/src/components/Progress/Progress.tokens.scss +44 -0
- package/src/components/Progress/Progress.tsx +129 -0
- package/src/components/Progress/index.ts +2 -0
- package/src/components/QrCode/QrCode.module.scss +97 -0
- package/src/components/QrCode/QrCode.tokens.scss +17 -0
- package/src/components/QrCode/QrCode.tsx +233 -0
- package/src/components/QrCode/index.ts +2 -0
- package/src/components/QrCode/qr.ts +161 -0
- package/src/components/Radio/Radio.module.scss +175 -0
- package/src/components/Radio/Radio.tokens.scss +59 -0
- package/src/components/Radio/Radio.tsx +127 -0
- package/src/components/Radio/RadioGroup.module.scss +42 -0
- package/src/components/Radio/RadioGroup.tsx +120 -0
- package/src/components/Radio/RadioGroupContext.tsx +30 -0
- package/src/components/Radio/index.ts +4 -0
- package/src/components/Rail/Rail.module.scss +510 -0
- package/src/components/Rail/Rail.tokens.scss +92 -0
- package/src/components/Rail/Rail.tsx +287 -0
- package/src/components/Rail/RailCollapseToggle.tsx +57 -0
- package/src/components/Rail/RailFooter.tsx +17 -0
- package/src/components/Rail/RailGroup.tsx +728 -0
- package/src/components/Rail/RailGroupContext.ts +9 -0
- package/src/components/Rail/RailHeader.tsx +23 -0
- package/src/components/Rail/RailItem.tsx +119 -0
- package/src/components/Rail/RailSection.tsx +39 -0
- package/src/components/Rail/RailSpacer.tsx +19 -0
- package/src/components/Rail/index.ts +9 -0
- package/src/components/RelativeDateInput/RelativeDateInput.module.scss +15 -0
- package/src/components/RelativeDateInput/RelativeDateInput.tokens.scss +6 -0
- package/src/components/RelativeDateInput/RelativeDateInput.tsx +474 -0
- package/src/components/RelativeDateInput/index.ts +10 -0
- package/src/components/RelativeDateInput/relativeDate.ts +127 -0
- package/src/components/RichText/RichText.module.scss +5 -0
- package/src/components/RichText/RichText.tsx +70 -0
- package/src/components/RichText/RichTextAttachment.module.scss +82 -0
- package/src/components/RichText/RichTextAttachment.tsx +122 -0
- package/src/components/RichText/_prose.scss +79 -0
- package/src/components/RichText/attachmentIcon.tsx +24 -0
- package/src/components/RichText/engine/attachment.ts +154 -0
- package/src/components/RichText/engine/autolink.ts +64 -0
- package/src/components/RichText/engine/blockUnit.ts +174 -0
- package/src/components/RichText/engine/colorMarks.ts +85 -0
- package/src/components/RichText/engine/escape.ts +11 -0
- package/src/components/RichText/engine/fromHtml.ts +353 -0
- package/src/components/RichText/engine/fromMarkdown.ts +20 -0
- package/src/components/RichText/engine/inlines.ts +82 -0
- package/src/components/RichText/engine/listDepths.ts +32 -0
- package/src/components/RichText/engine/marks.ts +80 -0
- package/src/components/RichText/engine/mdToHtml.ts +178 -0
- package/src/components/RichText/engine/model.ts +157 -0
- package/src/components/RichText/engine/position.ts +118 -0
- package/src/components/RichText/engine/renderDoc.tsx +395 -0
- package/src/components/RichText/engine/renderLink.ts +15 -0
- package/src/components/RichText/engine/renderMention.ts +16 -0
- package/src/components/RichText/engine/safeHref.ts +22 -0
- package/src/components/RichText/engine/toHtml.ts +154 -0
- package/src/components/RichText/engine/toMarkdown.ts +97 -0
- package/src/components/RichText/engine/transforms.ts +434 -0
- package/src/components/RichText/imageMaxHeightStyle.ts +10 -0
- package/src/components/RichText/index.ts +31 -0
- package/src/components/RichTextEditor/RichTextAttachmentConfig.tsx +264 -0
- package/src/components/RichTextEditor/RichTextBlockControls.tsx +365 -0
- package/src/components/RichTextEditor/RichTextBlockMenu.tsx +162 -0
- package/src/components/RichTextEditor/RichTextColorMenu.tsx +115 -0
- package/src/components/RichTextEditor/RichTextEditor.module.scss +298 -0
- package/src/components/RichTextEditor/RichTextEditor.tsx +1910 -0
- package/src/components/RichTextEditor/RichTextImageResizer.tsx +131 -0
- package/src/components/RichTextEditor/RichTextLinkEditor.tsx +151 -0
- package/src/components/RichTextEditor/RichTextMentionMenu.tsx +99 -0
- package/src/components/RichTextEditor/RichTextToolbar.tsx +379 -0
- package/src/components/RichTextEditor/autolinkInput.ts +65 -0
- package/src/components/RichTextEditor/blockDrop.ts +9 -0
- package/src/components/RichTextEditor/blockReflow.ts +62 -0
- package/src/components/RichTextEditor/commands.ts +300 -0
- package/src/components/RichTextEditor/history.ts +93 -0
- package/src/components/RichTextEditor/icons.tsx +152 -0
- package/src/components/RichTextEditor/imageSize.ts +70 -0
- package/src/components/RichTextEditor/index.ts +5 -0
- package/src/components/RichTextEditor/input.ts +209 -0
- package/src/components/RichTextEditor/inputRules.ts +71 -0
- package/src/components/RichTextEditor/links.ts +103 -0
- package/src/components/RichTextEditor/mentionContext.ts +37 -0
- package/src/components/RichTextEditor/mentions.ts +28 -0
- package/src/components/RichTextEditor/preventSelectionLoss.ts +15 -0
- package/src/components/RichTextEditor/selection.ts +415 -0
- package/src/components/RichTextEditor/shortcuts.ts +44 -0
- package/src/components/RichTextEditor/useAnchoredFloating.ts +50 -0
- package/src/components/RichTextEditor/useAttachmentConfig.ts +134 -0
- package/src/components/RichTextEditor/useDismissOnOutsidePointerDown.ts +26 -0
- package/src/components/RichTextEditor/useLinkEditor.ts +107 -0
- package/src/components/RichTextEditor/useMention.ts +226 -0
- package/src/components/RichTextEditor/useOverlayRect.ts +73 -0
- package/src/components/RichTextEditor/useUpload.ts +246 -0
- package/src/components/Screen/Screen.module.scss +46 -0
- package/src/components/Screen/Screen.tokens.scss +20 -0
- package/src/components/Screen/Screen.tsx +97 -0
- package/src/components/Screen/index.ts +2 -0
- package/src/components/ScrollArea/ScrollArea.module.scss +39 -0
- package/src/components/ScrollArea/ScrollArea.tokens.scss +15 -0
- package/src/components/ScrollArea/ScrollArea.tsx +154 -0
- package/src/components/ScrollArea/index.ts +2 -0
- package/src/components/Select/Chip.tsx +45 -0
- package/src/components/Select/Empty.tsx +39 -0
- package/src/components/Select/Error.tsx +51 -0
- package/src/components/Select/HiddenInputs.tsx +44 -0
- package/src/components/Select/Listbox.tsx +557 -0
- package/src/components/Select/Loading.tsx +30 -0
- package/src/components/Select/Select.module.scss +512 -0
- package/src/components/Select/Select.tokens.scss +140 -0
- package/src/components/Select/Select.tsx +685 -0
- package/src/components/Select/Trigger.tsx +952 -0
- package/src/components/Select/context.ts +101 -0
- package/src/components/Select/emptyStateText.ts +19 -0
- package/src/components/Select/index.ts +9 -0
- package/src/components/Select/useSelectState.ts +157 -0
- package/src/components/Select/utils-types.ts +7 -0
- package/src/components/Select/utils.ts +122 -0
- package/src/components/SettingRow/SettingRow.module.scss +166 -0
- package/src/components/SettingRow/SettingRow.tokens.scss +37 -0
- package/src/components/SettingRow/SettingRow.tsx +242 -0
- package/src/components/SettingRow/index.ts +7 -0
- package/src/components/Skeleton/Skeleton.module.scss +55 -0
- package/src/components/Skeleton/Skeleton.tokens.scss +17 -0
- package/src/components/Skeleton/Skeleton.tsx +131 -0
- package/src/components/Skeleton/index.ts +4 -0
- package/src/components/Skeleton/useSkeletonVisibility.ts +95 -0
- package/src/components/Slider/Slider.module.scss +293 -0
- package/src/components/Slider/Slider.tokens.scss +98 -0
- package/src/components/Slider/Slider.tsx +624 -0
- package/src/components/Slider/index.ts +9 -0
- package/src/components/SlotGrid/SlotGrid.module.scss +61 -0
- package/src/components/SlotGrid/SlotGrid.tokens.scss +21 -0
- package/src/components/SlotGrid/SlotGrid.tsx +111 -0
- package/src/components/SlotGrid/index.ts +2 -0
- package/src/components/SocialButton/SocialButton.module.scss +4 -0
- package/src/components/SocialButton/SocialButton.tsx +40 -0
- package/src/components/SocialButton/index.ts +2 -0
- package/src/components/Sortable/Sortable.module.scss +177 -0
- package/src/components/Sortable/Sortable.tokens.scss +27 -0
- package/src/components/Sortable/Sortable.tsx +572 -0
- package/src/components/Sortable/containerAwareCollision.ts +125 -0
- package/src/components/Sortable/index.ts +13 -0
- package/src/components/SortableGroup/SortableGroup.module.scss +23 -0
- package/src/components/SortableGroup/SortableGroup.tsx +315 -0
- package/src/components/SortableGroup/index.ts +4 -0
- package/src/components/SortableGroup/moveSortableItem.ts +39 -0
- package/src/components/Sparkline/Sparkline.module.scss +28 -0
- package/src/components/Sparkline/Sparkline.tokens.scss +7 -0
- package/src/components/Sparkline/Sparkline.tsx +133 -0
- package/src/components/Sparkline/index.ts +2 -0
- package/src/components/Sparkline/sparklineModel.ts +119 -0
- package/src/components/Split/Split.module.scss +158 -0
- package/src/components/Split/Split.tokens.scss +10 -0
- package/src/components/Split/Split.tsx +231 -0
- package/src/components/Split/index.ts +2 -0
- package/src/components/Stack/Stack.module.scss +67 -0
- package/src/components/Stack/Stack.tokens.scss +11 -0
- package/src/components/Stack/Stack.tsx +100 -0
- package/src/components/Stack/index.ts +2 -0
- package/src/components/StagePath/StagePath.module.scss +255 -0
- package/src/components/StagePath/StagePath.tokens.scss +43 -0
- package/src/components/StagePath/StagePath.tsx +176 -0
- package/src/components/StagePath/index.ts +2 -0
- package/src/components/StatGroup/StatGroup.module.scss +6 -0
- package/src/components/StatGroup/StatGroup.tsx +70 -0
- package/src/components/StatGroup/StatGroupContext.ts +10 -0
- package/src/components/StatGroup/StatTile.module.scss +99 -0
- package/src/components/StatGroup/StatTile.tokens.scss +35 -0
- package/src/components/StatGroup/StatTile.tsx +143 -0
- package/src/components/StatGroup/index.ts +4 -0
- package/src/components/Sticky/Sticky.module.scss +98 -0
- package/src/components/Sticky/Sticky.tokens.scss +17 -0
- package/src/components/Sticky/Sticky.tsx +103 -0
- package/src/components/Sticky/index.ts +2 -0
- package/src/components/Switch/Switch.module.scss +182 -0
- package/src/components/Switch/Switch.tokens.scss +59 -0
- package/src/components/Switch/Switch.tsx +214 -0
- package/src/components/Switch/index.ts +2 -0
- package/src/components/Table/Table.module.scss +308 -0
- package/src/components/Table/Table.tokens.scss +79 -0
- package/src/components/Table/Table.tsx +381 -0
- package/src/components/Table/index.ts +15 -0
- package/src/components/TableOfContents/TableOfContents.module.scss +83 -0
- package/src/components/TableOfContents/TableOfContents.tokens.scss +26 -0
- package/src/components/TableOfContents/TableOfContents.tsx +192 -0
- package/src/components/TableOfContents/activeSection.ts +18 -0
- package/src/components/TableOfContents/index.ts +2 -0
- package/src/components/Tabs/Tabs.module.scss +359 -0
- package/src/components/Tabs/Tabs.tokens.scss +50 -0
- package/src/components/Tabs/Tabs.tsx +538 -0
- package/src/components/Tabs/index.ts +2 -0
- package/src/components/Text/Text.module.scss +115 -0
- package/src/components/Text/Text.tokens.scss +55 -0
- package/src/components/Text/Text.tsx +197 -0
- package/src/components/Text/index.ts +2 -0
- package/src/components/Textarea/Textarea.module.scss +94 -0
- package/src/components/Textarea/Textarea.tokens.scss +48 -0
- package/src/components/Textarea/Textarea.tsx +246 -0
- package/src/components/Textarea/index.ts +2 -0
- package/src/components/Thread/Thread.module.scss +161 -0
- package/src/components/Thread/Thread.tokens.scss +32 -0
- package/src/components/Thread/Thread.tsx +176 -0
- package/src/components/Thread/index.ts +2 -0
- package/src/components/TimeField/TimeField.module.scss +232 -0
- package/src/components/TimeField/TimeField.tsx +793 -0
- package/src/components/TimeField/index.ts +2 -0
- package/src/components/Timeline/Timeline.module.scss +58 -0
- package/src/components/Timeline/Timeline.tokens.scss +13 -0
- package/src/components/Timeline/Timeline.tsx +53 -0
- package/src/components/Timeline/index.ts +2 -0
- package/src/components/Title/Title.module.scss +84 -0
- package/src/components/Title/Title.tokens.scss +37 -0
- package/src/components/Title/Title.tsx +150 -0
- package/src/components/Title/index.ts +2 -0
- package/src/components/Toast/Toast.module.scss +299 -0
- package/src/components/Toast/Toast.tokens.scss +65 -0
- package/src/components/Toast/Toast.tsx +122 -0
- package/src/components/Toast/ToastViewport.tsx +166 -0
- package/src/components/Toast/api.ts +175 -0
- package/src/components/Toast/index.ts +5 -0
- package/src/components/Toast/store.ts +133 -0
- package/src/components/Toast/useToastTimer.ts +94 -0
- package/src/components/Tooltip/Tooltip.module.scss +99 -0
- package/src/components/Tooltip/Tooltip.tokens.scss +23 -0
- package/src/components/Tooltip/Tooltip.tsx +341 -0
- package/src/components/Tooltip/index.ts +2 -0
- package/src/components/TopBar/TopBar.module.scss +235 -0
- package/src/components/TopBar/TopBar.tokens.scss +79 -0
- package/src/components/TopBar/TopBar.tsx +87 -0
- package/src/components/TopBar/TopBarEnd.tsx +20 -0
- package/src/components/TopBar/TopBarIconButton.tsx +86 -0
- package/src/components/TopBar/TopBarSearch.tsx +319 -0
- package/src/components/TopBar/TopBarSearchPanel.tsx +268 -0
- package/src/components/TopBar/TopBarStart.tsx +20 -0
- package/src/components/TopBar/index.ts +11 -0
- package/src/components/Tour/Spotlight.tsx +121 -0
- package/src/components/Tour/Tour.module.scss +210 -0
- package/src/components/Tour/Tour.tokens.scss +58 -0
- package/src/components/Tour/Tour.tsx +617 -0
- package/src/components/Tour/index.ts +2 -0
- package/src/components/Tour/useTourTarget.ts +115 -0
- package/src/components/TreeView/TreeView.module.scss +268 -0
- package/src/components/TreeView/TreeView.tokens.scss +36 -0
- package/src/components/TreeView/TreeView.tsx +536 -0
- package/src/components/TreeView/index.ts +3 -0
- package/src/components/TreeView/treeModel.ts +224 -0
- package/src/components/VisuallyHidden/VisuallyHidden.module.scss +7 -0
- package/src/components/VisuallyHidden/VisuallyHidden.tsx +29 -0
- package/src/components/VisuallyHidden/index.ts +2 -0
- package/src/components/WidgetPreview/WidgetPreview.module.scss +11 -0
- package/src/components/WidgetPreview/WidgetPreview.tokens.scss +26 -0
- package/src/components/WidgetPreview/WidgetPreview.tsx +36 -0
- package/src/components/WidgetPreview/WidgetShape.module.scss +140 -0
- package/src/components/WidgetPreview/WidgetShape.tsx +159 -0
- package/src/components/WidgetPreview/index.ts +2 -0
- package/src/components/_internal/Trend.tsx +27 -0
- package/src/components/_internal/choiceTile.scss +74 -0
- package/src/components/_internal/collapse.scss +10 -0
- package/src/components/_internal/collapse.ts +58 -0
- package/src/components/_internal/currency.ts +257 -0
- package/src/components/_internal/dragAnnouncements.ts +200 -0
- package/src/components/_internal/fieldWiring.ts +225 -0
- package/src/components/_internal/gridSpan.ts +54 -0
- package/src/components/_internal/isoDay.ts +35 -0
- package/src/components/_internal/letterKey.ts +26 -0
- package/src/components/_internal/overlay/focusRestore.ts +21 -0
- package/src/components/_internal/overlay/index.ts +12 -0
- package/src/components/_internal/overlay/tourHold.ts +23 -0
- package/src/components/_internal/overlay/useFocusTrap.ts +120 -0
- package/src/components/_internal/overlay/useInOverlay.ts +81 -0
- package/src/components/_internal/overlay/useOverlayStack.ts +232 -0
- package/src/components/_internal/overlay/useScrollLock.ts +112 -0
- package/src/components/_internal/refs.ts +48 -0
- package/src/components/_internal/statusColor.ts +26 -0
- package/src/components/_internal/timeUtils.ts +23 -0
- package/src/components/_internal/useAsyncOptions.ts +145 -0
- package/src/components/_internal/useClippedTooltip.ts +50 -0
- package/src/components/_internal/useControllableState.ts +50 -0
- package/src/components.manifest.json +1141 -0
- package/src/hooks/useBelowBreakpoint.ts +58 -0
- package/src/i18n/I18nProvider.tsx +52 -0
- package/src/i18n/LocaleProvider.tsx +17 -0
- package/src/i18n/en.ts +648 -0
- package/src/i18n/format.ts +71 -0
- package/src/i18n/index.ts +13 -0
- package/src/i18n/messages.ts +1275 -0
- package/src/i18n/ru.ts +677 -0
- package/src/i18n/useLocale.ts +19 -0
- package/src/i18n/useTranslation.ts +58 -0
- package/src/index.ts +913 -0
- package/src/palette/index.ts +2 -0
- package/src/palette/palette.ts +108 -0
- package/src/styles/dark.scss +4 -0
- package/src/styles/global.scss +7 -0
- package/src/styles/mixins.scss +143 -0
- package/src/styles/reset.scss +78 -0
- package/src/styles/tokens.scss +18 -0
- package/src/styles/typography.scss +44 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# `<DropdownMenu>` — action menus from a trigger
|
|
2
|
+
|
|
3
|
+
```tsx
|
|
4
|
+
<DropdownMenu>
|
|
5
|
+
<DropdownMenu.Trigger>
|
|
6
|
+
<Button variant="secondary">Actions</Button>
|
|
7
|
+
</DropdownMenu.Trigger>
|
|
8
|
+
<DropdownMenu.Content align="end">
|
|
9
|
+
<DropdownMenu.Item onSelect={edit}>Edit</DropdownMenu.Item>
|
|
10
|
+
<DropdownMenu.Item onSelect={duplicate} shortcut="⌘D">
|
|
11
|
+
Duplicate
|
|
12
|
+
</DropdownMenu.Item>
|
|
13
|
+
<DropdownMenu.Separator />
|
|
14
|
+
<DropdownMenu.Item onSelect={remove} tone="danger">
|
|
15
|
+
Delete
|
|
16
|
+
</DropdownMenu.Item>
|
|
17
|
+
</DropdownMenu.Content>
|
|
18
|
+
</DropdownMenu>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
<!-- props:start -->
|
|
22
|
+
|
|
23
|
+
## Props
|
|
24
|
+
|
|
25
|
+
### `DropdownMenuProps`
|
|
26
|
+
|
|
27
|
+
<!-- prettier-ignore -->
|
|
28
|
+
| Prop | Type | Required | Description |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| `children` | `ReactNode` | yes | Must contain exactly one `<DropdownMenu.Trigger>` and one `<DropdownMenu.Content>`. |
|
|
31
|
+
| `open` | `boolean` | no | Controlled open state. Provide alongside `onOpenChange` to drive open externally. Omit both to let DropdownMenu own its own state (the common case). |
|
|
32
|
+
| `onOpenChange` | `((open: boolean) => void)` | no | Fired whenever DropdownMenu wants to change open state. Required when `open` is provided. |
|
|
33
|
+
| `defaultOpen` | `boolean` | no | Default open state for uncontrolled usage. Defaults to `false`. |
|
|
34
|
+
|
|
35
|
+
### `DropdownMenuCheckboxItemProps`
|
|
36
|
+
|
|
37
|
+
<!-- prettier-ignore -->
|
|
38
|
+
| Prop | Type | Required | Description |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| `checked` | `boolean` | yes | Whether the item is checked. |
|
|
41
|
+
| `onCheckedChange` | `(checked: boolean) => void` | yes | Called with the new checked state when activated (click or Enter/Space). |
|
|
42
|
+
| `closeOnSelect` | `boolean` | no | Whether activating closes the entire menu chain. Defaults to `false` — checkbox items typically toggle in place inside a multi-select menu. Set to `true` for single-toggle "apply and close" patterns. |
|
|
43
|
+
| `disabled` | `boolean` | no | Disabled items don't fire `onCheckedChange`, are skipped by keyboard nav, and render dimmed. |
|
|
44
|
+
| `icon` | `ReactNode` | no | Leading icon, rendered in a fixed-size slot before the label (parity with `<DropdownMenu.Item icon>`). Prefer this over inlining an icon into `children`: typeahead derives its match string from the string children, so an inlined leading icon leaves the JSX whitespace `" "` as the first string child and breaks first-letter type-to-select. Passing the icon here keeps the typeahead label the pure label string. Mark the glyph `aria-hidden`. |
|
|
45
|
+
| `shortcut` | `string` | no | Optional trailing shortcut hint (e.g. `'⌘D'`). Visual cue only — does NOT register a global key handler. |
|
|
46
|
+
| `meta` | `ReactNode` | no | Trailing secondary content *about the item itself* — a region code, a count, a `<Badge>`. Distinct from `shortcut`, which is a keyboard hint and is styled (and free to evolve) as one. `ReactNode`, so a Badge or Dot can go here. It is NOT `aria-hidden`, so it joins the item's accessible name ("demo RU" rather than a second identical "demo") — which is the point when the label alone is ambiguous. It is a prop, not a child, so it stays out of the typeahead label; type-to-select still matches the pure label text. Renders before `shortcut` when both are present, keeping the keyboard hint rightmost. |
|
|
47
|
+
| `children` | `ReactNode` | yes | Item content. May include a `<DropdownMenu.ItemIndicator>` as a direct child to provide a custom indicator glyph. |
|
|
48
|
+
| …native | | | plus native `<div>` attributes |
|
|
49
|
+
|
|
50
|
+
### `DropdownMenuContentProps`
|
|
51
|
+
|
|
52
|
+
<!-- prettier-ignore -->
|
|
53
|
+
| Prop | Type | Required | Description |
|
|
54
|
+
|---|---|---|---|
|
|
55
|
+
| `side` | `'top' \| 'bottom' \| 'left' \| 'right'` | no | Preferred side. Default `'bottom'`. Auto-flips on collision. |
|
|
56
|
+
| `align` | `'start' \| 'center' \| 'end'` | no | Edge alignment. Default `'start'`. |
|
|
57
|
+
| `sideOffset` | `number` | no | Gap in px between trigger and menu. Default `4`. |
|
|
58
|
+
| `minWidth` | `string \| number` | no | Preferred minimum width in px or any CSS length. Defaults to the trigger's width and is reduced when necessary to keep the menu within the viewport. |
|
|
59
|
+
| …native | | | plus native `<div>` attributes |
|
|
60
|
+
|
|
61
|
+
### `DropdownMenuGroupProps`
|
|
62
|
+
|
|
63
|
+
<!-- prettier-ignore -->
|
|
64
|
+
| Prop | Type | Required | Description |
|
|
65
|
+
|---|---|---|---|
|
|
66
|
+
| `children` | `ReactNode` | yes | Menu items (and optionally a `<DropdownMenu.Label>`) to include in the group. |
|
|
67
|
+
| …native | | | plus native `<div>` attributes |
|
|
68
|
+
|
|
69
|
+
### `DropdownMenuItemIndicatorProps`
|
|
70
|
+
|
|
71
|
+
<!-- prettier-ignore -->
|
|
72
|
+
| Prop | Type | Required | Description |
|
|
73
|
+
|---|---|---|---|
|
|
74
|
+
| `children` | `ReactNode` | no | Indicator content (icon, custom glyph, animated element) to render in the parent item's indicator slot. The parent — CheckboxItem or RadioItem — decides when this is rendered based on its own `checked` state. |
|
|
75
|
+
| …native | | | plus native `<span>` attributes |
|
|
76
|
+
|
|
77
|
+
### `DropdownMenuItemProps`
|
|
78
|
+
|
|
79
|
+
<!-- prettier-ignore -->
|
|
80
|
+
| Prop | Type | Required | Description |
|
|
81
|
+
|---|---|---|---|
|
|
82
|
+
| `onSelect` | `() => void` | yes | Called when the item is activated (click or Enter/Space). The consumer performs the action. |
|
|
83
|
+
| `tone` | `'default' \| 'danger'` | no | Visual tone. - `'default'` — normal action. - `'danger'` — destructive (Delete, Revoke, Remove). Reserve for irreversible operations. |
|
|
84
|
+
| `icon` | `ReactNode` | no | Leading icon. Rendered in a fixed-size slot so labels stay aligned across items. |
|
|
85
|
+
| `shortcut` | `string` | no | Trailing shortcut hint (e.g. `'⌘D'`). Visual cue only — does NOT register a global key handler. |
|
|
86
|
+
| `meta` | `ReactNode` | no | Trailing secondary content *about the item itself* — a region code, a count, a `<Badge>`. Distinct from `shortcut`, which is a keyboard hint and is styled (and free to evolve) as one. `ReactNode`, so a Badge or Dot can go here. It is NOT `aria-hidden`, so it joins the item's accessible name ("demo RU" rather than a second identical "demo") — which is the point when the label alone is ambiguous. It is a prop, not a child, so it stays out of the typeahead label; type-to-select still matches the pure label text. Renders before `shortcut` when both are present, keeping the keyboard hint rightmost. |
|
|
87
|
+
| `disabled` | `boolean` | no | Disabled items are skipped by keyboard nav, dimmed, and don't fire `onSelect` on click. |
|
|
88
|
+
| `closeOnSelect` | `boolean` | no | Whether to close the menu after `onSelect` fires. Defaults to `true`. Set to `false` when this item is wrapped in a Popover/ConfirmationPopover trigger — the trigger will open its panel on this click; closing the menu would unmount the popover before the user could interact with it. The menu can be dismissed separately (Escape or outside-click). |
|
|
89
|
+
| …native | | | plus native `<div>` attributes |
|
|
90
|
+
|
|
91
|
+
### `DropdownMenuLabelProps`
|
|
92
|
+
|
|
93
|
+
<!-- prettier-ignore -->
|
|
94
|
+
| Prop | Type | Required | Description |
|
|
95
|
+
|---|---|---|---|
|
|
96
|
+
| `children` | `ReactNode` | yes | The label text content. |
|
|
97
|
+
| …native | | | plus native `<div>` attributes |
|
|
98
|
+
|
|
99
|
+
### `DropdownMenuRadioGroupProps`
|
|
100
|
+
|
|
101
|
+
<!-- prettier-ignore -->
|
|
102
|
+
| Prop | Type | Required | Description |
|
|
103
|
+
|---|---|---|---|
|
|
104
|
+
| `value` | `string` | yes | The currently-selected value. Must match the `value` prop of one of the child RadioItems. |
|
|
105
|
+
| `onValueChange` | `(value: string) => void` | yes | Called with the new value when a `<DropdownMenu.RadioItem>` is activated. |
|
|
106
|
+
| `children` | `ReactNode` | yes | `<DropdownMenu.RadioItem>` children (and optionally `<DropdownMenu.Label>`). |
|
|
107
|
+
| …native | | | plus native `<div>` attributes |
|
|
108
|
+
|
|
109
|
+
### `DropdownMenuRadioItemProps`
|
|
110
|
+
|
|
111
|
+
<!-- prettier-ignore -->
|
|
112
|
+
| Prop | Type | Required | Description |
|
|
113
|
+
|---|---|---|---|
|
|
114
|
+
| `value` | `string` | yes | The value this item represents. Activating sets the parent RadioGroup's value to this. |
|
|
115
|
+
| `closeOnSelect` | `boolean` | no | Whether activating closes the entire menu chain. Defaults to `true` — radio selection IS the action; the menu's job is done once a value is chosen. Set to `false` for preview-style selection where the menu stays open. |
|
|
116
|
+
| `disabled` | `boolean` | no | Disabled items don't fire `onValueChange`, are skipped by keyboard nav, and render dimmed. |
|
|
117
|
+
| `icon` | `ReactNode` | no | Leading icon, rendered in a fixed-size slot before the label (parity with `<DropdownMenu.Item icon>`). Prefer this over inlining an icon into `children`: typeahead derives its match string from the string children, so an inlined leading icon leaves the JSX whitespace `" "` as the first string child and breaks first-letter type-to-select. Passing the icon here keeps the typeahead label the pure label string. Mark the glyph `aria-hidden`. |
|
|
118
|
+
| `shortcut` | `string` | no | Optional trailing shortcut hint (e.g. `'⌘N'`). Visual cue only — does NOT register a global key handler. |
|
|
119
|
+
| `meta` | `ReactNode` | no | Trailing secondary content *about the item itself* — a region code, a count, a `<Badge>`. Distinct from `shortcut`, which is a keyboard hint and is styled (and free to evolve) as one. `ReactNode`, so a Badge or Dot can go here. It is NOT `aria-hidden`, so it joins the item's accessible name ("demo RU" rather than a second identical "demo") — which is the point when the label alone is ambiguous. It is a prop, not a child, so it stays out of the typeahead label; type-to-select still matches the pure label text. Renders before `shortcut` when both are present, keeping the keyboard hint rightmost. |
|
|
120
|
+
| `children` | `ReactNode` | yes | Item content. May include a `<DropdownMenu.ItemIndicator>` as a direct child to provide a custom indicator glyph. |
|
|
121
|
+
| …native | | | plus native `<div>` attributes |
|
|
122
|
+
|
|
123
|
+
### `DropdownMenuSeparatorProps`
|
|
124
|
+
|
|
125
|
+
<!-- prettier-ignore -->
|
|
126
|
+
| Prop | Type | Required | Description |
|
|
127
|
+
|---|---|---|---|
|
|
128
|
+
| …native | | | plus native `<div>` attributes |
|
|
129
|
+
|
|
130
|
+
### `DropdownMenuSubContentProps`
|
|
131
|
+
|
|
132
|
+
<!-- prettier-ignore -->
|
|
133
|
+
| Prop | Type | Required | Description |
|
|
134
|
+
|---|---|---|---|
|
|
135
|
+
| `side` | `'top' \| 'bottom' \| 'left' \| 'right'` | no | Preferred side. Default `'bottom'`. Auto-flips on collision. |
|
|
136
|
+
| `align` | `'start' \| 'center' \| 'end'` | no | Edge alignment. Default `'start'`. |
|
|
137
|
+
| `sideOffset` | `number` | no | Gap in px between trigger and menu. Default `4`. |
|
|
138
|
+
| `minWidth` | `string \| number` | no | Preferred minimum width in px or any CSS length. Defaults to the trigger's width and is reduced when necessary to keep the menu within the viewport. |
|
|
139
|
+
| …native | | | plus native HTML attributes |
|
|
140
|
+
|
|
141
|
+
### `DropdownMenuSubProps`
|
|
142
|
+
|
|
143
|
+
<!-- prettier-ignore -->
|
|
144
|
+
| Prop | Type | Required | Description |
|
|
145
|
+
|---|---|---|---|
|
|
146
|
+
| `children` | `ReactNode` | yes | The submenu trigger and content to render. Should contain exactly one `<DropdownMenu.SubTrigger>` and one `<DropdownMenu.SubContent>`. |
|
|
147
|
+
| `open` | `boolean` | no | Controlled open state. When provided, `defaultOpen` is ignored. |
|
|
148
|
+
| `onOpenChange` | `((open: boolean) => void)` | no | Called when the open state changes (user opens or closes the sub). |
|
|
149
|
+
| `defaultOpen` | `boolean` | no | Initial open state when uncontrolled. Defaults to `false`. |
|
|
150
|
+
|
|
151
|
+
### `DropdownMenuSubTriggerProps`
|
|
152
|
+
|
|
153
|
+
<!-- prettier-ignore -->
|
|
154
|
+
| Prop | Type | Required | Description |
|
|
155
|
+
|---|---|---|---|
|
|
156
|
+
| `disabled` | `boolean` | no | When `true`, the trigger renders dimmed and pointer/keyboard interaction does not open the sub. |
|
|
157
|
+
| `icon` | `ReactNode` | no | Optional leading icon. Rendered in a fixed-size slot, matching `<DropdownMenu.Item>`'s icon slot. |
|
|
158
|
+
| `children` | `ReactNode` | yes | The trigger label text. String children participate in the parent menu's typeahead. |
|
|
159
|
+
| …native | | | plus native `<div>` attributes |
|
|
160
|
+
|
|
161
|
+
### `DropdownMenuTriggerProps`
|
|
162
|
+
|
|
163
|
+
<!-- prettier-ignore -->
|
|
164
|
+
| Prop | Type | Required | Description |
|
|
165
|
+
|---|---|---|---|
|
|
166
|
+
| `children` | `ReactElement<unknown, string \| JSXElementConstructor<any>>` | yes | Exactly one React element. The Trigger clones this element to inject a ref, `aria-haspopup="menu"`, `aria-expanded`, `aria-controls`, and the pointerdown/keyboard handlers that open the menu. The child must accept a ref (i.e. use `forwardRef` if it's a custom component); a raw `<button>` or the library's `<Button>` both qualify. |
|
|
167
|
+
|
|
168
|
+
<!-- props:end -->
|
|
169
|
+
|
|
170
|
+
- Compound API: `<DropdownMenu>` is the provider; `<Trigger>` clones its single child to inject ARIA + handlers; `<Content>` portals to `document.body` and positions itself with Floating UI; `<Item>` renders a `menuitem`; `<Separator>` renders a divider.
|
|
171
|
+
- Trigger child must accept a ref via `forwardRef`. `<Button>` does.
|
|
172
|
+
- `<Item>` props: `onSelect` (required), `disabled`, `tone` (`'default'` | `'danger'`), `icon`, `shortcut`, `meta`, `closeOnSelect` (default `true`; set to `false` when wrapping the Item in a `<Popover.Trigger>` or `<ConfirmationPopover>` — otherwise the menu close would unmount the popover before it can render).
|
|
173
|
+
- `<Content>` props: `side` (`'top'` | `'bottom'`, default `'bottom'`), `align` (`'start'` | `'center'` | `'end'`, default `'start'`), `sideOffset` (default `4`), `minWidth`.
|
|
174
|
+
- Keyboard: Enter/Space/ArrowDown on trigger opens with first item active; ArrowUp opens with last; Arrow/Home/End navigate skipping disabled and separators; Enter/Space activates; Escape closes and returns focus to trigger; Tab closes and returns focus to trigger (then continues normal traversal); typeahead jumps to first matching label (500ms debounce).
|
|
175
|
+
- Opens with a short scale-fade from the trigger side (140 ms `ease-out`). Closes instantly by design — menu close should feel like "get out of the way", not "play a transition". Respects `prefers-reduced-motion: reduce`.
|
|
176
|
+
- For value selection (pick a status, country, etc.), use `<Select>` (not yet shipped) — DropdownMenu is for actions, not form values.
|
|
177
|
+
- **Overlay host (like Popover).** A `DropdownMenu` content panel is also an overlay host: a `Popover` / `ConfirmationPopover` / `Select` / date-time popover (`DatePicker` / `DateRangePicker` / `TimeField`) opened from a `DropdownMenu.Item` auto-elevates to `--z-overlay-floating` (1190) so it floats above the menu (and above any Popover the menu itself lives in). Normal submenus are unaffected — they inherit the root trigger's overlay state.
|
|
178
|
+
|
|
179
|
+
#### v2 — submenus, checkboxes, radios, groups
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
<DropdownMenu>
|
|
183
|
+
<DropdownMenu.Trigger>
|
|
184
|
+
<Button variant="secondary">Filters</Button>
|
|
185
|
+
</DropdownMenu.Trigger>
|
|
186
|
+
<DropdownMenu.Content>
|
|
187
|
+
<DropdownMenu.Group>
|
|
188
|
+
<DropdownMenu.Label>Status</DropdownMenu.Label>
|
|
189
|
+
<DropdownMenu.CheckboxItem checked={active} onCheckedChange={setActive}>
|
|
190
|
+
Active
|
|
191
|
+
</DropdownMenu.CheckboxItem>
|
|
192
|
+
<DropdownMenu.CheckboxItem checked={pending} onCheckedChange={setPending}>
|
|
193
|
+
Pending
|
|
194
|
+
</DropdownMenu.CheckboxItem>
|
|
195
|
+
</DropdownMenu.Group>
|
|
196
|
+
|
|
197
|
+
<DropdownMenu.Separator />
|
|
198
|
+
|
|
199
|
+
<DropdownMenu.Group>
|
|
200
|
+
<DropdownMenu.Label>Sort by</DropdownMenu.Label>
|
|
201
|
+
<DropdownMenu.RadioGroup value={sort} onValueChange={setSort}>
|
|
202
|
+
<DropdownMenu.RadioItem value="name">Name</DropdownMenu.RadioItem>
|
|
203
|
+
<DropdownMenu.RadioItem value="date">Date</DropdownMenu.RadioItem>
|
|
204
|
+
</DropdownMenu.RadioGroup>
|
|
205
|
+
</DropdownMenu.Group>
|
|
206
|
+
|
|
207
|
+
<DropdownMenu.Sub>
|
|
208
|
+
<DropdownMenu.SubTrigger>More</DropdownMenu.SubTrigger>
|
|
209
|
+
<DropdownMenu.SubContent>
|
|
210
|
+
<DropdownMenu.Item onSelect={exportCsv}>Export CSV</DropdownMenu.Item>
|
|
211
|
+
<DropdownMenu.Item onSelect={exportJson}>Export JSON</DropdownMenu.Item>
|
|
212
|
+
</DropdownMenu.SubContent>
|
|
213
|
+
</DropdownMenu.Sub>
|
|
214
|
+
</DropdownMenu.Content>
|
|
215
|
+
</DropdownMenu>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
- `<CheckboxItem>` — `role="menuitemcheckbox"`, `aria-checked`. Default `closeOnSelect={false}` (multi-select friendly). Pass `closeOnSelect` to override. Checked items render an accent-tinted row + 2px left accent (no glyph by default).
|
|
219
|
+
- `<RadioGroup>` + `<RadioItem>` — `role="radiogroup"` / `role="menuitemradio"`. Default `closeOnSelect={true}` (radio = the selection IS the action). Selected item gets the same accent-tinted-row treatment as checked CheckboxItem.
|
|
220
|
+
- **Leading `icon` on `CheckboxItem` / `RadioItem`** (parity with `<Item icon>`) — pass a per-row glyph via the `icon` prop, **not** inlined into `children`. Typeahead derives its match string from the string children, so an inlined leading icon leaves the JSX whitespace `" "` as the first string child and kills first-letter type-to-select; the `icon` prop keeps the typeahead label the pure string. Mark the glyph `aria-hidden`. `icon={<Moon size={14} aria-hidden />}`.
|
|
221
|
+
- `<Group>` + `<Label>` — wrap a section. Group is `role="group"` with `aria-labelledby` to the Label. Label outside Group still renders, no aria wiring.
|
|
222
|
+
- `<Sub>` + `<SubTrigger>` + `<SubContent>` — nested menu. SubTrigger registers in the parent menu; SubContent is its own portaled panel. Opens on click, hover (100ms delay), Enter, or ArrowRight. Closes on ArrowLeft (level-only), Escape (level-only), click-outside (all levels), or selecting an item with `closeOnSelect=true` (all levels — cascading close).
|
|
223
|
+
- `<ItemIndicator>` — optional slot child of CheckboxItem/RadioItem that adds a custom indicator glyph alongside the tinted-row treatment. Omit entirely when the row tint is sufficient (the common case). Detection is shallow: must be a direct child.
|
|
224
|
+
- Per WAI-ARIA, mixing CheckboxItem and RadioItem in the same RadioGroup is invalid; CheckboxItems live outside RadioGroup.
|
|
225
|
+
- **Trailing `meta` on `Item` / `CheckboxItem` / `RadioItem`** — secondary content _about the item itself_ (a region code, a count, a `<Badge>`). `ReactNode`. It is **not** `shortcut`: `shortcut` is a keyboard hint, styled as one, and free to become a `<Kbd>` key cap. Two rows whose labels legitimately collide (two workspaces both named `demo`) are disambiguated with `meta`, not `shortcut`.
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
<DropdownMenu.RadioGroup value={workspace} onValueChange={setWorkspace}>
|
|
229
|
+
<DropdownMenu.RadioItem value="demo-eu" meta="EU">
|
|
230
|
+
demo
|
|
231
|
+
</DropdownMenu.RadioItem>
|
|
232
|
+
<DropdownMenu.RadioItem value="demo-ru" meta="RU">
|
|
233
|
+
demo
|
|
234
|
+
</DropdownMenu.RadioItem>
|
|
235
|
+
</DropdownMenu.RadioGroup>
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`meta` renders after the label and before `shortcut` (the keyboard hint stays rightmost). It carries no `aria-hidden`, so it **joins the accessible name** — a screen reader announces "demo RU". Because it is a prop and not a child, it stays **out of the typeahead label**: type-to-select still matches the bare label.
|
|
239
|
+
|
|
240
|
+
- ❌ Using DropdownMenu as a panel (a notification centre, a header with a "Mark all as read" button, rich feed rows). It is `role="menu"`, which may only hold menu items; a header button is invalid ARIA and unreachable by the menu's arrow keys. Use `Popover` + `ScrollArea`.
|
|
241
|
+
|
|
242
|
+
#### More usage
|
|
243
|
+
|
|
244
|
+
```tsx
|
|
245
|
+
// Controlled open (rare — usually let DropdownMenu manage state)
|
|
246
|
+
<DropdownMenu open={open} onOpenChange={setOpen}>...</DropdownMenu>
|
|
247
|
+
|
|
248
|
+
// Table row kebab
|
|
249
|
+
<DropdownMenu>
|
|
250
|
+
<DropdownMenu.Trigger>
|
|
251
|
+
<Button variant="ghost" aria-label="Row actions">⋯</Button>
|
|
252
|
+
</DropdownMenu.Trigger>
|
|
253
|
+
<DropdownMenu.Content align="end">
|
|
254
|
+
<DropdownMenu.Item onSelect={() => view(row)}>View</DropdownMenu.Item>
|
|
255
|
+
<DropdownMenu.Item onSelect={() => archive(row)}>Archive</DropdownMenu.Item>
|
|
256
|
+
</DropdownMenu.Content>
|
|
257
|
+
</DropdownMenu>
|
|
258
|
+
|
|
259
|
+
// CheckboxItem that applies then closes
|
|
260
|
+
<DropdownMenu.CheckboxItem checked={isOn} onCheckedChange={setOn} closeOnSelect>
|
|
261
|
+
Apply and close
|
|
262
|
+
</DropdownMenu.CheckboxItem>
|
|
263
|
+
|
|
264
|
+
// RadioItem that keeps the menu open (e.g. live preview)
|
|
265
|
+
<DropdownMenu.RadioItem value="compact" closeOnSelect={false}>Compact</DropdownMenu.RadioItem>
|
|
266
|
+
|
|
267
|
+
// Custom glyph alongside the tinted checked row
|
|
268
|
+
<DropdownMenu.CheckboxItem checked={isOn} onCheckedChange={setOn}>
|
|
269
|
+
<DropdownMenu.ItemIndicator><CheckIcon size={14} /></DropdownMenu.ItemIndicator>
|
|
270
|
+
Show archived
|
|
271
|
+
</DropdownMenu.CheckboxItem>
|
|
272
|
+
|
|
273
|
+
// Controlled submenu
|
|
274
|
+
<DropdownMenu.Sub open={subOpen} onOpenChange={setSubOpen}>...</DropdownMenu.Sub>
|
|
275
|
+
|
|
276
|
+
// Item with both trailing slots: `meta` qualifies the item and joins the accessible name
|
|
277
|
+
// ("Duplicate 3 files"); `shortcut` is a keyboard hint.
|
|
278
|
+
<DropdownMenu.Item onSelect={onDuplicate} meta="3 files" shortcut="⌘D">Duplicate</DropdownMenu.Item>
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
#### When NOT to use
|
|
282
|
+
|
|
283
|
+
- An always-visible row of actions: use a `<Cluster>` of Buttons in a toolbar. Menus are for actions that don't deserve permanent screen space.
|
|
284
|
+
- Navigation between pages: use the sidebar or a `<Link>`. Menu items are for actions, not page transitions.
|
|
285
|
+
- `CheckboxItem` for a one-off action (use `Item`) or for mutually exclusive choices (use `RadioGroup`); `RadioGroup` for an action menu or for multi-select (use `CheckboxItem`s).
|
|
286
|
+
- `Group` around a single Item, as a generic layout primitive (use `<Stack>` / `<Cluster>`), or around a `RadioGroup` that needs no visible Label (`RadioGroup` already has `role="radiogroup"`).
|
|
287
|
+
- `Label` as a clickable item: it has no `role="menuitem"` and is not keyboard-focusable; use a disabled `Item` for a selectable header-style row. Outside a `Group` it carries no `aria-labelledby` wiring.
|
|
288
|
+
- `Sub` for top-level sections (use `Group` + `Label`), beyond 2–3 nesting levels, or on touch-first surfaces — submenus rely on hover and lateral arrow keys.
|
|
289
|
+
|
|
290
|
+
#### Rules and anti-patterns
|
|
291
|
+
|
|
292
|
+
- `RadioItem` must be inside a `RadioGroup`, and `SubTrigger` inside a `Sub` — both throw in dev otherwise. A `Sub` holds exactly one `SubTrigger` and one `SubContent`.
|
|
293
|
+
- `Content` renders only while the menu is open. `Separator` is a decorative `role="separator"`, not focusable.
|
|
294
|
+
- ❌ Multiple `<DropdownMenu.Trigger>`s in one `<DropdownMenu>`: use one DropdownMenu per trigger.
|
|
295
|
+
- ❌ `tone="danger"` for non-destructive actions like "Filter" or "Sort"; reserve it for irreversible destructive operations.
|
|
296
|
+
- ❌ Nesting a full `<DropdownMenu>` root inside another; use `<DropdownMenu.Sub>`.
|
|
297
|
+
- ❌ Putting `<ItemIndicator>` deeper than a direct child of CheckboxItem / RadioItem: the custom glyph is silently dropped (the row still looks selected). In a plain `<Item>` it just renders inline as any other child.
|
|
298
|
+
- ❌ Using `shortcut` for text that is not a keyboard hint (a region code, a count, a status) — use `meta`.
|
|
299
|
+
- ❌ Several checked CheckboxItems in a "pick one" context: switch to `RadioGroup`.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# `<EmojiPicker>` — searchable emoji grid (reactions + input)
|
|
2
|
+
|
|
3
|
+
**Use to let the user pick an emoji** — a reaction chip, an inline insert into a
|
|
4
|
+
message/comment. Searchable, category-sectioned, keyboard-navigable 8-column grid
|
|
5
|
+
over a **curated common set** (not the full ~1900-emoji Unicode catalog;
|
|
6
|
+
skin-tone / ZWJ variants are out). It's the chooser only — calls
|
|
7
|
+
`onSelect(emoji: string)` on click or Enter/Space; it has no notion of which
|
|
8
|
+
emoji are already chosen or their counts. The bare picker is a surface — pair it
|
|
9
|
+
with a `Popover` (or use `EmojiPickerPopover`).
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
// Inside a Popover you control (e.g. an "add reaction" button on a comment):
|
|
13
|
+
<Popover>
|
|
14
|
+
<Popover.Trigger>
|
|
15
|
+
<Button iconOnly variant="ghost" aria-label="Add reaction">
|
|
16
|
+
<Smile size={16} />
|
|
17
|
+
</Button>
|
|
18
|
+
</Popover.Trigger>
|
|
19
|
+
<Popover.Content>
|
|
20
|
+
<EmojiPicker onSelect={(emoji) => addReaction(emoji)} />
|
|
21
|
+
</Popover.Content>
|
|
22
|
+
</Popover>
|
|
23
|
+
|
|
24
|
+
// Batteries-included wrapper — owns the Popover, closes on select:
|
|
25
|
+
<EmojiPickerPopover
|
|
26
|
+
trigger={<Button variant="secondary" size="sm">Add reaction</Button>}
|
|
27
|
+
onSelect={(emoji) => appendToDraft(emoji)}
|
|
28
|
+
/>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
<!-- props:start -->
|
|
32
|
+
|
|
33
|
+
## Props
|
|
34
|
+
|
|
35
|
+
### `EmojiPickerProps`
|
|
36
|
+
|
|
37
|
+
<!-- prettier-ignore -->
|
|
38
|
+
| Prop | Type | Required | Description |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| `invalid` | `boolean` | no | Consumed so a Field / SettingRow wrapping the picker cannot leak it onto the root div. The picker has no value to validate, so it renders nothing. |
|
|
41
|
+
| `required` | `boolean` | no | Consumed for Field / SettingRow composition; the picker has no value, so nothing is forwarded. |
|
|
42
|
+
| `onSelect` | `(emoji: string) => void` | yes | Fired with the chosen emoji character (e.g. `'👍'`) when the user clicks a cell or presses Enter/Space on a focused cell. This is the picker's single output — wire it to insert into an editor, set a reaction, etc. |
|
|
43
|
+
| `recent` | `string[]` | no | Recently-used emoji characters (e.g. `['👍', '🎉', '❤️']`), most-recent first. When provided, a "Recently used" section renders at the top of the grid (only while not searching). The consumer owns persistence — keep the list yourself (e.g. in localStorage), update it in `onSelect`, and pass it back. Duplicates are de-duped; a char outside the curated set still renders (labelled by the char). Omit or pass `[]` for no recent section. |
|
|
44
|
+
| …native | | | plus native `<div>` attributes |
|
|
45
|
+
|
|
46
|
+
### `EmojiPickerPopoverProps`
|
|
47
|
+
|
|
48
|
+
<!-- prettier-ignore -->
|
|
49
|
+
| Prop | Type | Required | Description |
|
|
50
|
+
|---|---|---|---|
|
|
51
|
+
| `trigger` | `ReactNode` | yes | The element that opens the picker. Must be a single element that accepts a ref (this library's `<Button>` or a raw `<button>`); the open/close + ARIA wiring is injected by `Popover.Trigger`. |
|
|
52
|
+
| `onSelect` | `(emoji: string) => void` | yes | Fired with the chosen emoji character. Selecting always closes the popover (both controlled and uncontrolled). |
|
|
53
|
+
| `recent` | `string[]` | no | Recently-used emoji chars shown in a top "Recently used" section — see `EmojiPicker`. |
|
|
54
|
+
| `open` | `boolean` | no | Controlled open state. Provide alongside `onOpenChange` to drive open externally. Omit both to let the wrapper own its state (the common case). |
|
|
55
|
+
| `onOpenChange` | `((open: boolean) => void)` | no | Fired whenever the popover wants to change open state. Required when `open` is provided. |
|
|
56
|
+
| `defaultOpen` | `boolean` | no | Initial open state for uncontrolled usage. Defaults to `false`. |
|
|
57
|
+
|
|
58
|
+
<!-- props:end -->
|
|
59
|
+
|
|
60
|
+
`EmojiPickerPopover` takes `trigger` + `onSelect`, plus the standard
|
|
61
|
+
controlled-open contract (`open` / `onOpenChange` / `defaultOpen`).
|
|
62
|
+
|
|
63
|
+
`recent?: string[]` (on both) pins a "Recently used" section at the top (shown only
|
|
64
|
+
while not searching). The consumer owns persistence — keep the list (e.g.
|
|
65
|
+
localStorage), update it in `onSelect` (move-to-front + de-dupe + cap), pass it back.
|
|
66
|
+
|
|
67
|
+
**When NOT to use:** a small fixed reaction set (👍 ❤️ 🎉) → render a `Cluster`
|
|
68
|
+
of `Button`s; a searchable grid is overkill for 3-6 choices. Also not for inline
|
|
69
|
+
`:smile`-style autocomplete (the editor's suggestion engine owns that) or for
|
|
70
|
+
rendering existing reaction counts (the consumer builds that display).
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
// Controlled wrapper
|
|
74
|
+
const [open, setOpen] = useState(false);
|
|
75
|
+
<EmojiPickerPopover open={open} onOpenChange={setOpen} trigger={<Button>Emoji</Button>} onSelect={setEmoji} />
|
|
76
|
+
|
|
77
|
+
// Reaction toggle on a comment
|
|
78
|
+
<EmojiPickerPopover
|
|
79
|
+
trigger={<Button size="sm" variant="secondary">React</Button>}
|
|
80
|
+
onSelect={(char) => toggleReaction(commentId, char)}
|
|
81
|
+
/>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
❌ Expecting it to show which emoji a message already has or how many times — it only chooses.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# `<EmptyState>` — "nothing here" container
|
|
2
|
+
|
|
3
|
+
```tsx
|
|
4
|
+
<EmptyState
|
|
5
|
+
icon={<Inbox size={32} />}
|
|
6
|
+
title="No contacts yet"
|
|
7
|
+
description="Add your first contact to get started."
|
|
8
|
+
actions={<Button>Add contact</Button>}
|
|
9
|
+
/>
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
<!-- props:start -->
|
|
13
|
+
|
|
14
|
+
## Props
|
|
15
|
+
|
|
16
|
+
<!-- prettier-ignore -->
|
|
17
|
+
| Prop | Type | Required | Description |
|
|
18
|
+
|---|---|---|---|
|
|
19
|
+
| `icon` | `ReactNode` | no | Icon rendered above the title. Pass a lucide icon, custom SVG, or any ReactNode. Sized by the consumer — recommended: sm=24, md=32, lg=48. Omit for an icon-less empty state. |
|
|
20
|
+
| `title` | `ReactNode` | yes | Required title. Rendered as a semantic heading (default `<h3>`). Accepts ReactNode so inline emphasis works (e.g., `<>Found <strong>0</strong> results</>`). Keep it short and announceable — AT users hear it via heading navigation. |
|
|
21
|
+
| `description` | `ReactNode` | no | Optional description rendered below the title. |
|
|
22
|
+
| `actions` | `ReactNode` | no | Optional action(s) rendered below the description. Typically a `<Button>` or a `<Cluster gap="sm">` of buttons. |
|
|
23
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | no | Visual size. Defaults to `'md'`. - `'sm'` — compact for inline / popover use (empty Select results, empty filter chips). Icon target 24px, font-size-sm title. - `'md'` — default for cards / sections (DataTable empty row, inbox empty). Icon target 32px, font-size-md title. - `'lg'` — hero / full-page empty states. Icon target 48px, font-size-xl title. |
|
|
24
|
+
| `align` | `'center' \| 'start'` | no | Horizontal alignment of the stacked content. Defaults to `'center'`. Use `'start'` when the empty state sits in a tight column where centering would look stranded. |
|
|
25
|
+
| `headingLevel` | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | no | Heading level for the `title`. Defaults to `3` (renders `<h3>`). Set higher (4–6) when the empty state lives deep inside the page's heading hierarchy. Set to `2` when the empty state IS the page's primary content. Values outside `1–6` clamp to `3`. |
|
|
26
|
+
| …native | | | plus native HTML attributes |
|
|
27
|
+
|
|
28
|
+
<!-- props:end -->
|
|
29
|
+
|
|
30
|
+
- Use `<Skeleton>` for **loading** states — EmptyState implies "nothing here," not "data on its way."
|
|
31
|
+
- No `variant="error"` — error treatments need different a11y (live regions, retry actions). Use a future `<Alert>` or render a danger-tinted EmptyState with your own error message.
|
|
32
|
+
- No automatic `aria-hidden` on the icon — consumer's icon may be semantic (e.g., a country-flag icon in a "No results for this region" state). If the icon is purely decorative, the consumer should pass `aria-hidden`.
|
|
33
|
+
- The wrapper `<section>` only becomes a screen-reader landmark when it has an accessible name — pass `aria-label` (or `aria-labelledby`) when the empty state should be navigable as a region (typically when it IS the page's primary content with `headingLevel={1 | 2}`).
|
|
34
|
+
- Not for a page-level 404 / 500 — use a dedicated error page.
|
|
35
|
+
- For unusual layouts compose `<Stack>` + `<Button>` directly; this component is deliberately inflexible.
|
|
36
|
+
- ❌ A long sentence as `title` — keep titles short; long strings hurt heading navigation.
|
|
37
|
+
- ❌ Multiple primary action buttons — one clear next action; secondaries are `ghost`.
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
// Multiple actions
|
|
41
|
+
<EmptyState
|
|
42
|
+
icon={<Search size={32} />}
|
|
43
|
+
title="No results"
|
|
44
|
+
description="Try a different query or clear the filters."
|
|
45
|
+
actions={
|
|
46
|
+
<Cluster gap="sm" justify="center">
|
|
47
|
+
<Button onClick={clearFilters}>Clear filters</Button>
|
|
48
|
+
<Button variant="ghost" onClick={openSearch}>New search</Button>
|
|
49
|
+
</Cluster>
|
|
50
|
+
}
|
|
51
|
+
/>
|
|
52
|
+
|
|
53
|
+
// Inline (e.g. a Select dropdown's empty results)
|
|
54
|
+
<EmptyState size="sm" icon={<SearchX size={24} />} title="No matches" />
|
|
55
|
+
```
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# `<EntityChip>` — inline entity-link chip
|
|
2
|
+
|
|
3
|
+
```tsx
|
|
4
|
+
// Inline, inside a sentence — canonically a link to its entity:
|
|
5
|
+
<Text>
|
|
6
|
+
Reassigned <EntityChip href="/contacts/12" icon={<User size={14} />} label="Priya Shah" /> to this deal.
|
|
7
|
+
</Text>
|
|
8
|
+
|
|
9
|
+
// href, prefix + status:
|
|
10
|
+
<EntityChip
|
|
11
|
+
href="/tasks/5"
|
|
12
|
+
prefix="ENG-5"
|
|
13
|
+
label="Fix login bug"
|
|
14
|
+
status={{ label: 'In progress', category: 'in_progress' }}
|
|
15
|
+
/>
|
|
16
|
+
|
|
17
|
+
// RouterLink via `as`, or a status color override:
|
|
18
|
+
import { Link as RouterLink } from 'react-router-dom';
|
|
19
|
+
<EntityChip as={RouterLink} to="/deals/9" label="Acme Corp" status={{ label: 'At risk', color: 'amber' }} />
|
|
20
|
+
|
|
21
|
+
// Chip fill override (categorical, independent of status):
|
|
22
|
+
<EntityChip href="/deals/9" label="Acme Corp" color="violet" />
|
|
23
|
+
|
|
24
|
+
// One-line list row: only the label ellipsizes; adornments inside the chip:
|
|
25
|
+
<EntityChip
|
|
26
|
+
truncate
|
|
27
|
+
href="/tasks/5"
|
|
28
|
+
icon={<CheckSquare size={14} />}
|
|
29
|
+
prefix="ENG-5"
|
|
30
|
+
label="Fix the login bug that only happens on Safari"
|
|
31
|
+
status={{ label: 'In progress', category: 'in_progress' }}
|
|
32
|
+
trailing={<ArrowUp size={14} aria-label="High priority" />}
|
|
33
|
+
/>
|
|
34
|
+
|
|
35
|
+
// Segmented task chip — coloured `before`/`after` parts, capped label:
|
|
36
|
+
<EntityChip
|
|
37
|
+
as={RouterLink} to="/tasks/ENG-15"
|
|
38
|
+
prefix="ENG-15" label="Fix the login bug on Safari" labelMaxWidth={40}
|
|
39
|
+
before={[{ kind: 'icon', icon: <Bug />, label: 'Bug', color: 'red' }]}
|
|
40
|
+
after={[
|
|
41
|
+
{ kind: 'icon', icon: <Equal />, label: 'Normal priority', color: 'slate' },
|
|
42
|
+
{ kind: 'text', text: 'Reported', color: 'amber' },
|
|
43
|
+
]}
|
|
44
|
+
/>
|
|
45
|
+
|
|
46
|
+
// `labelWeight="semibold"` — a heavier key + title:
|
|
47
|
+
<EntityChip href="/tasks/ENG-15" prefix="ENG-15" label="Fix the login bug on Safari" labelWeight="semibold" />
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
<!-- props:start -->
|
|
51
|
+
|
|
52
|
+
## Props
|
|
53
|
+
|
|
54
|
+
<!-- prettier-ignore -->
|
|
55
|
+
| Prop | Type | Required | Description |
|
|
56
|
+
|---|---|---|---|
|
|
57
|
+
| `icon` | `ReactNode` | no | Leading icon — consumer passes the element (e.g. a lucide icon). Rendered aria-hidden. |
|
|
58
|
+
| `label` | `ReactNode` | no | Entity name. Optional at the type level only to satisfy the polymorphic `forwardRef` generic (same workaround `<Rail.Item>` documents on its `children`); in practice every chip needs a label. |
|
|
59
|
+
| `prefix` | `ReactNode` | no | Muted leading run before the name (e.g. task key `ENG-5`). |
|
|
60
|
+
| `status` | `EntityChipStatus` | no | Inline workflow status `{ label, category?, color? }`, separated by a small dot and rendered in the status's own color. `category` (`to_do`/`in_progress`/`open`/`done`/`won`/`lost`) resolves a default palette color (same mapping as `<PillMenu>`); `color` overrides it. The dot takes the resolved color too. |
|
|
61
|
+
| `color` | `PaletteColor` | no | Optional categorical palette color for the chip fill. When set, takes precedence over the default accent chip tokens: the chip fills with the matching `--color-palette-<name>-bg/-fg` pair (same contract as `Badge color` — picking a readable pair is the consumer's call). Omit for the default fill, which matches RichText's `@mention` styling (`--color-accent-bg-subtle` / `--color-accent`) so a chip and a rendered mention read as the same visual object. The `status` run keeps its own resolved color independent of this prop, and `unavailable` still mutes the label/status text over any `color`. |
|
|
62
|
+
| `href` | `string` | no | Renders `as="a"` with this href when `as` is omitted. |
|
|
63
|
+
| `loading` | `boolean` | no | Loading placeholder: icon slot + `…` body, aria-busy; the label stays in the DOM visually hidden so the chip keeps its accessible name. Purely visual — with a link target (`href`/`as`) the chip stays a live, keyboard-reachable link while loading. The state is announced: a localized word is rendered visually hidden, so a linked chip's name becomes "Appointment (loading)". `aria-busy` alone did not do this. It is a GLOBAL ARIA state, so unlike `aria-disabled` it is perfectly valid on the chip's role-less span and browsers do expose it — but no mainstream screen reader conveys `busy` as a state on a non-live element, and the ellipsis is `aria-hidden`. The label reached the user fine; no signal of the LOADING STATE did. Know the trade: the accessible name CHANGES when loading resolves — and by more than this word. The loading branch renders neither `prefix` nor `status` (nor `before`/`after` segments), so a chip with both goes from "Fix login bug (loading)" to "ENG-5 Fix login bug In progress". That is unavoidable when announcing a transient state through the name, and it is why this was initially left alone. Note it also means a consumer query like `getByRole('link', { name: 'Appointment' })` no longer matches a LOADING chip. Measured, the mutation itself is benign: Chromium keeps the SAME accessibility node across the transition (same backendNodeId) and focus survives, so nothing is torn down and rebuilt — the name and `busy` simply change on the existing object. The alternative — an `aria-live` region — has to be owned by the consumer, because only the consumer knows whether a given chip resolving is worth interrupting someone for. To take that route, override this word to `''` at your TOP-LEVEL provider: the override is global to a provider subtree (there is no per-chip opt-out), `I18nProvider` requires a `locale`, and a nested provider replaces rather than extends its parent — so wrapping a single chip would silently discard every other override you have set. |
|
|
64
|
+
| `unavailable` | `boolean` | no | Entity missing/no access: muted styling. With a link target (`href`/`as`) the chip remains a real link — unavailable is a visual state, not a disabling one. Only a target-less chip (bare span) becomes non-interactive with aria-disabled. The state is also announced: a localized word is rendered visually hidden inside the chip. A linked chip's accessible name becomes "Appointment (unavailable)"; a target-less chip is `role=generic`, which has no accessible name at all, so the word is announced as part of the chip's text in reading order. Either way it reaches the user. That matters because the canonical use is to withhold the entity's name and show a TYPE word instead — without the state, a masked reference is indistinguishable from a real entity that happens to be called "Appointment". Colour alone cannot carry it, and `aria-disabled` does not either: browsers do expose it, but it carries no meaning on a non-widget role such as `generic`, so no assistive tech conveys it. `loading` is announced the same way — see that prop for why `aria-busy` alone was not enough, and for the name-mutation trade it carries. Do NOT put an `aria-label` on the chip. It replaces the whole name and takes the state word with it; the state lives in the chip's contents. Override the word via the i18n provider (`entityChip.unavailable`); it carries its own punctuation so a locale can choose different marks. |
|
|
65
|
+
| `truncate` | `boolean` | no | Single-line mode for list rows. The chip is capped at its container's width (`max-width: 100%`, `min-width: 0`, so it also shrinks as a flex item) and only the `label` ellipsizes — `icon`, `prefix`, `status` and `trailing` keep their full size. Default `false`: the label wraps, which is right for a chip inside running text. The full label stays in the DOM, so the accessible name is unchanged. A clipped label shows its full text in a tooltip on hover or keyboard focus — don't add a `title`, which would give a double tooltip. |
|
|
66
|
+
| `trailing` | `ReactNode` | no | Extra adornments inside the chip, after `status` (e.g. a priority icon or a status `<Badge>`), kept at full size under `truncate`. Not rendered while `loading` (same as `prefix`/`status`). Non-interactive content only: the chip is itself a link, so a button or link here is invalid nested interactive content. Its text JOINS the chip's accessible name ("ENG-5 Fix login bug High") — give a decorative icon `aria-hidden`, and a meaningful one a short text alternative. |
|
|
67
|
+
| `before` | `readonly EntityChipSegment[]` | no | Coloured segments before the chip's core, in order (e.g. the task type). Any segment turns the chip segmented: one line, only the outer corners rounded, only the label shrinks (as with `truncate`). Every segment's text joins the accessible name ("Bug ENG-15 Fix login bug Normal Reported"). Not rendered while `loading` or `unavailable`. |
|
|
68
|
+
| `after` | `readonly EntityChipSegment[]` | no | Coloured segments after the core, in order (e.g. priority, status). See `before`. |
|
|
69
|
+
| `labelMaxWidth` | `number` | no | Caps the label's width, a positive number of `ch`; past it the label ellipsizes on one line (also on a chip without `truncate`). For chips in running text, where the container edge is a whole paragraph away. The full label stays in the DOM and the accessible name; a clipped label shows it in a tooltip on hover or keyboard focus. |
|
|
70
|
+
| `labelEllipsis` | `'end' \| 'start'` | no | Which end of a clipped label is cut. Applies only where the label can clip at all (`truncate`, segments, or `labelMaxWidth`); ignored on a wrapping chip. - `'end'` (default) — `Fix the login bu…`. Right for titles, whose distinctive part is the start. - `'start'` — `…/pull/1116`. For labels whose distinctive part is the tail, e.g. a URL path under a host `prefix`. The text keeps its order; `prefix` and segments stay whole, and the tooltip still shows it all. |
|
|
71
|
+
| `labelWeight` | `'medium' \| 'semibold'` | no | Font weight for `label`. `'medium'` (default) matches a plain chip's fixed weight and the RichText `@mention` — most chips should leave this unset. `'medium'` does NOT apply to `prefix`: `.prefix` carries no font-weight rule of its own and simply inherits (normal), so a default chip's key is lighter than its title. `'semibold'` is the one value that touches BOTH — it sets `prefix` AND `label` to the same heavier weight (a task-chip design that wants its key heavier along with its title). Use `'semibold'` for a design that explicitly wants that. Don't reach for a styled `<Text weight="semibold">` around `label` to get a heavier title instead (see the clipped-label tooltip bullet in `docs/components/EntityChip.md`) — it buys nothing: the clipped-label tooltip reads the label's own `textContent` and always renders it plain, in the tooltip's own color, regardless of what the label node carries. Only this prop changes the rendered weight. |
|
|
72
|
+
| `as` | `ElementType` | no | |
|
|
73
|
+
| …native | | | plus native attributes of the `as` element (default `<a>`) |
|
|
74
|
+
|
|
75
|
+
<!-- props:end -->
|
|
76
|
+
|
|
77
|
+
- Polymorphic inline chip: optional `icon` (rendered `aria-hidden`), optional muted `prefix` (e.g. a task key), the `label`, and an optional colored `status`. All inline `<span>`s inside one root — safe to drop directly inside a `<p>`/`<Text>`.
|
|
78
|
+
- **An EntityChip is always a link to its entity**: pass `href` (renders `<a href>`) or `as` (`RouterLink`, `'button'`, any component — same polymorphic contract as `<Link>`). The bare `<span>` form (no target) is for rare non-navigable contexts only.
|
|
79
|
+
- Default chip fill matches RichText's `@mention` styling (`--color-accent-bg-subtle` / `--color-accent`) — a chip and a rendered mention read as the same visual object in both themes. `color?: PaletteColor` overrides the fill (same inline-injection contract as `Badge color`) — independent of `status`, which keeps its own resolved color. `unavailable` still mutes the label/status/dot over any `color`.
|
|
80
|
+
- ⚠️ **On a chip with a link target, both state words change the accessible name**, so a name-exact query stops matching: `getByRole('link', { name: 'Appointment' })` misses a chip that is loading or unavailable. If your tests select chips by name over lists that render placeholders, use a regex or query before the state applies.
|
|
81
|
+
- **`loading` is announced too.** Same mechanism, and `aria-busy` alone did not do it either — it is a _global_ ARIA state so it IS valid on the role-less span and browsers expose it, but no mainstream screen reader reliably conveys `busy` on a non-live element, and the `…` is `aria-hidden`. The label reached the user; the state did not. A linked chip's name becomes `"Appointment (loading)"`. **The trade:** the accessible name changes when loading resolves. Announcing a transient state through the name always costs that; the alternative is a consumer-owned `aria-live` region, since only the consumer knows whether a chip resolving is worth interrupting for. Override the word to `''` **at your top-level provider** if you'd rather handle it yourself — a nested `I18nProvider` replaces its parent rather than extending it, so wrapping a single chip would discard every other override you have set.
|
|
82
|
+
- **`unavailable` is announced, not just muted.** A localized word is rendered visually hidden inside the chip. A **linked** chip's accessible name becomes `"Appointment (unavailable)"`; a **target-less** chip is `role=generic`, which has no accessible name at all, so the word is announced as part of the chip's text in reading order. Either way it reaches the user.
|
|
83
|
+
- Why `aria-disabled` was not enough: browsers do expose it, but it carries no meaning on a non-widget role such as `generic`, so no assistive tech conveys it. This matters because the canonical use is to withhold the entity's name and show a TYPE word instead — without the state, a masked reference is indistinguishable from a real entity that happens to be called "Appointment".
|
|
84
|
+
- ❌ Don't put an `aria-label` on the chip — it replaces the whole name and takes the state word with it. The state lives in the chip's contents. Override the word via `<I18nProvider overrides={{ entityChip: { unavailable: '…' } }}>` instead; it carries its own punctuation so a locale can pick different marks.
|
|
85
|
+
- **`truncate`** — single-line mode for list rows: the chip caps at its container (`max-width: 100%`, `min-width: 0`) and only `label` ellipsizes; `icon`/`prefix`/`status`/`trailing` keep full size. The accessible name keeps the full label. Default wraps — right for chips in running text, so don't set `truncate` there.
|
|
86
|
+
- **`trailing`** — adornments inside the chip after `status` (a priority icon, a `<Badge>`), full size under `truncate`, not rendered while `loading`. Its text JOINS the link's name (`aria-hidden` a decorative icon). ❌ Never interactive content — the chip is a link; row actions go beside it.
|
|
87
|
+
- Hover affordance on link/button chips: the background deepens a step plus a brightness dip. Never a weight change, never an underline, even under aggressive consumer link CSS.
|
|
88
|
+
- Chip text inherits the surrounding font size — inside a heading it renders at heading size, by design (that's what keeps the chip box symmetric around the local text in any context).
|
|
89
|
+
- **Segments** (`before` / `after`): coloured parts butted against the chip — `{ kind: 'icon', icon, label, color?, size? }` (label = accessible name + tooltip) or `{ kind: 'text', text, color?, tooltip?, size? }`; `size` is in em of the chip text, at most 1 (larger is clamped, so a segment never makes the chip taller or knocks its text off the label's baseline); glyph default 0.85em, text default 0.9em. The whole chip stays one link; every segment joins its name. Any segment makes the chip one line (only the label shrinks) with only the outer corners rounded. Not rendered while `loading`/`unavailable`. `labelMaxWidth` (ch) caps the label in running text; a clipped label shows its full text in a tooltip on hover or keyboard focus. That text is always plain; a non-string `label` is read when the tooltip opens, so it can show old text if the label changes while the tooltip is open. `labelEllipsis="start"` cuts a clipped label from its START (`…/pull/1116`) for labels whose tail is the distinctive part, e.g. a URL path under a host `prefix`; default `'end'`. Ignored on a chip whose label can't clip.
|
|
90
|
+
- **A text segment's text sits on the label's baseline, not centred**: the segment's own box keeps the chip's font-size/line-height (so its box and first-line baseline match the core exactly); the smaller `--entity-chip-segment-text-size` lives on an inner span instead, which then sits on that baseline through normal inline layout. Icon (glyph) segments stay vertically centred, as before — only text segments changed.
|
|
91
|
+
- **The clipped-label tooltip is always plain text**: it reads the label element's own `textContent` when it opens, not the `label` node itself — so a styled `label` (e.g. a `<Text tone="accent">`) never leaks its color/weight into the tooltip. No prop controls this; it's automatic.
|
|
92
|
+
- **`labelWeight`**: `'medium'` (default, matches a plain chip / the RichText `@mention`) applies to `label` only — `prefix` has no weight rule of its own and stays inherited (normal). `'semibold'` is the one value that also touches `prefix`, setting BOTH `prefix` and `label` together (a heavier key + title, e.g. a segmented task chip). Backed by a component token (`--entity-chip-label-font-weight-semibold`), not by wrapping `label` in a styled `<Text>` — see the anti-pattern below.
|
|
93
|
+
- **When NOT to use**: plain status with no linked entity → `<Badge>`/`<PillMenu>`; standalone navigation with no icon/prefix/status chrome → `<Link>`; removable filter pills → `<FilterChip>`.
|
|
94
|
+
- **Anti-pattern**: nesting a `<Badge>` inside another `<Badge>` to fake an entity-with-status chip — `EntityChip` replaces that composition. `status.color` and the chip's own `color` are `PaletteColor` names, never raw hex strings. Omitting a link target (`href`/`as`) is also an anti-pattern — an EntityChip should link to its entity. Nesting `<IconTile>`/`<Badge>` in `icon`/`trailing` to fake coloured parts is also an anti-pattern — use `before`/`after` segments instead. Wrapping `label` in a styled `<Text weight="semibold">` to get a heavier title is also an anti-pattern — use `labelWeight="semibold"`; it buys nothing anyway, since the clipped-label tooltip always renders the label's plain text regardless of how `label` is styled.
|
|
95
|
+
- ❌ Block-level children (e.g. a `<div>`) inside `label` / `prefix` — the inline-safety contract requires span-only content.
|
|
96
|
+
- ❌ An icon segment without a meaningful `label` — it is the segment's accessible name; a decorative glyph belongs in `icon`, not a segment.
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
// Loading / unavailable — still live links with a target
|
|
100
|
+
<EntityChip href="/contacts/7" label="Contact" loading />
|
|
101
|
+
<EntityChip href="/contacts/9" label="Deleted contact" unavailable />
|
|
102
|
+
```
|