@wheelhouse/ui 0.2.2 → 0.2.4
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/dist/blocks/columns/columns-types.d.ts +40 -0
- package/dist/blocks/columns/columns-types.d.ts.map +1 -0
- package/dist/blocks/columns/columns-types.js +10 -0
- package/dist/blocks/columns/columns-utils.d.ts +13 -0
- package/dist/blocks/columns/columns-utils.d.ts.map +1 -0
- package/dist/blocks/columns/columns-utils.js +85 -0
- package/dist/blocks/columns/columns.d.ts +3 -0
- package/dist/blocks/columns/columns.d.ts.map +1 -0
- package/dist/blocks/columns/columns.js +79 -0
- package/dist/blocks/columns/columns.stories.d.ts +12 -0
- package/dist/blocks/columns/columns.stories.d.ts.map +1 -0
- package/dist/blocks/columns/columns.stories.js +67 -0
- package/dist/blocks/columns/index.d.ts +6 -0
- package/dist/blocks/columns/index.d.ts.map +1 -0
- package/dist/blocks/columns/index.js +3 -0
- package/dist/blocks/date-selector/date-selector-context.d.ts.map +1 -0
- package/dist/blocks/date-selector/date-selector-default-i18n.d.ts +10 -0
- package/dist/blocks/date-selector/date-selector-default-i18n.d.ts.map +1 -0
- package/dist/blocks/date-selector/date-selector-default-i18n.js +29 -0
- package/dist/blocks/date-selector/date-selector-i18n-resources.d.ts +11 -0
- package/dist/blocks/date-selector/date-selector-i18n-resources.d.ts.map +1 -0
- package/dist/blocks/date-selector/date-selector-i18n-resources.js +248 -0
- package/dist/blocks/date-selector/date-selector-i18n.shared.d.ts +12 -0
- package/dist/blocks/date-selector/date-selector-i18n.shared.d.ts.map +1 -0
- package/dist/blocks/date-selector/date-selector-i18n.shared.js +84 -0
- package/dist/{components → blocks}/date-selector/date-selector-parts.d.ts +9 -0
- package/dist/blocks/date-selector/date-selector-parts.d.ts.map +1 -0
- package/dist/{components → blocks}/date-selector/date-selector-parts.js +21 -6
- package/dist/{components → blocks}/date-selector/date-selector-types.d.ts +70 -0
- package/dist/blocks/date-selector/date-selector-types.d.ts.map +1 -0
- package/dist/{components → blocks}/date-selector/date-selector-types.js +22 -0
- package/dist/blocks/date-selector/date-selector-value.d.ts +81 -0
- package/dist/blocks/date-selector/date-selector-value.d.ts.map +1 -0
- package/dist/blocks/date-selector/date-selector-value.js +423 -0
- package/dist/{components → blocks}/date-selector/date-selector.d.ts +1 -1
- package/dist/blocks/date-selector/date-selector.d.ts.map +1 -0
- package/dist/blocks/date-selector/date-selector.js +191 -0
- package/dist/{components → blocks}/date-selector/date-selector.stories.d.ts +14 -0
- package/dist/blocks/date-selector/date-selector.stories.d.ts.map +1 -0
- package/dist/blocks/date-selector/date-selector.stories.js +299 -0
- package/dist/blocks/date-selector/index.d.ts +11 -0
- package/dist/blocks/date-selector/index.d.ts.map +1 -0
- package/dist/blocks/date-selector/index.js +8 -0
- package/dist/{components → blocks}/date-selector/use-date-selector.d.ts +4 -3
- package/dist/blocks/date-selector/use-date-selector.d.ts.map +1 -0
- package/dist/{components → blocks}/date-selector/use-date-selector.js +14 -8
- package/dist/blocks/floating-menu-widget/floating-menu-widget.d.ts +26 -0
- package/dist/blocks/floating-menu-widget/floating-menu-widget.d.ts.map +1 -0
- package/dist/blocks/floating-menu-widget/floating-menu-widget.js +200 -0
- package/dist/blocks/floating-menu-widget/floating-menu-widget.stories.d.ts +15 -0
- package/dist/blocks/floating-menu-widget/floating-menu-widget.stories.d.ts.map +1 -0
- package/dist/blocks/floating-menu-widget/floating-menu-widget.stories.js +22 -0
- package/dist/blocks/floating-menu-widget/index.d.ts +3 -0
- package/dist/blocks/floating-menu-widget/index.d.ts.map +1 -0
- package/dist/blocks/floating-menu-widget/index.js +1 -0
- package/dist/blocks/index.d.ts +5 -0
- package/dist/blocks/index.d.ts.map +1 -0
- package/dist/blocks/index.js +4 -0
- package/dist/blocks/navigation/index.d.ts +5 -0
- package/dist/blocks/navigation/index.d.ts.map +1 -0
- package/dist/blocks/navigation/index.js +2 -0
- package/dist/blocks/navigation/navigation-types.d.ts +60 -0
- package/dist/blocks/navigation/navigation-types.d.ts.map +1 -0
- package/dist/blocks/navigation/navigation-types.js +1 -0
- package/dist/blocks/navigation/navigation.d.ts +9 -0
- package/dist/blocks/navigation/navigation.d.ts.map +1 -0
- package/dist/blocks/navigation/navigation.demo.d.ts +4 -0
- package/dist/blocks/navigation/navigation.demo.d.ts.map +1 -0
- package/dist/blocks/navigation/navigation.demo.js +46 -0
- package/dist/blocks/navigation/navigation.js +98 -0
- package/dist/blocks/navigation/navigation.stories.d.ts +14 -0
- package/dist/blocks/navigation/navigation.stories.d.ts.map +1 -0
- package/dist/blocks/navigation/navigation.stories.js +16 -0
- package/dist/components/accordion/accordion.stories.js +1 -1
- package/dist/components/alert/alert.stories.js +1 -1
- package/dist/components/alert-dialog/alert-dialog.stories.js +1 -1
- package/dist/components/aspect-ratio/aspect-ratio.stories.js +1 -1
- package/dist/components/avatar/avatar.stories.js +1 -1
- package/dist/components/badge/badge.stories.js +1 -1
- package/dist/components/breadcrumb/breadcrumb.stories.js +1 -1
- package/dist/components/button/button.d.ts +18 -11
- package/dist/components/button/button.d.ts.map +1 -1
- package/dist/components/button/button.js +27 -14
- package/dist/components/button/button.stories.d.ts +11 -0
- package/dist/components/button/button.stories.d.ts.map +1 -1
- package/dist/components/button/button.stories.js +85 -1
- package/dist/components/button-group/button-group.d.ts +10 -4
- package/dist/components/button-group/button-group.d.ts.map +1 -1
- package/dist/components/button-group/button-group.js +15 -3
- package/dist/components/button-group/button-group.stories.js +1 -1
- package/dist/components/button-group/index.d.ts +2 -2
- package/dist/components/button-group/index.d.ts.map +1 -1
- package/dist/components/button-group/index.js +1 -1
- package/dist/components/calendar/calendar.stories.js +1 -1
- package/dist/components/card/card.stories.js +1 -1
- package/dist/components/checkbox/checkbox.stories.js +1 -1
- package/dist/components/collapsible/collapsible.stories.js +1 -1
- package/dist/components/combobox/combobox.stories.js +1 -1
- package/dist/components/command/command.stories.js +1 -1
- package/dist/components/context-menu/context-menu.stories.js +1 -1
- package/dist/components/dialog/dialog.stories.js +1 -1
- package/dist/components/direction/direction.stories.js +1 -1
- package/dist/components/drawer/drawer.stories.js +1 -1
- package/dist/components/dropdown-menu/dropdown-menu.d.ts +9 -2
- package/dist/components/dropdown-menu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/dropdown-menu/dropdown-menu.js +4 -1
- package/dist/components/dropdown-menu/dropdown-menu.stories.js +1 -1
- package/dist/components/dropdown-menu/index.d.ts +2 -2
- package/dist/components/dropdown-menu/index.d.ts.map +1 -1
- package/dist/components/dropdown-menu/index.js +1 -1
- package/dist/components/empty/empty.stories.js +1 -1
- package/dist/components/field/field.stories.js +1 -1
- package/dist/components/filters/filter-date-metric-value.d.ts +32 -0
- package/dist/components/filters/filter-date-metric-value.d.ts.map +1 -0
- package/dist/components/filters/filter-date-metric-value.js +406 -0
- package/dist/components/filters/filter-fields-listing-demo.d.ts +12 -0
- package/dist/components/filters/filter-fields-listing-demo.d.ts.map +1 -0
- package/dist/components/filters/filter-fields-listing-demo.js +565 -0
- package/dist/components/filters/filters-defaults.d.ts +4 -0
- package/dist/components/filters/filters-defaults.d.ts.map +1 -1
- package/dist/components/filters/filters-defaults.js +59 -1
- package/dist/components/filters/filters-i18n-resources.d.ts +277 -0
- package/dist/components/filters/filters-i18n-resources.d.ts.map +1 -0
- package/dist/components/filters/filters-i18n-resources.js +276 -0
- package/dist/components/filters/filters-i18n.shared.d.ts +16 -0
- package/dist/components/filters/filters-i18n.shared.d.ts.map +1 -0
- package/dist/components/filters/filters-i18n.shared.js +111 -0
- package/dist/components/filters/filters-types.d.ts +40 -1
- package/dist/components/filters/filters-types.d.ts.map +1 -1
- package/dist/components/filters/filters-utils.d.ts +28 -1
- package/dist/components/filters/filters-utils.d.ts.map +1 -1
- package/dist/components/filters/filters-utils.js +102 -0
- package/dist/components/filters/filters.d.ts +21 -3
- package/dist/components/filters/filters.d.ts.map +1 -1
- package/dist/components/filters/filters.js +493 -290
- package/dist/components/filters/filters.stories.d.ts +107 -2
- package/dist/components/filters/filters.stories.d.ts.map +1 -1
- package/dist/components/filters/filters.stories.js +224 -30
- package/dist/components/filters/index.d.ts +4 -1
- package/dist/components/filters/index.d.ts.map +1 -1
- package/dist/components/filters/index.js +4 -1
- package/dist/components/frame/frame.stories.js +1 -1
- package/dist/components/hover-card/hover-card.stories.js +1 -1
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -2
- package/dist/components/input/input.stories.js +1 -1
- package/dist/components/input-group/input-group.stories.js +1 -1
- package/dist/components/item/item.stories.js +1 -1
- package/dist/components/kbd/kbd.stories.js +1 -1
- package/dist/components/label/label.stories.js +1 -1
- package/dist/components/menubar/menubar.stories.js +1 -1
- package/dist/components/native-select/native-select.stories.js +1 -1
- package/dist/components/navigation-menu/navigation-menu.stories.js +1 -1
- package/dist/components/pagination/pagination.stories.js +1 -1
- package/dist/components/popover/index.d.ts +1 -0
- package/dist/components/popover/index.d.ts.map +1 -1
- package/dist/components/popover/index.js +1 -0
- package/dist/components/popover/popover-handle.d.ts +6 -0
- package/dist/components/popover/popover-handle.d.ts.map +1 -0
- package/dist/components/popover/popover-handle.js +6 -0
- package/dist/components/popover/popover.d.ts +41 -7
- package/dist/components/popover/popover.d.ts.map +1 -1
- package/dist/components/popover/popover.js +50 -3
- package/dist/components/popover/popover.stories.js +1 -1
- package/dist/components/progress/progress.js +1 -1
- package/dist/components/progress/progress.stories.d.ts +11 -2
- package/dist/components/progress/progress.stories.d.ts.map +1 -1
- package/dist/components/progress/progress.stories.js +78 -5
- package/dist/components/radio-group/radio-group.stories.js +1 -1
- package/dist/components/resizable/resizable.stories.js +1 -1
- package/dist/components/scroll-area/scroll-area.stories.js +1 -1
- package/dist/components/select/select.stories.js +1 -1
- package/dist/components/separator/separator.stories.js +1 -1
- package/dist/components/sheet/sheet.stories.js +1 -1
- package/dist/components/sidebar/index.d.ts +2 -0
- package/dist/components/sidebar/index.d.ts.map +1 -0
- package/dist/components/sidebar/index.js +1 -0
- package/dist/components/sidebar/sidebar.d.ts +64 -0
- package/dist/components/sidebar/sidebar.d.ts.map +1 -0
- package/dist/components/sidebar/sidebar.js +255 -0
- package/dist/components/sidebar/sidebar.stories.d.ts +20 -0
- package/dist/components/sidebar/sidebar.stories.d.ts.map +1 -0
- package/dist/components/sidebar/sidebar.stories.js +184 -0
- package/dist/components/skeleton/index.d.ts +3 -0
- package/dist/components/skeleton/index.d.ts.map +1 -0
- package/dist/components/skeleton/index.js +1 -0
- package/dist/components/skeleton/skeleton.d.ts +7 -0
- package/dist/components/skeleton/skeleton.d.ts.map +1 -0
- package/dist/components/skeleton/skeleton.js +8 -0
- package/dist/components/slider/slider.stories.js +1 -1
- package/dist/components/sonner/sonner.stories.js +1 -1
- package/dist/components/sortable/sortable.stories.js +1 -1
- package/dist/components/spinner/spinner.stories.js +1 -1
- package/dist/components/status-indicator/status-indicator.stories.js +1 -1
- package/dist/components/switch/switch.stories.js +1 -1
- package/dist/components/tabs/tabs.stories.js +1 -1
- package/dist/components/text/text.stories.js +1 -1
- package/dist/components/textarea/textarea.stories.js +1 -1
- package/dist/components/toggle/toggle.stories.js +1 -1
- package/dist/components/toggle-group/toggle-group.stories.js +1 -1
- package/dist/components/tooltip/tooltip.stories.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/llms.txt +10 -5
- package/package.json +8 -4
- package/dist/components/date-selector/date-selector-context.d.ts.map +0 -1
- package/dist/components/date-selector/date-selector-parts.d.ts.map +0 -1
- package/dist/components/date-selector/date-selector-types.d.ts.map +0 -1
- package/dist/components/date-selector/date-selector-value.d.ts +0 -47
- package/dist/components/date-selector/date-selector-value.d.ts.map +0 -1
- package/dist/components/date-selector/date-selector-value.js +0 -183
- package/dist/components/date-selector/date-selector.d.ts.map +0 -1
- package/dist/components/date-selector/date-selector.js +0 -144
- package/dist/components/date-selector/date-selector.stories.d.ts.map +0 -1
- package/dist/components/date-selector/date-selector.stories.js +0 -144
- package/dist/components/date-selector/index.d.ts +0 -7
- package/dist/components/date-selector/index.d.ts.map +0 -1
- package/dist/components/date-selector/index.js +0 -5
- package/dist/components/date-selector/use-date-selector.d.ts.map +0 -1
- package/dist/components/navigation-pattern-1/index.d.ts +0 -3
- package/dist/components/navigation-pattern-1/index.d.ts.map +0 -1
- package/dist/components/navigation-pattern-1/index.js +0 -1
- package/dist/components/navigation-pattern-1/pattern-1.config.d.ts +0 -47
- package/dist/components/navigation-pattern-1/pattern-1.config.d.ts.map +0 -1
- package/dist/components/navigation-pattern-1/pattern-1.config.js +0 -55
- package/dist/components/navigation-pattern-1/pattern-1.d.ts +0 -7
- package/dist/components/navigation-pattern-1/pattern-1.d.ts.map +0 -1
- package/dist/components/navigation-pattern-1/pattern-1.js +0 -83
- package/dist/components/navigation-pattern-1/pattern-1.stories.d.ts +0 -16
- package/dist/components/navigation-pattern-1/pattern-1.stories.d.ts.map +0 -1
- package/dist/components/navigation-pattern-1/pattern-1.stories.js +0 -20
- /package/dist/{components → blocks}/date-selector/date-selector-context.d.ts +0 -0
- /package/dist/{components → blocks}/date-selector/date-selector-context.js +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Bell, ChevronDown, Menu, Search, X } from 'lucide-react';
|
|
5
|
+
import { Avatar, AvatarFallback, AvatarImage } from '../../components/avatar';
|
|
6
|
+
import { Badge } from '../../components/badge';
|
|
7
|
+
import { Button } from '../../components/button';
|
|
8
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../../components/collapsible';
|
|
9
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuLinkItem, DropdownMenuSeparator, DropdownMenuTrigger, } from '../../components/dropdown-menu';
|
|
10
|
+
import { Separator } from '../../components/separator';
|
|
11
|
+
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '../../components/sheet';
|
|
12
|
+
import { cn } from '../../lib/utils';
|
|
13
|
+
const navLinkClass = 'rounded-md px-3 py-1 text-sm font-medium text-muted-foreground hover:bg-primary/5 outline-none focus-visible:ring-2 focus-visible:ring-ring';
|
|
14
|
+
const sheetNavLinkClass = 'flex items-center gap-2 rounded-md px-3 py-2.5 text-sm font-normal text-muted-foreground hover:bg-accent hover:text-accent-foreground';
|
|
15
|
+
function primaryNavKey(entry, index) {
|
|
16
|
+
return entry.kind === 'link' ? `link-${entry.label}-${entry.href}-${index}` : `submenu-${entry.label}`;
|
|
17
|
+
}
|
|
18
|
+
function externalAnchorProps(external) {
|
|
19
|
+
if (!external)
|
|
20
|
+
return {};
|
|
21
|
+
return { target: '_blank', rel: 'noopener noreferrer' };
|
|
22
|
+
}
|
|
23
|
+
function composeNavAnchorClick(closeMobile, userOnClick) {
|
|
24
|
+
if (!closeMobile)
|
|
25
|
+
return userOnClick;
|
|
26
|
+
if (!userOnClick)
|
|
27
|
+
return () => closeMobile();
|
|
28
|
+
return (e) => {
|
|
29
|
+
userOnClick(e);
|
|
30
|
+
closeMobile();
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function BrandLogo({ className, ...props }) {
|
|
34
|
+
return (_jsxs("svg", { viewBox: "0 0 282 196", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": true, className: cn('h-5 w-auto shrink-0', className), ...props, children: [_jsx("path", { d: "M113.84 192.61L182.63 73.4702C201.1 41.4702 178.01 1.47021 141.07 1.47021H3.4999C3.149 1.47057 2.80437 1.56325 2.50062 1.73893C2.19687 1.91462 1.94468 2.16712 1.76939 2.4711C1.5941 2.77508 1.50186 3.11983 1.50195 3.47073C1.50204 3.82163 1.59445 4.16633 1.7699 4.47021L110.38 192.61C110.556 192.913 110.808 193.165 111.112 193.34C111.415 193.515 111.76 193.607 112.11 193.607C112.46 193.607 112.805 193.515 113.108 193.34C113.412 193.165 113.664 192.913 113.84 192.61Z", fill: "#AA1DA5" }), _jsx("path", { d: "M171.33 192.61L279.93 4.5C280.106 4.19611 280.198 3.85141 280.198 3.50051C280.198 3.14961 280.106 2.80487 279.931 2.50089C279.755 2.19691 279.503 1.9444 279.2 1.76872C278.896 1.59303 278.551 1.50036 278.2 1.5H140.74C103.74 1.5 80.6402 41.5 99.1302 73.57L167.86 192.57C168.032 192.877 168.282 193.134 168.584 193.314C168.887 193.494 169.232 193.591 169.584 193.595C169.936 193.599 170.283 193.51 170.589 193.337C170.896 193.164 171.152 192.913 171.33 192.61V192.61Z", fill: "#D926D2" }), _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M142.811 1.5H140.74C103.74 1.5 80.6402 41.5 99.1302 73.57L140.858 145.817L182.63 73.4702C200.808 41.976 178.729 2.73259 142.811 1.5Z", fill: "#71146D" })] }));
|
|
35
|
+
}
|
|
36
|
+
function MobileToolbarActions({ secondary }) {
|
|
37
|
+
const iconItems = secondary.filter((s) => s.kind === 'search' || s.kind === 'notifications');
|
|
38
|
+
if (iconItems.length === 0)
|
|
39
|
+
return null;
|
|
40
|
+
return (_jsx("div", { className: "flex shrink-0 items-center gap-3", children: iconItems.map((item, i) => {
|
|
41
|
+
if (item.kind === 'search') {
|
|
42
|
+
return (_jsx(Button, { type: "button", variant: "ghost", className: "size-9 p-0 [&_svg]:size-5", "aria-label": item.ariaLabel ?? 'Search', onClick: item.onClick, children: _jsx(Search, { className: "text-muted-foreground" }) }, `toolbar-search-${i}`));
|
|
43
|
+
}
|
|
44
|
+
return (_jsx(Button, { type: "button", variant: "ghost", className: "size-9 p-0 [&_svg]:size-5", "aria-label": item.ariaLabel ?? 'Notifications', onClick: item.onClick, children: _jsx(Bell, { className: "text-muted-foreground" }) }, `toolbar-bell-${i}`));
|
|
45
|
+
}) }));
|
|
46
|
+
}
|
|
47
|
+
function MobileSheetMenuSection({ menu, onNavigate }) {
|
|
48
|
+
return (_jsxs(_Fragment, { children: [_jsx("p", { className: "px-3 pb-1 text-xs font-medium tracking-wide text-muted-foreground uppercase", children: menu.triggerLabel }), menu.items.map((item) => (_jsx("a", { className: sheetNavLinkClass, href: item.href, ...externalAnchorProps(item.external), onClick: composeNavAnchorClick(onNavigate, item.onClick), children: item.label }, item.href)))] }));
|
|
49
|
+
}
|
|
50
|
+
function MobileSheetAccountSection({ account, onNavigate }) {
|
|
51
|
+
const { user } = account;
|
|
52
|
+
const initials = user.initials ??
|
|
53
|
+
user.name
|
|
54
|
+
.split(/\s+/)
|
|
55
|
+
.map((p) => p[0])
|
|
56
|
+
.join('')
|
|
57
|
+
.slice(0, 2)
|
|
58
|
+
.toUpperCase();
|
|
59
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-3 rounded-md px-3 py-2", children: [_jsxs(Avatar, { className: "size-8 border-0 after:hidden", children: [user.avatarSrc ? _jsx(AvatarImage, { src: user.avatarSrc, alt: user.avatarAlt ?? user.name }) : null, _jsx(AvatarFallback, { children: initials })] }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "truncate text-sm font-medium text-foreground", children: user.name }), _jsx("p", { className: "truncate text-xs text-muted-foreground", children: user.email })] })] }), account.sections.map((section, si) => (_jsxs(React.Fragment, { children: [si > 0 ? _jsx(Separator, { className: "my-2" }) : null, section.map((item) => (_jsx("a", { className: sheetNavLinkClass, href: item.href, ...externalAnchorProps(item.external), onClick: composeNavAnchorClick(onNavigate, item.onClick), children: item.label }, `${item.href}-${item.label}`)))] }, `user-section-${si}`))), _jsx(Separator, { className: "my-2" }), _jsx("a", { className: cn(sheetNavLinkClass, 'text-destructive-foreground hover:bg-destructive/10 hover:text-destructive-foreground'), href: account.logOut.href, ...externalAnchorProps(account.logOut.external), onClick: composeNavAnchorClick(onNavigate, account.logOut.onClick), children: account.logOut.label })] }));
|
|
60
|
+
}
|
|
61
|
+
function MobileNavLinks({ primary, secondary, onNavigate }) {
|
|
62
|
+
const sheetMenus = secondary.filter((s) => s.kind === 'menu');
|
|
63
|
+
const sheetAccounts = secondary.filter((s) => s.kind === 'account');
|
|
64
|
+
return (_jsxs("div", { className: "flex flex-col gap-0.5 p-4 pt-2", children: [primary.map((entry, i) => {
|
|
65
|
+
if (entry.kind === 'link') {
|
|
66
|
+
return (_jsxs("a", { className: cn(sheetNavLinkClass, entry.active && 'text-primary'), href: entry.href, ...externalAnchorProps(entry.external), onClick: composeNavAnchorClick(onNavigate, entry.onClick), children: [entry.label, entry.badge ? _jsx(Badge, { size: "sm", children: entry.badge.label }) : null] }, primaryNavKey(entry, i)));
|
|
67
|
+
}
|
|
68
|
+
return (_jsxs(Collapsible, { className: "w-full", children: [_jsx(CollapsibleTrigger, { render: _jsxs("button", { type: "button", className: cn(sheetNavLinkClass, 'group flex w-full cursor-default justify-between font-normal text-muted-foreground hover:text-accent-foreground'), children: [_jsx("span", { children: entry.label }), _jsx(ChevronDown, { className: "size-4 shrink-0 opacity-80 transition-transform group-data-[panel-open]:rotate-180" })] }) }), _jsx(CollapsibleContent, { className: "flex flex-col gap-0.5 pt-0.5 pb-1", children: entry.items.map((sub) => (_jsx("a", { className: cn(sheetNavLinkClass, 'py-2 pl-8 text-sm'), href: sub.href, ...externalAnchorProps(sub.external), onClick: composeNavAnchorClick(onNavigate, sub.onClick), children: sub.label }, sub.href))) })] }, primaryNavKey(entry, i)));
|
|
69
|
+
}), (sheetMenus.length > 0 || sheetAccounts.length > 0) && primary.length > 0 ? _jsx(Separator, { className: "my-3" }) : null, sheetMenus.map((menu, mi) => (_jsxs(React.Fragment, { children: [mi > 0 ? _jsx(Separator, { className: "my-3" }) : null, _jsx(MobileSheetMenuSection, { menu: menu, onNavigate: onNavigate })] }, `sheet-menu-${menu.triggerLabel}-${mi}`))), sheetAccounts.map((account, ai) => (_jsxs(React.Fragment, { children: [ai > 0 || sheetMenus.length > 0 ? _jsx(Separator, { className: "my-3" }) : null, _jsx(MobileSheetAccountSection, { account: account, onNavigate: onNavigate })] }, `sheet-account-${account.triggerLabel}-${ai}`)))] }));
|
|
70
|
+
}
|
|
71
|
+
function DesktopSecondaryCluster({ secondary }) {
|
|
72
|
+
return (_jsx("div", { className: "flex items-center gap-2", children: secondary.map((item, i) => {
|
|
73
|
+
if (item.kind === 'search') {
|
|
74
|
+
return (_jsx(Button, { type: "button", variant: "ghost", size: "icon", "aria-label": item.ariaLabel ?? 'Search', onClick: item.onClick, children: _jsx(Search, { className: "size-4 text-muted-foreground" }) }, `ds-search-${i}`));
|
|
75
|
+
}
|
|
76
|
+
if (item.kind === 'notifications') {
|
|
77
|
+
return (_jsx(Button, { type: "button", variant: "ghost", size: "icon", "aria-label": item.ariaLabel ?? 'Notifications', onClick: item.onClick, children: _jsx(Bell, { className: "size-4 text-muted-foreground" }) }, `ds-bell-${i}`));
|
|
78
|
+
}
|
|
79
|
+
if (item.kind === 'menu') {
|
|
80
|
+
return (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { className: cn(navLinkClass, 'inline-flex cursor-default items-center gap-0 border-0 bg-transparent'), children: [item.triggerLabel, _jsx(ChevronDown, { className: "ml-1 size-4 opacity-80" })] }), _jsx(DropdownMenuContent, { align: "start", className: "min-w-48", children: item.items.map((link) => (_jsx(DropdownMenuLinkItem, { href: link.href, ...externalAnchorProps(link.external), onClick: link.onClick, children: link.label }, link.href))) })] }, `ds-menu-${item.triggerLabel}-${i}`));
|
|
81
|
+
}
|
|
82
|
+
return (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { className: cn(navLinkClass, 'inline-flex cursor-default items-center gap-0 border-0 bg-transparent'), children: [item.triggerLabel, _jsx(ChevronDown, { className: "ml-1 size-4 opacity-80" })] }), _jsxs(DropdownMenuContent, { align: "end", className: "min-w-56", children: [_jsxs(DropdownMenuLabel, { className: "font-normal", children: [_jsx("span", { className: "block text-sm font-medium", children: item.user.name }), _jsx("span", { className: "block text-xs text-muted-foreground", children: item.user.email })] }), _jsx(DropdownMenuSeparator, {}), item.sections.map((section, si) => (_jsxs(React.Fragment, { children: [si > 0 ? _jsx(DropdownMenuSeparator, {}) : null, section.map((link) => (_jsx(DropdownMenuLinkItem, { href: link.href, ...externalAnchorProps(link.external), onClick: link.onClick, children: link.label }, `${link.href}-${link.label}`)))] }, `user-dd-${i}-${si}`))), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLinkItem, { variant: "destructive", href: item.logOut.href, ...externalAnchorProps(item.logOut.external), onClick: item.logOut.onClick, children: item.logOut.label })] })] }, `ds-account-${item.triggerLabel}-${i}`));
|
|
83
|
+
}) }));
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Responsive app header: **`primary`** routes beside the logo; **`secondary`** is an ordered list of search, notifications, menus, and account blocks.
|
|
87
|
+
* Omit **`search`** / **`notifications`** entries to hide those icon buttons.
|
|
88
|
+
*/
|
|
89
|
+
export function Navigation({ className, primary, secondary, ...props }) {
|
|
90
|
+
const [mobileMenuOpen, setMobileMenuOpen] = React.useState(false);
|
|
91
|
+
const sheetId = React.useId().replace(/:/g, '');
|
|
92
|
+
return (_jsxs("div", { "data-slot": "navigation", className: cn(className), ...props, children: [_jsx("nav", { className: "lg:hidden", "aria-label": "Main", children: _jsxs("div", { className: "relative flex h-14 items-center justify-between border-b border-border bg-background px-4", children: [_jsxs(Button, { type: "button", variant: "ghost", className: "relative -ml-2 h-9 w-9 shrink-0 px-0 [&_svg]:size-5", "aria-expanded": mobileMenuOpen, "aria-controls": `navigation-mobile-sheet-${sheetId}`, "aria-label": mobileMenuOpen ? 'Close menu' : 'Open menu', onClick: () => setMobileMenuOpen((open) => !open), children: [_jsx("span", { className: cn('absolute transition-all duration-300', mobileMenuOpen ? '-rotate-90 opacity-0' : 'rotate-0 opacity-100'), "aria-hidden": true, children: _jsx(Menu, {}) }), _jsx("span", { className: cn('absolute transition-all duration-300', mobileMenuOpen ? 'rotate-0 opacity-100' : '-rotate-90 opacity-0'), "aria-hidden": true, children: _jsx(X, {}) })] }), _jsx("div", { className: "pointer-events-none absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2", children: _jsx(BrandLogo, { className: "h-6 w-auto" }) }), _jsx(MobileToolbarActions, { secondary: secondary })] }) }), _jsx(Sheet, { open: mobileMenuOpen, onOpenChange: setMobileMenuOpen, children: _jsxs(SheetContent, { id: `navigation-mobile-sheet-${sheetId}`, side: "left", showCloseButton: false, className: "flex h-[100dvh] max-h-[100dvh] w-full flex-col gap-0 overflow-hidden p-0 sm:max-w-sm", children: [_jsxs(SheetHeader, { className: "shrink-0 border-b border-border text-left", children: [_jsx(SheetTitle, { children: "Menu" }), _jsx(SheetDescription, { className: "sr-only", children: "Primary navigation links for the application." })] }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto overscroll-contain", children: _jsx(MobileNavLinks, { primary: primary, secondary: secondary, onNavigate: () => setMobileMenuOpen(false) }) })] }) }), _jsx("nav", { className: "hidden h-12 border-b border-border bg-background lg:block", "aria-label": "Main", children: _jsxs("div", { className: "container flex h-full items-center justify-between px-6", children: [_jsxs("div", { className: "flex items-center gap-x-3", children: [_jsx(BrandLogo, {}), _jsx("div", { className: "flex items-center gap-x-1", children: primary.map((entry, i) => {
|
|
93
|
+
if (entry.kind === 'link') {
|
|
94
|
+
return (_jsxs("a", { className: cn(navLinkClass, entry.active && 'text-primary', entry.badge && 'inline-flex items-center gap-1'), href: entry.href, ...externalAnchorProps(entry.external), onClick: entry.onClick, children: [entry.label, entry.badge ? (_jsx(Badge, { variant: "outline", size: "sm", children: entry.badge.label })) : null] }, primaryNavKey(entry, i)));
|
|
95
|
+
}
|
|
96
|
+
return (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { className: cn(navLinkClass, 'inline-flex cursor-default items-center gap-0 border-0 bg-transparent'), children: [entry.label, _jsx(ChevronDown, { className: "ml-1 size-4 opacity-80" })] }), _jsx(DropdownMenuContent, { align: "start", className: "min-w-48", children: entry.items.map((sub) => (_jsx(DropdownMenuLinkItem, { href: sub.href, ...externalAnchorProps(sub.external), onClick: sub.onClick, children: sub.label }, sub.href))) })] }, primaryNavKey(entry, i)));
|
|
97
|
+
}) })] }), _jsx(DesktopSecondaryCluster, { secondary: secondary })] }) })] }));
|
|
98
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { StoryObj } from '@storybook/react';
|
|
2
|
+
import { Navigation } from './navigation';
|
|
3
|
+
declare const meta: {
|
|
4
|
+
title: string;
|
|
5
|
+
component: typeof Navigation;
|
|
6
|
+
tags: string[];
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: string;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export default meta;
|
|
12
|
+
type Story = StoryObj<typeof Navigation>;
|
|
13
|
+
export declare const Default: Story;
|
|
14
|
+
//# sourceMappingURL=navigation.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.stories.d.ts","sourceRoot":"","sources":["../../../src/blocks/navigation/navigation.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,QAAA,MAAM,IAAI;;;;;;;CAOyB,CAAC;AAEpC,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,UAAU,CAAC,CAAC;AAEzC,eAAO,MAAM,OAAO,EAAE,KAIrB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { navigationDemoModel } from './navigation.demo';
|
|
2
|
+
import { Navigation } from './navigation';
|
|
3
|
+
const meta = {
|
|
4
|
+
title: 'Blocks/Navigation',
|
|
5
|
+
component: Navigation,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'fullscreen',
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
export default meta;
|
|
12
|
+
export const Default = {
|
|
13
|
+
args: {
|
|
14
|
+
...navigationDemoModel,
|
|
15
|
+
},
|
|
16
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './accordion';
|
|
3
3
|
const meta = {
|
|
4
|
-
title: '
|
|
4
|
+
title: 'Components/Accordion',
|
|
5
5
|
component: Accordion,
|
|
6
6
|
tags: ['autodocs'],
|
|
7
7
|
parameters: {
|
|
@@ -3,7 +3,7 @@ import { Alert, AlertAction, AlertDescription, AlertTitle } from './alert';
|
|
|
3
3
|
import { Button } from '../button';
|
|
4
4
|
import { AlertTriangle, Info } from 'lucide-react';
|
|
5
5
|
const meta = {
|
|
6
|
-
title: '
|
|
6
|
+
title: 'Components/Alert',
|
|
7
7
|
component: Alert,
|
|
8
8
|
tags: ['autodocs'],
|
|
9
9
|
parameters: {
|
|
@@ -3,7 +3,7 @@ import { AlertCircle } from 'lucide-react';
|
|
|
3
3
|
import { Button } from '../button';
|
|
4
4
|
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogTitle, AlertDialogTrigger, } from './alert-dialog';
|
|
5
5
|
const meta = {
|
|
6
|
-
title: '
|
|
6
|
+
title: 'Components/Alert Dialog',
|
|
7
7
|
component: AlertDialog,
|
|
8
8
|
tags: ['autodocs'],
|
|
9
9
|
parameters: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage } from '.';
|
|
3
3
|
const meta = {
|
|
4
|
-
title: '
|
|
4
|
+
title: 'Components/Avatar',
|
|
5
5
|
component: Avatar,
|
|
6
6
|
tags: ['autodocs'],
|
|
7
7
|
parameters: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from '.';
|
|
3
3
|
const meta = {
|
|
4
|
-
title: '
|
|
4
|
+
title: 'Components/Breadcrumb',
|
|
5
5
|
component: Breadcrumb,
|
|
6
6
|
tags: ['autodocs'],
|
|
7
7
|
parameters: {
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { Button as ButtonPrimitive } from '@base-ui/react/button';
|
|
2
2
|
import { type VariantProps } from 'class-variance-authority';
|
|
3
3
|
declare const buttonVariantStyles: {
|
|
4
|
-
readonly default: "border-primary bg-primary text-primary-foreground shadow-xs shadow-primary/24 not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] hover:bg-primary/90 data-pressed:bg-primary/90 [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none";
|
|
5
|
-
readonly outline: "border-input bg-popover text-foreground shadow-xs/5 not-dark:bg-clip-padding not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] hover:bg-accent/50 data-pressed:bg-accent/50 dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] dark:hover:bg-input/64 dark:data-pressed:bg-input/64 [:disabled,:active,[data-pressed]]:shadow-none";
|
|
6
|
-
readonly secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/90 data-pressed:bg-secondary/90 [:active,[data-pressed]]:bg-secondary/80";
|
|
7
|
-
readonly ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50";
|
|
8
|
-
readonly destructive: "border-destructive-foreground/10 bg-destructive/50 text-destructive-foreground shadow-xs shadow-destructive-foreground/10 hover:bg-destructive/80 data-pressed:bg-destructive/70 [:disabled,:active,[data-pressed]]:shadow-none";
|
|
9
|
-
readonly 'destructive-outline': "border-destructive-foreground/10 border-destructive-foreground/15 bg-popover text-destructive-foreground shadow-xs shadow-destructive-foreground/3 not-dark:bg-clip-padding not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] hover:bg-destructive/50 data-pressed:border-destructive-foreground/32 data-pressed:bg-destructive-foreground/8
|
|
10
|
-
readonly link: "text-primary underline-offset-4 hover:underline";
|
|
4
|
+
readonly default: "border-primary bg-primary text-primary-foreground shadow-xs shadow-primary/24 not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] hover:bg-primary/90 data-pressed:bg-primary/90 [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none [&_[data-slot=button-loading-indicator]]:text-primary-foreground";
|
|
5
|
+
readonly outline: "border-input bg-popover text-foreground shadow-xs/5 not-dark:bg-clip-padding not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] hover:bg-accent/50 data-pressed:bg-accent/50 dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] dark:hover:bg-input/64 dark:data-pressed:bg-input/64 [:disabled,:active,[data-pressed]]:shadow-none [&_[data-slot=button-loading-indicator]]:text-foreground";
|
|
6
|
+
readonly secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/90 data-pressed:bg-secondary/90 [:active,[data-pressed]]:bg-secondary/80 [&_[data-slot=button-loading-indicator]]:text-secondary-foreground";
|
|
7
|
+
readonly ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50 [&_[data-slot=button-loading-indicator]]:text-foreground";
|
|
8
|
+
readonly destructive: "border-destructive-foreground/10 bg-destructive/50 text-destructive-foreground shadow-xs shadow-destructive-foreground/10 hover:bg-destructive/80 data-pressed:bg-destructive/70 [:disabled,:active,[data-pressed]]:shadow-none [&_[data-slot=button-loading-indicator]]:text-destructive-foreground";
|
|
9
|
+
readonly 'destructive-outline': "border-destructive-foreground/10 border-destructive-foreground/15 bg-popover text-destructive-foreground shadow-xs shadow-destructive-foreground/3 not-dark:bg-clip-padding not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] hover:bg-destructive/50 data-pressed:border-destructive-foreground/32 data-pressed:bg-destructive-foreground/8 dark:border-destructive-foreground/30 dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [&_[data-slot=button-loading-indicator]]:text-destructive-foreground";
|
|
10
|
+
readonly link: "text-primary underline-offset-4 hover:underline [&_[data-slot=button-loading-indicator]]:text-primary";
|
|
11
11
|
};
|
|
12
12
|
declare const buttonSizeStyles: {
|
|
13
|
-
readonly default: "h-8 gap-2 px-[calc(--spacing(3)-1px)] has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2";
|
|
13
|
+
readonly default: "h-8 gap-2 px-[calc(--spacing(3)-1px)] has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3 sm:[&_svg:not([class*='size-'])]:size-3";
|
|
14
14
|
readonly xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3";
|
|
15
|
-
readonly sm: "h-7 gap-1.5 rounded-[min(var(--radius-md),12px)] px-[calc(--spacing(2.5)-1px)] text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-
|
|
16
|
-
readonly lg: "h-9 gap-1.5 px-[calc(--spacing(3.5)-1px)] has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3 sm:text-base";
|
|
15
|
+
readonly sm: "h-7 gap-1.5 rounded-[min(var(--radius-md),12px)] px-[calc(--spacing(2.5)-1px)] text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3.5 sm:[&_svg:not([class*='size-'])]:size-3.5";
|
|
16
|
+
readonly lg: "h-9 gap-1.5 px-[calc(--spacing(3.5)-1px)] has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3 sm:text-base [&_svg:not([class*='size-'])]:size-3.5 sm:[&_svg:not([class*='size-'])]:size-3.5";
|
|
17
17
|
readonly icon: "size-8";
|
|
18
18
|
readonly 'icon-xs': "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3";
|
|
19
19
|
readonly 'icon-sm': "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg";
|
|
@@ -28,10 +28,17 @@ declare const buttonVariants: (props?: ({
|
|
|
28
28
|
/**
|
|
29
29
|
* Props for `Button`. Inherits additional behavior from
|
|
30
30
|
* [Base UI Button](https://base-ui.com/react/components/button).
|
|
31
|
+
*
|
|
32
|
+
* When `loading` is true: shows a centered {@link Spinner}, sets `data-loading` on the root,
|
|
33
|
+
* uses `text-transparent` so label and icons stay mounted but invisible (inherited color), sets
|
|
34
|
+
* explicit `color` on `[data-slot="button-loading-indicator"]` per variant, forces `disabled`,
|
|
35
|
+
* and sets `aria-busy`.
|
|
31
36
|
*/
|
|
32
37
|
export type ButtonProps = ButtonPrimitive.Props & VariantProps<typeof buttonVariants> & {
|
|
33
38
|
className?: string;
|
|
39
|
+
/** Shows a spinner and non-interactive disabled behavior while true. */
|
|
40
|
+
loading?: boolean;
|
|
34
41
|
};
|
|
35
|
-
declare function Button({ className, variant, size, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
42
|
+
declare function Button({ className, variant, size, loading, disabled, children, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
36
43
|
export { Button, buttonVariants };
|
|
37
44
|
//# sourceMappingURL=button.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/components/button/button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/components/button/button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKlE,QAAA,MAAM,mBAAmB;;;;;;;;CAaf,CAAC;AAEX,QAAA,MAAM,gBAAgB;;;;;;;;;CAUZ,CAAC;AAEX,eAAO,MAAM,iBAAiB,EAAuC,CAAC,MAAM,OAAO,mBAAmB,CAAC,EAAE,CAAC;AAE1G,eAAO,MAAM,cAAc,EAAoC,CAAC,MAAM,OAAO,gBAAgB,CAAC,EAAE,CAAC;AAEjG,QAAA,MAAM,cAAc;;;8EAYnB,CAAC;AAaF;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC,KAAK,GAC3C,YAAY,CAAC,OAAO,cAAc,CAAC,GAAG;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEN,iBAAS,MAAM,CAAC,EAAE,SAAS,EAAE,OAAmB,EAAE,IAAgB,EAAE,OAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,WAAW,2CAqB/H;AAED,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Button as ButtonPrimitive } from '@base-ui/react/button';
|
|
3
3
|
import { cva } from 'class-variance-authority';
|
|
4
4
|
import { cn } from '../../lib/utils';
|
|
5
|
+
import { Spinner } from '../spinner';
|
|
5
6
|
const buttonVariantStyles = {
|
|
6
|
-
default: 'border-primary bg-primary text-primary-foreground shadow-xs shadow-primary/24 not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] hover:bg-primary/90 data-pressed:bg-primary/90 [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none',
|
|
7
|
-
outline: 'border-input bg-popover text-foreground shadow-xs/5 not-dark:bg-clip-padding not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] hover:bg-accent/50 data-pressed:bg-accent/50 dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] dark:hover:bg-input/64 dark:data-pressed:bg-input/64 [:disabled,:active,[data-pressed]]:shadow-none',
|
|
8
|
-
secondary: 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/90 data-pressed:bg-secondary/90 [:active,[data-pressed]]:bg-secondary/80',
|
|
9
|
-
ghost: 'hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50',
|
|
10
|
-
destructive: 'border-destructive-foreground/10 bg-destructive/50 text-destructive-foreground shadow-xs shadow-destructive-foreground/10 hover:bg-destructive/80 data-pressed:bg-destructive/70 [:disabled,:active,[data-pressed]]:shadow-none',
|
|
11
|
-
'destructive-outline': 'border-destructive-foreground/10 border-destructive-foreground/15 bg-popover text-destructive-foreground shadow-xs shadow-destructive-foreground/3 not-dark:bg-clip-padding not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] hover:bg-destructive/50 data-pressed:border-destructive-foreground/32 data-pressed:bg-destructive-foreground/8
|
|
12
|
-
link: 'text-primary underline-offset-4 hover:underline',
|
|
7
|
+
default: 'border-primary bg-primary text-primary-foreground shadow-xs shadow-primary/24 not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] hover:bg-primary/90 data-pressed:bg-primary/90 [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none [&_[data-slot=button-loading-indicator]]:text-primary-foreground',
|
|
8
|
+
outline: 'border-input bg-popover text-foreground shadow-xs/5 not-dark:bg-clip-padding not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] hover:bg-accent/50 data-pressed:bg-accent/50 dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] dark:hover:bg-input/64 dark:data-pressed:bg-input/64 [:disabled,:active,[data-pressed]]:shadow-none [&_[data-slot=button-loading-indicator]]:text-foreground',
|
|
9
|
+
secondary: 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/90 data-pressed:bg-secondary/90 [:active,[data-pressed]]:bg-secondary/80 [&_[data-slot=button-loading-indicator]]:text-secondary-foreground',
|
|
10
|
+
ghost: 'hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50 [&_[data-slot=button-loading-indicator]]:text-foreground',
|
|
11
|
+
destructive: 'border-destructive-foreground/10 bg-destructive/50 text-destructive-foreground shadow-xs shadow-destructive-foreground/10 hover:bg-destructive/80 data-pressed:bg-destructive/70 [:disabled,:active,[data-pressed]]:shadow-none [&_[data-slot=button-loading-indicator]]:text-destructive-foreground',
|
|
12
|
+
'destructive-outline': 'border-destructive-foreground/10 border-destructive-foreground/15 bg-popover text-destructive-foreground shadow-xs shadow-destructive-foreground/3 not-dark:bg-clip-padding not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] hover:bg-destructive/50 data-pressed:border-destructive-foreground/32 data-pressed:bg-destructive-foreground/8 dark:border-destructive-foreground/30 dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [&_[data-slot=button-loading-indicator]]:text-destructive-foreground',
|
|
13
|
+
link: 'text-primary underline-offset-4 hover:underline [&_[data-slot=button-loading-indicator]]:text-primary',
|
|
13
14
|
};
|
|
14
15
|
const buttonSizeStyles = {
|
|
15
|
-
default:
|
|
16
|
+
default: "h-8 gap-2 px-[calc(--spacing(3)-1px)] has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3 sm:[&_svg:not([class*='size-'])]:size-3",
|
|
16
17
|
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
17
|
-
sm: "h-7 gap-1.5 rounded-[min(var(--radius-md),12px)] px-[calc(--spacing(2.5)-1px)] text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-
|
|
18
|
-
lg:
|
|
18
|
+
sm: "h-7 gap-1.5 rounded-[min(var(--radius-md),12px)] px-[calc(--spacing(2.5)-1px)] text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3.5 sm:[&_svg:not([class*='size-'])]:size-3.5",
|
|
19
|
+
lg: "h-9 gap-1.5 px-[calc(--spacing(3.5)-1px)] has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3 sm:text-base [&_svg:not([class*='size-'])]:size-3.5 sm:[&_svg:not([class*='size-'])]:size-3.5",
|
|
19
20
|
icon: 'size-8',
|
|
20
21
|
'icon-xs': "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
|
21
22
|
'icon-sm': 'size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg',
|
|
@@ -23,7 +24,7 @@ const buttonSizeStyles = {
|
|
|
23
24
|
};
|
|
24
25
|
export const buttonVariantKeys = Object.keys(buttonVariantStyles);
|
|
25
26
|
export const buttonSizeKeys = Object.keys(buttonSizeStyles);
|
|
26
|
-
const buttonVariants = cva("group/button relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-md border border-transparent text-base font-medium whitespace-nowrap transition-shadow outline-none [text-box-edge:cap_alphabetic] [text-box-trim:trim-both] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 disabled:shadow-none disabled:inset-shadow-none disabled:before:shadow-none in-data-[slot=button-group]:before:rounded-none sm:text-sm pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 data-disabled:cursor-not-allowed data-disabled:opacity-50 data-disabled:shadow-none data-disabled:inset-shadow-none data-disabled:before:shadow-none [&_svg]:pointer-events-none [&_svg]:-mx-0.5 [&_svg]:shrink-0 [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4", {
|
|
27
|
+
const buttonVariants = cva("group/button relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-md border border-transparent text-base font-medium whitespace-nowrap transition-shadow outline-none [text-box-edge:cap_alphabetic] [text-box-trim:trim-both] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 disabled:shadow-none disabled:inset-shadow-none disabled:before:shadow-none in-data-[slot=button-group]:before:rounded-none data-loading:text-transparent data-loading:select-none sm:text-sm pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 data-disabled:cursor-not-allowed data-disabled:opacity-50 data-disabled:shadow-none data-disabled:inset-shadow-none data-disabled:before:shadow-none [&_svg]:pointer-events-none [&_svg]:-mx-0.5 [&_svg]:shrink-0 [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4", {
|
|
27
28
|
variants: {
|
|
28
29
|
variant: buttonVariantStyles,
|
|
29
30
|
size: buttonSizeStyles,
|
|
@@ -33,7 +34,19 @@ const buttonVariants = cva("group/button relative inline-flex shrink-0 cursor-po
|
|
|
33
34
|
size: 'default',
|
|
34
35
|
},
|
|
35
36
|
});
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
const spinnerSizeByButtonSize = {
|
|
38
|
+
default: 'size-3 sm:size-3',
|
|
39
|
+
xs: 'size-3',
|
|
40
|
+
sm: 'size-3.5 sm:size-3.5',
|
|
41
|
+
lg: 'size-3.5 sm:size-3.5',
|
|
42
|
+
icon: 'size-4',
|
|
43
|
+
'icon-xs': 'size-3',
|
|
44
|
+
'icon-sm': 'size-3.5',
|
|
45
|
+
'icon-lg': 'size-4',
|
|
46
|
+
};
|
|
47
|
+
function Button({ className, variant = 'default', size = 'default', loading = false, disabled, children, ...props }) {
|
|
48
|
+
const isDisabled = Boolean(disabled || loading);
|
|
49
|
+
const spinnerClass = spinnerSizeByButtonSize[size ?? 'default'];
|
|
50
|
+
return (_jsxs(ButtonPrimitive, { "data-slot": "button", "data-loading": loading || undefined, className: cn(buttonVariants({ variant, size, className })), disabled: isDisabled, "aria-busy": loading || undefined, ...props, children: [children, loading ? (_jsx("span", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", "aria-hidden": true, children: _jsx(Spinner, { "data-slot": "button-loading-indicator", "aria-hidden": true, className: cn('shrink-0', spinnerClass) }) })) : null] }));
|
|
38
51
|
}
|
|
39
52
|
export { Button, buttonVariants };
|
|
@@ -13,4 +13,15 @@ export declare const DestructiveOutline: Story;
|
|
|
13
13
|
export declare const Link: Story;
|
|
14
14
|
export declare const Small: Story;
|
|
15
15
|
export declare const Large: Story;
|
|
16
|
+
export declare const Icon: Story;
|
|
17
|
+
export declare const WithIcon: Story;
|
|
18
|
+
export declare const Rounded: Story;
|
|
19
|
+
export declare const Loading: Story;
|
|
20
|
+
export declare const LoadingInteractive: Story;
|
|
21
|
+
export declare const LoadingWithIcon: Story;
|
|
22
|
+
export declare const LoadingIconOnly: Story;
|
|
23
|
+
/** Manual composition when you need a custom indicator or copy outside the built-in `loading` prop. */
|
|
24
|
+
export declare const Spinner: Story;
|
|
25
|
+
export declare const ButtonGroup: Story;
|
|
26
|
+
export declare const AsLink: Story;
|
|
16
27
|
//# sourceMappingURL=button.stories.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.stories.d.ts","sourceRoot":"","sources":["../../../src/components/button/button.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"button.stories.d.ts","sourceRoot":"","sources":["../../../src/components/button/button.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAMvD,OAAO,EAAE,MAAM,EAAqC,MAAM,UAAU,CAAC;AAErE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,MAAM,CA4B7B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAgDnC,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,OAAO,EAAE,KAiBrB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAGrB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAGvB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAGnB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAGzB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAGhC,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAGlB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAGnB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAGnB,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAuBlB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAgBtB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAiBrB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAUrB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAsBhC,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAiB7B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAqB7B,CAAC;AAEF,uGAAuG;AACvG,eAAO,MAAM,OAAO,EAAE,KAoBrB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAiBzB,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,KAepB,CAAC"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { ChevronRight, Download, Plus } from 'lucide-react';
|
|
4
|
+
import { ButtonGroup as ButtonGroupRoot } from '../button-group';
|
|
5
|
+
import { Spinner as LoadingSpinner } from '../spinner';
|
|
2
6
|
import { Button, buttonSizeKeys, buttonVariantKeys } from './button';
|
|
3
7
|
const meta = {
|
|
4
|
-
title: '
|
|
8
|
+
title: 'Components/Button',
|
|
5
9
|
component: Button,
|
|
6
10
|
parameters: {
|
|
7
11
|
layout: 'centered',
|
|
@@ -26,6 +30,7 @@ const meta = {
|
|
|
26
30
|
control: 'select',
|
|
27
31
|
options: buttonSizeKeys,
|
|
28
32
|
},
|
|
33
|
+
loading: { control: 'boolean' },
|
|
29
34
|
},
|
|
30
35
|
};
|
|
31
36
|
export default meta;
|
|
@@ -78,3 +83,82 @@ export const Large = {
|
|
|
78
83
|
tags: ['!autodocs'],
|
|
79
84
|
args: { size: 'lg' },
|
|
80
85
|
};
|
|
86
|
+
export const Icon = {
|
|
87
|
+
parameters: {
|
|
88
|
+
layout: 'centered',
|
|
89
|
+
},
|
|
90
|
+
render: () => (_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsx(Button, { variant: "outline", size: "icon-xs", "aria-label": "Add", children: _jsx(Plus, {}) }), _jsx(Button, { variant: "outline", size: "icon-sm", "aria-label": "Add", children: _jsx(Plus, {}) }), _jsx(Button, { variant: "outline", size: "icon", "aria-label": "Add", children: _jsx(Plus, {}) }), _jsx(Button, { variant: "outline", size: "icon-lg", "aria-label": "Add", children: _jsx(Plus, {}) }), _jsx(Button, { variant: "default", size: "icon", "aria-label": "Add", children: _jsx(Plus, {}) })] })),
|
|
91
|
+
};
|
|
92
|
+
export const WithIcon = {
|
|
93
|
+
parameters: {
|
|
94
|
+
layout: 'centered',
|
|
95
|
+
},
|
|
96
|
+
render: () => (_jsxs("div", { className: "flex flex-col items-start gap-3", children: [_jsxs(Button, { variant: "outline", size: "sm", children: [_jsx(Download, { "data-icon": "inline-start" }), "Download"] }), _jsxs(Button, { variant: "default", size: "sm", children: ["Continue", _jsx(ChevronRight, { "data-icon": "inline-end" })] })] })),
|
|
97
|
+
};
|
|
98
|
+
export const Rounded = {
|
|
99
|
+
parameters: {
|
|
100
|
+
layout: 'centered',
|
|
101
|
+
},
|
|
102
|
+
render: () => (_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsx(Button, { className: "rounded-full", size: "sm", children: "Pill default" }), _jsx(Button, { variant: "outline", className: "rounded-full", size: "sm", children: "Pill outline" }), _jsx(Button, { variant: "secondary", className: "rounded-full", size: "sm", children: "Pill secondary" })] })),
|
|
103
|
+
};
|
|
104
|
+
export const Loading = {
|
|
105
|
+
parameters: {
|
|
106
|
+
layout: 'centered',
|
|
107
|
+
},
|
|
108
|
+
args: {
|
|
109
|
+
loading: true,
|
|
110
|
+
children: 'Submit',
|
|
111
|
+
variant: 'default',
|
|
112
|
+
size: 'sm',
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
export const LoadingInteractive = {
|
|
116
|
+
parameters: {
|
|
117
|
+
layout: 'centered',
|
|
118
|
+
controls: { disable: true },
|
|
119
|
+
},
|
|
120
|
+
render: function LoadingInteractiveRender() {
|
|
121
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
122
|
+
return (_jsx(Button, { loading: isLoading, onClick: () => {
|
|
123
|
+
setIsLoading(true);
|
|
124
|
+
window.setTimeout(() => {
|
|
125
|
+
setIsLoading(false);
|
|
126
|
+
}, 1200);
|
|
127
|
+
}, children: "Submit" }));
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
export const LoadingWithIcon = {
|
|
131
|
+
tags: ['!autodocs'],
|
|
132
|
+
parameters: {
|
|
133
|
+
layout: 'centered',
|
|
134
|
+
},
|
|
135
|
+
render: () => (_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsxs(Button, { variant: "outline", size: "sm", loading: true, children: [_jsx(Download, { "data-icon": "inline-start" }), "Download"] }), _jsxs(Button, { variant: "default", size: "sm", loading: true, children: ["Continue", _jsx(ChevronRight, { "data-icon": "inline-end" })] })] })),
|
|
136
|
+
};
|
|
137
|
+
export const LoadingIconOnly = {
|
|
138
|
+
tags: ['!autodocs'],
|
|
139
|
+
parameters: {
|
|
140
|
+
layout: 'centered',
|
|
141
|
+
},
|
|
142
|
+
render: () => (_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsx(Button, { variant: "outline", size: "icon-xs", "aria-label": "Saving", loading: true, children: _jsx(Plus, { "aria-hidden": true }) }), _jsx(Button, { variant: "outline", size: "icon-sm", "aria-label": "Saving", loading: true, children: _jsx(Plus, { "aria-hidden": true }) }), _jsx(Button, { variant: "outline", size: "icon", "aria-label": "Saving", loading: true, children: _jsx(Plus, { "aria-hidden": true }) }), _jsx(Button, { variant: "outline", size: "icon-lg", "aria-label": "Saving", loading: true, children: _jsx(Plus, { "aria-hidden": true }) })] })),
|
|
143
|
+
};
|
|
144
|
+
/** Manual composition when you need a custom indicator or copy outside the built-in `loading` prop. */
|
|
145
|
+
export const Spinner = {
|
|
146
|
+
parameters: {
|
|
147
|
+
layout: 'centered',
|
|
148
|
+
},
|
|
149
|
+
render: () => (_jsxs("div", { className: "flex flex-col items-start gap-3", children: [_jsxs(Button, { variant: "outline", size: "sm", disabled: true, "aria-busy": "true", children: [_jsx("span", { "data-slot": "button-loading-indicator", className: "inline-flex", children: _jsx(LoadingSpinner, { className: "size-4", "aria-hidden": true }) }), "Saving\u2026"] }), _jsxs(Button, { variant: "destructive-outline", size: "sm", disabled: true, "aria-busy": "true", children: [_jsx("span", { "data-slot": "button-loading-indicator", className: "inline-flex", children: _jsx(LoadingSpinner, { className: "size-4", "aria-hidden": true }) }), "Removing\u2026"] })] })),
|
|
150
|
+
};
|
|
151
|
+
export const ButtonGroup = {
|
|
152
|
+
parameters: {
|
|
153
|
+
layout: 'centered',
|
|
154
|
+
},
|
|
155
|
+
render: () => (_jsxs(ButtonGroupRoot, { orientation: "horizontal", children: [_jsx(Button, { variant: "outline", size: "sm", children: "List" }), _jsx(Button, { variant: "outline", size: "sm", children: "Board" }), _jsx(Button, { variant: "outline", size: "sm", children: "Timeline" })] })),
|
|
156
|
+
};
|
|
157
|
+
export const AsLink = {
|
|
158
|
+
parameters: {
|
|
159
|
+
layout: 'centered',
|
|
160
|
+
},
|
|
161
|
+
render: () => (_jsx(Button, { variant: "link", size: "sm", nativeButton: false,
|
|
162
|
+
// eslint-disable-next-line jsx-a11y/anchor-has-content -- label provided as children
|
|
163
|
+
render: _jsx("a", { href: "https://example.com", rel: "noreferrer" }), children: "Visit example.com" })),
|
|
164
|
+
};
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
1
2
|
import { useRender } from '@base-ui/react/use-render';
|
|
2
3
|
import { type VariantProps } from 'class-variance-authority';
|
|
3
4
|
import { Separator } from '../separator';
|
|
5
|
+
declare const buttonGroupTextVariants: (props?: ({
|
|
6
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
7
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
4
8
|
declare const buttonGroupVariants: (props?: ({
|
|
5
9
|
orientation?: "horizontal" | "vertical" | null | undefined;
|
|
6
10
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
11
|
/** Props for `ButtonGroup`. */
|
|
8
|
-
export type ButtonGroupProps =
|
|
12
|
+
export type ButtonGroupProps = ComponentProps<'div'> & VariantProps<typeof buttonGroupVariants>;
|
|
9
13
|
declare function ButtonGroup({ className, orientation, ...props }: ButtonGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
/** Props for `ButtonGroupText`. */
|
|
15
|
+
export type ButtonGroupTextProps = useRender.ComponentProps<'div'> & VariantProps<typeof buttonGroupTextVariants>;
|
|
16
|
+
declare function ButtonGroupText({ className, size, render, ...props }: ButtonGroupTextProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
17
|
+
declare function ButtonGroupSeparator({ className, orientation, ...props }: ComponentProps<typeof Separator>): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupTextVariants, buttonGroupVariants };
|
|
13
19
|
//# sourceMappingURL=button-group.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button-group.d.ts","sourceRoot":"","sources":["../../../src/components/button-group/button-group.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"button-group.d.ts","sourceRoot":"","sources":["../../../src/components/button-group/button-group.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,QAAA,MAAM,uBAAuB;;8EAW3B,CAAC;AAEH,QAAA,MAAM,mBAAmB;;8EAexB,CAAC;AAEF,+BAA+B;AAC/B,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhG,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,WAA0B,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB,2CAIzF;AAED,mCAAmC;AACnC,MAAM,MAAM,oBAAoB,GAAG,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAElH,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,8FAcnF;AAED,iBAAS,oBAAoB,CAAC,EAAE,SAAS,EAAE,WAAwB,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,2CAShH;AAED,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,eAAe,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -4,6 +4,18 @@ import { useRender } from '@base-ui/react/use-render';
|
|
|
4
4
|
import { cva } from 'class-variance-authority';
|
|
5
5
|
import { cn } from '../../lib/utils';
|
|
6
6
|
import { Separator } from '../separator';
|
|
7
|
+
const buttonGroupTextVariants = cva('flex shrink-0 items-center gap-2 rounded-lg border bg-muted font-medium [&_svg]:pointer-events-none', {
|
|
8
|
+
variants: {
|
|
9
|
+
size: {
|
|
10
|
+
sm: "h-7 px-2 text-[0.8rem] leading-none [&_svg:not([class*='size-'])]:size-3.5",
|
|
11
|
+
default: "min-h-8 px-2.5 text-sm [&_svg:not([class*='size-'])]:size-4",
|
|
12
|
+
lg: "h-9 px-3 text-base [&_svg:not([class*='size-'])]:size-4",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
size: 'default',
|
|
17
|
+
},
|
|
18
|
+
});
|
|
7
19
|
const buttonGroupVariants = cva("flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-lg [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1", {
|
|
8
20
|
variants: {
|
|
9
21
|
orientation: {
|
|
@@ -18,11 +30,11 @@ const buttonGroupVariants = cva("flex w-fit items-stretch *:focus-visible:relati
|
|
|
18
30
|
function ButtonGroup({ className, orientation = 'horizontal', ...props }) {
|
|
19
31
|
return (_jsx("div", { role: "group", "data-slot": "button-group", "data-orientation": orientation, className: cn(buttonGroupVariants({ orientation }), className), ...props }));
|
|
20
32
|
}
|
|
21
|
-
function ButtonGroupText({ className, render, ...props }) {
|
|
33
|
+
function ButtonGroupText({ className, size, render, ...props }) {
|
|
22
34
|
return useRender({
|
|
23
35
|
defaultTagName: 'div',
|
|
24
36
|
props: mergeProps({
|
|
25
|
-
className: cn(
|
|
37
|
+
className: cn(buttonGroupTextVariants({ size }), className),
|
|
26
38
|
}, props),
|
|
27
39
|
render,
|
|
28
40
|
state: {
|
|
@@ -33,4 +45,4 @@ function ButtonGroupText({ className, render, ...props }) {
|
|
|
33
45
|
function ButtonGroupSeparator({ className, orientation = 'vertical', ...props }) {
|
|
34
46
|
return (_jsx(Separator, { "data-slot": "button-group-separator", orientation: orientation, className: cn('relative self-stretch bg-input data-horizontal:mx-px data-horizontal:w-auto data-vertical:my-px data-vertical:h-auto', className), ...props }));
|
|
35
47
|
}
|
|
36
|
-
export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants };
|
|
48
|
+
export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupTextVariants, buttonGroupVariants };
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Button } from '../button';
|
|
3
3
|
import { ButtonGroup, ButtonGroupSeparator, ButtonGroupText } from './button-group';
|
|
4
4
|
const meta = {
|
|
5
|
-
title: '
|
|
5
|
+
title: 'Components/ButtonGroup',
|
|
6
6
|
component: ButtonGroup,
|
|
7
7
|
parameters: {
|
|
8
8
|
layout: 'centered',
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants } from './button-group';
|
|
2
|
-
export type { ButtonGroupProps } from './button-group';
|
|
1
|
+
export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupTextVariants, buttonGroupVariants } from './button-group';
|
|
2
|
+
export type { ButtonGroupProps, ButtonGroupTextProps } from './button-group';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/button-group/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/button-group/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,eAAe,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAClI,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants } from './button-group';
|
|
1
|
+
export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupTextVariants, buttonGroupVariants } from './button-group';
|