@kinetixui/ui 0.8.0 → 0.10.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/index.d.ts +121 -1
- package/dist/index.js +285 -0
- package/package.json +2 -2
- package/src/components/banner.tsx +89 -0
- package/src/components/button-group.tsx +71 -0
- package/src/components/description-list.tsx +52 -0
- package/src/components/native-select.tsx +82 -0
- package/src/components/segmented-control.tsx +50 -0
- package/src/components/timeline.tsx +70 -0
- package/src/index.ts +28 -0
- package/src/stories/Banner.stories.tsx +28 -0
- package/src/stories/ButtonGroup.stories.tsx +32 -0
- package/src/stories/DescriptionList.stories.tsx +26 -0
- package/src/stories/NativeSelect.stories.tsx +33 -0
- package/src/stories/SegmentedControl.stories.tsx +25 -0
- package/src/stories/Timeline.stories.tsx +28 -0
package/dist/index.d.ts
CHANGED
|
@@ -1252,7 +1252,127 @@ declare const EmptyTitle: React$1.ForwardRefExoticComponent<React$1.HTMLAttribut
|
|
|
1252
1252
|
declare const EmptyDescription: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLParagraphElement> & React$1.RefAttributes<HTMLParagraphElement>>;
|
|
1253
1253
|
declare const EmptyContent: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
|
|
1254
1254
|
|
|
1255
|
+
/**
|
|
1256
|
+
* ButtonGroup — visually joins adjacent buttons into a connected cluster
|
|
1257
|
+
* (segmented-control style): inner corners squared off, shared borders
|
|
1258
|
+
* overlapped by 1px so they don't double up, the focused child raised
|
|
1259
|
+
* above its neighbours so its ring isn't clipped. Gap-fill addition (not
|
|
1260
|
+
* in the original Figma source) — matches the shadcn/ui ButtonGroup API
|
|
1261
|
+
* shape. Works with any child that renders its own border/radius (Button,
|
|
1262
|
+
* ButtonGroupText, a Select trigger, …), not just `<Button>`.
|
|
1263
|
+
*/
|
|
1264
|
+
interface ButtonGroupProps extends React$1.HTMLAttributes<HTMLDivElement> {
|
|
1265
|
+
orientation?: "horizontal" | "vertical";
|
|
1266
|
+
}
|
|
1267
|
+
declare const ButtonGroup: React$1.ForwardRefExoticComponent<ButtonGroupProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
1268
|
+
interface ButtonGroupSeparatorProps extends React$1.HTMLAttributes<HTMLDivElement> {
|
|
1269
|
+
orientation?: "horizontal" | "vertical";
|
|
1270
|
+
}
|
|
1271
|
+
/** A thin divider between segments — useful between non-outline buttons, where the group's own overlap trick has no shared border to lean on. */
|
|
1272
|
+
declare const ButtonGroupSeparator: React$1.ForwardRefExoticComponent<ButtonGroupSeparatorProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
1273
|
+
/** A static, non-interactive label segment inside a group — e.g. a unit or a prefix next to steppers. */
|
|
1274
|
+
declare const ButtonGroupText: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLSpanElement> & React$1.RefAttributes<HTMLSpanElement>>;
|
|
1275
|
+
|
|
1276
|
+
/**
|
|
1277
|
+
* NativeSelect — a styled wrapper around the native `<select>` element,
|
|
1278
|
+
* for when a form should submit synchronously without JS (or just prefers
|
|
1279
|
+
* the OS-native picker on mobile) instead of Select's Radix popover.
|
|
1280
|
+
* Matches Input's `inputVariants` styling 1:1 so the two are drop-in
|
|
1281
|
+
* interchangeable in a Field. Gap-fill addition (not in the original
|
|
1282
|
+
* Figma source) — matches the shadcn/ui Native Select API shape.
|
|
1283
|
+
*/
|
|
1284
|
+
declare const nativeSelectVariants: (props?: ({
|
|
1285
|
+
state?: "Default" | "Focus" | "Disabled" | "Error" | null | undefined;
|
|
1286
|
+
corners?: "sharp" | "default" | "pill" | "rounded" | null | undefined;
|
|
1287
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
1288
|
+
interface NativeSelectProps extends Omit<React$1.SelectHTMLAttributes<HTMLSelectElement>, "size">, VariantProps<typeof nativeSelectVariants> {
|
|
1289
|
+
}
|
|
1290
|
+
declare const NativeSelect: React$1.ForwardRefExoticComponent<NativeSelectProps & React$1.RefAttributes<HTMLSelectElement>>;
|
|
1291
|
+
interface NativeSelectOptionProps extends React$1.OptionHTMLAttributes<HTMLOptionElement> {
|
|
1292
|
+
}
|
|
1293
|
+
declare const NativeSelectOption: React$1.ForwardRefExoticComponent<NativeSelectOptionProps & React$1.RefAttributes<HTMLOptionElement>>;
|
|
1294
|
+
interface NativeSelectOptGroupProps extends React$1.OptgroupHTMLAttributes<HTMLOptGroupElement> {
|
|
1295
|
+
}
|
|
1296
|
+
declare const NativeSelectOptGroup: React$1.ForwardRefExoticComponent<NativeSelectOptGroupProps & React$1.RefAttributes<HTMLOptGroupElement>>;
|
|
1297
|
+
|
|
1298
|
+
/**
|
|
1299
|
+
* DescriptionList — `<dl>` term/detail rows with the site's own spec-sheet
|
|
1300
|
+
* skin (mono, uppercase, tracked term labels; a divided rounded shell).
|
|
1301
|
+
* Lifted out of two hand-rolled call sites — `ComponentMeta`'s doc-page
|
|
1302
|
+
* spec strip and the homepage's "spec" card — into a reusable component.
|
|
1303
|
+
* Gap-fill addition (not in the original Figma source).
|
|
1304
|
+
*/
|
|
1305
|
+
declare const DescriptionList: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDListElement> & React$1.RefAttributes<HTMLDListElement>>;
|
|
1306
|
+
interface DescriptionListItemProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "children"> {
|
|
1307
|
+
term: React$1.ReactNode;
|
|
1308
|
+
children: React$1.ReactNode;
|
|
1309
|
+
/** `row` (default) puts the term and value side by side; `stacked` puts the value below a full-width term — better for long values. */
|
|
1310
|
+
layout?: "row" | "stacked";
|
|
1311
|
+
}
|
|
1312
|
+
declare const DescriptionListItem: React$1.ForwardRefExoticComponent<DescriptionListItemProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
1313
|
+
|
|
1314
|
+
/**
|
|
1315
|
+
* Banner — a full-bleed, page-level notice (info/promo/maintenance),
|
|
1316
|
+
* optionally dismissible and stickied to the top of the viewport. Distinct
|
|
1317
|
+
* from `Alert` (in-flow, static) and `Sonner` (transient toast): Banner is
|
|
1318
|
+
* edge-to-edge and persistent until dismissed. Distinct from `Inform`
|
|
1319
|
+
* (contained, rounded inline card): Banner has no rounded corners or own
|
|
1320
|
+
* width — it spans whatever it's placed in, typically the full viewport.
|
|
1321
|
+
* Reuses `Inform`'s intent taxonomy and icon set for a consistent look.
|
|
1322
|
+
* Gap-fill addition (not in the original Figma source).
|
|
1323
|
+
*/
|
|
1324
|
+
declare const bannerVariants: (props?: ({
|
|
1325
|
+
variant?: "success" | "warning" | "error" | "information" | "action" | null | undefined;
|
|
1326
|
+
sticky?: boolean | null | undefined;
|
|
1327
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
1328
|
+
interface BannerProps extends React$1.HTMLAttributes<HTMLDivElement>, VariantProps<typeof bannerVariants> {
|
|
1329
|
+
hideIcon?: boolean;
|
|
1330
|
+
onDismiss?: () => void;
|
|
1331
|
+
/** optional CTA rendered inline after the message */
|
|
1332
|
+
action?: {
|
|
1333
|
+
label: React$1.ReactNode;
|
|
1334
|
+
onClick?: () => void;
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
declare const Banner: React$1.ForwardRefExoticComponent<BannerProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
1338
|
+
|
|
1339
|
+
/**
|
|
1340
|
+
* SegmentedControl — an iOS-style single-select strip. Functionally
|
|
1341
|
+
* `ToggleGroup type="single"`: a thin, documented preset over the same
|
|
1342
|
+
* Radix primitive with the segmented look (`Tabs`' `TabsList`/
|
|
1343
|
+
* `TabsTrigger` visual treatment — filled track, raised active segment)
|
|
1344
|
+
* instead of `Toggle`'s individually-outlined-button look. `type="single"`
|
|
1345
|
+
* is fixed, not exposed — a segmented control that could go fully
|
|
1346
|
+
* unselected or multi-select isn't the pattern. Gap-fill addition (not in
|
|
1347
|
+
* the original Figma source).
|
|
1348
|
+
*/
|
|
1349
|
+
type SegmentedControlProps = Omit<ToggleGroupPrimitive.ToggleGroupSingleProps, "type">;
|
|
1350
|
+
declare const SegmentedControl: React$1.ForwardRefExoticComponent<SegmentedControlProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
1351
|
+
declare const SegmentedControlItem: React$1.ForwardRefExoticComponent<Omit<ToggleGroupPrimitive.ToggleGroupItemProps & React$1.RefAttributes<HTMLButtonElement>, "ref"> & React$1.RefAttributes<HTMLButtonElement>>;
|
|
1352
|
+
|
|
1353
|
+
/**
|
|
1354
|
+
* Timeline — ordered events down a rail (dot, connector, time, content).
|
|
1355
|
+
* `alternating` lays content left/right of a centered rail (desktop);
|
|
1356
|
+
* the default is a single left-aligned rail. Same rail/dot/connector
|
|
1357
|
+
* technique as `Stepper`, but for a history/activity log rather than a
|
|
1358
|
+
* progress indicator — no complete/current/upcoming states, an array of
|
|
1359
|
+
* arbitrary events instead. Gap-fill addition (not in the original Figma
|
|
1360
|
+
* source).
|
|
1361
|
+
*/
|
|
1362
|
+
interface TimelineItem {
|
|
1363
|
+
time?: React$1.ReactNode;
|
|
1364
|
+
title: React$1.ReactNode;
|
|
1365
|
+
content?: React$1.ReactNode;
|
|
1366
|
+
/** custom dot content — defaults to a filled circle */
|
|
1367
|
+
icon?: React$1.ReactNode;
|
|
1368
|
+
}
|
|
1369
|
+
interface TimelineProps extends React$1.HTMLAttributes<HTMLOListElement> {
|
|
1370
|
+
items: TimelineItem[];
|
|
1371
|
+
alternating?: boolean;
|
|
1372
|
+
}
|
|
1373
|
+
declare const Timeline: React$1.ForwardRefExoticComponent<TimelineProps & React$1.RefAttributes<HTMLOListElement>>;
|
|
1374
|
+
|
|
1255
1375
|
/** Merges Tailwind class names, resolving conflicts (clsx + tailwind-merge). */
|
|
1256
1376
|
declare function cn(...inputs: ClassValue[]): string;
|
|
1257
1377
|
|
|
1258
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppBar, AppBarActions, AppBarBrand, AppBarLink, type AppBarLinkProps, AppBarNav, AspectRatio, AudioPlayer, type AudioPlayerProps, Avatar, AvatarFallback, AvatarGroup, type AvatarGroupProps, AvatarImage, Badge, type BadgeProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, type ButtonProps, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, type CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Checkbox, CircularProgress, type CircularProgressProps, CodeBlock, type CodeBlockFile, type CodeBlockProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DataTable, DatePicker, type DatePickerProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, 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, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, type EmptyMediaProps, EmptyTitle, Fab, type FabProps, Field, FieldControl, FieldDescription, FieldLabel, FieldMessage, FileUpload, FileUploadItem, type FileUploadItemProps, type FileUploadProps, Footer, FooterBottom, FooterColumn, type FooterColumnProps, FooterLink, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, HoverCard, HoverCardContent, HoverCardTrigger, Image, type ImageProps, Inform, type InformProps, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Kbd, KbdGroup, type KbdGroupProps, type KbdProps, Label, List, ListItem, type ListItemProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, Metric, type MetricProps, Modal, type ModalProps, type ModalType, NavigationBar, type NavigationBarProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NumberInput, type NumberInputProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PasswordInput, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, Quote, type QuoteProps, RadioGroup, RadioGroupItem, Rating, type RatingProps, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarProvider, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Spinner, type SpinnerProps, Stepper, type StepperProps, type StepperStep, Switch, TabBar, TabBarItem, type TabBarItemProps, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableOfContents, type TableOfContentsProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, type TagProps, Textarea, type TextareaProps, Toaster, type TocItem, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UploadFile, badgeVariants, buttonVariants, cn, emptyMediaVariants, fabVariants, formatBytes, informVariants, inputVariants, messageVariants, navigationMenuTriggerStyle, spinnerVariants, tagVariants, textareaVariants, toggleVariants, useAppBar, useFormField, useSidebar };
|
|
1378
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppBar, AppBarActions, AppBarBrand, AppBarLink, type AppBarLinkProps, AppBarNav, AspectRatio, AudioPlayer, type AudioPlayerProps, Avatar, AvatarFallback, AvatarGroup, type AvatarGroupProps, AvatarImage, Badge, type BadgeProps, Banner, type BannerProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, type ButtonGroupProps, ButtonGroupSeparator, type ButtonGroupSeparatorProps, ButtonGroupText, type ButtonProps, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, type CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Checkbox, CircularProgress, type CircularProgressProps, CodeBlock, type CodeBlockFile, type CodeBlockProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DataTable, DatePicker, type DatePickerProps, DescriptionList, DescriptionListItem, type DescriptionListItemProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, 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, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, type EmptyMediaProps, EmptyTitle, Fab, type FabProps, Field, FieldControl, FieldDescription, FieldLabel, FieldMessage, FileUpload, FileUploadItem, type FileUploadItemProps, type FileUploadProps, Footer, FooterBottom, FooterColumn, type FooterColumnProps, FooterLink, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, HoverCard, HoverCardContent, HoverCardTrigger, Image, type ImageProps, Inform, type InformProps, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Kbd, KbdGroup, type KbdGroupProps, type KbdProps, Label, List, ListItem, type ListItemProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, Metric, type MetricProps, Modal, type ModalProps, type ModalType, NativeSelect, NativeSelectOptGroup, type NativeSelectOptGroupProps, NativeSelectOption, type NativeSelectOptionProps, type NativeSelectProps, NavigationBar, type NavigationBarProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NumberInput, type NumberInputProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PasswordInput, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, Quote, type QuoteProps, RadioGroup, RadioGroupItem, Rating, type RatingProps, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, SegmentedControl, SegmentedControlItem, type SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarProvider, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Spinner, type SpinnerProps, Stepper, type StepperProps, type StepperStep, Switch, TabBar, TabBarItem, type TabBarItemProps, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableOfContents, type TableOfContentsProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, type TagProps, Textarea, type TextareaProps, Timeline, type TimelineItem, type TimelineProps, Toaster, type TocItem, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UploadFile, badgeVariants, bannerVariants, buttonVariants, cn, emptyMediaVariants, fabVariants, formatBytes, informVariants, inputVariants, messageVariants, nativeSelectVariants, navigationMenuTriggerStyle, spinnerVariants, tagVariants, textareaVariants, toggleVariants, useAppBar, useFormField, useSidebar };
|
package/dist/index.js
CHANGED
|
@@ -3935,6 +3935,277 @@ var EmptyContent = React67.forwardRef(
|
|
|
3935
3935
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx72("div", { ref, className: cn("flex flex-col items-center gap-3", className), ...props })
|
|
3936
3936
|
);
|
|
3937
3937
|
EmptyContent.displayName = "EmptyContent";
|
|
3938
|
+
|
|
3939
|
+
// src/components/button-group.tsx
|
|
3940
|
+
import * as React68 from "react";
|
|
3941
|
+
import { jsx as jsx73 } from "react/jsx-runtime";
|
|
3942
|
+
var ButtonGroup = React68.forwardRef(
|
|
3943
|
+
({ className, orientation = "horizontal", ...props }, ref) => /* @__PURE__ */ jsx73(
|
|
3944
|
+
"div",
|
|
3945
|
+
{
|
|
3946
|
+
ref,
|
|
3947
|
+
role: "group",
|
|
3948
|
+
"data-orientation": orientation,
|
|
3949
|
+
className: cn(
|
|
3950
|
+
"flex w-fit items-stretch [&>*]:relative [&>*]:focus-visible:z-10",
|
|
3951
|
+
orientation === "horizontal" ? "flex-row [&>*:not(:first-child)]:-ml-px [&>*:not(:first-child)]:rounded-l-none [&>*:not(:last-child)]:rounded-r-none" : "flex-col [&>*:not(:first-child)]:-mt-px [&>*:not(:first-child)]:rounded-t-none [&>*:not(:last-child)]:rounded-b-none",
|
|
3952
|
+
className
|
|
3953
|
+
),
|
|
3954
|
+
...props
|
|
3955
|
+
}
|
|
3956
|
+
)
|
|
3957
|
+
);
|
|
3958
|
+
ButtonGroup.displayName = "ButtonGroup";
|
|
3959
|
+
var ButtonGroupSeparator = React68.forwardRef(
|
|
3960
|
+
({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx73(
|
|
3961
|
+
"div",
|
|
3962
|
+
{
|
|
3963
|
+
ref,
|
|
3964
|
+
role: "separator",
|
|
3965
|
+
"aria-orientation": orientation,
|
|
3966
|
+
className: cn("shrink-0 self-stretch bg-border", orientation === "vertical" ? "my-1.5 w-px" : "mx-1.5 h-px", className),
|
|
3967
|
+
...props
|
|
3968
|
+
}
|
|
3969
|
+
)
|
|
3970
|
+
);
|
|
3971
|
+
ButtonGroupSeparator.displayName = "ButtonGroupSeparator";
|
|
3972
|
+
var ButtonGroupText = React68.forwardRef(
|
|
3973
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx73(
|
|
3974
|
+
"span",
|
|
3975
|
+
{
|
|
3976
|
+
ref,
|
|
3977
|
+
className: cn(
|
|
3978
|
+
"flex items-center gap-1.5 rounded-md border border-input bg-muted px-3 text-label-md text-foreground",
|
|
3979
|
+
className
|
|
3980
|
+
),
|
|
3981
|
+
...props
|
|
3982
|
+
}
|
|
3983
|
+
)
|
|
3984
|
+
);
|
|
3985
|
+
ButtonGroupText.displayName = "ButtonGroupText";
|
|
3986
|
+
|
|
3987
|
+
// src/components/native-select.tsx
|
|
3988
|
+
import * as React69 from "react";
|
|
3989
|
+
import { ChevronDown as ChevronDown4 } from "lucide-react";
|
|
3990
|
+
import { cva as cva19 } from "class-variance-authority";
|
|
3991
|
+
import { jsx as jsx74, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
3992
|
+
var nativeSelectVariants = cva19(
|
|
3993
|
+
[
|
|
3994
|
+
"flex w-full appearance-none border border-input bg-background px-3 py-3 pr-9",
|
|
3995
|
+
"font-sans text-[14px] leading-5 tracking-[0.25px] text-foreground",
|
|
3996
|
+
"outline-none transition-colors",
|
|
3997
|
+
"focus-visible:border-primary focus-visible:shadow-focus",
|
|
3998
|
+
"disabled:cursor-not-allowed disabled:opacity-disabled",
|
|
3999
|
+
"aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:border-destructive aria-[invalid=true]:focus-visible:shadow-focus-destructive"
|
|
4000
|
+
],
|
|
4001
|
+
{
|
|
4002
|
+
variants: {
|
|
4003
|
+
state: {
|
|
4004
|
+
Default: "",
|
|
4005
|
+
Focus: "border-primary shadow-focus",
|
|
4006
|
+
Error: "border-destructive",
|
|
4007
|
+
Disabled: "opacity-disabled pointer-events-none"
|
|
4008
|
+
},
|
|
4009
|
+
corners: {
|
|
4010
|
+
sharp: "rounded-none",
|
|
4011
|
+
default: "rounded-sm",
|
|
4012
|
+
rounded: "rounded-md",
|
|
4013
|
+
pill: "rounded-full px-4"
|
|
4014
|
+
}
|
|
4015
|
+
},
|
|
4016
|
+
defaultVariants: { state: "Default", corners: "default" }
|
|
4017
|
+
}
|
|
4018
|
+
);
|
|
4019
|
+
var NativeSelect = React69.forwardRef(
|
|
4020
|
+
({ className, state, corners, disabled, "aria-invalid": ariaInvalid, children, ...props }, ref) => /* @__PURE__ */ jsxs41("div", { className: "relative", children: [
|
|
4021
|
+
/* @__PURE__ */ jsx74(
|
|
4022
|
+
"select",
|
|
4023
|
+
{
|
|
4024
|
+
ref,
|
|
4025
|
+
"data-slot": "native-select",
|
|
4026
|
+
"data-state": state ? state.toLowerCase() : void 0,
|
|
4027
|
+
"aria-invalid": ariaInvalid ?? (state === "Error" || void 0),
|
|
4028
|
+
disabled: disabled || state === "Disabled",
|
|
4029
|
+
className: cn(nativeSelectVariants({ state, corners }), className),
|
|
4030
|
+
...props,
|
|
4031
|
+
children
|
|
4032
|
+
}
|
|
4033
|
+
),
|
|
4034
|
+
/* @__PURE__ */ jsx74(ChevronDown4, { className: "pointer-events-none absolute right-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" })
|
|
4035
|
+
] })
|
|
4036
|
+
);
|
|
4037
|
+
NativeSelect.displayName = "NativeSelect";
|
|
4038
|
+
var NativeSelectOption = React69.forwardRef(
|
|
4039
|
+
({ ...props }, ref) => /* @__PURE__ */ jsx74("option", { ref, ...props })
|
|
4040
|
+
);
|
|
4041
|
+
NativeSelectOption.displayName = "NativeSelectOption";
|
|
4042
|
+
var NativeSelectOptGroup = React69.forwardRef(
|
|
4043
|
+
({ ...props }, ref) => /* @__PURE__ */ jsx74("optgroup", { ref, ...props })
|
|
4044
|
+
);
|
|
4045
|
+
NativeSelectOptGroup.displayName = "NativeSelectOptGroup";
|
|
4046
|
+
|
|
4047
|
+
// src/components/description-list.tsx
|
|
4048
|
+
import * as React70 from "react";
|
|
4049
|
+
import { jsx as jsx75, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
4050
|
+
var DescriptionList = React70.forwardRef(
|
|
4051
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx75(
|
|
4052
|
+
"dl",
|
|
4053
|
+
{
|
|
4054
|
+
ref,
|
|
4055
|
+
className: cn("divide-y divide-border rounded-lg border border-border bg-muted/20", className),
|
|
4056
|
+
...props
|
|
4057
|
+
}
|
|
4058
|
+
)
|
|
4059
|
+
);
|
|
4060
|
+
DescriptionList.displayName = "DescriptionList";
|
|
4061
|
+
var DescriptionListItem = React70.forwardRef(
|
|
4062
|
+
({ className, term, children, layout = "row", ...props }, ref) => /* @__PURE__ */ jsxs42(
|
|
4063
|
+
"div",
|
|
4064
|
+
{
|
|
4065
|
+
ref,
|
|
4066
|
+
className: cn("gap-3 px-3.5 py-2.5", layout === "row" ? "flex items-baseline" : "flex flex-col", className),
|
|
4067
|
+
...props,
|
|
4068
|
+
children: [
|
|
4069
|
+
/* @__PURE__ */ jsx75(
|
|
4070
|
+
"dt",
|
|
4071
|
+
{
|
|
4072
|
+
className: cn(
|
|
4073
|
+
"shrink-0 font-mono text-[10px] uppercase tracking-[0.14em] text-muted-foreground",
|
|
4074
|
+
layout === "row" && "w-24"
|
|
4075
|
+
),
|
|
4076
|
+
children: term
|
|
4077
|
+
}
|
|
4078
|
+
),
|
|
4079
|
+
/* @__PURE__ */ jsx75("dd", { className: "min-w-0 text-body-sm text-foreground", children })
|
|
4080
|
+
]
|
|
4081
|
+
}
|
|
4082
|
+
)
|
|
4083
|
+
);
|
|
4084
|
+
DescriptionListItem.displayName = "DescriptionListItem";
|
|
4085
|
+
|
|
4086
|
+
// src/components/banner.tsx
|
|
4087
|
+
import * as React71 from "react";
|
|
4088
|
+
import { cva as cva20 } from "class-variance-authority";
|
|
4089
|
+
import { CircleAlert as CircleAlert3, CircleCheck as CircleCheck3, Info as Info3, TriangleAlert as TriangleAlert4, X as X8 } from "lucide-react";
|
|
4090
|
+
import { jsx as jsx76, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
4091
|
+
var bannerVariants = cva20(
|
|
4092
|
+
"flex w-full items-start gap-2.5 border-b px-4 py-3 text-body-sm font-sans [&>svg]:mt-0.5 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
4093
|
+
{
|
|
4094
|
+
variants: {
|
|
4095
|
+
variant: {
|
|
4096
|
+
information: "border-info/20 bg-info/10 text-info",
|
|
4097
|
+
warning: "border-warning/25 bg-warning/15 text-warning",
|
|
4098
|
+
success: "border-success/25 bg-success/15 text-success",
|
|
4099
|
+
error: "border-destructive/20 bg-destructive/10 text-destructive",
|
|
4100
|
+
action: "border-transparent bg-foreground text-background"
|
|
4101
|
+
},
|
|
4102
|
+
sticky: {
|
|
4103
|
+
true: "sticky top-0 z-40",
|
|
4104
|
+
false: ""
|
|
4105
|
+
}
|
|
4106
|
+
},
|
|
4107
|
+
defaultVariants: { variant: "information", sticky: false }
|
|
4108
|
+
}
|
|
4109
|
+
);
|
|
4110
|
+
var ICON2 = {
|
|
4111
|
+
information: Info3,
|
|
4112
|
+
warning: TriangleAlert4,
|
|
4113
|
+
success: CircleCheck3,
|
|
4114
|
+
error: CircleAlert3,
|
|
4115
|
+
action: Info3
|
|
4116
|
+
};
|
|
4117
|
+
var Banner = React71.forwardRef(
|
|
4118
|
+
({ className, variant = "information", sticky, hideIcon, onDismiss, action, children, ...props }, ref) => {
|
|
4119
|
+
const Icon2 = ICON2[variant ?? "information"];
|
|
4120
|
+
return /* @__PURE__ */ jsxs43("div", { ref, role: "banner", className: cn(bannerVariants({ variant, sticky }), className), ...props, children: [
|
|
4121
|
+
!hideIcon && /* @__PURE__ */ jsx76(Icon2, {}),
|
|
4122
|
+
/* @__PURE__ */ jsxs43("div", { className: "mx-auto flex min-w-0 max-w-4xl flex-1 flex-wrap items-center justify-center gap-x-3 gap-y-1 text-center", children: [
|
|
4123
|
+
/* @__PURE__ */ jsx76("span", { children }),
|
|
4124
|
+
action && /* @__PURE__ */ jsx76(
|
|
4125
|
+
"button",
|
|
4126
|
+
{
|
|
4127
|
+
type: "button",
|
|
4128
|
+
onClick: action.onClick,
|
|
4129
|
+
className: "inline-flex shrink-0 items-center gap-1.5 text-label-md font-medium underline-offset-2 outline-none hover:underline focus-visible:underline",
|
|
4130
|
+
children: action.label
|
|
4131
|
+
}
|
|
4132
|
+
)
|
|
4133
|
+
] }),
|
|
4134
|
+
onDismiss && /* @__PURE__ */ jsx76(
|
|
4135
|
+
"button",
|
|
4136
|
+
{
|
|
4137
|
+
type: "button",
|
|
4138
|
+
onClick: onDismiss,
|
|
4139
|
+
"aria-label": "Dismiss",
|
|
4140
|
+
className: "-m-0.5 shrink-0 rounded-[2px] p-0.5 opacity-muted outline-none transition-opacity hover:opacity-visible focus-visible:opacity-visible focus-visible:ring-1 focus-visible:ring-current",
|
|
4141
|
+
children: /* @__PURE__ */ jsx76(X8, { className: "size-3.5" })
|
|
4142
|
+
}
|
|
4143
|
+
)
|
|
4144
|
+
] });
|
|
4145
|
+
}
|
|
4146
|
+
);
|
|
4147
|
+
Banner.displayName = "Banner";
|
|
4148
|
+
|
|
4149
|
+
// src/components/segmented-control.tsx
|
|
4150
|
+
import * as React72 from "react";
|
|
4151
|
+
import * as ToggleGroupPrimitive2 from "@radix-ui/react-toggle-group";
|
|
4152
|
+
import { jsx as jsx77 } from "react/jsx-runtime";
|
|
4153
|
+
var SegmentedControl = React72.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx77(
|
|
4154
|
+
ToggleGroupPrimitive2.Root,
|
|
4155
|
+
{
|
|
4156
|
+
ref,
|
|
4157
|
+
type: "single",
|
|
4158
|
+
className: cn("inline-flex items-center rounded-lg bg-muted p-1 font-sans", className),
|
|
4159
|
+
...props
|
|
4160
|
+
}
|
|
4161
|
+
));
|
|
4162
|
+
SegmentedControl.displayName = "SegmentedControl";
|
|
4163
|
+
var SegmentedControlItem = React72.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx77(
|
|
4164
|
+
ToggleGroupPrimitive2.Item,
|
|
4165
|
+
{
|
|
4166
|
+
ref,
|
|
4167
|
+
className: cn(
|
|
4168
|
+
"inline-flex flex-1 items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-label-md font-medium text-muted-foreground transition-all",
|
|
4169
|
+
"outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
4170
|
+
"disabled:pointer-events-none disabled:opacity-disabled",
|
|
4171
|
+
"data-[state=on]:bg-background data-[state=on]:text-foreground data-[state=on]:shadow-sm",
|
|
4172
|
+
className
|
|
4173
|
+
),
|
|
4174
|
+
...props
|
|
4175
|
+
}
|
|
4176
|
+
));
|
|
4177
|
+
SegmentedControlItem.displayName = "SegmentedControlItem";
|
|
4178
|
+
|
|
4179
|
+
// src/components/timeline.tsx
|
|
4180
|
+
import * as React73 from "react";
|
|
4181
|
+
import { jsx as jsx78, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
4182
|
+
var Body = ({ item, align }) => /* @__PURE__ */ jsxs44("div", { className: cn("pb-6", align === "right" && "text-right"), children: [
|
|
4183
|
+
item.time && /* @__PURE__ */ jsx78("p", { className: "text-label-sm text-muted-foreground", children: item.time }),
|
|
4184
|
+
/* @__PURE__ */ jsx78("p", { className: "text-label-md font-medium text-foreground", children: item.title }),
|
|
4185
|
+
item.content && /* @__PURE__ */ jsx78("div", { className: "text-body-sm text-muted-foreground", children: item.content })
|
|
4186
|
+
] });
|
|
4187
|
+
var Rail = ({ item, isLast }) => /* @__PURE__ */ jsxs44("div", { className: "flex flex-col items-center", children: [
|
|
4188
|
+
/* @__PURE__ */ jsx78("span", { className: "flex size-2.5 shrink-0 items-center justify-center rounded-full bg-primary", children: item.icon }),
|
|
4189
|
+
!isLast && /* @__PURE__ */ jsx78("span", { "aria-hidden": true, className: "my-1 w-px flex-1 bg-border" })
|
|
4190
|
+
] });
|
|
4191
|
+
var Timeline = React73.forwardRef(
|
|
4192
|
+
({ className, items, alternating = false, ...props }, ref) => /* @__PURE__ */ jsx78("ol", { ref, className: cn("flex flex-col font-sans", className), ...props, children: items.map((item, i) => {
|
|
4193
|
+
const isLast = i === items.length - 1;
|
|
4194
|
+
if (!alternating) {
|
|
4195
|
+
return /* @__PURE__ */ jsxs44("li", { className: "grid grid-cols-[auto_1fr] gap-x-3", children: [
|
|
4196
|
+
/* @__PURE__ */ jsx78(Rail, { item, isLast }),
|
|
4197
|
+
/* @__PURE__ */ jsx78(Body, { item, align: "left" })
|
|
4198
|
+
] }, i);
|
|
4199
|
+
}
|
|
4200
|
+
const onRight = i % 2 === 0;
|
|
4201
|
+
return /* @__PURE__ */ jsxs44("li", { className: "grid grid-cols-[1fr_auto_1fr] gap-x-4", children: [
|
|
4202
|
+
onRight ? /* @__PURE__ */ jsx78("div", {}) : /* @__PURE__ */ jsx78(Body, { item, align: "right" }),
|
|
4203
|
+
/* @__PURE__ */ jsx78(Rail, { item, isLast }),
|
|
4204
|
+
onRight ? /* @__PURE__ */ jsx78(Body, { item, align: "left" }) : /* @__PURE__ */ jsx78("div", {})
|
|
4205
|
+
] }, i);
|
|
4206
|
+
}) })
|
|
4207
|
+
);
|
|
4208
|
+
Timeline.displayName = "Timeline";
|
|
3938
4209
|
export {
|
|
3939
4210
|
Accordion,
|
|
3940
4211
|
AccordionContent,
|
|
@@ -3966,6 +4237,7 @@ export {
|
|
|
3966
4237
|
AvatarGroup,
|
|
3967
4238
|
AvatarImage,
|
|
3968
4239
|
Badge,
|
|
4240
|
+
Banner,
|
|
3969
4241
|
Breadcrumb,
|
|
3970
4242
|
BreadcrumbEllipsis,
|
|
3971
4243
|
BreadcrumbItem,
|
|
@@ -3974,6 +4246,9 @@ export {
|
|
|
3974
4246
|
BreadcrumbPage,
|
|
3975
4247
|
BreadcrumbSeparator,
|
|
3976
4248
|
Button,
|
|
4249
|
+
ButtonGroup,
|
|
4250
|
+
ButtonGroupSeparator,
|
|
4251
|
+
ButtonGroupText,
|
|
3977
4252
|
Calendar,
|
|
3978
4253
|
Card,
|
|
3979
4254
|
CardContent,
|
|
@@ -4024,6 +4299,8 @@ export {
|
|
|
4024
4299
|
ContextMenuTrigger,
|
|
4025
4300
|
DataTable,
|
|
4026
4301
|
DatePicker,
|
|
4302
|
+
DescriptionList,
|
|
4303
|
+
DescriptionListItem,
|
|
4027
4304
|
Dialog,
|
|
4028
4305
|
DialogClose,
|
|
4029
4306
|
DialogContent,
|
|
@@ -4122,6 +4399,9 @@ export {
|
|
|
4122
4399
|
MenubarTrigger,
|
|
4123
4400
|
Metric,
|
|
4124
4401
|
Modal,
|
|
4402
|
+
NativeSelect,
|
|
4403
|
+
NativeSelectOptGroup,
|
|
4404
|
+
NativeSelectOption,
|
|
4125
4405
|
NavigationBar,
|
|
4126
4406
|
NavigationMenu,
|
|
4127
4407
|
NavigationMenuContent,
|
|
@@ -4154,6 +4434,8 @@ export {
|
|
|
4154
4434
|
ResizablePanelGroup,
|
|
4155
4435
|
ScrollArea,
|
|
4156
4436
|
ScrollBar,
|
|
4437
|
+
SegmentedControl,
|
|
4438
|
+
SegmentedControlItem,
|
|
4157
4439
|
Select,
|
|
4158
4440
|
SelectContent,
|
|
4159
4441
|
SelectGroup,
|
|
@@ -4211,6 +4493,7 @@ export {
|
|
|
4211
4493
|
TabsTrigger,
|
|
4212
4494
|
Tag,
|
|
4213
4495
|
Textarea,
|
|
4496
|
+
Timeline,
|
|
4214
4497
|
Toaster,
|
|
4215
4498
|
Toggle,
|
|
4216
4499
|
ToggleGroup,
|
|
@@ -4220,6 +4503,7 @@ export {
|
|
|
4220
4503
|
TooltipProvider,
|
|
4221
4504
|
TooltipTrigger,
|
|
4222
4505
|
badgeVariants,
|
|
4506
|
+
bannerVariants,
|
|
4223
4507
|
buttonVariants,
|
|
4224
4508
|
cn,
|
|
4225
4509
|
emptyMediaVariants,
|
|
@@ -4228,6 +4512,7 @@ export {
|
|
|
4228
4512
|
informVariants,
|
|
4229
4513
|
inputVariants,
|
|
4230
4514
|
messageVariants,
|
|
4515
|
+
nativeSelectVariants,
|
|
4231
4516
|
navigationMenuTriggerStyle,
|
|
4232
4517
|
spinnerVariants,
|
|
4233
4518
|
tagVariants,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kinetixui/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "KinetixUI React components — CVA + Radix + Tailwind on the KinetixUI token contract. Also distributed via the kinetixui CLI as a component registry.",
|
|
6
6
|
"keywords": [
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"react-dom": ">=18"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
|
-
"@kinetixui/tokens": "0.
|
|
93
|
+
"@kinetixui/tokens": "0.10.0",
|
|
94
94
|
"@testing-library/jest-dom": "^7.0.1",
|
|
95
95
|
"@testing-library/react": "^16.3.3",
|
|
96
96
|
"@testing-library/user-event": "^14.6.7",
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
5
|
+
import { CircleAlert, CircleCheck, Info, TriangleAlert, X } from "lucide-react";
|
|
6
|
+
import { cn } from "../lib/utils";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Banner — a full-bleed, page-level notice (info/promo/maintenance),
|
|
10
|
+
* optionally dismissible and stickied to the top of the viewport. Distinct
|
|
11
|
+
* from `Alert` (in-flow, static) and `Sonner` (transient toast): Banner is
|
|
12
|
+
* edge-to-edge and persistent until dismissed. Distinct from `Inform`
|
|
13
|
+
* (contained, rounded inline card): Banner has no rounded corners or own
|
|
14
|
+
* width — it spans whatever it's placed in, typically the full viewport.
|
|
15
|
+
* Reuses `Inform`'s intent taxonomy and icon set for a consistent look.
|
|
16
|
+
* Gap-fill addition (not in the original Figma source).
|
|
17
|
+
*/
|
|
18
|
+
const bannerVariants = cva(
|
|
19
|
+
"flex w-full items-start gap-2.5 border-b px-4 py-3 text-body-sm font-sans [&>svg]:mt-0.5 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
20
|
+
{
|
|
21
|
+
variants: {
|
|
22
|
+
variant: {
|
|
23
|
+
information: "border-info/20 bg-info/10 text-info",
|
|
24
|
+
warning: "border-warning/25 bg-warning/15 text-warning",
|
|
25
|
+
success: "border-success/25 bg-success/15 text-success",
|
|
26
|
+
error: "border-destructive/20 bg-destructive/10 text-destructive",
|
|
27
|
+
action: "border-transparent bg-foreground text-background",
|
|
28
|
+
},
|
|
29
|
+
sticky: {
|
|
30
|
+
true: "sticky top-0 z-40",
|
|
31
|
+
false: "",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
defaultVariants: { variant: "information", sticky: false },
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const ICON = {
|
|
39
|
+
information: Info,
|
|
40
|
+
warning: TriangleAlert,
|
|
41
|
+
success: CircleCheck,
|
|
42
|
+
error: CircleAlert,
|
|
43
|
+
action: Info,
|
|
44
|
+
} as const;
|
|
45
|
+
|
|
46
|
+
export interface BannerProps
|
|
47
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
48
|
+
VariantProps<typeof bannerVariants> {
|
|
49
|
+
hideIcon?: boolean;
|
|
50
|
+
onDismiss?: () => void;
|
|
51
|
+
/** optional CTA rendered inline after the message */
|
|
52
|
+
action?: { label: React.ReactNode; onClick?: () => void };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const Banner = React.forwardRef<HTMLDivElement, BannerProps>(
|
|
56
|
+
({ className, variant = "information", sticky, hideIcon, onDismiss, action, children, ...props }, ref) => {
|
|
57
|
+
const Icon = ICON[variant ?? "information"];
|
|
58
|
+
return (
|
|
59
|
+
<div ref={ref} role="banner" className={cn(bannerVariants({ variant, sticky }), className)} {...props}>
|
|
60
|
+
{!hideIcon && <Icon />}
|
|
61
|
+
<div className="mx-auto flex min-w-0 max-w-4xl flex-1 flex-wrap items-center justify-center gap-x-3 gap-y-1 text-center">
|
|
62
|
+
<span>{children}</span>
|
|
63
|
+
{action && (
|
|
64
|
+
<button
|
|
65
|
+
type="button"
|
|
66
|
+
onClick={action.onClick}
|
|
67
|
+
className="inline-flex shrink-0 items-center gap-1.5 text-label-md font-medium underline-offset-2 outline-none hover:underline focus-visible:underline"
|
|
68
|
+
>
|
|
69
|
+
{action.label}
|
|
70
|
+
</button>
|
|
71
|
+
)}
|
|
72
|
+
</div>
|
|
73
|
+
{onDismiss && (
|
|
74
|
+
<button
|
|
75
|
+
type="button"
|
|
76
|
+
onClick={onDismiss}
|
|
77
|
+
aria-label="Dismiss"
|
|
78
|
+
className="-m-0.5 shrink-0 rounded-[2px] p-0.5 opacity-muted outline-none transition-opacity hover:opacity-visible focus-visible:opacity-visible focus-visible:ring-1 focus-visible:ring-current"
|
|
79
|
+
>
|
|
80
|
+
<X className="size-3.5" />
|
|
81
|
+
</button>
|
|
82
|
+
)}
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
Banner.displayName = "Banner";
|
|
88
|
+
|
|
89
|
+
export { Banner, bannerVariants };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../lib/utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ButtonGroup — visually joins adjacent buttons into a connected cluster
|
|
8
|
+
* (segmented-control style): inner corners squared off, shared borders
|
|
9
|
+
* overlapped by 1px so they don't double up, the focused child raised
|
|
10
|
+
* above its neighbours so its ring isn't clipped. Gap-fill addition (not
|
|
11
|
+
* in the original Figma source) — matches the shadcn/ui ButtonGroup API
|
|
12
|
+
* shape. Works with any child that renders its own border/radius (Button,
|
|
13
|
+
* ButtonGroupText, a Select trigger, …), not just `<Button>`.
|
|
14
|
+
*/
|
|
15
|
+
export interface ButtonGroupProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
16
|
+
orientation?: "horizontal" | "vertical";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const ButtonGroup = React.forwardRef<HTMLDivElement, ButtonGroupProps>(
|
|
20
|
+
({ className, orientation = "horizontal", ...props }, ref) => (
|
|
21
|
+
<div
|
|
22
|
+
ref={ref}
|
|
23
|
+
role="group"
|
|
24
|
+
data-orientation={orientation}
|
|
25
|
+
className={cn(
|
|
26
|
+
"flex w-fit items-stretch [&>*]:relative [&>*]:focus-visible:z-10",
|
|
27
|
+
orientation === "horizontal"
|
|
28
|
+
? "flex-row [&>*:not(:first-child)]:-ml-px [&>*:not(:first-child)]:rounded-l-none [&>*:not(:last-child)]:rounded-r-none"
|
|
29
|
+
: "flex-col [&>*:not(:first-child)]:-mt-px [&>*:not(:first-child)]:rounded-t-none [&>*:not(:last-child)]:rounded-b-none",
|
|
30
|
+
className,
|
|
31
|
+
)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
),
|
|
35
|
+
);
|
|
36
|
+
ButtonGroup.displayName = "ButtonGroup";
|
|
37
|
+
|
|
38
|
+
export interface ButtonGroupSeparatorProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
39
|
+
orientation?: "horizontal" | "vertical";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** A thin divider between segments — useful between non-outline buttons, where the group's own overlap trick has no shared border to lean on. */
|
|
43
|
+
const ButtonGroupSeparator = React.forwardRef<HTMLDivElement, ButtonGroupSeparatorProps>(
|
|
44
|
+
({ className, orientation = "vertical", ...props }, ref) => (
|
|
45
|
+
<div
|
|
46
|
+
ref={ref}
|
|
47
|
+
role="separator"
|
|
48
|
+
aria-orientation={orientation}
|
|
49
|
+
className={cn("shrink-0 self-stretch bg-border", orientation === "vertical" ? "my-1.5 w-px" : "mx-1.5 h-px", className)}
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
),
|
|
53
|
+
);
|
|
54
|
+
ButtonGroupSeparator.displayName = "ButtonGroupSeparator";
|
|
55
|
+
|
|
56
|
+
/** A static, non-interactive label segment inside a group — e.g. a unit or a prefix next to steppers. */
|
|
57
|
+
const ButtonGroupText = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(
|
|
58
|
+
({ className, ...props }, ref) => (
|
|
59
|
+
<span
|
|
60
|
+
ref={ref}
|
|
61
|
+
className={cn(
|
|
62
|
+
"flex items-center gap-1.5 rounded-md border border-input bg-muted px-3 text-label-md text-foreground",
|
|
63
|
+
className,
|
|
64
|
+
)}
|
|
65
|
+
{...props}
|
|
66
|
+
/>
|
|
67
|
+
),
|
|
68
|
+
);
|
|
69
|
+
ButtonGroupText.displayName = "ButtonGroupText";
|
|
70
|
+
|
|
71
|
+
export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../lib/utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* DescriptionList — `<dl>` term/detail rows with the site's own spec-sheet
|
|
8
|
+
* skin (mono, uppercase, tracked term labels; a divided rounded shell).
|
|
9
|
+
* Lifted out of two hand-rolled call sites — `ComponentMeta`'s doc-page
|
|
10
|
+
* spec strip and the homepage's "spec" card — into a reusable component.
|
|
11
|
+
* Gap-fill addition (not in the original Figma source).
|
|
12
|
+
*/
|
|
13
|
+
const DescriptionList = React.forwardRef<HTMLDListElement, React.HTMLAttributes<HTMLDListElement>>(
|
|
14
|
+
({ className, ...props }, ref) => (
|
|
15
|
+
<dl
|
|
16
|
+
ref={ref}
|
|
17
|
+
className={cn("divide-y divide-border rounded-lg border border-border bg-muted/20", className)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
),
|
|
21
|
+
);
|
|
22
|
+
DescriptionList.displayName = "DescriptionList";
|
|
23
|
+
|
|
24
|
+
export interface DescriptionListItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
|
|
25
|
+
term: React.ReactNode;
|
|
26
|
+
children: React.ReactNode;
|
|
27
|
+
/** `row` (default) puts the term and value side by side; `stacked` puts the value below a full-width term — better for long values. */
|
|
28
|
+
layout?: "row" | "stacked";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const DescriptionListItem = React.forwardRef<HTMLDivElement, DescriptionListItemProps>(
|
|
32
|
+
({ className, term, children, layout = "row", ...props }, ref) => (
|
|
33
|
+
<div
|
|
34
|
+
ref={ref}
|
|
35
|
+
className={cn("gap-3 px-3.5 py-2.5", layout === "row" ? "flex items-baseline" : "flex flex-col", className)}
|
|
36
|
+
{...props}
|
|
37
|
+
>
|
|
38
|
+
<dt
|
|
39
|
+
className={cn(
|
|
40
|
+
"shrink-0 font-mono text-[10px] uppercase tracking-[0.14em] text-muted-foreground",
|
|
41
|
+
layout === "row" && "w-24",
|
|
42
|
+
)}
|
|
43
|
+
>
|
|
44
|
+
{term}
|
|
45
|
+
</dt>
|
|
46
|
+
<dd className="min-w-0 text-body-sm text-foreground">{children}</dd>
|
|
47
|
+
</div>
|
|
48
|
+
),
|
|
49
|
+
);
|
|
50
|
+
DescriptionListItem.displayName = "DescriptionListItem";
|
|
51
|
+
|
|
52
|
+
export { DescriptionList, DescriptionListItem };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { ChevronDown } from "lucide-react";
|
|
5
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
6
|
+
import { cn } from "../lib/utils";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* NativeSelect — a styled wrapper around the native `<select>` element,
|
|
10
|
+
* for when a form should submit synchronously without JS (or just prefers
|
|
11
|
+
* the OS-native picker on mobile) instead of Select's Radix popover.
|
|
12
|
+
* Matches Input's `inputVariants` styling 1:1 so the two are drop-in
|
|
13
|
+
* interchangeable in a Field. Gap-fill addition (not in the original
|
|
14
|
+
* Figma source) — matches the shadcn/ui Native Select API shape.
|
|
15
|
+
*/
|
|
16
|
+
const nativeSelectVariants = cva(
|
|
17
|
+
[
|
|
18
|
+
"flex w-full appearance-none border border-input bg-background px-3 py-3 pr-9",
|
|
19
|
+
"font-sans text-[14px] leading-5 tracking-[0.25px] text-foreground",
|
|
20
|
+
"outline-none transition-colors",
|
|
21
|
+
"focus-visible:border-primary focus-visible:shadow-focus",
|
|
22
|
+
"disabled:cursor-not-allowed disabled:opacity-disabled",
|
|
23
|
+
"aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:border-destructive aria-[invalid=true]:focus-visible:shadow-focus-destructive",
|
|
24
|
+
],
|
|
25
|
+
{
|
|
26
|
+
variants: {
|
|
27
|
+
state: {
|
|
28
|
+
Default: "",
|
|
29
|
+
Focus: "border-primary shadow-focus",
|
|
30
|
+
Error: "border-destructive",
|
|
31
|
+
Disabled: "opacity-disabled pointer-events-none",
|
|
32
|
+
},
|
|
33
|
+
corners: {
|
|
34
|
+
sharp: "rounded-none",
|
|
35
|
+
default: "rounded-sm",
|
|
36
|
+
rounded: "rounded-md",
|
|
37
|
+
pill: "rounded-full px-4",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
defaultVariants: { state: "Default", corners: "default" },
|
|
41
|
+
},
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
export interface NativeSelectProps
|
|
45
|
+
extends Omit<React.SelectHTMLAttributes<HTMLSelectElement>, "size">,
|
|
46
|
+
VariantProps<typeof nativeSelectVariants> {}
|
|
47
|
+
|
|
48
|
+
const NativeSelect = React.forwardRef<HTMLSelectElement, NativeSelectProps>(
|
|
49
|
+
({ className, state, corners, disabled, "aria-invalid": ariaInvalid, children, ...props }, ref) => (
|
|
50
|
+
<div className="relative">
|
|
51
|
+
<select
|
|
52
|
+
ref={ref}
|
|
53
|
+
data-slot="native-select"
|
|
54
|
+
data-state={state ? state.toLowerCase() : undefined}
|
|
55
|
+
aria-invalid={ariaInvalid ?? (state === "Error" || undefined)}
|
|
56
|
+
disabled={disabled || state === "Disabled"}
|
|
57
|
+
className={cn(nativeSelectVariants({ state, corners }), className)}
|
|
58
|
+
{...props}
|
|
59
|
+
>
|
|
60
|
+
{children}
|
|
61
|
+
</select>
|
|
62
|
+
<ChevronDown className="pointer-events-none absolute right-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
|
|
63
|
+
</div>
|
|
64
|
+
),
|
|
65
|
+
);
|
|
66
|
+
NativeSelect.displayName = "NativeSelect";
|
|
67
|
+
|
|
68
|
+
export interface NativeSelectOptionProps extends React.OptionHTMLAttributes<HTMLOptionElement> {}
|
|
69
|
+
|
|
70
|
+
const NativeSelectOption = React.forwardRef<HTMLOptionElement, NativeSelectOptionProps>(
|
|
71
|
+
({ ...props }, ref) => <option ref={ref} {...props} />,
|
|
72
|
+
);
|
|
73
|
+
NativeSelectOption.displayName = "NativeSelectOption";
|
|
74
|
+
|
|
75
|
+
export interface NativeSelectOptGroupProps extends React.OptgroupHTMLAttributes<HTMLOptGroupElement> {}
|
|
76
|
+
|
|
77
|
+
const NativeSelectOptGroup = React.forwardRef<HTMLOptGroupElement, NativeSelectOptGroupProps>(
|
|
78
|
+
({ ...props }, ref) => <optgroup ref={ref} {...props} />,
|
|
79
|
+
);
|
|
80
|
+
NativeSelectOptGroup.displayName = "NativeSelectOptGroup";
|
|
81
|
+
|
|
82
|
+
export { NativeSelect, NativeSelectOption, NativeSelectOptGroup, nativeSelectVariants };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
|
|
5
|
+
import { cn } from "../lib/utils";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* SegmentedControl — an iOS-style single-select strip. Functionally
|
|
9
|
+
* `ToggleGroup type="single"`: a thin, documented preset over the same
|
|
10
|
+
* Radix primitive with the segmented look (`Tabs`' `TabsList`/
|
|
11
|
+
* `TabsTrigger` visual treatment — filled track, raised active segment)
|
|
12
|
+
* instead of `Toggle`'s individually-outlined-button look. `type="single"`
|
|
13
|
+
* is fixed, not exposed — a segmented control that could go fully
|
|
14
|
+
* unselected or multi-select isn't the pattern. Gap-fill addition (not in
|
|
15
|
+
* the original Figma source).
|
|
16
|
+
*/
|
|
17
|
+
export type SegmentedControlProps = Omit<ToggleGroupPrimitive.ToggleGroupSingleProps, "type">;
|
|
18
|
+
|
|
19
|
+
const SegmentedControl = React.forwardRef<
|
|
20
|
+
React.ElementRef<typeof ToggleGroupPrimitive.Root>,
|
|
21
|
+
SegmentedControlProps
|
|
22
|
+
>(({ className, ...props }, ref) => (
|
|
23
|
+
<ToggleGroupPrimitive.Root
|
|
24
|
+
ref={ref}
|
|
25
|
+
type="single"
|
|
26
|
+
className={cn("inline-flex items-center rounded-lg bg-muted p-1 font-sans", className)}
|
|
27
|
+
{...props}
|
|
28
|
+
/>
|
|
29
|
+
));
|
|
30
|
+
SegmentedControl.displayName = "SegmentedControl";
|
|
31
|
+
|
|
32
|
+
const SegmentedControlItem = React.forwardRef<
|
|
33
|
+
React.ElementRef<typeof ToggleGroupPrimitive.Item>,
|
|
34
|
+
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item>
|
|
35
|
+
>(({ className, ...props }, ref) => (
|
|
36
|
+
<ToggleGroupPrimitive.Item
|
|
37
|
+
ref={ref}
|
|
38
|
+
className={cn(
|
|
39
|
+
"inline-flex flex-1 items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-label-md font-medium text-muted-foreground transition-all",
|
|
40
|
+
"outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
41
|
+
"disabled:pointer-events-none disabled:opacity-disabled",
|
|
42
|
+
"data-[state=on]:bg-background data-[state=on]:text-foreground data-[state=on]:shadow-sm",
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
));
|
|
48
|
+
SegmentedControlItem.displayName = "SegmentedControlItem";
|
|
49
|
+
|
|
50
|
+
export { SegmentedControl, SegmentedControlItem };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../lib/utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Timeline — ordered events down a rail (dot, connector, time, content).
|
|
8
|
+
* `alternating` lays content left/right of a centered rail (desktop);
|
|
9
|
+
* the default is a single left-aligned rail. Same rail/dot/connector
|
|
10
|
+
* technique as `Stepper`, but for a history/activity log rather than a
|
|
11
|
+
* progress indicator — no complete/current/upcoming states, an array of
|
|
12
|
+
* arbitrary events instead. Gap-fill addition (not in the original Figma
|
|
13
|
+
* source).
|
|
14
|
+
*/
|
|
15
|
+
export interface TimelineItem {
|
|
16
|
+
time?: React.ReactNode;
|
|
17
|
+
title: React.ReactNode;
|
|
18
|
+
content?: React.ReactNode;
|
|
19
|
+
/** custom dot content — defaults to a filled circle */
|
|
20
|
+
icon?: React.ReactNode;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface TimelineProps extends React.HTMLAttributes<HTMLOListElement> {
|
|
24
|
+
items: TimelineItem[];
|
|
25
|
+
alternating?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const Body = ({ item, align }: { item: TimelineItem; align: "left" | "right" }) => (
|
|
29
|
+
<div className={cn("pb-6", align === "right" && "text-right")}>
|
|
30
|
+
{item.time && <p className="text-label-sm text-muted-foreground">{item.time}</p>}
|
|
31
|
+
<p className="text-label-md font-medium text-foreground">{item.title}</p>
|
|
32
|
+
{item.content && <div className="text-body-sm text-muted-foreground">{item.content}</div>}
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const Rail = ({ item, isLast }: { item: TimelineItem; isLast: boolean }) => (
|
|
37
|
+
<div className="flex flex-col items-center">
|
|
38
|
+
<span className="flex size-2.5 shrink-0 items-center justify-center rounded-full bg-primary">{item.icon}</span>
|
|
39
|
+
{!isLast && <span aria-hidden className="my-1 w-px flex-1 bg-border" />}
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const Timeline = React.forwardRef<HTMLOListElement, TimelineProps>(
|
|
44
|
+
({ className, items, alternating = false, ...props }, ref) => (
|
|
45
|
+
<ol ref={ref} className={cn("flex flex-col font-sans", className)} {...props}>
|
|
46
|
+
{items.map((item, i) => {
|
|
47
|
+
const isLast = i === items.length - 1;
|
|
48
|
+
if (!alternating) {
|
|
49
|
+
return (
|
|
50
|
+
<li key={i} className="grid grid-cols-[auto_1fr] gap-x-3">
|
|
51
|
+
<Rail item={item} isLast={isLast} />
|
|
52
|
+
<Body item={item} align="left" />
|
|
53
|
+
</li>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
const onRight = i % 2 === 0;
|
|
57
|
+
return (
|
|
58
|
+
<li key={i} className="grid grid-cols-[1fr_auto_1fr] gap-x-4">
|
|
59
|
+
{onRight ? <div /> : <Body item={item} align="right" />}
|
|
60
|
+
<Rail item={item} isLast={isLast} />
|
|
61
|
+
{onRight ? <Body item={item} align="left" /> : <div />}
|
|
62
|
+
</li>
|
|
63
|
+
);
|
|
64
|
+
})}
|
|
65
|
+
</ol>
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
Timeline.displayName = "Timeline";
|
|
69
|
+
|
|
70
|
+
export { Timeline };
|
package/src/index.ts
CHANGED
|
@@ -323,5 +323,33 @@ export {
|
|
|
323
323
|
emptyMediaVariants,
|
|
324
324
|
type EmptyMediaProps,
|
|
325
325
|
} from "./components/empty";
|
|
326
|
+
export {
|
|
327
|
+
ButtonGroup,
|
|
328
|
+
ButtonGroupSeparator,
|
|
329
|
+
ButtonGroupText,
|
|
330
|
+
type ButtonGroupProps,
|
|
331
|
+
type ButtonGroupSeparatorProps,
|
|
332
|
+
} from "./components/button-group";
|
|
333
|
+
export {
|
|
334
|
+
NativeSelect,
|
|
335
|
+
NativeSelectOption,
|
|
336
|
+
NativeSelectOptGroup,
|
|
337
|
+
nativeSelectVariants,
|
|
338
|
+
type NativeSelectProps,
|
|
339
|
+
type NativeSelectOptionProps,
|
|
340
|
+
type NativeSelectOptGroupProps,
|
|
341
|
+
} from "./components/native-select";
|
|
342
|
+
export {
|
|
343
|
+
DescriptionList,
|
|
344
|
+
DescriptionListItem,
|
|
345
|
+
type DescriptionListItemProps,
|
|
346
|
+
} from "./components/description-list";
|
|
347
|
+
export { Banner, bannerVariants, type BannerProps } from "./components/banner";
|
|
348
|
+
export {
|
|
349
|
+
SegmentedControl,
|
|
350
|
+
SegmentedControlItem,
|
|
351
|
+
type SegmentedControlProps,
|
|
352
|
+
} from "./components/segmented-control";
|
|
353
|
+
export { Timeline, type TimelineItem, type TimelineProps } from "./components/timeline";
|
|
326
354
|
|
|
327
355
|
export { cn } from "./lib/utils";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
|
|
2
|
+
Source of truth: apps/web/src/registry/demos.tsx */
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
5
|
+
import { Banner } from "@kinetixui/ui";
|
|
6
|
+
|
|
7
|
+
const Demo = () => (
|
|
8
|
+
<div className="flex w-full flex-col gap-3">
|
|
9
|
+
<Banner variant="information" onDismiss={() => {}} action={{ label: "Learn more" }}>
|
|
10
|
+
A new version of KinetixUI is available.
|
|
11
|
+
</Banner>
|
|
12
|
+
<Banner variant="action" action={{ label: "Upgrade" }}>
|
|
13
|
+
You’re on the free plan — upgrade for unlimited projects.
|
|
14
|
+
</Banner>
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const meta = {
|
|
19
|
+
title: "Feedback/Banner",
|
|
20
|
+
parameters: {
|
|
21
|
+
layout: "centered",
|
|
22
|
+
docs: { source: { code: "<Banner variant=\"information\" onDismiss={close} action={{ label: \"Learn more\" }}>\\n A new version of KinetixUI is available.\\n</Banner>", language: "tsx" } },
|
|
23
|
+
},
|
|
24
|
+
} satisfies Meta;
|
|
25
|
+
|
|
26
|
+
export default meta;
|
|
27
|
+
|
|
28
|
+
export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
|
|
2
|
+
Source of truth: apps/web/src/registry/demos.tsx */
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
5
|
+
import { Button, ButtonGroup } from "@kinetixui/ui";
|
|
6
|
+
import { Bold, Italic, Underline } from "lucide-react";
|
|
7
|
+
|
|
8
|
+
const Demo = () => (
|
|
9
|
+
<ButtonGroup>
|
|
10
|
+
<Button variant="Outline" size="icon" aria-label="Bold">
|
|
11
|
+
<Bold />
|
|
12
|
+
</Button>
|
|
13
|
+
<Button variant="Outline" size="icon" aria-label="Italic">
|
|
14
|
+
<Italic />
|
|
15
|
+
</Button>
|
|
16
|
+
<Button variant="Outline" size="icon" aria-label="Underline">
|
|
17
|
+
<Underline />
|
|
18
|
+
</Button>
|
|
19
|
+
</ButtonGroup>
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const meta = {
|
|
23
|
+
title: "Controls & Actions/ButtonGroup",
|
|
24
|
+
parameters: {
|
|
25
|
+
layout: "centered",
|
|
26
|
+
docs: { source: { code: "<ButtonGroup>\\n <Button variant=\"Outline\" size=\"icon\"><Bold /></Button>\\n <Button variant=\"Outline\" size=\"icon\"><Italic /></Button>\\n <Button variant=\"Outline\" size=\"icon\"><Underline /></Button>\\n</ButtonGroup>", language: "tsx" } },
|
|
27
|
+
},
|
|
28
|
+
} satisfies Meta;
|
|
29
|
+
|
|
30
|
+
export default meta;
|
|
31
|
+
|
|
32
|
+
export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
|
|
2
|
+
Source of truth: apps/web/src/registry/demos.tsx */
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
5
|
+
import { Avatar, DescriptionList, DescriptionListItem } from "@kinetixui/ui";
|
|
6
|
+
|
|
7
|
+
const Demo = () => (
|
|
8
|
+
<DescriptionList className="w-full max-w-sm">
|
|
9
|
+
<DescriptionListItem term="Category">Data Display</DescriptionListItem>
|
|
10
|
+
<DescriptionListItem term="Built on">Radix Avatar</DescriptionListItem>
|
|
11
|
+
<DescriptionListItem term="Platforms">React, SwiftUI, Compose, Flutter</DescriptionListItem>
|
|
12
|
+
<DescriptionListItem term="CLI">npx @kinetixui/cli add avatar</DescriptionListItem>
|
|
13
|
+
</DescriptionList>
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const meta = {
|
|
17
|
+
title: "Data Display/DescriptionList",
|
|
18
|
+
parameters: {
|
|
19
|
+
layout: "centered",
|
|
20
|
+
docs: { source: { code: "<DescriptionList>\\n <DescriptionListItem term=\"Category\">Data Display</DescriptionListItem>\\n <DescriptionListItem term=\"Built on\">Radix Avatar</DescriptionListItem>\\n</DescriptionList>", language: "tsx" } },
|
|
21
|
+
},
|
|
22
|
+
} satisfies Meta;
|
|
23
|
+
|
|
24
|
+
export default meta;
|
|
25
|
+
|
|
26
|
+
export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
|
|
2
|
+
Source of truth: apps/web/src/registry/demos.tsx */
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
5
|
+
import { NativeSelect, NativeSelectOptGroup, NativeSelectOption, Select } from "@kinetixui/ui";
|
|
6
|
+
|
|
7
|
+
const Demo = () => (
|
|
8
|
+
<NativeSelect className="max-w-xs" defaultValue="">
|
|
9
|
+
<NativeSelectOption value="" disabled>
|
|
10
|
+
Select a fruit…
|
|
11
|
+
</NativeSelectOption>
|
|
12
|
+
<NativeSelectOptGroup label="Citrus">
|
|
13
|
+
<NativeSelectOption value="orange">Orange</NativeSelectOption>
|
|
14
|
+
<NativeSelectOption value="lemon">Lemon</NativeSelectOption>
|
|
15
|
+
</NativeSelectOptGroup>
|
|
16
|
+
<NativeSelectOptGroup label="Stone fruit">
|
|
17
|
+
<NativeSelectOption value="peach">Peach</NativeSelectOption>
|
|
18
|
+
<NativeSelectOption value="plum">Plum</NativeSelectOption>
|
|
19
|
+
</NativeSelectOptGroup>
|
|
20
|
+
</NativeSelect>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const meta = {
|
|
24
|
+
title: "Form Inputs/NativeSelect",
|
|
25
|
+
parameters: {
|
|
26
|
+
layout: "centered",
|
|
27
|
+
docs: { source: { code: "<NativeSelect defaultValue=\"\">\\n <NativeSelectOption value=\"\" disabled>Select a fruit…</NativeSelectOption>\\n <NativeSelectOptGroup label=\"Citrus\">\\n <NativeSelectOption value=\"orange\">Orange</NativeSelectOption>\\n </NativeSelectOptGroup>\\n</NativeSelect>", language: "tsx" } },
|
|
28
|
+
},
|
|
29
|
+
} satisfies Meta;
|
|
30
|
+
|
|
31
|
+
export default meta;
|
|
32
|
+
|
|
33
|
+
export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
|
|
2
|
+
Source of truth: apps/web/src/registry/demos.tsx */
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
5
|
+
import { List, SegmentedControl, SegmentedControlItem } from "@kinetixui/ui";
|
|
6
|
+
|
|
7
|
+
const Demo = () => (
|
|
8
|
+
<SegmentedControl defaultValue="grid" className="w-full max-w-xs">
|
|
9
|
+
<SegmentedControlItem value="list">List</SegmentedControlItem>
|
|
10
|
+
<SegmentedControlItem value="grid">Grid</SegmentedControlItem>
|
|
11
|
+
<SegmentedControlItem value="board">Board</SegmentedControlItem>
|
|
12
|
+
</SegmentedControl>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const meta = {
|
|
16
|
+
title: "Controls & Actions/SegmentedControl",
|
|
17
|
+
parameters: {
|
|
18
|
+
layout: "centered",
|
|
19
|
+
docs: { source: { code: "<SegmentedControl defaultValue=\"grid\">\\n <SegmentedControlItem value=\"list\">List</SegmentedControlItem>\\n <SegmentedControlItem value=\"grid\">Grid</SegmentedControlItem>\\n <SegmentedControlItem value=\"board\">Board</SegmentedControlItem>\\n</SegmentedControl>", language: "tsx" } },
|
|
20
|
+
},
|
|
21
|
+
} satisfies Meta;
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
|
|
25
|
+
export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* AUTO-GENERATED by scripts/gen-stories.mjs — do not edit.
|
|
2
|
+
Source of truth: apps/web/src/registry/demos.tsx */
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
5
|
+
import { SegmentedControl, Timeline } from "@kinetixui/ui";
|
|
6
|
+
|
|
7
|
+
const Demo = () => (
|
|
8
|
+
<Timeline
|
|
9
|
+
className="w-full max-w-sm"
|
|
10
|
+
items={[
|
|
11
|
+
{ time: "2 hours ago", title: "Deployed to production", content: "v0.9.0 shipped." },
|
|
12
|
+
{ time: "Yesterday", title: "Opened PR #100", content: "feat(ui): add SegmentedControl" },
|
|
13
|
+
{ time: "3 days ago", title: "Project created" },
|
|
14
|
+
]}
|
|
15
|
+
/>
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const meta = {
|
|
19
|
+
title: "Data Display/Timeline",
|
|
20
|
+
parameters: {
|
|
21
|
+
layout: "centered",
|
|
22
|
+
docs: { source: { code: "<Timeline\\n items={[\\n { time: \"2 hours ago\", title: \"Deployed to production\", content: \"v0.9.0 shipped.\" },\\n { time: \"Yesterday\", title: \"Opened PR #100\" },\\n ]}\\n/>", language: "tsx" } },
|
|
23
|
+
},
|
|
24
|
+
} satisfies Meta;
|
|
25
|
+
|
|
26
|
+
export default meta;
|
|
27
|
+
|
|
28
|
+
export const Default: StoryObj<typeof meta> = { render: () => <Demo /> };
|