@lessly/ui 4.1.1 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-LTHOLX7I.js → chunk-OMJRQ4JY.js} +33 -3
- package/dist/index.d.ts +47 -3
- package/dist/index.js +31 -11
- package/dist/router.d.ts +27 -6
- package/dist/router.js +128 -44
- package/dist/styles-federated.css +48 -12
- package/dist/styles.css +48 -12
- package/dist/tailwind-preset.js +30 -4
- package/package.json +2 -2
|
@@ -256,7 +256,11 @@ var SheetOverlay = React3.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
256
256
|
{
|
|
257
257
|
ref,
|
|
258
258
|
className: cn(
|
|
259
|
-
|
|
259
|
+
// The scrim's state-scoped pair is the panel's below, so the two arrive as one — and an
|
|
260
|
+
// unprefixed 500 would slow the close as well as the open. Naming a duration at all is what
|
|
261
|
+
// makes `prefers-reduced-motion` reach the fade: an unset `--tw-duration` falls to
|
|
262
|
+
// tw-animate-css's own literal 0.15s, which no media query can collapse.
|
|
263
|
+
"fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:duration-300 data-[state=open]:duration-500",
|
|
260
264
|
className
|
|
261
265
|
),
|
|
262
266
|
...props
|
|
@@ -613,13 +617,16 @@ function RailMark({ collapsed, className }) {
|
|
|
613
617
|
}
|
|
614
618
|
);
|
|
615
619
|
}
|
|
620
|
+
function railToggleLabel(collapsed) {
|
|
621
|
+
return collapsed ? "Expand sidebar" : "Collapse sidebar";
|
|
622
|
+
}
|
|
616
623
|
var RailToggle = React7.forwardRef(function RailToggle2({ collapsed, className, "aria-label": ariaLabel, ...rest }, ref) {
|
|
617
624
|
return /* @__PURE__ */ jsx7(
|
|
618
625
|
"button",
|
|
619
626
|
{
|
|
620
627
|
ref,
|
|
621
628
|
type: "button",
|
|
622
|
-
"aria-label": ariaLabel ?? (collapsed
|
|
629
|
+
"aria-label": ariaLabel ?? railToggleLabel(collapsed),
|
|
623
630
|
"aria-expanded": !collapsed,
|
|
624
631
|
className: cn(
|
|
625
632
|
RAIL_COLUMN_BOX,
|
|
@@ -632,6 +639,25 @@ var RailToggle = React7.forwardRef(function RailToggle2({ collapsed, className,
|
|
|
632
639
|
);
|
|
633
640
|
});
|
|
634
641
|
|
|
642
|
+
// src/hooks/use-sidebar-drawer.ts
|
|
643
|
+
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
644
|
+
var SidebarDrawerContext = createContext2(false);
|
|
645
|
+
function useSidebarDrawer() {
|
|
646
|
+
return useContext2(SidebarDrawerContext);
|
|
647
|
+
}
|
|
648
|
+
var NOT_IN_A_DRAWER = () => {
|
|
649
|
+
};
|
|
650
|
+
var SidebarDrawerDismissContext = createContext2(null);
|
|
651
|
+
function useSidebarDismiss() {
|
|
652
|
+
return useContext2(SidebarDrawerDismissContext) ?? NOT_IN_A_DRAWER;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// src/components/sidebar-drawer.tsx
|
|
656
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
657
|
+
function SidebarDrawer({ children, onDismiss }) {
|
|
658
|
+
return /* @__PURE__ */ jsx8(SidebarDrawerContext.Provider, { value: true, children: /* @__PURE__ */ jsx8(SidebarDrawerDismissContext.Provider, { value: onDismiss ?? null, children }) });
|
|
659
|
+
}
|
|
660
|
+
|
|
635
661
|
export {
|
|
636
662
|
cn,
|
|
637
663
|
buttonVariants,
|
|
@@ -657,5 +683,9 @@ export {
|
|
|
657
683
|
useSidebar,
|
|
658
684
|
NavRow,
|
|
659
685
|
RAIL_COLUMN_BOX,
|
|
660
|
-
|
|
686
|
+
railToggleLabel,
|
|
687
|
+
RailToggle,
|
|
688
|
+
useSidebarDrawer,
|
|
689
|
+
useSidebarDismiss,
|
|
690
|
+
SidebarDrawer
|
|
661
691
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -2551,6 +2551,11 @@ type NavRowProps = NavRowOwnProps & Omit<React$1.ComponentPropsWithoutRef<'butto
|
|
|
2551
2551
|
* not an entity opening as a page, so the hover fill is the whole affordance. */
|
|
2552
2552
|
declare const NavRow: React$1.ForwardRefExoticComponent<NavRowProps & React$1.RefAttributes<HTMLButtonElement>>;
|
|
2553
2553
|
|
|
2554
|
+
/** What the control answers to, from the state it is in: the name says what the press will do, so a
|
|
2555
|
+
* closed rail's control is `Expand sidebar`. It is a function rather than two strings at the call
|
|
2556
|
+
* site because the tooltip a call site composes has to say what the control is called — and two
|
|
2557
|
+
* hand-written copies of a pair like this are two copies to keep in step. */
|
|
2558
|
+
declare function railToggleLabel(collapsed: boolean): string;
|
|
2554
2559
|
interface RailToggleProps extends React$1.ComponentPropsWithoutRef<'button'> {
|
|
2555
2560
|
/** Which state the rail is in now, not what the press will do. The mark and the accessible name
|
|
2556
2561
|
* are both read off it, so a rail cannot say one thing and draw another. */
|
|
@@ -2574,7 +2579,9 @@ interface RailToggleProps extends React$1.ComponentPropsWithoutRef<'button'> {
|
|
|
2574
2579
|
* console gives the control the words its command palette already uses for it.
|
|
2575
2580
|
*
|
|
2576
2581
|
* No tooltip of its own. On a closed rail every neighbour has one, so the call site composes it —
|
|
2577
|
-
* and the label it shows is
|
|
2582
|
+
* and the label it shows is `railToggleLabel(collapsed)`, the same resolver the accessible name
|
|
2583
|
+
* above falls back to, so the two cannot say different things. `AppSidebar` composes exactly that
|
|
2584
|
+
* at its foot.
|
|
2578
2585
|
*/
|
|
2579
2586
|
declare const RailToggle: React$1.ForwardRefExoticComponent<RailToggleProps & React$1.RefAttributes<HTMLButtonElement>>;
|
|
2580
2587
|
|
|
@@ -2586,6 +2593,14 @@ interface QuickSearchRowProps {
|
|
|
2586
2593
|
/**
|
|
2587
2594
|
* The second way in, stated rather than implied — this is the one fact a person needs before they
|
|
2588
2595
|
* stop reaching for the sidebar at all. `false` for a rail with no shortcut bound.
|
|
2596
|
+
*
|
|
2597
|
+
* Only an unset prop takes the default. `false` and `null` both mean this rail has no shortcut,
|
|
2598
|
+
* on either surface — `shortcut={binding ?? null}` is the shape a caller reaches for and it has
|
|
2599
|
+
* to mean what it says.
|
|
2600
|
+
*
|
|
2601
|
+
* Unset, it is `⌘K` on a rail and nothing at all inside a `<SidebarDrawer>`: a drawer is the
|
|
2602
|
+
* shape a phone gets, and a phone has no key to press. Set, it is what the row states on either
|
|
2603
|
+
* surface — a drawer opened on a tablet with a keyboard really does have one.
|
|
2589
2604
|
*/
|
|
2590
2605
|
shortcut?: React$1.ReactNode;
|
|
2591
2606
|
/**
|
|
@@ -2613,6 +2628,26 @@ declare namespace QuickSearchRow {
|
|
|
2613
2628
|
var displayName: string;
|
|
2614
2629
|
}
|
|
2615
2630
|
|
|
2631
|
+
/** Marks everything below as drawn inside a drawer — a rail, and every part it holds — and hands it
|
|
2632
|
+
* the way out. `AppShell` wraps its sheet's contents in it and passes its own close as `onDismiss`,
|
|
2633
|
+
* which is what lets a rail that navigates by state close the sheet it navigated in. A product that
|
|
2634
|
+
* builds its own rail inside its own sheet writes this itself; without it every such rail keeps
|
|
2635
|
+
* printing ⌘K on a phone.
|
|
2636
|
+
*
|
|
2637
|
+
* Its own module, and not beside `AppSidebar`. This ships from `@lessly/ui` while the rail ships
|
|
2638
|
+
* from `@lessly/ui/router`, and a module both entries reach lands in the chunk they share — so
|
|
2639
|
+
* written in `app-sidebar.tsx` this dragged `react-router` into `import { Button } from
|
|
2640
|
+
* '@lessly/ui'` and broke resolution for a consumer who skipped the optional peer (#878). Nothing
|
|
2641
|
+
* here imports anything but React and the contexts. */
|
|
2642
|
+
declare function SidebarDrawer({ children, onDismiss }: {
|
|
2643
|
+
children: React$1.ReactNode;
|
|
2644
|
+
onDismiss?: () => void;
|
|
2645
|
+
}): React$1.JSX.Element;
|
|
2646
|
+
|
|
2647
|
+
/** How a part inside a drawer closes it. Outside one it is a no-op, so a rail row can call it
|
|
2648
|
+
* unconditionally rather than asking which surface it is on first. */
|
|
2649
|
+
declare function useSidebarDismiss(): () => void;
|
|
2650
|
+
|
|
2616
2651
|
type NavSectionLabelProps = React$1.HTMLAttributes<HTMLDivElement>;
|
|
2617
2652
|
/** Section header for nav rails and menu popups. Insets match the 0.3.0 prototype
|
|
2618
2653
|
* (4px 4px 2px 8px), so it hangs slightly left of the rows it labels. */
|
|
@@ -2754,6 +2789,15 @@ interface OrgProductSwitcherProps {
|
|
|
2754
2789
|
* console offers it.
|
|
2755
2790
|
*/
|
|
2756
2791
|
trigger?: 'stacked' | 'inline';
|
|
2792
|
+
/**
|
|
2793
|
+
* Whether the `stacked` trigger draws its own leading mark, or holds the place open and draws
|
|
2794
|
+
* nothing in it. `hold` is for a surface that draws that mark itself and can only carry one: a
|
|
2795
|
+
* rail stands the organization's mark on its glyph column at both widths, and a trigger drawing
|
|
2796
|
+
* a second puts two marks 2px apart in one band. The place is held rather than closed so the name
|
|
2797
|
+
* starts on the column it starts on either way, and the trigger's own box is untouched, so the
|
|
2798
|
+
* menu anchors where it did. The `inline` trigger has never drawn a mark and reads neither value.
|
|
2799
|
+
*/
|
|
2800
|
+
mark?: 'draw' | 'hold';
|
|
2757
2801
|
/** Accessible name for the trigger. Defaults to `"<org> / <product>"`, and to whatever the
|
|
2758
2802
|
* trigger reads before an org resolves. */
|
|
2759
2803
|
'aria-label'?: string;
|
|
@@ -2776,7 +2820,7 @@ interface OrgProductSwitcherProps {
|
|
|
2776
2820
|
* `activeProductId` for the newly-selected org. Wiring org/product switches to routing is the
|
|
2777
2821
|
* consumer's job.
|
|
2778
2822
|
*/
|
|
2779
|
-
declare function OrgProductSwitcher({ organizations, activeOrgId, onOrgSelect, products, activeProductId, onProductSelect, actions, trigger, className, ...props }: OrgProductSwitcherProps): React$1.JSX.Element;
|
|
2823
|
+
declare function OrgProductSwitcher({ organizations, activeOrgId, onOrgSelect, products, activeProductId, onProductSelect, actions, trigger, mark, className, ...props }: OrgProductSwitcherProps): React$1.JSX.Element;
|
|
2780
2824
|
declare namespace OrgProductSwitcher {
|
|
2781
2825
|
var displayName: string;
|
|
2782
2826
|
}
|
|
@@ -3780,4 +3824,4 @@ interface RatingScaleProps extends Omit<React$1.ComponentPropsWithoutRef<typeof
|
|
|
3780
3824
|
}
|
|
3781
3825
|
declare const RatingScale: React$1.ForwardRefExoticComponent<RatingScaleProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
3782
3826
|
|
|
3783
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AddPicker, type AddPickerItem, type AddPickerProps, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AspectRatio, AttachmentChip, type AttachmentChipProps, type AttachmentState, AutoHeight, type AutoHeightProps, Avatar, AvatarFallback, AvatarImage, BackLink, type BackLinkProps, Badge, type BadgeProps, type BeneficialOwnerPayload, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, type ButtonProps, COUNTRY_OPTIONS, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardNote, type CardNoteProps, type CardProps, CardTitle, type CardTitleProps, Carousel, type CarouselApi, CarouselContent, type CarouselContextProps, CarouselItem, CarouselNext, type CarouselOptions, type CarouselPlugin, CarouselPrevious, type CarouselProps, Checkbox, Code, CodeBlock, type CodeBlockProps, type CodeLang, type CodeProps, type CodeVariant, Col, type ColProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, type CommandDialogGroup, type CommandDialogItem, type CommandDialogProps, CommandEmpty, CommandGroup, CommandInput, CommandItem, type CommandItemProps, CommandList, CommandSeparator, CommandShortcut, ConfirmDialog, type ConfirmDialogProps, type ConfirmDialogStepUp, ConnectorCard, type ConnectorCardProps, type ConnectorOrigin, type ConnectorStatus, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, type CopyButtonProps, DatePicker, type DatePickerProps, DecorativeIcon, type DecorativeIconProps, type DeltaDirection, type DeltaTone, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DocsLink, type DocsLinkProps, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, EntityRow, type EntityRowOpens, type EntityRowOpensProps, type EntityRowProps, EntityTile, type EntityTileProps, ExtensionIcon, type ExtensionIconProps, FeedbackButton, type FeedbackButtonLabels, type FeedbackButtonProps, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, GlyphAvatar, type GlyphAvatarProps, type GrantRole, type GrantRoleNotes, GrantRolePicker, type GrantRolePickerProps, GrantRow, type GrantRowProps, Grid, GridOverlay, type GridOverlayProps, type GridProps, HoverCard, HoverCardContent, HoverCardTrigger, IconHint, type IconHintProps, ImageCropDialog, type ImageCropDialogProps, type ImageCropShape, type ImageCropType, ImageCropper, type ImageCropperProps, ImageUpload, type ImageUploadProps, type ImageUploadSize, InlineError, type InlineErrorProps, Input, InputAddon, type InputAddonProps, InputGroup, InputGroupInput, type InputGroupInputProps, type InputGroupProps, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Label, ListCells, type ListCellsProps, type ListColumn, type ListColumnWidth, ListHeader, type ListHeaderProps, MISSING_TONE, Medallion, type MedallionProps, MenuDivider, MenuPopup, type MenuPopupProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, NavRow, type NavRowMark, type NavRowProps, type NavRowVariant, NavSectionLabel, type NavSectionLabelProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, type NotifClass, type NotificationAction, NotificationBell, type NotificationBellProps, NotificationCenter, type NotificationCenterProps, type NotificationClass, type NotificationDeepLink, type NotificationItem, type NotificationMute, type NotificationPreferences, type NotificationProduct, NotificationRow, type NotificationRowProps, NotificationSettings, type NotificationSettingsProps, type NotificationSeverity, type NotificationSubscription, type NotificationThreshold, NotificationToast, type NotificationToastDwell, type NotificationToastProps, NotificationToaster, type NotificationToasterPosition, type NotificationToasterProps, OptionCard, type OptionCardProps, OrgProductSwitcher, type OrgProductSwitcherAction, type OrgProductSwitcherItem, type OrgProductSwitcherProduct, type OrgProductSwitcherProps, type OrganizationOnboardingDefaults, OrganizationOnboardingForm, type OrganizationOnboardingFormProps, type OrganizationOnboardingPayload, PageColumn, type PageColumnProps, PageHeader, type PageHeaderProps, type PageHeaderSize, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, type PaginationLinkProps, PaginationNext, PaginationPrevious, PersonAvatar, type PersonAvatarProps, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, type ProductStatus, Progress, QuickSearchRow, type QuickSearchRowProps, RadioGroup, RadioGroupItem, RailToggle, type RailToggleProps, RatingScale, type RatingScaleProps, type RatingScaleSize, RemovableChip, type RemovableChipProps, RemoveButton, type RemoveButtonProps, RequestRow, type RequestRowProps, type RequestState, type RequestSurface, type ResolvedTheme, type Responsive, ScrollArea, ScrollBar, SecretReveal, type SecretRevealProps, SectionIntro, type SectionIntroProps, Select, type SelectOption, type SelectProps, Separator, SettingRow, type SettingRowProps, type Severity, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarBackHeader, type SidebarBackHeaderProps, SidebarProductHeader, type SidebarProductHeaderProps, Skeleton, Slider, StarRating, type StarRatingProps, type StarRatingSize, StatCard, type StatCardProps, StatusDot, type StatusDotProps, StepUpChallenge, type StepUpChallengeProps, type StepUpMethod, type StepUpProof, Switch, type SwitchProps, TOAST_DWELL, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, type TableProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, type TextareaProps, type Theme, ThemePicker, type ThemePickerProps, ThemeToggle, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopBar, type TopBarProps, TopBarUtilities, type TopBarUtilitiesProps, type TopBarUtility, type UseFreshHighlightResult, type UseSidebarOptions, type UseSidebarResult, UserMenu, type UserMenuItem, type UserMenuProps, type UserMenuUser, WEIGHT_TONE, alertVariants, attachmentChipVariants, badgeVariants, buttonVariants, cn, formatRelativeAge, grantRemoveLabel, isKnownExtensionIcon, isNotificationSettled, navigationMenuTriggerStyle, productStatusBadge, severityBadgeVariant, severityLabels, statusDotVariants, toggleVariants, useCarousel, useFormField, useFreshHighlight, useIsMobile, useSidebar, useTheme };
|
|
3827
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AddPicker, type AddPickerItem, type AddPickerProps, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AspectRatio, AttachmentChip, type AttachmentChipProps, type AttachmentState, AutoHeight, type AutoHeightProps, Avatar, AvatarFallback, AvatarImage, BackLink, type BackLinkProps, Badge, type BadgeProps, type BeneficialOwnerPayload, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, type ButtonProps, COUNTRY_OPTIONS, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardNote, type CardNoteProps, type CardProps, CardTitle, type CardTitleProps, Carousel, type CarouselApi, CarouselContent, type CarouselContextProps, CarouselItem, CarouselNext, type CarouselOptions, type CarouselPlugin, CarouselPrevious, type CarouselProps, Checkbox, Code, CodeBlock, type CodeBlockProps, type CodeLang, type CodeProps, type CodeVariant, Col, type ColProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, type CommandDialogGroup, type CommandDialogItem, type CommandDialogProps, CommandEmpty, CommandGroup, CommandInput, CommandItem, type CommandItemProps, CommandList, CommandSeparator, CommandShortcut, ConfirmDialog, type ConfirmDialogProps, type ConfirmDialogStepUp, ConnectorCard, type ConnectorCardProps, type ConnectorOrigin, type ConnectorStatus, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, type CopyButtonProps, DatePicker, type DatePickerProps, DecorativeIcon, type DecorativeIconProps, type DeltaDirection, type DeltaTone, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DocsLink, type DocsLinkProps, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, EntityRow, type EntityRowOpens, type EntityRowOpensProps, type EntityRowProps, EntityTile, type EntityTileProps, ExtensionIcon, type ExtensionIconProps, FeedbackButton, type FeedbackButtonLabels, type FeedbackButtonProps, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, GlyphAvatar, type GlyphAvatarProps, type GrantRole, type GrantRoleNotes, GrantRolePicker, type GrantRolePickerProps, GrantRow, type GrantRowProps, Grid, GridOverlay, type GridOverlayProps, type GridProps, HoverCard, HoverCardContent, HoverCardTrigger, IconHint, type IconHintProps, ImageCropDialog, type ImageCropDialogProps, type ImageCropShape, type ImageCropType, ImageCropper, type ImageCropperProps, ImageUpload, type ImageUploadProps, type ImageUploadSize, InlineError, type InlineErrorProps, Input, InputAddon, type InputAddonProps, InputGroup, InputGroupInput, type InputGroupInputProps, type InputGroupProps, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Label, ListCells, type ListCellsProps, type ListColumn, type ListColumnWidth, ListHeader, type ListHeaderProps, MISSING_TONE, Medallion, type MedallionProps, MenuDivider, MenuPopup, type MenuPopupProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, NavRow, type NavRowMark, type NavRowProps, type NavRowVariant, NavSectionLabel, type NavSectionLabelProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, type NotifClass, type NotificationAction, NotificationBell, type NotificationBellProps, NotificationCenter, type NotificationCenterProps, type NotificationClass, type NotificationDeepLink, type NotificationItem, type NotificationMute, type NotificationPreferences, type NotificationProduct, NotificationRow, type NotificationRowProps, NotificationSettings, type NotificationSettingsProps, type NotificationSeverity, type NotificationSubscription, type NotificationThreshold, NotificationToast, type NotificationToastDwell, type NotificationToastProps, NotificationToaster, type NotificationToasterPosition, type NotificationToasterProps, OptionCard, type OptionCardProps, OrgProductSwitcher, type OrgProductSwitcherAction, type OrgProductSwitcherItem, type OrgProductSwitcherProduct, type OrgProductSwitcherProps, type OrganizationOnboardingDefaults, OrganizationOnboardingForm, type OrganizationOnboardingFormProps, type OrganizationOnboardingPayload, PageColumn, type PageColumnProps, PageHeader, type PageHeaderProps, type PageHeaderSize, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, type PaginationLinkProps, PaginationNext, PaginationPrevious, PersonAvatar, type PersonAvatarProps, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, type ProductStatus, Progress, QuickSearchRow, type QuickSearchRowProps, RadioGroup, RadioGroupItem, RailToggle, type RailToggleProps, RatingScale, type RatingScaleProps, type RatingScaleSize, RemovableChip, type RemovableChipProps, RemoveButton, type RemoveButtonProps, RequestRow, type RequestRowProps, type RequestState, type RequestSurface, type ResolvedTheme, type Responsive, ScrollArea, ScrollBar, SecretReveal, type SecretRevealProps, SectionIntro, type SectionIntroProps, Select, type SelectOption, type SelectProps, Separator, SettingRow, type SettingRowProps, type Severity, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarBackHeader, type SidebarBackHeaderProps, SidebarDrawer, SidebarProductHeader, type SidebarProductHeaderProps, Skeleton, Slider, StarRating, type StarRatingProps, type StarRatingSize, StatCard, type StatCardProps, StatusDot, type StatusDotProps, StepUpChallenge, type StepUpChallengeProps, type StepUpMethod, type StepUpProof, Switch, type SwitchProps, TOAST_DWELL, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, type TableProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, type TextareaProps, type Theme, ThemePicker, type ThemePickerProps, ThemeToggle, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopBar, type TopBarProps, TopBarUtilities, type TopBarUtilitiesProps, type TopBarUtility, type UseFreshHighlightResult, type UseSidebarOptions, type UseSidebarResult, UserMenu, type UserMenuItem, type UserMenuProps, type UserMenuUser, WEIGHT_TONE, alertVariants, attachmentChipVariants, badgeVariants, buttonVariants, cn, formatRelativeAge, grantRemoveLabel, isKnownExtensionIcon, isNotificationSettled, navigationMenuTriggerStyle, productStatusBadge, railToggleLabel, severityBadgeVariant, severityLabels, statusDotVariants, toggleVariants, useCarousel, useFormField, useFreshHighlight, useIsMobile, useSidebar, useSidebarDismiss, useTheme };
|
package/dist/index.js
CHANGED
|
@@ -15,15 +15,19 @@ import {
|
|
|
15
15
|
SheetPortal,
|
|
16
16
|
SheetTitle,
|
|
17
17
|
SheetTrigger,
|
|
18
|
+
SidebarDrawer,
|
|
18
19
|
Tooltip,
|
|
19
20
|
TooltipContent,
|
|
20
21
|
TooltipProvider,
|
|
21
22
|
TooltipTrigger,
|
|
22
23
|
buttonVariants,
|
|
23
24
|
cn,
|
|
25
|
+
railToggleLabel,
|
|
24
26
|
useIsMobile,
|
|
25
|
-
useSidebar
|
|
26
|
-
|
|
27
|
+
useSidebar,
|
|
28
|
+
useSidebarDismiss,
|
|
29
|
+
useSidebarDrawer
|
|
30
|
+
} from "./chunk-OMJRQ4JY.js";
|
|
27
31
|
|
|
28
32
|
// src/components/auto-height.tsx
|
|
29
33
|
import * as React from "react";
|
|
@@ -149,7 +153,10 @@ var DialogOverlay = React3.forwardRef(({ className, ...props }, ref) => /* @__PU
|
|
|
149
153
|
{
|
|
150
154
|
ref,
|
|
151
155
|
className: cn(
|
|
152
|
-
|
|
156
|
+
// The scrim's duration is the panel's, so the two arrive as one. Naming it is what makes
|
|
157
|
+
// `prefers-reduced-motion` reach the fade: `animate-in` reads `--tw-duration`, and an unset
|
|
158
|
+
// one falls to tw-animate-css's own literal 0.15s, which no media query can collapse.
|
|
159
|
+
"fixed inset-0 z-50 bg-black/50 duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
153
160
|
className
|
|
154
161
|
),
|
|
155
162
|
...props
|
|
@@ -1174,7 +1181,10 @@ var AlertDialogOverlay = React21.forwardRef(({ className, ...props }, ref) => /*
|
|
|
1174
1181
|
{
|
|
1175
1182
|
ref,
|
|
1176
1183
|
className: cn(
|
|
1177
|
-
|
|
1184
|
+
// The scrim's duration is the panel's, so the two arrive as one. Naming it is what makes
|
|
1185
|
+
// `prefers-reduced-motion` reach the fade: `animate-in` reads `--tw-duration`, and an unset
|
|
1186
|
+
// one falls to tw-animate-css's own literal 0.15s, which no media query can collapse.
|
|
1187
|
+
"fixed inset-0 z-50 bg-black/50 duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1178
1188
|
className
|
|
1179
1189
|
),
|
|
1180
1190
|
...props
|
|
@@ -4534,14 +4544,17 @@ function useFreshHighlight() {
|
|
|
4534
4544
|
// src/components/quick-search-row.tsx
|
|
4535
4545
|
import { Search as Search2 } from "lucide-react";
|
|
4536
4546
|
import { jsx as jsx74, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
4547
|
+
var DEFAULT_SHORTCUT = "\u2318K";
|
|
4537
4548
|
function QuickSearchRow({
|
|
4538
4549
|
onOpen,
|
|
4539
4550
|
label = "Quick search",
|
|
4540
|
-
shortcut
|
|
4551
|
+
shortcut,
|
|
4541
4552
|
collapsed = false,
|
|
4542
4553
|
icon
|
|
4543
4554
|
}) {
|
|
4544
|
-
const
|
|
4555
|
+
const drawer = useSidebarDrawer();
|
|
4556
|
+
const stated = shortcut === void 0 ? drawer ? false : DEFAULT_SHORTCUT : shortcut;
|
|
4557
|
+
const name = stated ? `${label} ${stated}` : label;
|
|
4545
4558
|
if (!collapsed) {
|
|
4546
4559
|
return /* @__PURE__ */ jsxs48(
|
|
4547
4560
|
"button",
|
|
@@ -4563,7 +4576,7 @@ function QuickSearchRow({
|
|
|
4563
4576
|
children: [
|
|
4564
4577
|
/* @__PURE__ */ jsx74("span", { className: "flex size-4 shrink-0 items-center justify-center [&_svg]:size-4", "aria-hidden": "true", children: icon ?? /* @__PURE__ */ jsx74(Search2, {}) }),
|
|
4565
4578
|
/* @__PURE__ */ jsx74("span", { className: "min-w-0 flex-1 truncate", children: label }),
|
|
4566
|
-
|
|
4579
|
+
stated && /* @__PURE__ */ jsx74("span", { className: "shrink-0 text-xs font-medium text-text-tertiary", children: stated })
|
|
4567
4580
|
]
|
|
4568
4581
|
}
|
|
4569
4582
|
);
|
|
@@ -4703,12 +4716,15 @@ function ItemLabel({ item, kind }) {
|
|
|
4703
4716
|
}
|
|
4704
4717
|
var MARK_SIZE = { md: "sm", sm: "xs" };
|
|
4705
4718
|
var ICON_BOX = { md: "size-8 rounded-md", sm: "size-6 rounded-sm" };
|
|
4719
|
+
function MarkSlot({ size }) {
|
|
4720
|
+
return /* @__PURE__ */ jsx78("span", { "aria-hidden": "true", className: cn("shrink-0", ICON_BOX[size]) });
|
|
4721
|
+
}
|
|
4706
4722
|
function Mark2({ item, kind, size, reserve }) {
|
|
4707
4723
|
if (item.icon) {
|
|
4708
4724
|
return /* @__PURE__ */ jsx78("span", { className: cn("flex shrink-0 items-center justify-center overflow-hidden", ICON_BOX[size]), "aria-hidden": "true", children: item.icon });
|
|
4709
4725
|
}
|
|
4710
4726
|
const name = nameOf(item);
|
|
4711
|
-
if (!name) return reserve ? /* @__PURE__ */ jsx78(
|
|
4727
|
+
if (!name) return reserve ? /* @__PURE__ */ jsx78(MarkSlot, { size }) : null;
|
|
4712
4728
|
return /* @__PURE__ */ jsx78(EntityTile, { name, tone: kind === "product" ? "auto" : "neutral", size: MARK_SIZE[size] });
|
|
4713
4729
|
}
|
|
4714
4730
|
function OrgProductSwitcher({
|
|
@@ -4720,6 +4736,7 @@ function OrgProductSwitcher({
|
|
|
4720
4736
|
onProductSelect,
|
|
4721
4737
|
actions,
|
|
4722
4738
|
trigger = "stacked",
|
|
4739
|
+
mark = "draw",
|
|
4723
4740
|
className,
|
|
4724
4741
|
...props
|
|
4725
4742
|
}) {
|
|
@@ -4788,7 +4805,7 @@ function OrgProductSwitcher({
|
|
|
4788
4805
|
/* @__PURE__ */ jsx78(ChevronsUpDown3, { size: 14, "aria-hidden": "true", className: "shrink-0 text-text-tertiary" })
|
|
4789
4806
|
] })
|
|
4790
4807
|
) : /* @__PURE__ */ jsxs51(DropdownMenuTrigger, { "aria-label": ariaLabel, className: cn(triggerBox, className), children: [
|
|
4791
|
-
triggerMark && /* @__PURE__ */ jsx78(Mark2, { item: triggerMark, kind: markKind, size: "md" }),
|
|
4808
|
+
triggerMark && (mark === "hold" ? /* @__PURE__ */ jsx78(MarkSlot, { size: "md" }) : /* @__PURE__ */ jsx78(Mark2, { item: triggerMark, kind: markKind, size: "md" })),
|
|
4792
4809
|
orgLevel ? /* @__PURE__ */ jsx78("span", { className: "flex min-w-0 flex-1 flex-col", children: /* @__PURE__ */ jsx78(NameLine, { className: orgName ? "font-semibold text-text-primary" : "text-text-tertiary", children: orgName ?? NO_ORG_LABEL }) }) : /* @__PURE__ */ jsxs51("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
4793
4810
|
orgName && /* @__PURE__ */ jsx78("span", { className: "truncate text-xs leading-[normal] text-text-tertiary", children: orgName }),
|
|
4794
4811
|
/* @__PURE__ */ jsx78(NameLine, { className: productName ? "font-semibold text-text-primary" : "text-text-tertiary", children: productLabel })
|
|
@@ -4882,7 +4899,7 @@ function SidebarBackHeader({
|
|
|
4882
4899
|
...rowProps,
|
|
4883
4900
|
children: [
|
|
4884
4901
|
/* @__PURE__ */ jsx79("span", { className: arrowBox, children: /* @__PURE__ */ jsx79("span", { className: cn(arrowPlate, arrowClassName), ...arrowRest, children: /* @__PURE__ */ jsx79(Arrow, {}) }) }),
|
|
4885
|
-
/* @__PURE__ */ jsx79("span", { className: cn(titleBox, titleClassName), ...titleRest, children: title })
|
|
4902
|
+
/* @__PURE__ */ jsx79("span", { className: cn(titleBox, titleClassName), ...titleRest, children: /* @__PURE__ */ jsx79("span", { "data-slot": "nav-row-label", children: title }) })
|
|
4886
4903
|
]
|
|
4887
4904
|
}
|
|
4888
4905
|
);
|
|
@@ -4906,7 +4923,7 @@ function SidebarBackHeader({
|
|
|
4906
4923
|
onClick: onTitleClick,
|
|
4907
4924
|
className: cn(titleBox, focusRing, titleClassName),
|
|
4908
4925
|
...titleRest,
|
|
4909
|
-
children: title
|
|
4926
|
+
children: /* @__PURE__ */ jsx79("span", { "data-slot": "nav-row-label", children: title })
|
|
4910
4927
|
}
|
|
4911
4928
|
)
|
|
4912
4929
|
] });
|
|
@@ -7980,6 +7997,7 @@ export {
|
|
|
7980
7997
|
SheetTitle,
|
|
7981
7998
|
SheetTrigger,
|
|
7982
7999
|
SidebarBackHeader,
|
|
8000
|
+
SidebarDrawer,
|
|
7983
8001
|
SidebarProductHeader,
|
|
7984
8002
|
Skeleton,
|
|
7985
8003
|
Slider,
|
|
@@ -8027,6 +8045,7 @@ export {
|
|
|
8027
8045
|
isNotificationSettled,
|
|
8028
8046
|
navigationMenuTriggerStyle,
|
|
8029
8047
|
productStatusBadge,
|
|
8048
|
+
railToggleLabel,
|
|
8030
8049
|
severityBadgeVariant,
|
|
8031
8050
|
severityLabels,
|
|
8032
8051
|
statusDotVariants,
|
|
@@ -8037,5 +8056,6 @@ export {
|
|
|
8037
8056
|
useFreshHighlight,
|
|
8038
8057
|
useIsMobile,
|
|
8039
8058
|
useSidebar,
|
|
8059
|
+
useSidebarDismiss,
|
|
8040
8060
|
useTheme
|
|
8041
8061
|
};
|
package/dist/router.d.ts
CHANGED
|
@@ -68,16 +68,37 @@ interface SidebarNavProps {
|
|
|
68
68
|
declare function SidebarNav({ items, collapsed, basePath, LinkComponent, isItemActive, className, }: SidebarNavProps): React.JSX.Element;
|
|
69
69
|
|
|
70
70
|
interface AppSidebarProps {
|
|
71
|
-
|
|
71
|
+
/** The rows in the middle, as links. Optional since #878: a rail whose middle is not a list of
|
|
72
|
+
* links writes it as `children` instead. */
|
|
73
|
+
items?: NavItem[];
|
|
74
|
+
/** The middle, written by the caller — panes, disclosures, a back row, anything `NavItem` has no
|
|
75
|
+
* field for. It stands exactly where the rows stand, and it owns its own scrolling: the box the
|
|
76
|
+
* rail gives it holds the rail's own inset and does not scroll, so an `overflow-y-auto` region
|
|
77
|
+
* inside it measures against the rail's own height instead of against a box the padding made
|
|
78
|
+
* taller.
|
|
79
|
+
*
|
|
80
|
+
* Like `railTop` it takes a function, for the same reason: the rail drives its own collapse, so
|
|
81
|
+
* this is the only way a caller's node can read a state it has no other route to.
|
|
82
|
+
*
|
|
83
|
+
* Passing this and `items` together is a caller error. This wins — a middle somebody wrote is
|
|
84
|
+
* the more specific instruction, where a list may have arrived through a wrapper's spread — and
|
|
85
|
+
* development says so out loud, because the alternative is rows that render nowhere in silence. */
|
|
86
|
+
children?: React.ReactNode | ((collapsed: boolean) => React.ReactNode);
|
|
72
87
|
/** Expanded-slot mark/wordmark, rendered when `header` is absent. Also the narrow rail's fallback
|
|
73
88
|
* when `logoCollapsed` isn't given. */
|
|
74
89
|
logo?: React.ReactNode;
|
|
75
|
-
/**
|
|
76
|
-
*
|
|
90
|
+
/** The band's mark — a small one, standing on the glyph column at 32. It is drawn at both widths
|
|
91
|
+
* and never fades: at the narrow width it is the whole of the identity, and at the wide one it is
|
|
92
|
+
* the mark the node in `header` leads with. Falls back to `logo`. */
|
|
77
93
|
logoCollapsed?: React.ReactNode;
|
|
78
94
|
/** Identity slot above the rail — e.g. an <OrgProductSwitcher/> (#266). Falls back to `logo`.
|
|
79
|
-
* Expanded-only:
|
|
80
|
-
*
|
|
95
|
+
* Expanded-only: it fades out at the narrow width, because a switcher clipped to the rail's own
|
|
96
|
+
* width reads as a tile with a severed word beside it.
|
|
97
|
+
*
|
|
98
|
+
* A node here draws no mark of its own. `logoCollapsed ?? logo` is the band's one mark and the
|
|
99
|
+
* rail draws it at BOTH widths, so a second one stands 2px beside it, solid, in the same band.
|
|
100
|
+
* `OrgProductSwitcher` yields its own with `mark="hold"`, which leaves its box and its words
|
|
101
|
+
* exactly where they are. */
|
|
81
102
|
header?: React.ReactNode;
|
|
82
103
|
/** Top of the rail — e.g. a <QuickSearchRow/>. It sits between the header's rule and the rows,
|
|
83
104
|
* and it is pinned: outside the scroll region, so it holds one place while the rows below it
|
|
@@ -94,7 +115,7 @@ interface AppSidebarProps {
|
|
|
94
115
|
isItemActive?: (item: NavItem, pathname: string) => boolean;
|
|
95
116
|
className?: string;
|
|
96
117
|
}
|
|
97
|
-
declare function AppSidebar({ items, logo, logoCollapsed, header, railTop, collapsed: controlled, defaultCollapsed, onCollapsedChange, basePath, LinkComponent, isItemActive, className, }: AppSidebarProps): React.JSX.Element;
|
|
118
|
+
declare function AppSidebar({ items, children, logo, logoCollapsed, header, railTop, collapsed: controlled, defaultCollapsed, onCollapsedChange, basePath, LinkComponent, isItemActive, className, }: AppSidebarProps): React.JSX.Element;
|
|
98
119
|
|
|
99
120
|
interface AppShellProps {
|
|
100
121
|
/** The sidebar, typically an <AppSidebar/>. Rendered in the desktop rail and, on mobile, inside a
|
package/dist/router.js
CHANGED
|
@@ -9,14 +9,17 @@ import {
|
|
|
9
9
|
SheetDescription,
|
|
10
10
|
SheetTitle,
|
|
11
11
|
SheetTrigger,
|
|
12
|
+
SidebarDrawer,
|
|
12
13
|
Tooltip,
|
|
13
14
|
TooltipContent,
|
|
14
15
|
TooltipProvider,
|
|
15
16
|
TooltipTrigger,
|
|
16
17
|
cn,
|
|
18
|
+
railToggleLabel,
|
|
17
19
|
useIsMobile,
|
|
18
|
-
useSidebar
|
|
19
|
-
|
|
20
|
+
useSidebar,
|
|
21
|
+
useSidebarDrawer
|
|
22
|
+
} from "./chunk-OMJRQ4JY.js";
|
|
20
23
|
|
|
21
24
|
// src/components/extension-link.tsx
|
|
22
25
|
import { Link } from "react-router";
|
|
@@ -99,19 +102,19 @@ function SidebarNav({
|
|
|
99
102
|
}
|
|
100
103
|
|
|
101
104
|
// src/components/app-sidebar.tsx
|
|
102
|
-
import * as React from "react";
|
|
103
105
|
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
104
|
-
var SidebarDrawerContext = React.createContext(false);
|
|
105
|
-
function SidebarDrawer({ children }) {
|
|
106
|
-
return /* @__PURE__ */ jsx3(SidebarDrawerContext.Provider, { value: true, children });
|
|
107
|
-
}
|
|
108
106
|
function Divider({ testId, className }) {
|
|
109
107
|
return /* @__PURE__ */ jsx3("div", { "data-testid": testId, className: cn("h-px shrink-0 bg-border-subtle", className) });
|
|
110
108
|
}
|
|
111
109
|
var RAIL_WIDE = "w-[248px]";
|
|
112
110
|
var RAIL_NARROW = "w-[64px]";
|
|
111
|
+
var footTooltipOffset = (collapsed) => collapsed ? 16 : 4;
|
|
112
|
+
function drawsNothing(node) {
|
|
113
|
+
return node == null || typeof node === "boolean" || node === "" || Array.isArray(node) && node.length === 0;
|
|
114
|
+
}
|
|
113
115
|
function AppSidebar({
|
|
114
116
|
items,
|
|
117
|
+
children,
|
|
115
118
|
logo,
|
|
116
119
|
logoCollapsed,
|
|
117
120
|
header,
|
|
@@ -124,7 +127,7 @@ function AppSidebar({
|
|
|
124
127
|
isItemActive,
|
|
125
128
|
className
|
|
126
129
|
}) {
|
|
127
|
-
const drawer =
|
|
130
|
+
const drawer = useSidebarDrawer();
|
|
128
131
|
const { collapsed: railCollapsed, toggle } = useSidebar({
|
|
129
132
|
collapsed: controlled,
|
|
130
133
|
defaultCollapsed,
|
|
@@ -132,54 +135,135 @@ function AppSidebar({
|
|
|
132
135
|
});
|
|
133
136
|
const collapsed = drawer ? false : railCollapsed;
|
|
134
137
|
const railTopNode = typeof railTop === "function" ? railTop(collapsed) : railTop;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
138
|
+
const separateMark = header != null || logoCollapsed != null;
|
|
139
|
+
const asked = typeof children === "function" ? children(collapsed) : children;
|
|
140
|
+
const written = drawsNothing(asked) ? null : asked;
|
|
141
|
+
if (process.env.NODE_ENV !== "production" && written !== null && items != null) {
|
|
142
|
+
console.warn(
|
|
143
|
+
"[AppSidebar] `children` and `items` are two middles and only one is drawn: `children` wins and the rows are dropped. Put the links inside the middle you wrote, or drop `children`."
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
return (
|
|
147
|
+
// ONE PROVIDER, ROUND THE WHOLE RAIL.
|
|
148
|
+
//
|
|
149
|
+
// The rail composes a tooltip at its foot and `SidebarNav` composes one per row at the narrow
|
|
150
|
+
// width, and a provider per instance is what `.storybook/preview.tsx` states the rule against:
|
|
151
|
+
// nested, the foot's control opened at Radix's own 700ms while every row beside it opened at
|
|
152
|
+
// 200, and it could never join their skip-delay group. Here rather than left to `AppShell`, so
|
|
153
|
+
// a rail rendered on its own still has one — nesting inside the shell's is harmless.
|
|
154
|
+
/* @__PURE__ */ jsx3(TooltipProvider, { children: /* @__PURE__ */ jsx3(
|
|
155
|
+
"aside",
|
|
156
|
+
{
|
|
157
|
+
"data-collapsed": collapsed,
|
|
158
|
+
className: cn(
|
|
159
|
+
"flex h-full shrink-0 flex-col overflow-hidden motion-rail-collapse",
|
|
160
|
+
// A nav row drops its own label at the narrow width. What this fades is a label whatever
|
|
161
|
+
// stands in `railTop` keeps mounted at both — QuickSearchRow's, for one — so the closing
|
|
162
|
+
// edge slides over the words instead of cutting through them.
|
|
163
|
+
//
|
|
164
|
+
// The trailing mark goes on the same clock: a disclosure chevron is `nav-row-trailing`, it
|
|
165
|
+
// is as far past the closing edge as the words beside it, and left untimed it snapped out
|
|
166
|
+
// while they faded.
|
|
167
|
+
//
|
|
168
|
+
// `duration-fast` is the token scale rather than a typed number, so a `@lessly/tokens`
|
|
169
|
+
// release retunes it, and the step reaches the utility as `var(--motion-duration-fast,
|
|
170
|
+
// 100ms)` — the same variable `.motion-rail-collapse` reads, which the token layer's
|
|
171
|
+
// `prefers-reduced-motion` block takes to 0ms, so the words and the width stop together.
|
|
172
|
+
// `motion-reduce:transition-none` is what a consumer running the preset without
|
|
173
|
+
// `@lessly/ui/styles.css` stops on: they are left with the 100ms fallback, and no media
|
|
174
|
+
// query reaches a literal.
|
|
175
|
+
"[&_[data-slot=nav-row-label]]:transition-opacity [&_[data-slot=nav-row-label]]:duration-fast",
|
|
176
|
+
"[&_[data-slot=nav-row-label]]:motion-reduce:transition-none",
|
|
177
|
+
"[&_[data-slot=nav-row-trailing]]:transition-opacity [&_[data-slot=nav-row-trailing]]:duration-fast",
|
|
178
|
+
"[&_[data-slot=nav-row-trailing]]:motion-reduce:transition-none",
|
|
179
|
+
collapsed ? RAIL_NARROW : RAIL_WIDE,
|
|
180
|
+
collapsed && "[&_[data-slot=nav-row-label]]:opacity-0 [&_[data-slot=nav-row-trailing]]:opacity-0",
|
|
181
|
+
className
|
|
161
182
|
),
|
|
162
|
-
|
|
163
|
-
/* @__PURE__ */ jsx3(
|
|
164
|
-
|
|
183
|
+
children: /* @__PURE__ */ jsxs2("div", { className: cn("flex h-full shrink-0 flex-col", RAIL_WIDE), children: [
|
|
184
|
+
/* @__PURE__ */ jsx3("div", { className: cn("relative flex h-14 shrink-0 items-center", drawer ? "pl-3 pr-10" : "px-3"), children: separateMark ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
185
|
+
/* @__PURE__ */ jsx3(
|
|
186
|
+
"div",
|
|
187
|
+
{
|
|
188
|
+
"data-testid": "sidebar-identity-expanded",
|
|
189
|
+
"aria-hidden": collapsed || void 0,
|
|
190
|
+
inert: collapsed,
|
|
191
|
+
className: cn(
|
|
192
|
+
"flex w-full items-center gap-2 transition-opacity duration-normal motion-reduce:transition-none",
|
|
193
|
+
collapsed && "pointer-events-none opacity-0"
|
|
194
|
+
),
|
|
195
|
+
children: header ?? logo
|
|
196
|
+
}
|
|
197
|
+
),
|
|
198
|
+
/* @__PURE__ */ jsx3(
|
|
199
|
+
"div",
|
|
200
|
+
{
|
|
201
|
+
"data-testid": "sidebar-identity-collapsed",
|
|
202
|
+
"aria-hidden": !collapsed || void 0,
|
|
203
|
+
inert: !collapsed,
|
|
204
|
+
className: cn("absolute", RAIL_COLUMN_BOX, !collapsed && "pointer-events-none"),
|
|
205
|
+
children: logoCollapsed ?? logo
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
] }) : (
|
|
209
|
+
/* ONE MARK, MOUNTED ONCE.
|
|
210
|
+
With neither `header` nor `logoCollapsed`, both slots resolve to the same `logo`, and
|
|
211
|
+
a node fading into an identical node is not a transition — it is one mark ghosted off
|
|
212
|
+
another. Mounted twice it was worse than a picture: one `id` inside an SVG logo
|
|
213
|
+
belongs to two elements and `getElementById` finds the hidden one, a `ref` fires
|
|
214
|
+
twice and measures the transparent copy, effects subscribe twice, and `inert` pauses
|
|
215
|
+
no player.
|
|
216
|
+
It stands in RAIL_COLUMN_BOX at BOTH widths, which is the box the closed mark and the
|
|
217
|
+
foot's toggle already stand in: centre 32, the column every row's glyph is on. That
|
|
218
|
+
is a class list that never changes, so there is no frame for it to move on. */
|
|
219
|
+
/* @__PURE__ */ jsx3("div", { "data-testid": "sidebar-identity-single", className: RAIL_COLUMN_BOX, children: logo })
|
|
220
|
+
) }),
|
|
221
|
+
/* @__PURE__ */ jsx3(Divider, { testId: "sidebar-divider-header" }),
|
|
222
|
+
railTopNode && /* @__PURE__ */ jsx3("div", { "data-testid": "sidebar-rail-top", className: "shrink-0 px-3 pt-3", children: railTopNode }),
|
|
223
|
+
written !== null ? /* @__PURE__ */ jsx3(
|
|
224
|
+
"div",
|
|
225
|
+
{
|
|
226
|
+
"data-testid": "sidebar-body",
|
|
227
|
+
className: cn(
|
|
228
|
+
"flex min-h-0 flex-1 flex-col overflow-hidden px-3 pb-2",
|
|
229
|
+
railTopNode ? "pt-2" : "pt-3"
|
|
230
|
+
),
|
|
231
|
+
children: written
|
|
232
|
+
}
|
|
233
|
+
) : /* @__PURE__ */ jsx3(
|
|
234
|
+
ScrollArea,
|
|
235
|
+
{
|
|
236
|
+
className: "min-h-0 flex-1",
|
|
237
|
+
viewportClassName: cn("px-3 pb-2", railTopNode ? "pt-2" : "pt-3"),
|
|
238
|
+
viewportProps: { "data-testid": "sidebar-scroll" },
|
|
239
|
+
children: /* @__PURE__ */ jsx3(SidebarNav, { items: items ?? [], collapsed, basePath, LinkComponent, isItemActive })
|
|
240
|
+
}
|
|
241
|
+
),
|
|
242
|
+
!drawer && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
243
|
+
/* @__PURE__ */ jsx3(Divider, { testId: "sidebar-divider-foot" }),
|
|
244
|
+
/* @__PURE__ */ jsx3("div", { className: "flex shrink-0 px-3 py-2", children: /* @__PURE__ */ jsxs2(Tooltip, { children: [
|
|
245
|
+
/* @__PURE__ */ jsx3(TooltipTrigger, { asChild: true, "aria-describedby": void 0, children: /* @__PURE__ */ jsx3(RailToggle, { collapsed, onClick: toggle }) }),
|
|
246
|
+
/* @__PURE__ */ jsx3(TooltipContent, { side: "right", sideOffset: footTooltipOffset(collapsed), children: railToggleLabel(collapsed) })
|
|
247
|
+
] }) })
|
|
248
|
+
] })
|
|
165
249
|
] })
|
|
166
|
-
|
|
167
|
-
}
|
|
250
|
+
}
|
|
251
|
+
) })
|
|
168
252
|
);
|
|
169
253
|
}
|
|
170
254
|
|
|
171
255
|
// src/components/app-shell.tsx
|
|
172
|
-
import * as
|
|
256
|
+
import * as React from "react";
|
|
173
257
|
import { Menu } from "lucide-react";
|
|
174
258
|
import { useLocation as useLocation2 } from "react-router";
|
|
175
259
|
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
176
260
|
function expandedSidebar(sidebar) {
|
|
177
|
-
return
|
|
261
|
+
return React.isValidElement(sidebar) ? React.cloneElement(sidebar, { collapsed: false }) : sidebar;
|
|
178
262
|
}
|
|
179
263
|
function AppShell({ sidebar, topBar, children, className }) {
|
|
180
264
|
const { pathname } = useLocation2();
|
|
181
|
-
const [mobileOpen, setMobileOpen] =
|
|
182
|
-
|
|
265
|
+
const [mobileOpen, setMobileOpen] = React.useState(false);
|
|
266
|
+
React.useEffect(() => {
|
|
183
267
|
setMobileOpen(false);
|
|
184
268
|
}, [pathname]);
|
|
185
269
|
const isMobile = useIsMobile();
|
|
@@ -196,7 +280,7 @@ function AppShell({ sidebar, topBar, children, className }) {
|
|
|
196
280
|
/* @__PURE__ */ jsxs3(SheetContent, { side: "left", className: "w-[248px] bg-bg-primary p-0", children: [
|
|
197
281
|
/* @__PURE__ */ jsx4(SheetTitle, { className: "sr-only", children: "Navigation" }),
|
|
198
282
|
/* @__PURE__ */ jsx4(SheetDescription, { className: "sr-only", children: "Application navigation menu" }),
|
|
199
|
-
/* @__PURE__ */ jsx4(SidebarDrawer, { children: expandedSidebar(sidebar) })
|
|
283
|
+
/* @__PURE__ */ jsx4(SidebarDrawer, { onDismiss: () => setMobileOpen(false), children: expandedSidebar(sidebar) })
|
|
200
284
|
] })
|
|
201
285
|
] }),
|
|
202
286
|
/* @__PURE__ */ jsx4("div", { className: "flex items-center gap-2", children: topBar })
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
--bg-elevated: #252936;
|
|
20
20
|
--bg-overlay: #252936;
|
|
21
21
|
--bg-sunken: #0e1015;
|
|
22
|
-
--bg-selected: #
|
|
22
|
+
--bg-selected: #252735;
|
|
23
23
|
--bg-brand: #06297d;
|
|
24
24
|
--bg-brand-subtle: #1f2541;
|
|
25
25
|
--bg-brand-hover: #08349b;
|
|
@@ -103,12 +103,12 @@
|
|
|
103
103
|
--grid-container-max: 1440px;
|
|
104
104
|
|
|
105
105
|
/* typography text-styles — theme-invariant, :root only (see typographyVars in build.js) */
|
|
106
|
-
--text-display-xl-font-family: "
|
|
106
|
+
--text-display-xl-font-family: "Sora", "Inter", system-ui, -apple-system, sans-serif;
|
|
107
107
|
--text-display-xl-font-size: 3.5rem;
|
|
108
108
|
--text-display-xl-line-height: 1.05;
|
|
109
109
|
--text-display-xl-font-weight: 400;
|
|
110
110
|
--text-display-xl-letter-spacing: -0.02em;
|
|
111
|
-
--text-display-lg-font-family: "
|
|
111
|
+
--text-display-lg-font-family: "Sora", "Inter", system-ui, -apple-system, sans-serif;
|
|
112
112
|
--text-display-lg-font-size: 3rem;
|
|
113
113
|
--text-display-lg-line-height: 1.1;
|
|
114
114
|
--text-display-lg-font-weight: 400;
|
|
@@ -283,7 +283,7 @@
|
|
|
283
283
|
--bg-elevated: #edeef0;
|
|
284
284
|
--bg-overlay: #ffffff;
|
|
285
285
|
--bg-sunken: #e1e2e4;
|
|
286
|
-
--bg-selected: #
|
|
286
|
+
--bg-selected: #eceded;
|
|
287
287
|
--bg-brand-subtle: #e4ecfe;
|
|
288
288
|
--bg-brand-hover: #05226a;
|
|
289
289
|
--bg-brand-bright-hover: #0b4cd5;
|
|
@@ -342,6 +342,27 @@
|
|
|
342
342
|
--overlay-modal-bg: #ffffff;
|
|
343
343
|
--focus-ring-color: #0940b8;
|
|
344
344
|
|
|
345
|
+
/* Same value as :root on purpose, re-declared so .light lists every colour token a
|
|
346
|
+
light consumer gets rather than leaving some to inheritance. Why, and what holds
|
|
347
|
+
it honest: docs/tokens.md, "Theme invariance". */
|
|
348
|
+
--bg-brand: #06297d;
|
|
349
|
+
--bg-brand-bright: #165ff2;
|
|
350
|
+
--bg-success: #13703c;
|
|
351
|
+
--bg-success-bright: #21be63;
|
|
352
|
+
--bg-danger: #78100b;
|
|
353
|
+
--text-on-brand: #f6f7f7;
|
|
354
|
+
--text-on-success: #f6f7f7;
|
|
355
|
+
--text-on-success-bright: #08090c;
|
|
356
|
+
--text-on-warning: #08090c;
|
|
357
|
+
--text-on-danger: #f6f7f7;
|
|
358
|
+
--border-selected: #737c95;
|
|
359
|
+
--border-brand: #165ff2;
|
|
360
|
+
--border-warning: #b3780e;
|
|
361
|
+
--border-danger: #e82020;
|
|
362
|
+
--field-border-hover: #737c95;
|
|
363
|
+
--field-border-filled: #737c95;
|
|
364
|
+
--field-border-error: #e82020;
|
|
365
|
+
|
|
345
366
|
/* shadcn role bridge re-declared so .light on a nested element (not just <html>)
|
|
346
367
|
re-resolves the aliases to light values. */
|
|
347
368
|
--background: var(--bg-primary);
|
|
@@ -471,11 +492,15 @@
|
|
|
471
492
|
--color-bg-surface: var(--bg-surface);
|
|
472
493
|
--color-bg-elevated: var(--bg-elevated);
|
|
473
494
|
--color-bg-sunken: var(--bg-sunken);
|
|
495
|
+
--color-bg-brand: var(--bg-brand);
|
|
474
496
|
--color-bg-brand-subtle: var(--bg-brand-subtle);
|
|
475
497
|
--color-bg-brand-hover: var(--bg-brand-hover);
|
|
498
|
+
--color-bg-brand-bright: var(--bg-brand-bright);
|
|
499
|
+
--color-bg-success: var(--bg-success);
|
|
476
500
|
--color-bg-success-subtle: var(--bg-success-subtle);
|
|
477
501
|
--color-bg-warning: var(--bg-warning);
|
|
478
502
|
--color-bg-warning-subtle: var(--bg-warning-subtle);
|
|
503
|
+
--color-bg-danger: var(--bg-danger);
|
|
479
504
|
--color-bg-danger-subtle: var(--bg-danger-subtle);
|
|
480
505
|
--color-bg-teal-subtle: var(--bg-teal-subtle);
|
|
481
506
|
--color-bg-violet-subtle: var(--bg-violet-subtle);
|
|
@@ -485,6 +510,10 @@
|
|
|
485
510
|
--color-text-tertiary: var(--text-tertiary);
|
|
486
511
|
--color-text-disabled: var(--text-disabled);
|
|
487
512
|
--color-text-inverse: var(--text-inverse);
|
|
513
|
+
--color-text-on-brand: var(--text-on-brand);
|
|
514
|
+
--color-text-on-success: var(--text-on-success);
|
|
515
|
+
--color-text-on-warning: var(--text-on-warning);
|
|
516
|
+
--color-text-on-danger: var(--text-on-danger);
|
|
488
517
|
--color-text-brand: var(--text-brand);
|
|
489
518
|
--color-text-success: var(--text-success);
|
|
490
519
|
--color-text-warning: var(--text-warning);
|
|
@@ -502,8 +531,11 @@
|
|
|
502
531
|
--color-border-subtle: var(--border-subtle);
|
|
503
532
|
--color-border-default: var(--border-default);
|
|
504
533
|
--color-border-strong: var(--border-strong);
|
|
534
|
+
--color-border-brand: var(--border-brand);
|
|
505
535
|
--color-border-focus: var(--border-focus);
|
|
506
536
|
--color-border-success: var(--border-success);
|
|
537
|
+
--color-border-warning: var(--border-warning);
|
|
538
|
+
--color-border-danger: var(--border-danger);
|
|
507
539
|
}
|
|
508
540
|
|
|
509
541
|
/* === Fonts === */
|
|
@@ -606,8 +638,10 @@
|
|
|
606
638
|
|
|
607
639
|
/* === Motion === */
|
|
608
640
|
/* Backs the <AutoHeight> primitive: eases a container's height as its content changes size.
|
|
609
|
-
|
|
610
|
-
|
|
641
|
+
A real class because `height` is a property no Tailwind transition utility names: the only way to
|
|
642
|
+
write it in a class list is the arbitrary `transition-[height]`, which the content scanner can
|
|
643
|
+
drop the first time a file writes it. (The duration is not the reason — `duration-normal` carries
|
|
644
|
+
the same variable this line does.)
|
|
611
645
|
Overflow is NOT clipped here — the component clips only while the height is animating (so the
|
|
612
646
|
settled box doesn't slice focus rings or tooltips on full-width children). */
|
|
613
647
|
.motion-auto-height {
|
|
@@ -617,9 +651,11 @@
|
|
|
617
651
|
}
|
|
618
652
|
|
|
619
653
|
/* Backs ToggleGroup's `sliding` mark: one thumb that travels between equal-width slots instead of a
|
|
620
|
-
fill appearing on each. A
|
|
621
|
-
|
|
622
|
-
`
|
|
654
|
+
fill appearing on each. A named primitive rather than the three utilities that would now say the
|
|
655
|
+
same thing, so the thumb's timing is stated once and cannot drift between the call sites that
|
|
656
|
+
write it. `slide` because the thumb crosses the width of a slot — `ui`, the hover/focus tint step,
|
|
657
|
+
would clip it to near a snap. `standard` because it is on screen before and after and only moves
|
|
658
|
+
in place. */
|
|
623
659
|
.motion-segment-thumb {
|
|
624
660
|
transition-property: transform;
|
|
625
661
|
transition-duration: var(--motion-duration-slide);
|
|
@@ -630,9 +666,9 @@
|
|
|
630
666
|
frame as it travels. One class on both, so the mark cannot be retuned away from the edge it
|
|
631
667
|
answers for — the same reason two carets read one `caretMotion`. `transform` is here rather than
|
|
632
668
|
in a class of its own because the bar is that edge said in miniature: retune one and the two stop
|
|
633
|
-
arriving together. A real class for the reason the
|
|
634
|
-
|
|
635
|
-
|
|
669
|
+
arriving together. A real class for the reason the first one above is, and more so: `width,
|
|
670
|
+
transform` is a pair no Tailwind utility names at all, so writing it in a class list means the
|
|
671
|
+
arbitrary `transition-[width,transform]` — the form the scanner can drop. */
|
|
636
672
|
.motion-rail-collapse {
|
|
637
673
|
transition-property: width, transform;
|
|
638
674
|
transition-duration: var(--motion-duration-normal);
|
package/dist/styles.css
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
--bg-elevated: #252936;
|
|
19
19
|
--bg-overlay: #252936;
|
|
20
20
|
--bg-sunken: #0e1015;
|
|
21
|
-
--bg-selected: #
|
|
21
|
+
--bg-selected: #252735;
|
|
22
22
|
--bg-brand: #06297d;
|
|
23
23
|
--bg-brand-subtle: #1f2541;
|
|
24
24
|
--bg-brand-hover: #08349b;
|
|
@@ -102,12 +102,12 @@
|
|
|
102
102
|
--grid-container-max: 1440px;
|
|
103
103
|
|
|
104
104
|
/* typography text-styles — theme-invariant, :root only (see typographyVars in build.js) */
|
|
105
|
-
--text-display-xl-font-family: "
|
|
105
|
+
--text-display-xl-font-family: "Sora", "Inter", system-ui, -apple-system, sans-serif;
|
|
106
106
|
--text-display-xl-font-size: 3.5rem;
|
|
107
107
|
--text-display-xl-line-height: 1.05;
|
|
108
108
|
--text-display-xl-font-weight: 400;
|
|
109
109
|
--text-display-xl-letter-spacing: -0.02em;
|
|
110
|
-
--text-display-lg-font-family: "
|
|
110
|
+
--text-display-lg-font-family: "Sora", "Inter", system-ui, -apple-system, sans-serif;
|
|
111
111
|
--text-display-lg-font-size: 3rem;
|
|
112
112
|
--text-display-lg-line-height: 1.1;
|
|
113
113
|
--text-display-lg-font-weight: 400;
|
|
@@ -282,7 +282,7 @@
|
|
|
282
282
|
--bg-elevated: #edeef0;
|
|
283
283
|
--bg-overlay: #ffffff;
|
|
284
284
|
--bg-sunken: #e1e2e4;
|
|
285
|
-
--bg-selected: #
|
|
285
|
+
--bg-selected: #eceded;
|
|
286
286
|
--bg-brand-subtle: #e4ecfe;
|
|
287
287
|
--bg-brand-hover: #05226a;
|
|
288
288
|
--bg-brand-bright-hover: #0b4cd5;
|
|
@@ -341,6 +341,27 @@
|
|
|
341
341
|
--overlay-modal-bg: #ffffff;
|
|
342
342
|
--focus-ring-color: #0940b8;
|
|
343
343
|
|
|
344
|
+
/* Same value as :root on purpose, re-declared so .light lists every colour token a
|
|
345
|
+
light consumer gets rather than leaving some to inheritance. Why, and what holds
|
|
346
|
+
it honest: docs/tokens.md, "Theme invariance". */
|
|
347
|
+
--bg-brand: #06297d;
|
|
348
|
+
--bg-brand-bright: #165ff2;
|
|
349
|
+
--bg-success: #13703c;
|
|
350
|
+
--bg-success-bright: #21be63;
|
|
351
|
+
--bg-danger: #78100b;
|
|
352
|
+
--text-on-brand: #f6f7f7;
|
|
353
|
+
--text-on-success: #f6f7f7;
|
|
354
|
+
--text-on-success-bright: #08090c;
|
|
355
|
+
--text-on-warning: #08090c;
|
|
356
|
+
--text-on-danger: #f6f7f7;
|
|
357
|
+
--border-selected: #737c95;
|
|
358
|
+
--border-brand: #165ff2;
|
|
359
|
+
--border-warning: #b3780e;
|
|
360
|
+
--border-danger: #e82020;
|
|
361
|
+
--field-border-hover: #737c95;
|
|
362
|
+
--field-border-filled: #737c95;
|
|
363
|
+
--field-border-error: #e82020;
|
|
364
|
+
|
|
344
365
|
/* shadcn role bridge re-declared so .light on a nested element (not just <html>)
|
|
345
366
|
re-resolves the aliases to light values. */
|
|
346
367
|
--background: var(--bg-primary);
|
|
@@ -470,11 +491,15 @@
|
|
|
470
491
|
--color-bg-surface: var(--bg-surface);
|
|
471
492
|
--color-bg-elevated: var(--bg-elevated);
|
|
472
493
|
--color-bg-sunken: var(--bg-sunken);
|
|
494
|
+
--color-bg-brand: var(--bg-brand);
|
|
473
495
|
--color-bg-brand-subtle: var(--bg-brand-subtle);
|
|
474
496
|
--color-bg-brand-hover: var(--bg-brand-hover);
|
|
497
|
+
--color-bg-brand-bright: var(--bg-brand-bright);
|
|
498
|
+
--color-bg-success: var(--bg-success);
|
|
475
499
|
--color-bg-success-subtle: var(--bg-success-subtle);
|
|
476
500
|
--color-bg-warning: var(--bg-warning);
|
|
477
501
|
--color-bg-warning-subtle: var(--bg-warning-subtle);
|
|
502
|
+
--color-bg-danger: var(--bg-danger);
|
|
478
503
|
--color-bg-danger-subtle: var(--bg-danger-subtle);
|
|
479
504
|
--color-bg-teal-subtle: var(--bg-teal-subtle);
|
|
480
505
|
--color-bg-violet-subtle: var(--bg-violet-subtle);
|
|
@@ -484,6 +509,10 @@
|
|
|
484
509
|
--color-text-tertiary: var(--text-tertiary);
|
|
485
510
|
--color-text-disabled: var(--text-disabled);
|
|
486
511
|
--color-text-inverse: var(--text-inverse);
|
|
512
|
+
--color-text-on-brand: var(--text-on-brand);
|
|
513
|
+
--color-text-on-success: var(--text-on-success);
|
|
514
|
+
--color-text-on-warning: var(--text-on-warning);
|
|
515
|
+
--color-text-on-danger: var(--text-on-danger);
|
|
487
516
|
--color-text-brand: var(--text-brand);
|
|
488
517
|
--color-text-success: var(--text-success);
|
|
489
518
|
--color-text-warning: var(--text-warning);
|
|
@@ -501,8 +530,11 @@
|
|
|
501
530
|
--color-border-subtle: var(--border-subtle);
|
|
502
531
|
--color-border-default: var(--border-default);
|
|
503
532
|
--color-border-strong: var(--border-strong);
|
|
533
|
+
--color-border-brand: var(--border-brand);
|
|
504
534
|
--color-border-focus: var(--border-focus);
|
|
505
535
|
--color-border-success: var(--border-success);
|
|
536
|
+
--color-border-warning: var(--border-warning);
|
|
537
|
+
--color-border-danger: var(--border-danger);
|
|
506
538
|
}
|
|
507
539
|
|
|
508
540
|
/* === Fonts === */
|
|
@@ -647,8 +679,10 @@
|
|
|
647
679
|
|
|
648
680
|
/* === Motion === */
|
|
649
681
|
/* Backs the <AutoHeight> primitive: eases a container's height as its content changes size.
|
|
650
|
-
|
|
651
|
-
|
|
682
|
+
A real class because `height` is a property no Tailwind transition utility names: the only way to
|
|
683
|
+
write it in a class list is the arbitrary `transition-[height]`, which the content scanner can
|
|
684
|
+
drop the first time a file writes it. (The duration is not the reason — `duration-normal` carries
|
|
685
|
+
the same variable this line does.)
|
|
652
686
|
Overflow is NOT clipped here — the component clips only while the height is animating (so the
|
|
653
687
|
settled box doesn't slice focus rings or tooltips on full-width children). */
|
|
654
688
|
.motion-auto-height {
|
|
@@ -658,9 +692,11 @@
|
|
|
658
692
|
}
|
|
659
693
|
|
|
660
694
|
/* Backs ToggleGroup's `sliding` mark: one thumb that travels between equal-width slots instead of a
|
|
661
|
-
fill appearing on each. A
|
|
662
|
-
|
|
663
|
-
`
|
|
695
|
+
fill appearing on each. A named primitive rather than the three utilities that would now say the
|
|
696
|
+
same thing, so the thumb's timing is stated once and cannot drift between the call sites that
|
|
697
|
+
write it. `slide` because the thumb crosses the width of a slot — `ui`, the hover/focus tint step,
|
|
698
|
+
would clip it to near a snap. `standard` because it is on screen before and after and only moves
|
|
699
|
+
in place. */
|
|
664
700
|
.motion-segment-thumb {
|
|
665
701
|
transition-property: transform;
|
|
666
702
|
transition-duration: var(--motion-duration-slide);
|
|
@@ -671,9 +707,9 @@
|
|
|
671
707
|
frame as it travels. One class on both, so the mark cannot be retuned away from the edge it
|
|
672
708
|
answers for — the same reason two carets read one `caretMotion`. `transform` is here rather than
|
|
673
709
|
in a class of its own because the bar is that edge said in miniature: retune one and the two stop
|
|
674
|
-
arriving together. A real class for the reason the
|
|
675
|
-
|
|
676
|
-
|
|
710
|
+
arriving together. A real class for the reason the first one above is, and more so: `width,
|
|
711
|
+
transform` is a pair no Tailwind utility names at all, so writing it in a class list means the
|
|
712
|
+
arbitrary `transition-[width,transform]` — the form the scanner can drop. */
|
|
677
713
|
.motion-rail-collapse {
|
|
678
714
|
transition-property: width, transform;
|
|
679
715
|
transition-duration: var(--motion-duration-normal);
|
package/dist/tailwind-preset.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
// src/tailwind-preset.ts
|
|
2
2
|
import tokensPreset from "@lessly/tokens/tailwind-preset";
|
|
3
3
|
var upstreamTheme = tokensPreset.theme;
|
|
4
|
+
var boundToMotionVar = (name, fallback) => `var(--motion-duration-${name}, ${fallback})`;
|
|
5
|
+
var NUMERIC_DURATION_ALIASES = { 200: "normal", 300: "slow", 500: "slower" };
|
|
6
|
+
var upstreamDuration = (name) => {
|
|
7
|
+
const value = upstreamTheme.transitionDuration[name];
|
|
8
|
+
if (value === void 0) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
`@lessly/tokens no longer declares transitionDuration.${name}, which the numeric duration steps alias \u2014 repoint or drop NUMERIC_DURATION_ALIASES for it in src/tailwind-preset.ts.`
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
return value;
|
|
14
|
+
};
|
|
4
15
|
var lesslyPreset = {
|
|
5
16
|
// Spread first: darkMode must keep winning even if upstream ever adds one.
|
|
6
17
|
...tokensPreset,
|
|
@@ -30,11 +41,26 @@ var lesslyPreset = {
|
|
|
30
41
|
// is not there. Four of these steps are an upstream token's own value under the name Tailwind
|
|
31
42
|
// reads for it — 200ms is `normal`, 300ms `slow`, 500ms `slower`, 10 `raised`. Same deletion
|
|
32
43
|
// contract as the three above.
|
|
44
|
+
//
|
|
45
|
+
// Every step reaches the utility as its motion variable, upstream's literal behind it as the
|
|
46
|
+
// fallback, and the numeric steps bind to the variable of the key they alias. Only a
|
|
47
|
+
// declaration naming a variable is one the token layer's `prefers-reduced-motion` block can
|
|
48
|
+
// zero. Only the fallback keeps a consumer who takes the preset without `@lessly/ui/styles.css`
|
|
49
|
+
// on the durations they have: a `var()` with nothing to resolve and no fallback is invalid at
|
|
50
|
+
// computed-value time, and `transition-duration` drops to its initial `0s`.
|
|
33
51
|
transitionDuration: {
|
|
34
|
-
...
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
52
|
+
...Object.fromEntries(
|
|
53
|
+
Object.entries(upstreamTheme.transitionDuration).map(([name, value]) => [
|
|
54
|
+
name,
|
|
55
|
+
boundToMotionVar(name, value)
|
|
56
|
+
])
|
|
57
|
+
),
|
|
58
|
+
...Object.fromEntries(
|
|
59
|
+
Object.entries(NUMERIC_DURATION_ALIASES).map(([step, name]) => [
|
|
60
|
+
step,
|
|
61
|
+
boundToMotionVar(name, upstreamDuration(name))
|
|
62
|
+
])
|
|
63
|
+
)
|
|
38
64
|
},
|
|
39
65
|
zIndex: { ...upstreamTheme.zIndex, 10: "10", 20: "20", 50: "50" },
|
|
40
66
|
boxShadow: { ...upstreamTheme.boxShadow, none: "none" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lessly/ui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "Lessly design system — shared UI primitives, tokens, and theme",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@10.30.3",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@lessly/tokens": "^0.
|
|
76
|
+
"@lessly/tokens": "^0.9.0",
|
|
77
77
|
"@radix-ui/react-accordion": "^1.2.16",
|
|
78
78
|
"@radix-ui/react-alert-dialog": "^1.1.19",
|
|
79
79
|
"@radix-ui/react-aspect-ratio": "^1.1.11",
|