frappe-ui 1.0.0-beta.2 → 1.0.0-beta.21
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/experimental/FloatingWindow/FloatingWindow.cy.ts +328 -0
- package/experimental/FloatingWindow/FloatingWindow.vue +303 -0
- package/experimental/FloatingWindow/index.ts +8 -0
- package/experimental/FloatingWindow/types.ts +31 -0
- package/experimental/FloatingWindow/useFloatingWindow.ts +236 -0
- package/experimental/MultiEmailInput/MultiEmailInput.cy.ts +155 -0
- package/experimental/MultiEmailInput/MultiEmailInput.vue +472 -0
- package/experimental/MultiEmailInput/index.ts +17 -0
- package/experimental/MultiEmailInput/stories/AsyncSuggestions.vue +54 -0
- package/experimental/MultiEmailInput/stories/Basic.vue +18 -0
- package/experimental/MultiEmailInput/stories/CustomChip.vue +39 -0
- package/experimental/MultiEmailInput/stories/Labeling.vue +28 -0
- package/experimental/MultiEmailInput/types.ts +138 -0
- package/experimental/MultiEmailInput/utils.ts +60 -0
- package/experimental.ts +12 -0
- package/frappe/Billing/SignupBanner.vue +1 -1
- package/frappe/Billing/TrialBanner.vue +1 -1
- package/frappe/DataImport/DataImport.vue +1 -1
- package/frappe/DataImport/DataImportList.vue +1 -1
- package/frappe/DataImport/ImportSteps.vue +6 -6
- package/frappe/DataImport/MappingStep.vue +1 -1
- package/frappe/DataImport/PreviewStep.vue +9 -9
- package/frappe/DataImport/TemplateModal.vue +1 -1
- package/frappe/DataImport/UploadStep.vue +5 -5
- package/frappe/Filter/Filter.vue +1 -1
- package/frappe/Help/HelpModal.vue +1 -1
- package/frappe/Link/stories/Suffix.vue +2 -2
- package/frappe/Onboarding/GettingStartedBanner.vue +1 -1
- package/frappe/drive/components/AppSwitcher.vue +1 -1
- package/frappe/drive/components/InfoDialog.vue +3 -3
- package/frappe/drive/components/MoveDialog.vue +2 -2
- package/frappe/drive/components/Select/Select.vue +2 -2
- package/frappe/drive/components/ShareDialog.vue +1 -1
- package/frappe/telemetry/index.ts +88 -14
- package/frappe/telemetry/pulse.ts +78 -164
- package/frappe/telemetry/telemetry.test.ts +13 -79
- package/icons/IconPicker.vue +1 -1
- package/package.json +104 -34
- package/src/components/Alert/Alert.md +4 -0
- package/src/components/Alert/Alert.vue +4 -4
- package/src/components/Autocomplete/Autocomplete.vue +6 -6
- package/src/components/Avatar/Avatar.md +4 -0
- package/src/components/Avatar/Avatar.vue +23 -4
- package/src/components/Badge/Badge.api.md +1 -1
- package/src/components/Badge/Badge.cy.ts +34 -16
- package/src/components/Badge/Badge.md +20 -4
- package/src/components/Badge/Badge.vue +60 -45
- package/src/components/Badge/stories/CallMeta.vue +35 -0
- package/src/components/Badge/stories/EventStatus.vue +16 -0
- package/src/components/Badge/stories/ListStatus.vue +91 -0
- package/src/components/Badge/stories/Reactions.vue +33 -0
- package/src/components/Badge/stories/RowTags.vue +39 -0
- package/src/components/Badge/types.ts +1 -2
- package/src/components/BottomSheet/BottomSheet.api.md +57 -0
- package/src/components/BottomSheet/BottomSheet.vue +232 -0
- package/src/components/BottomSheet/index.ts +6 -0
- package/src/components/BottomSheet/types.ts +23 -0
- package/src/components/Breadcrumbs/Breadcrumbs.md +4 -0
- package/src/components/Breadcrumbs/Breadcrumbs.vue +3 -3
- package/src/components/Button/Button.api.md +37 -32
- package/src/components/Button/Button.cy.ts +18 -2
- package/src/components/Button/Button.md +20 -8
- package/src/components/Button/Button.vue +304 -284
- package/src/components/Button/stories/InlineActions.vue +10 -0
- package/src/components/Button/stories/LiveClassCard.vue +34 -0
- package/src/components/Button/stories/SectionAction.vue +17 -0
- package/src/components/Button/stories/SectionControls.vue +28 -0
- package/src/components/Button/stories/SelectionToolbar.vue +20 -0
- package/src/components/Button/stories/StackedActions.vue +10 -0
- package/src/components/Button/types.ts +38 -32
- package/src/components/Calendar/Calendar.api.md +16 -16
- package/src/components/Calendar/Calendar.vue +100 -73
- package/src/components/Calendar/CalendarDaily.vue +21 -20
- package/src/components/Calendar/CalendarMonthEvent.vue +30 -9
- package/src/components/Calendar/CalendarMonthly.vue +60 -39
- package/src/components/Calendar/CalendarTimeMarker.vue +9 -8
- package/src/components/Calendar/CalendarWeekDayEvent.vue +98 -42
- package/src/components/Calendar/CalendarWeekly.vue +77 -41
- package/src/components/Calendar/EventModalContent.vue +32 -16
- package/src/components/Calendar/NewEventModal.vue +19 -16
- package/src/components/Calendar/ShowMoreCalendarEvent.vue +11 -17
- package/src/components/Calendar/{calendarUtils.js → calendarUtils.ts} +76 -52
- package/src/components/Calendar/composables/{useCalendarData.js → useCalendarData.ts} +23 -11
- package/src/components/Calendar/composables/{useEventModal.js → useEventModal.ts} +16 -12
- package/src/components/Calendar/index.ts +12 -2
- package/src/components/Calendar/stories/CustomHeader.vue +1 -1
- package/src/components/Calendar/types.ts +106 -0
- package/src/components/Calendar/{useEventBase.js → useEventBase.ts} +40 -26
- package/src/components/Card.vue +2 -2
- package/src/components/Charts/ECharts.vue +1 -1
- package/src/components/Charts/NumberChart.vue +7 -7
- package/src/components/Charts/eChartOptions.ts +28 -13
- package/src/components/Checkbox/Checkbox.api.md +6 -0
- package/src/components/Checkbox/Checkbox.cy.ts +10 -2
- package/src/components/Checkbox/Checkbox.md +28 -0
- package/src/components/Checkbox/Checkbox.vue +9 -22
- package/src/components/Checkbox/stories/Group.vue +27 -0
- package/src/components/Checkbox/stories/HorizontalGroup.vue +24 -0
- package/src/components/Checkbox/stories/SettingRow.vue +23 -0
- package/src/components/Checkbox/stories/WithDescription.vue +27 -0
- package/src/components/Checkbox/types.ts +7 -0
- package/src/components/CodeEditor/CodeEditor.api.md +139 -0
- package/src/components/CodeEditor/CodeEditor.cy.ts +160 -0
- package/src/components/CodeEditor/CodeEditor.md +104 -0
- package/src/components/CodeEditor/CodeEditor.vue +556 -0
- package/src/components/CodeEditor/CodePreview.test.ts +49 -0
- package/src/components/CodeEditor/CodePreview.vue +45 -0
- package/src/components/CodeEditor/index.ts +17 -0
- package/src/components/CodeEditor/languages.ts +63 -0
- package/src/components/CodeEditor/stories/Default.vue +16 -0
- package/src/components/CodeEditor/stories/Labeling.vue +25 -0
- package/src/components/CodeEditor/stories/MaxHeight.vue +24 -0
- package/src/components/CodeEditor/stories/Preview.vue +36 -0
- package/src/components/CodeEditor/stories/Sizes.vue +15 -0
- package/src/components/CodeEditor/stories/Variants.vue +13 -0
- package/src/components/CodeEditor/theme.ts +272 -0
- package/src/components/CodeEditor/types.ts +69 -0
- package/src/components/Combobox/Combobox.api.md +19 -20
- package/src/components/Combobox/Combobox.cy.ts +54 -14
- package/src/components/Combobox/Combobox.md +4 -0
- package/src/components/Combobox/Combobox.vue +233 -247
- package/src/components/Combobox/ComboboxResults.vue +1 -1
- package/src/components/Combobox/stories/Clearable.vue +2 -2
- package/src/components/Combobox/stories/CreateNew.vue +1 -1
- package/src/components/Combobox/stories/Footer.vue +10 -2
- package/src/components/Combobox/stories/InDialog.vue +1 -1
- package/src/components/Combobox/types.ts +8 -29
- package/src/components/CommandPalette/CommandPaletteItem.vue +1 -1
- package/src/components/ContextMenu/ContextMenu.api.md +52 -0
- package/src/components/ContextMenu/ContextMenu.cy.ts +191 -0
- package/src/components/ContextMenu/ContextMenu.md +25 -0
- package/src/components/ContextMenu/ContextMenu.vue +106 -0
- package/src/components/ContextMenu/index.ts +2 -0
- package/src/components/ContextMenu/stories/FileList.vue +105 -0
- package/src/components/ContextMenu/stories/Groups.vue +95 -0
- package/src/components/ContextMenu/stories/Simple.vue +72 -0
- package/src/components/ContextMenu/types.ts +39 -0
- package/src/components/DatePicker/CalendarPanel.vue +128 -86
- package/src/components/DatePicker/DatePicker.vue +3 -9
- package/src/components/DatePicker/DateRangePicker.vue +4 -8
- package/src/components/DatePicker/DateTimePicker.cy.ts +4 -2
- package/src/components/DatePicker/DateTimePicker.vue +3 -9
- package/src/components/DatePicker/composables.ts +15 -37
- package/src/components/DatePicker/stories/Range.vue +1 -1
- package/src/components/DatePicker/types.ts +1 -1
- package/src/components/DesktopShell/DesktopShell.api.md +40 -0
- package/src/components/DesktopShell/DesktopShell.cy.ts +39 -0
- package/src/components/DesktopShell/DesktopShell.md +31 -0
- package/src/components/DesktopShell/DesktopShell.vue +81 -0
- package/src/components/DesktopShell/index.ts +3 -0
- package/src/components/DesktopShell/stories/Default.vue +97 -0
- package/src/components/DesktopShell/types.ts +2 -0
- package/src/components/Dialog/Dialog.api.md +7 -8
- package/src/components/Dialog/Dialog.md +4 -0
- package/src/components/Dialog/Dialog.vue +8 -7
- package/src/components/Dialog/stories/CommandPalette.vue +1 -1
- package/src/components/Dialog/stories/Wizard.vue +1 -1
- package/src/components/Dialogs.vue +11 -9
- package/src/components/Divider/Divider.api.md +1 -1
- package/src/components/Divider/Divider.md +4 -0
- package/src/components/Dropdown/Dropdown.api.md +10 -35
- package/src/components/Dropdown/Dropdown.md +10 -6
- package/src/components/Dropdown/Dropdown.vue +33 -47
- package/src/components/Dropdown/stories/{05_KebabMenu.vue → KebabMenu.vue} +3 -1
- package/src/components/Dropdown/stories/{06_UserMenu.vue → UserMenu.vue} +1 -1
- package/src/components/Dropdown/types.ts +25 -189
- package/src/components/Duration/Duration.api.md +92 -0
- package/src/components/Duration/Duration.cy.ts +183 -0
- package/src/components/Duration/Duration.md +98 -0
- package/src/components/Duration/Duration.vue +114 -0
- package/src/components/Duration/duration.ts +185 -0
- package/src/components/Duration/index.ts +8 -0
- package/src/components/Duration/stories/Default.vue +10 -0
- package/src/components/Duration/stories/Formats.vue +16 -0
- package/src/components/Duration/stories/RealWorld.vue +50 -0
- package/src/components/Duration/stories/Sizes.vue +15 -0
- package/src/components/Duration/stories/States.vue +21 -0
- package/src/components/Duration/types.ts +52 -0
- package/src/components/ErrorMessage/ErrorMessage.cy.ts +1 -1
- package/src/components/ErrorMessage/ErrorMessage.md +4 -0
- package/src/components/ErrorMessage/ErrorMessage.vue +1 -1
- package/src/components/FileUploader/FileUploader.api.md +36 -11
- package/src/components/FileUploader/FileUploader.cy.ts +66 -0
- package/src/components/FileUploader/FileUploader.md +4 -1
- package/src/components/FileUploader/FileUploader.vue +147 -106
- package/src/components/FileUploader/index.ts +6 -0
- package/src/components/FileUploader/types.ts +43 -0
- package/src/components/FormControl/FormControl.api.md +3 -4
- package/src/components/FormControl/FormControl.md +4 -0
- package/src/components/FormControl/stories/RealForm.vue +3 -3
- package/src/components/FormLabel.vue +5 -8
- package/src/components/HoverCard/HoverCard.api.md +100 -0
- package/src/components/HoverCard/HoverCard.cy.ts +103 -0
- package/src/components/HoverCard/HoverCard.md +52 -0
- package/src/components/HoverCard/HoverCard.vue +91 -0
- package/src/components/HoverCard/index.ts +2 -0
- package/src/components/HoverCard/stories/Arrow.vue +28 -0
- package/src/components/HoverCard/stories/Delays.vue +16 -0
- package/src/components/HoverCard/stories/Example.vue +28 -0
- package/src/components/HoverCard/types.ts +47 -0
- package/src/components/Icon/Icon.cy.ts +78 -0
- package/src/components/Icon/Icon.vue +50 -0
- package/src/components/Icon/index.ts +1 -0
- package/src/components/InputLabeling/InputDescription.vue +1 -1
- package/src/components/InputLabeling/InputError.vue +1 -1
- package/src/components/InputLabeling/InputLabel.vue +21 -7
- package/src/components/InputLabeling/RequiredIndicator.vue +1 -1
- package/src/components/ItemListRow/ItemListRow.vue +1 -1
- package/src/components/ItemListRow/stories/RowStates.vue +1 -1
- package/src/components/KeyboardShortcut.vue +4 -8
- package/src/components/KeyboardShortcutsModal/KeyboardShortcutsModal.api.md +22 -14
- package/src/components/KeyboardShortcutsModal/KeyboardShortcutsModal.vue +2 -2
- package/src/components/ListFilter/ListFilter.api.md +5 -6
- package/src/components/ListFilter/ListFilter.vue +161 -57
- package/src/components/ListFilter/NestedPopover.vue +17 -10
- package/src/components/ListFilter/SearchComplete.vue +31 -38
- package/src/components/ListItem.vue +1 -1
- package/src/components/ListView/ListEmptyState.vue +1 -1
- package/src/components/ListView/ListGroupHeader.vue +2 -2
- package/src/components/ListView/ListRow.vue +1 -1
- package/src/components/ListView/ListSelectBanner.vue +1 -1
- package/src/components/ListView/ListView.api.md +322 -6
- package/src/components/ListView/index.ts +25 -0
- package/src/components/ListView/stories/CustomList.vue +1 -1
- package/src/components/ListView/stories/GroupedRows.vue +1 -1
- package/src/components/LoadingIndicator.vue +13 -22
- package/src/components/LoadingText.vue +3 -13
- package/src/components/{Dropdown/DropdownMenuList.vue → Menu/Menu.vue} +110 -75
- package/src/components/{Dropdown/DropdownMenuItemContent.vue → Menu/MenuItemContent.vue} +23 -33
- package/src/components/{Dropdown/DropdownRenderContent.vue → Menu/MenuRenderContent.vue} +1 -1
- package/src/components/Menu/types.ts +225 -0
- package/src/components/{Dropdown → Menu}/utils.ts +36 -40
- package/src/components/MobileNav/MobileNav.api.md +70 -0
- package/src/components/MobileNav/MobileNav.cy.ts +89 -0
- package/src/components/MobileNav/MobileNav.md +34 -0
- package/src/components/MobileNav/MobileNav.vue +15 -0
- package/src/components/MobileNav/MobileNavItem.vue +125 -0
- package/src/components/MobileNav/index.ts +4 -0
- package/src/components/MobileNav/stories/Default.vue +40 -0
- package/src/components/MobileNav/types.ts +33 -0
- package/src/components/MobileShell/MobileShell.api.md +23 -0
- package/src/components/MobileShell/MobileShell.cy.ts +25 -0
- package/src/components/MobileShell/MobileShell.md +24 -0
- package/src/components/MobileShell/MobileShell.vue +41 -0
- package/src/components/MobileShell/index.ts +3 -0
- package/src/components/MobileShell/stories/Default.vue +75 -0
- package/src/components/MobileShell/types.ts +7 -0
- package/src/components/MonthPicker/MonthPicker.cy.ts +16 -0
- package/src/components/MonthPicker/MonthPicker.vue +19 -8
- package/src/components/MultiSelect/MultiSelect.api.md +3 -4
- package/src/components/MultiSelect/MultiSelect.md +42 -10
- package/src/components/MultiSelect/MultiSelect.vue +199 -227
- package/src/components/MultiSelect/MultiSelectResults.vue +1 -1
- package/src/components/MultiSelect/stories/Members.vue +1 -1
- package/src/components/MultiSelect/stories/TagsTrigger.vue +3 -3
- package/src/components/MultiSelect/types.ts +3 -3
- package/src/components/PageHeader/PageHeader.api.md +112 -0
- package/src/components/PageHeader/PageHeader.cy.ts +68 -0
- package/src/components/PageHeader/PageHeader.md +25 -0
- package/src/components/PageHeader/PageHeader.vue +13 -0
- package/src/components/PageHeader/PageHeaderBackButton.vue +29 -0
- package/src/components/PageHeader/PageHeaderBase.vue +51 -0
- package/src/components/PageHeader/PageHeaderMobile.vue +68 -0
- package/src/components/PageHeader/PageHeaderMobileTitle.vue +16 -0
- package/src/components/PageHeader/PageHeaderTarget.vue +13 -0
- package/src/components/PageHeader/PageHeaderTitle.vue +12 -0
- package/src/components/PageHeader/index.ts +7 -0
- package/src/components/PageHeader/stories/Default.vue +19 -0
- package/src/components/PageHeader/stories/Mobile.vue +24 -0
- package/src/components/PageHeader/target.ts +19 -0
- package/src/components/PageHeader/types.ts +19 -0
- package/src/components/Password/Password.md +4 -0
- package/src/components/Password/Password.vue +2 -2
- package/src/components/Popover/Popover.api.md +126 -42
- package/src/components/Popover/Popover.cy.ts +425 -41
- package/src/components/Popover/Popover.md +99 -4
- package/src/components/Popover/Popover.vue +288 -215
- package/src/components/Popover/index.ts +8 -1
- package/src/components/Popover/stories/Arrow.vue +16 -0
- package/src/components/Popover/stories/Bare.vue +20 -0
- package/src/components/Popover/stories/Click.vue +7 -4
- package/src/components/Popover/stories/Controlled.vue +22 -0
- package/src/components/Popover/stories/Dismissible.vue +19 -0
- package/src/components/Popover/stories/MatchTriggerWidth.vue +16 -0
- package/src/components/Popover/stories/SideAlign.vue +17 -0
- package/src/components/Popover/types.ts +101 -23
- package/src/components/Progress/Progress.cy.ts +2 -2
- package/src/components/Progress/Progress.md +4 -0
- package/src/components/Progress/Progress.vue +4 -4
- package/src/components/Rail/Rail.api.md +91 -0
- package/src/components/Rail/Rail.cy.ts +84 -0
- package/src/components/Rail/Rail.md +30 -0
- package/src/components/Rail/Rail.vue +16 -0
- package/src/components/Rail/RailItem.vue +134 -0
- package/src/components/Rail/RailItemBadge.vue +64 -0
- package/src/components/Rail/index.ts +2 -0
- package/src/components/Rail/stories/Default.vue +44 -0
- package/src/components/Rail/types.ts +37 -0
- package/src/components/Rating/Rating.md +4 -0
- package/src/components/Rating/Rating.vue +5 -8
- package/src/components/Rating/stories/CustomSlot.vue +2 -2
- package/src/components/ScrollArea/ScrollArea.api.md +59 -0
- package/src/components/ScrollArea/ScrollArea.vue +46 -0
- package/src/components/ScrollArea/ScrollBar.vue +101 -0
- package/src/components/ScrollArea/index.ts +2 -0
- package/src/components/Select/Select.cy.ts +16 -15
- package/src/components/Select/Select.md +4 -0
- package/src/components/Select/Select.vue +217 -203
- package/src/components/Select/stories/Example.vue +4 -3
- package/src/components/Select/stories/States.vue +1 -1
- package/src/components/Select/stories/TriggerSlots.vue +2 -2
- package/src/components/Select/utils.ts +4 -3
- package/src/components/SettingsDialog/SettingsBody.vue +23 -0
- package/src/components/SettingsDialog/SettingsContent.vue +7 -0
- package/src/components/SettingsDialog/SettingsDialog.api.md +273 -0
- package/src/components/SettingsDialog/SettingsDialog.cy.ts +126 -0
- package/src/components/SettingsDialog/SettingsDialog.md +43 -0
- package/src/components/SettingsDialog/SettingsDialog.vue +76 -0
- package/src/components/SettingsDialog/SettingsHeader.vue +36 -0
- package/src/components/SettingsDialog/SettingsNavGroup.vue +20 -0
- package/src/components/SettingsDialog/SettingsNavItem.vue +33 -0
- package/src/components/SettingsDialog/SettingsPanel.cy.ts +77 -0
- package/src/components/SettingsDialog/SettingsPanel.vue +26 -0
- package/src/components/SettingsDialog/SettingsRow.vue +52 -0
- package/src/components/SettingsDialog/SettingsSidebar.vue +16 -0
- package/src/components/SettingsDialog/index.ts +10 -0
- package/src/components/SettingsDialog/stories/Default.vue +99 -0
- package/src/components/SettingsDialog/stories/PanelBasic.vue +52 -0
- package/src/components/SettingsDialog/stories/panels/NotificationsPanel.vue +57 -0
- package/src/components/SettingsDialog/stories/panels/PreferencesPanel.vue +57 -0
- package/src/components/SettingsDialog/stories/panels/ProfilePanel.vue +38 -0
- package/src/components/SettingsDialog/stories/panels/UsersPanel.vue +83 -0
- package/src/components/SettingsDialog/types.ts +21 -0
- package/src/components/Sidebar/Sidebar.api.md +124 -65
- package/src/components/Sidebar/Sidebar.cy.ts +127 -76
- package/src/components/Sidebar/Sidebar.md +47 -3
- package/src/components/Sidebar/Sidebar.vue +64 -56
- package/src/components/Sidebar/SidebarCollapseToggle.vue +23 -0
- package/src/components/Sidebar/SidebarHeader.vue +76 -52
- package/src/components/Sidebar/SidebarItem.vue +159 -95
- package/src/components/Sidebar/SidebarItemIcon.vue +25 -0
- package/src/components/Sidebar/SidebarLabel.vue +34 -0
- package/src/components/Sidebar/SidebarSection.vue +29 -14
- package/src/components/Sidebar/index.ts +13 -2
- package/src/components/Sidebar/stories/Collapsed.vue +40 -0
- package/src/components/Sidebar/stories/Default.vue +153 -0
- package/src/components/Sidebar/stories/Legacy.vue +36 -0
- package/src/components/Sidebar/types.ts +105 -20
- package/src/components/Skeleton/Skeleton.cy.ts +21 -0
- package/src/components/Skeleton/Skeleton.md +21 -0
- package/src/components/Skeleton/Skeleton.vue +6 -0
- package/src/components/Skeleton/index.ts +1 -0
- package/src/components/Skeleton/stories/Card.vue +12 -0
- package/src/components/Skeleton/stories/List.vue +15 -0
- package/src/components/Skeleton/stories/Text.vue +11 -0
- package/src/components/Slider/Slider.api.md +1 -1
- package/src/components/Slider/Slider.cy.ts +29 -0
- package/src/components/Slider/Slider.md +10 -0
- package/src/components/Slider/Slider.vue +37 -9
- package/src/components/Slider/stories/NegativeValues.vue +12 -0
- package/src/components/Slider/types.ts +1 -1
- package/src/components/Spinner/Spinner.api.md +32 -0
- package/src/components/Spinner/Spinner.cy.ts +87 -0
- package/src/components/Spinner/Spinner.md +21 -0
- package/src/components/Spinner/Spinner.vue +168 -0
- package/src/components/Spinner/index.ts +2 -0
- package/src/components/Spinner/stories/InContext.vue +49 -0
- package/src/components/Spinner/stories/Sizes.vue +12 -0
- package/src/components/Spinner/stories/Themes.vue +10 -0
- package/src/components/Spinner/stories/Track.vue +12 -0
- package/src/components/Spinner/types.ts +14 -0
- package/src/components/Switch/Switch.md +4 -0
- package/src/components/Switch/Switch.vue +6 -23
- package/src/components/TabButtons/Pill.vue +161 -0
- package/src/components/TabButtons/TabButtons.api.md +52 -2
- package/src/components/TabButtons/TabButtons.cy.ts +18 -5
- package/src/components/TabButtons/TabButtons.md +49 -0
- package/src/components/TabButtons/TabButtons.vue +207 -109
- package/src/components/TabButtons/index.ts +11 -1
- package/src/components/TabButtons/pillTypes.ts +43 -0
- package/src/components/TabButtons/stories/PrefixSuffix.vue +65 -0
- package/src/components/TabButtons/stories/Sizes.vue +26 -0
- package/src/components/TabButtons/stories/Variants.vue +40 -0
- package/src/components/TabButtons/stories/Vertical.vue +64 -0
- package/src/components/TabButtons/types.ts +49 -0
- package/src/components/Tabs/Tabs.md +4 -0
- package/src/components/Tabs/Tabs.vue +1 -1
- package/src/components/TextEditor/TextEditor.cy.ts +1 -1
- package/src/components/TextEditor/TextEditor.md +3 -0
- package/src/components/TextEditor/TextEditor.vue +7 -4
- package/src/components/TextEditor/components/CodeBlockComponent.vue +4 -194
- package/src/components/TextEditor/components/FontColor.vue +1 -1
- package/src/components/TextEditor/components/LinkPopup.vue +1 -1
- package/src/components/TextEditor/components/MediaNodeView.vue +17 -17
- package/src/components/TextEditor/components/MentionList.vue +1 -1
- package/src/components/TextEditor/components/TextEditorBubbleMenu.vue +14 -5
- package/src/components/TextEditor/components/TextEditorFixedMenu.vue +3 -3
- package/src/components/TextEditor/components/{Menu.vue → TextEditorMenu.vue} +3 -3
- package/src/components/TextEditor/extensions/iframe/InsertIframe.vue +2 -2
- package/src/components/TextEditor/extensions/iframe/iframe-extension.ts +62 -19
- package/src/components/TextEditor/extensions/image-group/ImageGroupNodeView.vue +1 -1
- package/src/components/TextEditor/extensions/image-group/ImageGroupUploadDialog.vue +4 -4
- package/src/components/TextEditor/extensions/suggestion/SuggestionList.vue +1 -1
- package/src/components/TextEditor/extensions/toc-node/TocNodeView.vue +1 -1
- package/src/components/TextEditor/hljs-github.css +197 -0
- package/src/components/TextEditor/index.ts +13 -0
- package/src/components/TextInput/TextInput.cy.ts +8 -3
- package/src/components/TextInput/TextInput.md +4 -0
- package/src/components/TextInput/TextInput.vue +11 -15
- package/src/components/TextInput/stories/Slots.vue +1 -1
- package/src/components/Textarea/Textarea.cy.ts +1 -1
- package/src/components/Textarea/Textarea.md +4 -0
- package/src/components/Textarea/Textarea.vue +11 -15
- package/src/components/ThemeSwitcher/ThemePreview.vue +74 -0
- package/src/components/ThemeSwitcher/ThemeSwitcher.api.md +82 -0
- package/src/components/ThemeSwitcher/ThemeSwitcher.cy.ts +101 -0
- package/src/components/ThemeSwitcher/ThemeSwitcher.md +70 -0
- package/src/components/ThemeSwitcher/ThemeSwitcher.vue +145 -0
- package/src/components/ThemeSwitcher/index.ts +2 -0
- package/src/components/ThemeSwitcher/previews/PreviewWindow.vue +74 -0
- package/src/components/ThemeSwitcher/stories/Branded.vue +12 -0
- package/src/components/ThemeSwitcher/stories/Default.vue +7 -0
- package/src/components/ThemeSwitcher/stories/Menu.vue +53 -0
- package/src/components/ThemeSwitcher/stories/Toggle.vue +25 -0
- package/src/components/ThemeSwitcher/types.ts +35 -0
- package/src/components/TimePicker/TimePicker.api.md +67 -15
- package/src/components/TimePicker/TimePicker.cy.ts +130 -14
- package/src/components/TimePicker/TimePicker.md +6 -0
- package/src/components/TimePicker/TimePicker.vue +74 -19
- package/src/components/TimePicker/stories/Labeling.vue +21 -0
- package/src/components/TimePicker/stories/Range.vue +1 -1
- package/src/components/TimePicker/stories/SizesAndVariants.vue +23 -0
- package/src/components/TimePicker/stories/TwentyFour.vue +1 -1
- package/src/components/TimePicker/types.ts +15 -3
- package/src/components/TimePicker/utils.ts +82 -21
- package/src/components/Toast/Toast.md +1 -1
- package/src/components/Toast/Toast.sanitize.test.ts +50 -0
- package/src/components/Toast/Toast.test.ts +5 -0
- package/src/components/Toast/Toast.vue +7 -7
- package/src/components/Toast/ToastProvider.vue +18 -9
- package/src/components/Toast/stories/CustomIcon.vue +1 -1
- package/src/components/Toast/toast.ts +32 -8
- package/src/components/Tooltip/Tooltip.api.md +43 -5
- package/src/components/Tooltip/Tooltip.cy.ts +48 -0
- package/src/components/Tooltip/Tooltip.md +10 -0
- package/src/components/Tooltip/Tooltip.vue +20 -5
- package/src/components/Tooltip/TooltipBubble.vue +2 -2
- package/src/components/Tooltip/TooltipProvider.vue +53 -0
- package/src/components/Tooltip/index.ts +1 -0
- package/src/components/Tooltip/stories/Group.vue +22 -0
- package/src/components/Tooltip/stories/Slots.vue +2 -2
- package/src/components/Tooltip/types.ts +1 -1
- package/src/components/Tree/Tree.api.md +76 -18
- package/src/components/Tree/Tree.md +144 -2
- package/src/components/Tree/Tree.vue +276 -97
- package/src/components/Tree/TreeItem.vue +263 -0
- package/src/components/Tree/index.ts +9 -1
- package/src/components/Tree/stories/DragDrop.vue +94 -0
- package/src/components/Tree/stories/Example.vue +11 -34
- package/src/components/Tree/stories/ExpandAll.vue +48 -0
- package/src/components/Tree/stories/Guides.vue +49 -0
- package/src/components/Tree/stories/ListView.vue +74 -0
- package/src/components/Tree/tree.cy.ts +218 -90
- package/src/components/Tree/types.ts +114 -24
- package/src/components/Tree/useTreeDragDrop.ts +203 -0
- package/src/components/Tree/useTreeKeyboard.ts +109 -0
- package/src/components/VueGridLayout/Layout.vue +1 -1
- package/src/components/shared/picker/PickerShell.vue +20 -15
- package/src/components/shared/popover/PopoverPanel.vue +67 -0
- package/src/components/shared/popover/popoverPanel.css +102 -0
- package/src/components/shared/selection/utils.ts +6 -6
- package/src/composables/useAutofocusOnOpen.ts +2 -0
- package/src/composables/useScreenSize.ts +46 -0
- package/src/composables/useScrollContainer.ts +108 -0
- package/src/composables/useShortcut.ts +3 -0
- package/src/data-fetching/docStore.test.ts +74 -0
- package/src/data-fetching/docStore.ts +18 -7
- package/src/data-fetching/useCall/types.ts +1 -0
- package/src/data-fetching/useCall/useCall.test.ts +43 -0
- package/src/data-fetching/useCall/useCall.ts +17 -4
- package/src/data-fetching/useDoc/useDoc.test.ts +61 -2
- package/src/data-fetching/useDoc/useDoc.ts +35 -15
- package/src/data-fetching/useDoctype/useDoctype.ts +6 -5
- package/src/data-fetching/useFrappeFetch.ts +17 -4
- package/src/data-fetching/useList/types.ts +1 -0
- package/src/data-fetching/useList/useList.test.ts +40 -0
- package/src/data-fetching/useList/useList.ts +20 -13
- package/src/data-fetching/useNewDoc/useNewDoc.ts +9 -5
- package/src/directives/focus.ts +3 -3
- package/src/index.ts +105 -74
- package/src/mocks/handlers.ts +8 -0
- package/src/molecules/editor/Editor.cy.ts +6 -1
- package/src/molecules/editor/EditorBubbleMenu.vue +1 -1
- package/src/molecules/editor/EditorContent.vue +50 -9
- package/src/molecules/editor/EditorFixedMenu.vue +2 -1
- package/src/molecules/editor/EditorFloatingMenu.vue +1 -1
- package/src/molecules/editor/EditorTableMenu.vue +303 -0
- package/src/molecules/editor/MenuItems.vue +81 -69
- package/src/molecules/editor/commands.ts +10 -2
- package/src/molecules/editor/components/AttachmentNodeView.vue +115 -0
- package/src/molecules/editor/components/EditorDropZone.vue +105 -0
- package/src/molecules/editor/components/EditorPopover.vue +89 -0
- package/src/molecules/editor/components/MediaNodeView.vue +156 -49
- package/src/molecules/editor/components/MediaResizeHandles.vue +38 -0
- package/src/molecules/editor/components/MediaToolbar.vue +108 -54
- package/src/molecules/editor/components/TableContextMenu.vue +144 -0
- package/src/molecules/editor/components/UploadProgressIndicator.vue +33 -0
- package/src/molecules/editor/components/VideoControls.vue +208 -0
- package/src/molecules/editor/components/font-color/ColorSwatchGrid.vue +3 -5
- package/src/molecules/editor/components/font-color/fontColorController.ts +28 -23
- package/src/molecules/editor/components/font-color/swatches.ts +1 -1
- package/src/molecules/editor/components/media-node-view-controller.ts +4 -4
- package/src/molecules/editor/components/media-node-view-utils.test.ts +0 -13
- package/src/molecules/editor/components/media-node-view-utils.ts +0 -10
- package/src/molecules/editor/components/table-color/tableCellColorController.ts +80 -0
- package/src/molecules/editor/components/table-size-picker/TableSizePicker.vue +92 -0
- package/src/molecules/editor/components/table-size-picker/tableSizePickerController.ts +40 -0
- package/src/molecules/editor/composables/useEditorFileDrop.ts +117 -0
- package/src/molecules/editor/composables/useFloatingPopup.ts +46 -2
- package/src/molecules/editor/composables/useNodeViewResize.test.ts +60 -11
- package/src/molecules/editor/composables/useNodeViewResize.ts +80 -21
- package/src/molecules/editor/composables/useTableCellColorState.ts +78 -0
- package/src/molecules/editor/composables/useWindowFileDragging.ts +68 -0
- package/src/molecules/editor/extensions/attachment/attachment-engine.ts +250 -0
- package/src/molecules/editor/extensions/attachment/attachment-extension.ts +248 -0
- package/src/molecules/editor/extensions/attachment/attachment.flow.test.ts +80 -0
- package/src/molecules/editor/extensions/attachment/attachment.roundtrip.test.ts +50 -0
- package/src/molecules/editor/extensions/attachment/index.ts +5 -0
- package/src/molecules/editor/extensions/code-block/CodeBlockComponent.css +16 -26
- package/src/molecules/editor/extensions/code-block/CodeBlockComponent.vue +107 -22
- package/src/molecules/editor/extensions/content-paste/content-paste-extension.ts +5 -3
- package/src/molecules/editor/extensions/iframe/IframeInsertDialog.vue +34 -7
- package/src/molecules/editor/extensions/iframe/IframeNodeView.vue +54 -48
- package/src/molecules/editor/extensions/iframe/iframe-allowlist.ts +33 -4
- package/src/molecules/editor/extensions/iframe/iframe-commands.ts +49 -5
- package/src/molecules/editor/extensions/iframe/iframe-embed-utils.ts +30 -0
- package/src/molecules/editor/extensions/iframe/iframe-extension.ts +4 -4
- package/src/molecules/editor/extensions/iframe/iframeInsertDialogController.ts +12 -1
- package/src/molecules/editor/extensions/iframe/index.ts +4 -4
- package/src/molecules/editor/extensions/iframe/useIframeDialog.ts +25 -13
- package/src/molecules/editor/extensions/image/image-extension.ts +29 -11
- package/src/molecules/editor/extensions/image-group/ImageGroupGrid.vue +27 -11
- package/src/molecules/editor/extensions/image-group/ImageGroupGridCell.vue +55 -11
- package/src/molecules/editor/extensions/image-group/ImageGroupNodeView.vue +64 -31
- package/src/molecules/editor/extensions/image-group/ImageGroupUploadDialog.vue +84 -40
- package/src/molecules/editor/extensions/image-group/image-group-extension.ts +4 -3
- package/src/molecules/editor/extensions/image-group/useImageGroupDialog.ts +116 -17
- package/src/molecules/editor/extensions/link/LinkEditorPopup.vue +214 -71
- package/src/molecules/editor/extensions/link/link-click-plugin.ts +10 -15
- package/src/molecules/editor/extensions/link/link-commands.ts +24 -3
- package/src/molecules/editor/extensions/link/link-extension.ts +11 -2
- package/src/molecules/editor/extensions/link/link-popup-controller.test.ts +49 -0
- package/src/molecules/editor/extensions/link/link-popup-controller.ts +67 -2
- package/src/molecules/editor/extensions/link/link-shortcut-plugin.ts +7 -2
- package/src/molecules/editor/extensions/media-drop/media-drop-extension.ts +177 -0
- package/src/molecules/editor/extensions/shared/media-dimensions.ts +36 -3
- package/src/molecules/editor/extensions/shared/media-node-ops.ts +17 -0
- package/src/molecules/editor/extensions/shared/media-plugin.test.ts +60 -0
- package/src/molecules/editor/extensions/shared/media-plugin.ts +7 -37
- package/src/molecules/editor/extensions/shared/media-upload-engine.test.ts +39 -2
- package/src/molecules/editor/extensions/shared/media-upload-engine.ts +104 -10
- package/src/molecules/editor/extensions/shared/media-upload-state.ts +55 -0
- package/src/molecules/editor/extensions/shared/media-upload-types.ts +52 -1
- package/src/molecules/editor/extensions/shared/suggestion-helpers.ts +20 -0
- package/src/molecules/editor/extensions/shared/suggestion-types.ts +7 -0
- package/src/molecules/editor/extensions/shared/upload-types.ts +1 -0
- package/src/molecules/editor/extensions/slash-commands/slash-commands-extension.test.ts +38 -0
- package/src/molecules/editor/extensions/slash-commands/slash-commands-extension.ts +119 -55
- package/src/molecules/editor/extensions/suggestion/SuggestionList.vue +62 -22
- package/src/molecules/editor/extensions/suggestion/SuggestionListItem.vue +1 -1
- package/src/molecules/editor/extensions/suggestion/createSuggestionExtension.ts +4 -0
- package/src/molecules/editor/extensions/table/drag-scroll.ts +154 -0
- package/src/molecules/editor/extensions/table/table-cell-color.ts +188 -0
- package/src/molecules/editor/extensions/table/table-navigation.ts +560 -0
- package/src/molecules/editor/extensions/table/table-selection-overlay.ts +137 -0
- package/src/molecules/editor/extensions/toc-node/TocNodeView.vue +1 -1
- package/src/molecules/editor/extensions/toc-node/toc-render.ts +7 -3
- package/src/molecules/editor/extensions/video/video-extension.ts +72 -5
- package/src/molecules/editor/extensions.ts +176 -8
- package/src/molecules/editor/index.ts +9 -4
- package/src/molecules/editor/kits.test.ts +21 -1
- package/src/molecules/editor/kits.ts +56 -33
- package/src/molecules/editor/menu.test.ts +3 -1
- package/src/molecules/editor/menu.ts +180 -18
- package/src/molecules/editor/stories/Comment.vue +4 -4
- package/src/molecules/editor/stories/Inline.vue +1 -1
- package/src/molecules/editor/stories/Primitives.vue +1 -1
- package/src/molecules/editor/stories/RichText.vue +1 -1
- package/src/molecules/editor/style.css +80 -3
- package/src/molecules/editor/useEditor.test.ts +4 -0
- package/src/molecules/editor/useEditor.ts +7 -3
- package/src/molecules/list/List.cy.ts +626 -0
- package/src/molecules/list/List.vue +93 -0
- package/src/molecules/list/ListCell.vue +15 -0
- package/src/molecules/list/ListGroup.vue +40 -0
- package/src/molecules/list/ListHeader.vue +62 -0
- package/src/molecules/list/ListHeaderCell.vue +26 -0
- package/src/molecules/list/ListHeaderCellSort.vue +106 -0
- package/src/molecules/list/ListRow.vue +55 -0
- package/src/molecules/list/ListRowBase.vue +103 -0
- package/src/molecules/list/ListRows.vue +120 -0
- package/src/molecules/list/index.ts +24 -0
- package/src/molecules/list/list-context.ts +44 -0
- package/src/molecules/list/list.api.md +276 -0
- package/src/molecules/list/list.md +119 -0
- package/src/molecules/list/stories/Columns.vue +103 -0
- package/src/molecules/list/stories/Feed.vue +105 -0
- package/src/molecules/list/stories/Virtual.vue +31 -0
- package/src/molecules/list/style.css +173 -0
- package/src/molecules/list/types.ts +82 -0
- package/src/molecules/list/useVirtualRows.ts +80 -0
- package/src/resources/documentResource.d.ts +28 -0
- package/src/resources/documentResource.js +32 -4
- package/src/resources/documentResource.test.ts +111 -0
- package/src/resources/listResource.d.ts +33 -0
- package/src/resources/plugin.d.ts +7 -0
- package/src/resources/resources.d.ts +35 -0
- package/src/utils/{call.js → call.ts} +50 -9
- package/src/utils/config.ts +16 -1
- package/src/utils/confirmDialog.d.ts +17 -0
- package/src/utils/debounce.ts +6 -7
- package/src/utils/dialog.cy.ts +9 -9
- package/src/utils/fileSize.ts +36 -0
- package/src/utils/fileUploadHandler.ts +46 -6
- package/src/utils/frappeRequest.test.ts +79 -0
- package/src/utils/{frappeRequest.js → frappeRequest.ts} +76 -13
- package/src/utils/pageMeta.ts +1 -1
- package/src/utils/plugin.ts +58 -0
- package/src/utils/{request.js → request.ts} +28 -3
- package/src/utils/{socketio.js → socketio.ts} +11 -1
- package/src/utils/theme.ts +48 -57
- package/src/utils/useFileUpload.ts +80 -23
- package/tailwind/audit-token-drift.cjs +176 -0
- package/tailwind/colorPalette.js +69 -8
- package/tailwind/colors.json +1115 -397
- package/tailwind/figma-tokens-to-theme.js +364 -0
- package/tailwind/generated/colors.json +1217 -0
- package/tailwind/generated/effects.json +41 -0
- package/tailwind/generated/radius.json +20 -0
- package/tailwind/generated/typography.json +479 -0
- package/tailwind/migrate-tokens-v2.js +453 -0
- package/tailwind/migrate-tokens-v2.test.js +55 -0
- package/tailwind/plugin.js +220 -15
- package/tailwind/preset.js +15 -0
- package/tailwind/tokens.js +35 -37
- package/tsconfig.base.json +2 -2
- package/vitepress/components/Docs/CommandPalette.vue +214 -0
- package/vitepress/components/Docs/Demo.vue +60 -0
- package/vitepress/components/Docs/EmitsTable.vue +99 -0
- package/vitepress/components/Docs/MobileNavSheet.vue +148 -0
- package/vitepress/components/Docs/OnThisPage.vue +74 -0
- package/vitepress/components/Docs/PrevNextBtns.vue +58 -0
- package/vitepress/components/Docs/PropsTable.vue +185 -0
- package/vitepress/components/Docs/Search.vue +34 -0
- package/vitepress/components/Docs/Sidebar.vue +91 -0
- package/vitepress/components/Docs/SlotsTable.vue +99 -0
- package/vitepress/components/Docs/index.ts +13 -0
- package/vitepress/components/Docs/sidebarList.ts +33 -0
- package/vitepress/components/Layout.vue +58 -0
- package/vitepress/components/Navbar.vue +126 -0
- package/vitepress/components/index.ts +3 -0
- package/vitepress/composables/index.ts +3 -0
- package/vitepress/composables/useTheme.ts +39 -0
- package/vitepress/css/fonts/Inter-Italic.var.woff2 +0 -0
- package/vitepress/css/fonts/Inter.var.woff2 +0 -0
- package/vitepress/css/style.css +198 -0
- package/vitepress/index.d.ts +23 -0
- package/vitepress/index.node.ts +175 -0
- package/vitepress/index.ts +17 -0
- package/vitepress/plugins/colocatedComponentDocs.ts +164 -0
- package/vitepress/plugins/componentTransformer.ts +286 -0
- package/vitepress/plugins/index.ts +12 -0
- package/vitepress/state.ts +10 -0
- package/vitepress/theme/index.ts +21 -0
- package/frappe/telemetry/utils.ts +0 -15
- package/src/components/Badge/stories/Themes.vue +0 -10
- package/src/components/Badge/stories/Variants.vue +0 -10
- package/src/components/Button/stories/Icons.vue +0 -27
- package/src/components/Button/stories/Sizes.vue +0 -11
- package/src/components/Button/stories/Themes.vue +0 -10
- package/src/components/Button/stories/Variants.vue +0 -10
- package/src/components/Popover/stories/Hover.vue +0 -14
- package/src/components/Resource.vue +0 -21
- package/src/components/Sidebar/stories/Example.vue +0 -76
- package/src/components/Spinner.vue +0 -3
- package/src/components/TabButtons/TabButtons.story.vue +0 -22
- package/src/utils/plugin.js +0 -24
- /package/src/components/Dropdown/stories/{02_Shortcuts.vue → Shortcuts.vue} +0 -0
- /package/src/components/Dropdown/stories/{01_Simple.vue → Simple.vue} +0 -0
- /package/src/components/Dropdown/stories/{03_Submenus.vue → Submenus.vue} +0 -0
- /package/src/components/Dropdown/stories/{04_Switches.vue → Switches.vue} +0 -0
- /package/src/components/{Dropdown/DropdownRenderContentAsChild.vue → Menu/MenuRenderContentAsChild.vue} +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<!-- Auto Generated by scripts/propsgen.ts -->
|
|
2
|
+
<script setup>
|
|
3
|
+
import PropsTable from '@/components/Docs/PropsTable.vue'
|
|
4
|
+
import SlotsTable from '@/components/Docs/SlotsTable.vue'
|
|
5
|
+
import EmitsTable from '@/components/Docs/EmitsTable.vue'
|
|
6
|
+
|
|
7
|
+
const propsData = [
|
|
8
|
+
{
|
|
9
|
+
name: 'scroll',
|
|
10
|
+
description: 'Whether the content area scrolls as one page (default). Set `false` for\nmulti-pane layouts where inner panes own their own scroll — the content\narea then fills the remaining height and never page-scrolls.',
|
|
11
|
+
required: false,
|
|
12
|
+
type: 'boolean',
|
|
13
|
+
default: 'true'
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
const slotsData = [
|
|
18
|
+
{
|
|
19
|
+
name: 'rail',
|
|
20
|
+
description: '',
|
|
21
|
+
type: '{}'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'sidebar',
|
|
25
|
+
description: '',
|
|
26
|
+
type: '{}'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'default',
|
|
30
|
+
description: '',
|
|
31
|
+
type: '{}'
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
## API Reference
|
|
37
|
+
|
|
38
|
+
<PropsTable name="DesktopShell" :data="propsData"/>
|
|
39
|
+
|
|
40
|
+
<SlotsTable :data="slotsData"/>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { h } from 'vue'
|
|
2
|
+
import DesktopShell from './DesktopShell.vue'
|
|
3
|
+
import { getScrollContainer } from '../../composables/useScrollContainer'
|
|
4
|
+
|
|
5
|
+
describe('<DesktopShell />', () => {
|
|
6
|
+
it('renders the rail, sidebar, and default content slots', () => {
|
|
7
|
+
cy.mount(DesktopShell, {
|
|
8
|
+
slots: {
|
|
9
|
+
rail: () => h('div', { 'data-test': 'rail' }, 'rail'),
|
|
10
|
+
sidebar: () => h('div', { 'data-test': 'sidebar' }, 'sidebar'),
|
|
11
|
+
default: () => h('div', { 'data-test': 'page' }, 'page body'),
|
|
12
|
+
},
|
|
13
|
+
})
|
|
14
|
+
cy.get('[data-slot=desktop-shell]').should('exist')
|
|
15
|
+
cy.get('[data-test=rail]').should('exist')
|
|
16
|
+
cy.get('[data-test=sidebar]').should('exist')
|
|
17
|
+
cy.get('[data-slot=desktop-shell-content]').should(
|
|
18
|
+
'contain.text',
|
|
19
|
+
'page body',
|
|
20
|
+
)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('renders the structural content region without app styling', () => {
|
|
24
|
+
cy.mount(DesktopShell)
|
|
25
|
+
cy.get('[data-slot=desktop-shell-content]')
|
|
26
|
+
.should('have.class', 'flex')
|
|
27
|
+
.and('have.class', 'min-w-0')
|
|
28
|
+
.and('have.class', 'flex-1')
|
|
29
|
+
.and('not.have.class', 'rounded-lg')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('registers its scroll region so getScrollContainer() resolves', () => {
|
|
33
|
+
cy.mount(DesktopShell, { slots: { default: () => h('div', 'content') } })
|
|
34
|
+
cy.get('[data-slot=desktop-shell-content]').should('exist')
|
|
35
|
+
cy.then(() => {
|
|
36
|
+
expect(getScrollContainer()).to.not.be.null
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# DesktopShell
|
|
2
|
+
|
|
3
|
+
The desktop app frame. `DesktopShell` arranges an app's `Rail` and `Sidebar`
|
|
4
|
+
alongside the main content, and owns the skeleton the content needs: a pinned
|
|
5
|
+
`PageHeaderTarget` and a registered scroll region. Its mobile counterpart is a
|
|
6
|
+
separate family — [`MobileShell`](/docs/components/mobileshell) — because the
|
|
7
|
+
two are different navigation models, not one responsive component.
|
|
8
|
+
|
|
9
|
+
<ComponentPreview name="DesktopShell-Default" />
|
|
10
|
+
|
|
11
|
+
Put the icon column in `#rail`, the navigation panel in `#sidebar` (render it
|
|
12
|
+
conditionally to hide it on routes that don't need it), and the routed page in
|
|
13
|
+
the default slot. Pages declare their own `PageHeader` anywhere — it teleports
|
|
14
|
+
to the target the shell pins above the scroll region.
|
|
15
|
+
|
|
16
|
+
## Scroll container
|
|
17
|
+
|
|
18
|
+
The shell registers its scroll region into a small module registry, so
|
|
19
|
+
[`useScrollContainer()`](/docs/other/utilities) and the plain
|
|
20
|
+
`getScrollContainer()` resolve it with no wiring — a page can scroll-to-top or a
|
|
21
|
+
router `scrollBehavior` can read the scroll offset without the app owning a
|
|
22
|
+
global. Because the registry is a stack, swapping `DesktopShell` for
|
|
23
|
+
`MobileShell` on a viewport change hands the active container over cleanly.
|
|
24
|
+
|
|
25
|
+
## Theming the content region
|
|
26
|
+
|
|
27
|
+
The content region exposes `data-slot="desktop-shell-content"` for app-level
|
|
28
|
+
styling. Target that slot in CSS when an app needs a card, gutter, border,
|
|
29
|
+
background, or other product-specific surface treatment.
|
|
30
|
+
|
|
31
|
+
<!-- @include: ./DesktopShell.api.md -->
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div data-slot="desktop-shell" class="flex h-full">
|
|
3
|
+
<slot name="rail" />
|
|
4
|
+
<slot name="sidebar" />
|
|
5
|
+
|
|
6
|
+
<div
|
|
7
|
+
data-slot="desktop-shell-content"
|
|
8
|
+
class="flex min-w-0 flex-1 flex-col overflow-hidden"
|
|
9
|
+
>
|
|
10
|
+
<!-- Pages teleport their headers here; it stays pinned above the scroll. -->
|
|
11
|
+
<PageHeaderTarget />
|
|
12
|
+
|
|
13
|
+
<!--
|
|
14
|
+
The scroll region. Registered into the shared scroll-container registry
|
|
15
|
+
(via ScrollArea's exposed viewport element) so `useScrollContainer()` /
|
|
16
|
+
`getScrollContainer()` resolve it with zero app wiring.
|
|
17
|
+
-->
|
|
18
|
+
<ScrollArea v-if="scroll" ref="scrollArea" class="min-h-0 flex-1">
|
|
19
|
+
<slot />
|
|
20
|
+
</ScrollArea>
|
|
21
|
+
|
|
22
|
+
<!--
|
|
23
|
+
scroll=false: the content area fills the remaining height and never
|
|
24
|
+
page-scrolls, so inner panes own their own overflow — a list + detail
|
|
25
|
+
split, or a horizontally-scrolling board whose columns scroll on their
|
|
26
|
+
own. Without this apps fake it with `absolute inset-0` / hardcoded
|
|
27
|
+
`h-[calc(100vh-3rem)]` / `[&>div]:h-full`.
|
|
28
|
+
-->
|
|
29
|
+
<div v-else class="flex min-h-0 flex-1 flex-col overflow-hidden">
|
|
30
|
+
<slot />
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script setup lang="ts">
|
|
37
|
+
import { onBeforeUnmount, ref, watch } from 'vue'
|
|
38
|
+
import ScrollArea from '../ScrollArea/ScrollArea.vue'
|
|
39
|
+
import PageHeaderTarget from '../PageHeader/PageHeaderTarget.vue'
|
|
40
|
+
import {
|
|
41
|
+
registerScrollContainer,
|
|
42
|
+
unregisterScrollContainer,
|
|
43
|
+
} from '../../composables/useScrollContainer'
|
|
44
|
+
|
|
45
|
+
withDefaults(
|
|
46
|
+
defineProps<{
|
|
47
|
+
/**
|
|
48
|
+
* Whether the content area scrolls as one page (default). Set `false` for
|
|
49
|
+
* multi-pane layouts where inner panes own their own scroll — the content
|
|
50
|
+
* area then fills the remaining height and never page-scrolls.
|
|
51
|
+
*/
|
|
52
|
+
scroll?: boolean
|
|
53
|
+
}>(),
|
|
54
|
+
{ scroll: true },
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
const scrollArea = ref<InstanceType<typeof ScrollArea> | null>(null)
|
|
58
|
+
|
|
59
|
+
// Register the real scrolling viewport once ScrollArea exposes it, and follow it
|
|
60
|
+
// if it ever remounts. Unregister on teardown so a layout swap hands over to the
|
|
61
|
+
// other shell cleanly.
|
|
62
|
+
let registered: HTMLElement | null = null
|
|
63
|
+
watch(
|
|
64
|
+
() => scrollArea.value?.viewportElement ?? null,
|
|
65
|
+
(el) => {
|
|
66
|
+
if (registered && registered !== el) {
|
|
67
|
+
unregisterScrollContainer(registered)
|
|
68
|
+
registered = null
|
|
69
|
+
}
|
|
70
|
+
if (el && el !== registered) {
|
|
71
|
+
registerScrollContainer(el)
|
|
72
|
+
registered = el
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{ immediate: true },
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
onBeforeUnmount(() => {
|
|
79
|
+
if (registered) unregisterScrollContainer(registered)
|
|
80
|
+
})
|
|
81
|
+
</script>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import {
|
|
4
|
+
DesktopShell,
|
|
5
|
+
Rail,
|
|
6
|
+
RailItem,
|
|
7
|
+
Sidebar,
|
|
8
|
+
SidebarItem,
|
|
9
|
+
SidebarLabel,
|
|
10
|
+
PageHeader,
|
|
11
|
+
Button,
|
|
12
|
+
} from 'frappe-ui'
|
|
13
|
+
|
|
14
|
+
const community = ref('design')
|
|
15
|
+
const communities = [
|
|
16
|
+
{ id: 'design', initials: 'DE' },
|
|
17
|
+
{ id: 'engineering', initials: 'EN' },
|
|
18
|
+
{ id: 'marketing', initials: 'MK' },
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
const space = ref('Website')
|
|
22
|
+
const spaces = [
|
|
23
|
+
'Website',
|
|
24
|
+
'Brand',
|
|
25
|
+
'Illustration',
|
|
26
|
+
'Design System',
|
|
27
|
+
'Marketing Site',
|
|
28
|
+
'Mobile App',
|
|
29
|
+
'Research',
|
|
30
|
+
'Archive',
|
|
31
|
+
]
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<template>
|
|
35
|
+
<!-- Bounded height so the shell's `h-full` has something to fill in the preview. -->
|
|
36
|
+
<div class="h-[560px] overflow-hidden rounded-md border bg-surface-white">
|
|
37
|
+
<DesktopShell>
|
|
38
|
+
<template #rail>
|
|
39
|
+
<Rail>
|
|
40
|
+
<RailItem
|
|
41
|
+
label="Home"
|
|
42
|
+
variant="ghost"
|
|
43
|
+
icon="lucide-house"
|
|
44
|
+
:active="community === ''"
|
|
45
|
+
@click="community = ''"
|
|
46
|
+
/>
|
|
47
|
+
<div class="flex w-full flex-1 flex-col items-center gap-3 pt-3">
|
|
48
|
+
<RailItem
|
|
49
|
+
v-for="c in communities"
|
|
50
|
+
:key="c.id"
|
|
51
|
+
:label="c.id"
|
|
52
|
+
:active="community === c.id"
|
|
53
|
+
@click="community = c.id"
|
|
54
|
+
>
|
|
55
|
+
<span class="text-2xs-medium uppercase text-ink-gray-5">{{ c.initials }}</span>
|
|
56
|
+
</RailItem>
|
|
57
|
+
</div>
|
|
58
|
+
<RailItem label="Search" variant="ghost" icon="lucide-search" />
|
|
59
|
+
</Rail>
|
|
60
|
+
</template>
|
|
61
|
+
|
|
62
|
+
<template #sidebar>
|
|
63
|
+
<Sidebar disable-collapse width="14rem">
|
|
64
|
+
<div class="px-3 py-2 text-base font-medium text-ink-gray-8">Acme Design</div>
|
|
65
|
+
<div class="flex-1 overflow-y-auto px-2 pb-2">
|
|
66
|
+
<SidebarLabel class="px-2">Spaces</SidebarLabel>
|
|
67
|
+
<SidebarItem
|
|
68
|
+
v-for="s in spaces"
|
|
69
|
+
:key="s"
|
|
70
|
+
:active="s === space"
|
|
71
|
+
@click="space = s"
|
|
72
|
+
>
|
|
73
|
+
<template #prefix><span class="lucide-hash size-4" aria-hidden="true" /></template>
|
|
74
|
+
{{ s }}
|
|
75
|
+
</SidebarItem>
|
|
76
|
+
</div>
|
|
77
|
+
</Sidebar>
|
|
78
|
+
</template>
|
|
79
|
+
|
|
80
|
+
<!-- Declared in the page; teleports to the target the shell pins on top. -->
|
|
81
|
+
<PageHeader>
|
|
82
|
+
<span class="text-lg font-semibold text-ink-gray-8">{{ space }}</span>
|
|
83
|
+
<Button variant="subtle" icon-left="lucide-plus" label="New post" />
|
|
84
|
+
</PageHeader>
|
|
85
|
+
|
|
86
|
+
<div class="p-5">
|
|
87
|
+
<p
|
|
88
|
+
v-for="n in 40"
|
|
89
|
+
:key="n"
|
|
90
|
+
class="mb-3 text-base text-ink-gray-7"
|
|
91
|
+
>
|
|
92
|
+
Row {{ n }} — scroll the content; the header stays pinned above it.
|
|
93
|
+
</p>
|
|
94
|
+
</div>
|
|
95
|
+
</DesktopShell>
|
|
96
|
+
</div>
|
|
97
|
+
</template>
|
|
@@ -161,22 +161,21 @@
|
|
|
161
161
|
type: '[value: boolean]'
|
|
162
162
|
},
|
|
163
163
|
{
|
|
164
|
-
name: '
|
|
165
|
-
description: '
|
|
164
|
+
name: 'after-leave',
|
|
165
|
+
description: '',
|
|
166
166
|
type: '[]'
|
|
167
167
|
},
|
|
168
168
|
{
|
|
169
|
-
name: '
|
|
170
|
-
description: '',
|
|
169
|
+
name: 'close',
|
|
170
|
+
description: 'Fired when the component closes.',
|
|
171
171
|
type: '[]'
|
|
172
172
|
}
|
|
173
173
|
]
|
|
174
174
|
</script>
|
|
175
175
|
## API Reference
|
|
176
176
|
|
|
177
|
-
<PropsTable name="Dialog" :data="propsData"/>
|
|
178
|
-
|
|
179
|
-
<SlotsTable :data="slotsData"/>
|
|
177
|
+
<PropsTable name="Dialog" :data="propsData"/>
|
|
180
178
|
|
|
181
|
-
<
|
|
179
|
+
<SlotsTable :data="slotsData"/>
|
|
182
180
|
|
|
181
|
+
<EmitsTable :data="emitsData"/>
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
A flexible overlay for showing messages, forms, or actions. Keeps focus on content while allowing clear, user-friendly interactions.
|
|
4
4
|
|
|
5
|
+
## Playground
|
|
6
|
+
|
|
7
|
+
<ClientOnly><DialogBuilder /></ClientOnly>
|
|
8
|
+
|
|
5
9
|
## Share
|
|
6
10
|
|
|
7
11
|
A typical real-world dialog — rich `#default` body, an action-row `#actions`
|
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
>
|
|
15
15
|
<DialogContent
|
|
16
16
|
ref="contentRef"
|
|
17
|
-
class="my-8 inline-block w-full transform overflow-hidden rounded-xl bg-surface-
|
|
17
|
+
class="my-8 inline-block w-full transform overflow-hidden rounded-xl bg-surface-elevation-1 text-start align-middle shadow-xl dialog-content focus-visible:outline-none"
|
|
18
18
|
:class="sizeClass"
|
|
19
|
+
@pointerdown.stop
|
|
19
20
|
@open-auto-focus="handleOpenAutoFocus"
|
|
20
21
|
@escape-key-down="
|
|
21
22
|
(e: Event) => {
|
|
@@ -37,7 +38,7 @@
|
|
|
37
38
|
<template v-else>
|
|
38
39
|
<!-- legacy `#body-main`: full middle override (deprecated) -->
|
|
39
40
|
<slot v-if="$slots['body-main']" name="body-main" />
|
|
40
|
-
<div v-else class="bg-surface-
|
|
41
|
+
<div v-else class="bg-surface-elevation-1 px-4 pb-6 pt-5 sm:px-6">
|
|
41
42
|
<div class="flex">
|
|
42
43
|
<div class="w-full flex-1">
|
|
43
44
|
<!-- legacy `#body-header` (deprecated, warns + renders nothing if used; preserved for back-compat by rendering header) -->
|
|
@@ -74,7 +75,7 @@
|
|
|
74
75
|
<slot name="body-title">
|
|
75
76
|
<h3
|
|
76
77
|
v-if="resolved.title"
|
|
77
|
-
class="text-2xl
|
|
78
|
+
class="text-2xl-semibold leading-6 text-ink-gray-8"
|
|
78
79
|
>
|
|
79
80
|
{{ resolved.title }}
|
|
80
81
|
</h3>
|
|
@@ -369,10 +370,10 @@ const dialogIconClasses = computed(() => {
|
|
|
369
370
|
const theme = iconTheme.value
|
|
370
371
|
if (!theme) return 'text-ink-gray-5'
|
|
371
372
|
const map: Record<DialogTheme, string> = {
|
|
372
|
-
yellow: 'text-ink-amber-
|
|
373
|
-
blue: 'text-ink-blue-
|
|
374
|
-
red: 'text-ink-red-
|
|
375
|
-
green: 'text-ink-green-
|
|
373
|
+
yellow: 'text-ink-amber-6',
|
|
374
|
+
blue: 'text-ink-blue-6',
|
|
375
|
+
red: 'text-ink-red-8',
|
|
376
|
+
green: 'text-ink-green-6',
|
|
376
377
|
}
|
|
377
378
|
return map[theme]
|
|
378
379
|
})
|
|
@@ -131,7 +131,7 @@ function onEnter() {
|
|
|
131
131
|
</ul>
|
|
132
132
|
|
|
133
133
|
<div
|
|
134
|
-
class="flex items-center gap-4 border-t border-outline-
|
|
134
|
+
class="flex items-center gap-4 border-t border-outline-elevation-2 px-4 py-2 text-p-xs text-ink-gray-5"
|
|
135
135
|
>
|
|
136
136
|
<span class="flex items-center gap-1.5">
|
|
137
137
|
<KeyboardShortcut combo="ArrowUp" bg />
|
|
@@ -53,7 +53,7 @@ function reset() {
|
|
|
53
53
|
v-for="(_, i) in steps"
|
|
54
54
|
:key="i"
|
|
55
55
|
class="h-1 flex-1 rounded-full transition-colors"
|
|
56
|
-
:class="i <= step ? 'bg-surface-gray-
|
|
56
|
+
:class="i <= step ? 'bg-surface-gray-10' : 'bg-surface-gray-3'"
|
|
57
57
|
/>
|
|
58
58
|
</div>
|
|
59
59
|
|
|
@@ -7,24 +7,26 @@
|
|
|
7
7
|
:key="legacy.id ?? legacy"
|
|
8
8
|
/>
|
|
9
9
|
<!-- v1 imperative `dialog.*` stack. -->
|
|
10
|
-
<component
|
|
11
|
-
v-for="d in imperativeDialogs"
|
|
12
|
-
:is="d.component"
|
|
13
|
-
:key="d.id"
|
|
14
|
-
/>
|
|
10
|
+
<component v-for="d in imperativeDialogs" :is="d.component" :key="d.id" />
|
|
15
11
|
</div>
|
|
16
12
|
</template>
|
|
17
13
|
|
|
18
|
-
<script setup>
|
|
19
|
-
import { inject, provide } from 'vue'
|
|
20
|
-
import { dialogs as
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import { inject, provide, type InjectionKey, type Ref, type VNode } from 'vue'
|
|
16
|
+
import { dialogs as untypedLegacyDialogs } from '../utils/confirmDialog.js'
|
|
21
17
|
import { dialogs as imperativeDialogs } from '../utils/dialog'
|
|
22
18
|
|
|
19
|
+
type LegacyDialog = VNode & { id?: number }
|
|
20
|
+
|
|
21
|
+
const legacyDialogs = untypedLegacyDialogs as Ref<LegacyDialog[]>
|
|
22
|
+
|
|
23
23
|
// Only the outermost `<Dialogs />` host renders the stacks. Apps that wrap
|
|
24
24
|
// their tree in `<FrappeUIProvider>` (which mounts `<Dialogs />` internally)
|
|
25
25
|
// *and* also mount `<Dialogs />` manually for legacy `confirmDialog()` would
|
|
26
26
|
// otherwise see every dialog twice. A nested host yields to its ancestor.
|
|
27
|
-
const DIALOGS_HOST_KEY = Symbol.for(
|
|
27
|
+
const DIALOGS_HOST_KEY = Symbol.for(
|
|
28
|
+
'frappe-ui.dialogs-host',
|
|
29
|
+
) as InjectionKey<boolean>
|
|
28
30
|
const hasParentHost = inject(DIALOGS_HOST_KEY, false)
|
|
29
31
|
const isPrimaryHost = !hasParentHost
|
|
30
32
|
provide(DIALOGS_HOST_KEY, true)
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
name: 'options',
|
|
16
16
|
description: 'Array of dropdown options or grouped options.',
|
|
17
17
|
required: false,
|
|
18
|
-
type: '
|
|
18
|
+
type: 'MenuOptions',
|
|
19
19
|
default: '[]'
|
|
20
20
|
},
|
|
21
21
|
{
|
|
@@ -52,6 +52,12 @@
|
|
|
52
52
|
type: 'number',
|
|
53
53
|
default: '4'
|
|
54
54
|
},
|
|
55
|
+
{
|
|
56
|
+
name: 'matchTriggerWidth',
|
|
57
|
+
description: 'Whether the dropdown width should match the trigger element.',
|
|
58
|
+
required: false,
|
|
59
|
+
type: 'boolean'
|
|
60
|
+
},
|
|
55
61
|
{
|
|
56
62
|
name: 'portalTo',
|
|
57
63
|
description: 'Teleport target for dropdown portal content.',
|
|
@@ -71,36 +77,6 @@
|
|
|
71
77
|
name: 'trigger',
|
|
72
78
|
description: 'Explicit trigger slot renderer.',
|
|
73
79
|
type: 'DropdownTriggerSlotProps'
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
name: 'item',
|
|
77
|
-
description: 'Replaces the entire item row.',
|
|
78
|
-
type: 'DropdownItemSlotProps'
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
name: 'item-prefix',
|
|
82
|
-
description: 'Content rendered before the standard item label.',
|
|
83
|
-
type: 'DropdownItemSlotProps'
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
name: 'item-label',
|
|
87
|
-
description: 'Content rendered for the standard item label area.',
|
|
88
|
-
type: 'DropdownItemSlotProps'
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
name: 'item-suffix',
|
|
92
|
-
description: 'Content rendered after the standard item label.',
|
|
93
|
-
type: 'DropdownItemSlotProps'
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
name: 'group-label',
|
|
97
|
-
description: 'Custom renderer for group labels.',
|
|
98
|
-
type: 'DropdownGroupSlotProps'
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
name: 'empty',
|
|
102
|
-
description: 'Fallback content rendered when no items are available.',
|
|
103
|
-
type: 'any'
|
|
104
80
|
}
|
|
105
81
|
]
|
|
106
82
|
|
|
@@ -114,9 +90,8 @@
|
|
|
114
90
|
</script>
|
|
115
91
|
## API Reference
|
|
116
92
|
|
|
117
|
-
<PropsTable name="Dropdown" :data="propsData"/>
|
|
118
|
-
|
|
119
|
-
<SlotsTable :data="slotsData"/>
|
|
93
|
+
<PropsTable name="Dropdown" :data="propsData"/>
|
|
120
94
|
|
|
121
|
-
<
|
|
95
|
+
<SlotsTable :data="slotsData"/>
|
|
122
96
|
|
|
97
|
+
<EmitsTable :data="emitsData"/>
|
|
@@ -3,35 +3,39 @@
|
|
|
3
3
|
A flexible menu component for actions. Handles groups, nested submenus,
|
|
4
4
|
toggle rows, disabled items, custom triggers, and a built-in kebab pattern.
|
|
5
5
|
|
|
6
|
+
## Playground
|
|
7
|
+
|
|
8
|
+
<ClientOnly><DropdownBuilder /></ClientOnly>
|
|
9
|
+
|
|
6
10
|
## Simple
|
|
7
11
|
A plain actions menu with icons. The default trigger is an auto-generated `<Button>` — pass `button: { label }` to override its text.
|
|
8
12
|
|
|
9
|
-
<ComponentPreview name="Dropdown-
|
|
13
|
+
<ComponentPreview name="Dropdown-Simple" layout="stacked" />
|
|
10
14
|
|
|
11
15
|
## With Shortcuts
|
|
12
16
|
Keyboard shortcuts rendered in the row suffix. Use the `#item-suffix` slot and a custom `shortcut` field on each item to keep the label clean and the hint secondary.
|
|
13
17
|
|
|
14
|
-
<ComponentPreview name="Dropdown-
|
|
18
|
+
<ComponentPreview name="Dropdown-Shortcuts" layout="stacked" />
|
|
15
19
|
|
|
16
20
|
## Submenus
|
|
17
21
|
Grouped actions with nested submenus — the "Share" path recurses into "Invite people" which recurses into channel targets. Groups are just `{ group, options }` entries in the options array.
|
|
18
22
|
|
|
19
|
-
<ComponentPreview name="Dropdown-
|
|
23
|
+
<ComponentPreview name="Dropdown-Submenus" />
|
|
20
24
|
|
|
21
25
|
## Switches
|
|
22
26
|
Toggle items live inside the menu using `switch: true` + `switchValue`. Clicking a switch row fires `onClick(boolean)` with the new value and keeps the menu open, so consumers can flip multiple settings in one sitting.
|
|
23
27
|
|
|
24
|
-
<ComponentPreview name="Dropdown-
|
|
28
|
+
<ComponentPreview name="Dropdown-Switches" />
|
|
25
29
|
|
|
26
30
|
## Kebab Menu
|
|
27
31
|
The classic row-actions pattern — a ghost icon button that opens a grouped menu. `#trigger` swaps in the `LucideMoreHorizontal` button, and the `open` slot prop keeps the button in its `active` state while the menu is open.
|
|
28
32
|
|
|
29
|
-
<ComponentPreview name="Dropdown-
|
|
33
|
+
<ComponentPreview name="Dropdown-KebabMenu" />
|
|
30
34
|
|
|
31
35
|
## User Menu
|
|
32
36
|
A real workspace + profile menu — nested Apps / Theme submenus, account-group footer, and a completely custom trigger showing the workspace icon, product name, and current user.
|
|
33
37
|
|
|
34
|
-
<ComponentPreview name="Dropdown-
|
|
38
|
+
<ComponentPreview name="Dropdown-UserMenu" />
|
|
35
39
|
|
|
36
40
|
## Notes
|
|
37
41
|
|