Sep 2024 - New Components
A collection of links for navigating websites.
import { siteConfig } from "@/config/site" ;
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuDescription,
NavigationMenuItem,
NavigationMenuItemLabel,
NavigationMenuLink,
NavigationMenuTrigger,
} from "@repo/tailwindcss/ui/navigation-menu" ;
import type { ParentProps } from "solid-js" ;
import { For } from "solid-js" ;
const ListItem = (props : ParentProps <{ title : string ; href : string }>) => {
return (
< NavigationMenuLink
href={ props.href }
class= "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-[box-shadow,background-color] duration-200 hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-visible:outline-none focus-visible:ring-[1.5px] focus-visible:ring-ring"
>
< NavigationMenuItemLabel class= "text-sm font-medium leading-none" >
{ props.title }
</ NavigationMenuItemLabel >
< NavigationMenuDescription class= "line-clamp-2 text-sm leading-snug text-muted-foreground" >
{ props.children }
</ NavigationMenuDescription >
</ NavigationMenuLink >
);
};
const components : { title : string ; href : string ; description : string }[] = [
{
title: "Data Table" ,
href: "/docs/components/data-table" ,
description: "Powerful table and datagrids built using TanStack Table." ,
},
{
title: "Date Picker" ,
href: "/docs/components/date-picker" ,
description:
"A component that allows users to select a date from a calendar." ,
},
{
title: "OTP Field" ,
href: "/docs/components/otp-field" ,
description: "An accessible and customizable OTP Input component." ,
},
{
title: "Resizable" ,
href: "/docs/components/resizable" ,
description:
"A component that divides your interface into resizable sections." ,
},
{
title: "Sonner" ,
href: "/docs/components/sonner" ,
description: "An opinionated toast component for Solid." ,
},
{
title: "Toggle Group" ,
href: "/docs/components/toggle-group" ,
description:
"A set of two-state buttons that can be toggled on (pressed) or off (not pressed)." ,
},
];
const NavigationMenuDemo = () => {
return (
< NavigationMenu >
< NavigationMenuItem >
< NavigationMenuTrigger class= "transition-[box-shadow,background-color] focus-visible:outline-none focus-visible:ring-[1.5px] focus-visible:ring-ring data-[expanded]:bg-accent" >
Learn
</ NavigationMenuTrigger >
< NavigationMenuContent class= "grid gap-3 p-4 w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr] [&>li:first-of-type]:row-span-3" >
< NavigationMenuLink
href= "/"
class= "flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none transition-shadow duration-200 hover:shadow-md focus-visible:shadow-md focus-visible:ring-[1.5px] focus-visible:ring-ring"
>
< NavigationMenuItemLabel class= "mb-2 mt-4 text-lg font-medium" >
{ siteConfig.title }
</ NavigationMenuItemLabel >
< NavigationMenuDescription class= "text-sm leading-tight text-muted-foreground" >
{ siteConfig.description }
</ NavigationMenuDescription >
</ NavigationMenuLink >
< ListItem href= "/docs" title= "Introduction" >
{ siteConfig.description } .
</ ListItem >
< ListItem href= "/docs/installation" title= "Installation" >
How to install dependencies and structure your app.
</ ListItem >
< ListItem href= "/docs/components/typography" title= "Typography" >
Styles for headings, paragraphs, lists...etc.
</ ListItem >
</ NavigationMenuContent >
</ NavigationMenuItem >
< NavigationMenuItem >
< NavigationMenuTrigger class= "transition-[box-shadow,background-color] focus-visible:outline-none focus-visible:ring-1.5px focus-visible:ring-ring data-[expanded]:bg-accent" >
Overview
</ NavigationMenuTrigger >
< NavigationMenuContent class= "grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]" >
< For each={ components }>
{ (item) => (
< ListItem href={ item.href } title={ item.title }>
{ item.description }
</ ListItem >
) }
</ For >
</ NavigationMenuContent >
</ NavigationMenuItem >
< NavigationMenuTrigger
as= "a"
href= "/docs"
class= "transition-[box-shadow,background-color] focus-visible:outline-none focus-visible:ring-[1.5px] focus-visible:ring-ring data-[expanded]:bg-accent"
>
Documentation
</ NavigationMenuTrigger >
</ NavigationMenu >
);
};
export default NavigationMenuDemo;
Copy
Jun 2024 - New components
Number Field
A number input that allow users to input custom number entries with a keyboard.
import {
NumberField,
NumberFieldDecrementTrigger,
NumberFieldGroup,
NumberFieldIncrementTrigger,
NumberFieldInput,
NumberFieldLabel,
} from "@repo/tailwindcss/ui/number-field" ;
const NumberFieldDemo = () => {
const thisYear = () => new Date (Date. now ()). getUTCFullYear ();
const age = () => thisYear () - 2001 ;
return (
< NumberField defaultValue={ age () } minValue={ 0 }>
< NumberFieldLabel > Age </ NumberFieldLabel >
< NumberFieldGroup >
< NumberFieldDecrementTrigger aria-label= "Decrement" />
< NumberFieldInput />
< NumberFieldIncrementTrigger aria-label= "Increment" />
</ NumberFieldGroup >
</ NumberField >
);
};
export default NumberFieldDemo;
Copy
OTP Field
A fully featured OTP input component. Support all default keybindings and is accessible, Android and iOS copy, paste, cut and many more . Built on top of @corvu/otp-field
. An awesome work from Jasmin .
import {
OTPField,
OTPFieldGroup,
OTPFieldInput,
OTPFieldSeparator,
OTPFieldSlot,
} from "@repo/tailwindcss/ui/otp-field" ;
const OtpFieldDemo = () => {
return (
< OTPField maxLength={ 6 }>
< OTPFieldInput />
< OTPFieldGroup >
< OTPFieldSlot index={ 0 } />
< OTPFieldSlot index={ 1 } />
< OTPFieldSlot index={ 2 } />
</ OTPFieldGroup >
< OTPFieldSeparator />
< OTPFieldGroup >
< OTPFieldSlot index={ 3 } />
< OTPFieldSlot index={ 4 } />
< OTPFieldSlot index={ 5 } />
</ OTPFieldGroup >
</ OTPField >
);
};
export default OtpFieldDemo;
Copy
A visually persistent menu common in desktop applications that provides quick access to a consistent set of commands.
import {
Menubar,
MenubarCheckboxItem,
MenubarContent,
MenubarItem,
MenubarMenu,
MenubarRadioGroup,
MenubarRadioItem,
MenubarSeparator,
MenubarShortcut,
MenubarSub,
MenubarSubContent,
MenubarSubTrigger,
MenubarTrigger,
} from "@repo/tailwindcss/ui/menubar" ;
const MenubarDemo = () => {
return (
< Menubar >
< MenubarMenu >
< MenubarTrigger > File </ MenubarTrigger >
< MenubarContent >
< MenubarItem >
New Tab < MenubarShortcut > ⌘T </ MenubarShortcut >
</ MenubarItem >
< MenubarItem >
New Window < MenubarShortcut > ⌘N </ MenubarShortcut >
</ MenubarItem >
< MenubarItem disabled> New Incognito Window </ MenubarItem >
< MenubarSeparator />
< MenubarSub >
< MenubarSubTrigger > Share </ MenubarSubTrigger >
< MenubarSubContent >
< MenubarItem > Email link </ MenubarItem >
< MenubarItem > Messages </ MenubarItem >
< MenubarItem > Notes </ MenubarItem >
</ MenubarSubContent >
</ MenubarSub >
< MenubarSeparator />
< MenubarItem >
Print... < MenubarShortcut > ⌘P </ MenubarShortcut >
</ MenubarItem >
</ MenubarContent >
</ MenubarMenu >
< MenubarMenu >
< MenubarTrigger > Edit </ MenubarTrigger >
< MenubarContent >
< MenubarItem >
Undo < MenubarShortcut > ⌘Z </ MenubarShortcut >
</ MenubarItem >
< MenubarItem >
Redo < MenubarShortcut > ⇧⌘Z </ MenubarShortcut >
</ MenubarItem >
< MenubarSeparator />
< MenubarSub >
< MenubarSubTrigger > Find </ MenubarSubTrigger >
< MenubarSubContent >
< MenubarItem > Search the web </ MenubarItem >
< MenubarSeparator />
< MenubarItem > Find... </ MenubarItem >
< MenubarItem > Find Next </ MenubarItem >
< MenubarItem > Find Previous </ MenubarItem >
</ MenubarSubContent >
</ MenubarSub >
< MenubarSeparator />
< MenubarItem > Cut </ MenubarItem >
< MenubarItem > Copy </ MenubarItem >
< MenubarItem > Paste </ MenubarItem >
</ MenubarContent >
</ MenubarMenu >
< MenubarMenu >
< MenubarTrigger > View </ MenubarTrigger >
< MenubarContent >
< MenubarCheckboxItem > Always Show Bookmarks Bar </ MenubarCheckboxItem >
< MenubarCheckboxItem checked>
Always Show Full URLs
</ MenubarCheckboxItem >
< MenubarSeparator />
< MenubarItem inset>
Reload < MenubarShortcut > ⌘R </ MenubarShortcut >
</ MenubarItem >
< MenubarItem disabled inset>
Force Reload < MenubarShortcut > ⇧⌘R </ MenubarShortcut >
</ MenubarItem >
< MenubarSeparator />
< MenubarItem inset> Toggle Fullscreen </ MenubarItem >
< MenubarSeparator />
< MenubarItem inset> Hide Sidebar </ MenubarItem >
</ MenubarContent >
</ MenubarMenu >
< MenubarMenu >
< MenubarTrigger > Profiles </ MenubarTrigger >
< MenubarContent >
< MenubarRadioGroup value= "benoit" >
< MenubarRadioItem value= "andy" > Andy </ MenubarRadioItem >
< MenubarRadioItem value= "benoit" > Benoit </ MenubarRadioItem >
< MenubarRadioItem value= "Luis" > Luis </ MenubarRadioItem >
</ MenubarRadioGroup >
< MenubarSeparator />
< MenubarItem inset> Edit... </ MenubarItem >
< MenubarSeparator />
< MenubarItem inset> Add Profile... </ MenubarItem >
</ MenubarContent >
</ MenubarMenu >
</ Menubar >
);
};
export default MenubarDemo;
Copy
Calendar
New Calendar
demo.
import {
DatePicker,
DatePickerContent,
DatePickerContext,
DatePickerRangeText,
DatePickerTable,
DatePickerTableBody,
DatePickerTableCell,
DatePickerTableCellTrigger,
DatePickerTableHead,
DatePickerTableHeader,
DatePickerTableRow,
DatePickerView,
DatePickerViewControl,
DatePickerViewTrigger,
} from "@repo/tailwindcss/ui/date-picker" ;
import { For } from "solid-js" ;
const CalendarDemo = () => {
return (
< DatePicker open>
< DatePickerContent >
< DatePickerView view= "day" >
< DatePickerContext >
{ (context) => (
<>
< DatePickerViewControl >
< DatePickerViewTrigger >
< DatePickerRangeText />
</ DatePickerViewTrigger >
</ DatePickerViewControl >
< DatePickerTable >
< DatePickerTableHead >
< DatePickerTableRow >
< For each={ context ().weekDays }>
{ (weekDay) => (
< DatePickerTableHeader >
{ weekDay.short }
</ DatePickerTableHeader >
) }
</ For >
</ DatePickerTableRow >
</ DatePickerTableHead >
< DatePickerTableBody >
< For each={ context ().weeks }>
{ (week) => (
< DatePickerTableRow >
< For each={ week }>
{ (day) => (
< DatePickerTableCell value={ day }>
< DatePickerTableCellTrigger >
{ day.day }
</ DatePickerTableCellTrigger >
</ DatePickerTableCell >
) }
</ For >
</ DatePickerTableRow >
) }
</ For >
</ DatePickerTableBody >
</ DatePickerTable >
</>
) }
</ DatePickerContext >
</ DatePickerView >
< DatePickerView view= "month" >
< DatePickerContext >
{ (context) => (
<>
< DatePickerViewControl >
< DatePickerViewTrigger >
< DatePickerRangeText />
</ DatePickerViewTrigger >
</ DatePickerViewControl >
< DatePickerTable >
< DatePickerTableBody >
< For
each={ context (). getMonthsGrid ({
columns: 4 ,
format: "short" ,
}) }
>
{ (months) => (
< DatePickerTableRow >
< For each={ months }>
{ (month) => (
< DatePickerTableCell value={ month.value }>
< DatePickerTableCellTrigger >
{ month.label }
</ DatePickerTableCellTrigger >
</ DatePickerTableCell >
) }
</ For >
</ DatePickerTableRow >
) }
</ For >
</ DatePickerTableBody >
</ DatePickerTable >
</>
) }
</ DatePickerContext >
</ DatePickerView >
< DatePickerView view= "year" >
< DatePickerContext >
{ (context) => (
<>
< DatePickerViewControl >
< DatePickerViewTrigger >
< DatePickerRangeText />
</ DatePickerViewTrigger >
</ DatePickerViewControl >
< DatePickerTable >
< DatePickerTableBody >
< For
each={ context (). getYearsGrid ({
columns: 4 ,
}) }
>
{ (years) => (
< DatePickerTableRow >
< For each={ years }>
{ (year) => (
< DatePickerTableCell value={ year.value }>
< DatePickerTableCellTrigger >
{ year.label }
</ DatePickerTableCellTrigger >
</ DatePickerTableCell >
) }
</ For >
</ DatePickerTableRow >
) }
</ For >
</ DatePickerTableBody >
</ DatePickerTable >
</>
) }
</ DatePickerContext >
</ DatePickerView >
</ DatePickerContent >
</ DatePicker >
);
};
export default CalendarDemo;
Copy
May 2024 - CLI and components update
CLI Updates
diff
Track upstream component updates with diff
.
Run the diff
command to get a list of components that have updates available:
npx shadcn-solid diff
┌ shadcn-solid
│
◇ The following components have updates avaiable
│
● alert - path \t o \m y-ap \c omponents \u i \a lert.tsx
│
● card - path \t o \m y-ap \c omponents \u i \c ard.tsx
│
└ Run diff < componen t > to see the changes
Copy
Then run diff [component]
to see the changes:
npx shadcn-solid diff alert
const alertVariants = cva (
- "relative w-full rounded-lg border" ,
+ "relative w-full pl-12 rounded-lg border"
)
Copy
add
Adding multiple components or using —all is significantly faster
Schema update
The components.json
schema has been updated
New schema {
"$schema" : "https://shadcn-solid.com/schema.json" ,
"tailwind" : {
"config" : "tailwind.config.cjs" ,
"css" : {
"path" : "src/app.css" ,
"variable" : true
},
"color" : "slate" ,
"prefix" : ""
},
"alias" : {
"component" : "@/components" ,
"cn" : "@/libs/cn"
}
}
Copy
Component updates
We’ve added new components to shadcn-solid.
Toggle Group - A set of two-state buttons that can be toggled on (pressed) or off (not pressed).
Sonner - An opinionated toast component for Solid.
Toggle Group
import {
ToggleGroup,
ToggleGroupItem,
} from "@repo/tailwindcss/ui/toggle-group" ;
const ToggleGroupDemo = () => {
return (
< ToggleGroup multiple>
< ToggleGroupItem value= "bold" aria-label= "Toggle bold" >
< svg
xmlns= "http://www.w3.org/2000/svg"
class= "h-4 w-4"
viewBox= "0 0 24 24"
>
< path
fill= "none"
stroke= "currentColor"
stroke-linecap= "round"
stroke-linejoin= "round"
stroke-width= "2"
d= "M7 5h6a3.5 3.5 0 0 1 0 7H7zm6 7h1a3.5 3.5 0 0 1 0 7H7v-7"
/>
</ svg >
</ ToggleGroupItem >
< ToggleGroupItem value= "italic" aria-label= "Toggle italic" >
< svg
xmlns= "http://www.w3.org/2000/svg"
class= "h-4 w-4"
viewBox= "0 0 24 24"
>
< path
fill= "none"
stroke= "currentColor"
stroke-linecap= "round"
stroke-linejoin= "round"
stroke-width= "2"
d= "M11 5h6M7 19h6m1-14l-4 14"
/>
</ svg >
</ ToggleGroupItem >
< ToggleGroupItem value= "strikethrough" aria-label= "Toggle strikethrough" >
< svg
xmlns= "http://www.w3.org/2000/svg"
class= "h-4 w-4"
viewBox= "0 0 24 24"
>
< path
fill= "none"
stroke= "currentColor"
stroke-linecap= "round"
stroke-linejoin= "round"
stroke-width= "2"
d= "M7 5v5a5 5 0 0 0 10 0V5M5 19h14"
/>
</ svg >
</ ToggleGroupItem >
</ ToggleGroup >
);
};
export default ToggleGroupDemo;
Copy
Sonner
import { Button } from "@repo/tailwindcss/ui/button" ;
import { toast } from "solid-sonner" ;
const SonnerDemo = () => {
return (
< Button
variant= "outline"
onClick={ () =>
toast ( "Event has been created" , {
description: "Sunday, December 03, 2023 at 9:00 AM" ,
action: {
label: "Undo" ,
onClick : () => console. log ( "Undo" ),
},
})
}
>
Show Toast
</ Button >
);
};
export default SonnerDemo;
Copy
Transitioned two existing components, Splitter and Command , to utilize the new Resizable from corvu and the solid port of cmdk , respectively.
April 2024 - UnoCSS.
We’re excited to announce support for UnoCSS, an instant atomic CSS engine.
Framework selection
You can select your preferred CSS framework during project setup using the init
command:
◆ Which CSS framework would you like to use?
│ ○ TailwindCSS
│ ● UnoCSS
Copy
Component installation
A new --all
option has been added to the add
command. This enhancement simplifies installing all available components in one go.
March 2024 - Drawer.
Drawer - A draggable dialog that is attached to any side of the viewport.
Drawer
Built on top of Drawer component from Corvu .
March 2024 - Updated docs, UI, and fixed bugs.
February 2024 - New components, CLI and more
We’ve added new components to shadcn-solid and made a improvements to the CLI.
Here’s a quick overview of what’s new:
Carousel - A carousel component with motion, swipe gestures and keyboard support.
Pagination - A pagination component allows the user to select a specific page from a range of pages.
Command - A Composable command menu component.
Date Picker - A component that allows users to select a date from a calendar.
CLI updates - Support for custom Tailwind prefix , remove style
and more.
Date Picker
import {
DatePicker,
DatePickerContent,
DatePickerContext,
DatePickerControl,
DatePickerInput,
DatePickerPositioner,
DatePickerRangeText,
DatePickerTable,
DatePickerTableBody,
DatePickerTableCell,
DatePickerTableCellTrigger,
DatePickerTableHead,
DatePickerTableHeader,
DatePickerTableRow,
DatePickerTrigger,
DatePickerView,
DatePickerViewControl,
DatePickerViewTrigger,
} from "@repo/tailwindcss/ui/date-picker" ;
import { Index } from "solid-js" ;
import { Portal } from "solid-js/web" ;
const DatePickerDemo = () => {
return (
< DatePicker >
< DatePickerControl >
< DatePickerInput />
< DatePickerTrigger />
</ DatePickerControl >
< Portal >
< DatePickerPositioner >
< DatePickerContent >
< DatePickerView view= "day" >
< DatePickerContext >
{ (context) => (
<>
< DatePickerViewControl >
< DatePickerViewTrigger >
< DatePickerRangeText />
</ DatePickerViewTrigger >
</ DatePickerViewControl >
< DatePickerTable >
< DatePickerTableHead >
< DatePickerTableRow >
< Index each={ context ().weekDays }>
{ (weekDay) => (
< DatePickerTableHeader >
{ weekDay ().short }
</ DatePickerTableHeader >
) }
</ Index >
</ DatePickerTableRow >
</ DatePickerTableHead >
< DatePickerTableBody >
< Index each={ context ().weeks }>
{ (week) => (
< DatePickerTableRow >
< Index each={ week () }>
{ (day) => (
< DatePickerTableCell value={ day () }>
< DatePickerTableCellTrigger >
{ day ().day }
</ DatePickerTableCellTrigger >
</ DatePickerTableCell >
) }
</ Index >
</ DatePickerTableRow >
) }
</ Index >
</ DatePickerTableBody >
</ DatePickerTable >
</>
) }
</ DatePickerContext >
</ DatePickerView >
< DatePickerView view= "month" >
< DatePickerContext >
{ (context) => (
<>
< DatePickerViewControl >
< DatePickerViewTrigger >
< DatePickerRangeText />
</ DatePickerViewTrigger >
</ DatePickerViewControl >
< DatePickerTable >
< DatePickerTableBody >
< Index
each={ context (). getMonthsGrid ({
columns: 4 ,
format: "short" ,
}) }
>
{ (months) => (
< DatePickerTableRow >
< Index each={ months () }>
{ (month) => (
< DatePickerTableCell value={ month ().value }>
< DatePickerTableCellTrigger >
{ month ().label }
</ DatePickerTableCellTrigger >
</ DatePickerTableCell >
) }
</ Index >
</ DatePickerTableRow >
) }
</ Index >
</ DatePickerTableBody >
</ DatePickerTable >
</>
) }
</ DatePickerContext >
</ DatePickerView >
< DatePickerView view= "year" >
< DatePickerContext >
{ (context) => (
<>
< DatePickerViewControl >
< DatePickerViewTrigger >
< DatePickerRangeText />
</ DatePickerViewTrigger >
</ DatePickerViewControl >
< DatePickerTable >
< DatePickerTableBody >
< Index
each={ context (). getYearsGrid ({
columns: 4 ,
}) }
>
{ (years) => (
< DatePickerTableRow >
< Index each={ years () }>
{ (year) => (
< DatePickerTableCell value={ year ().value }>
< DatePickerTableCellTrigger >
{ year ().label }
</ DatePickerTableCellTrigger >
</ DatePickerTableCell >
) }
</ Index >
</ DatePickerTableRow >
) }
</ Index >
</ DatePickerTableBody >
</ DatePickerTable >
</>
) }
</ DatePickerContext >
</ DatePickerView >
</ DatePickerContent >
</ DatePickerPositioner >
</ Portal >
</ DatePicker >
);
};
export default DatePickerDemo;
Copy
Command
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandShortcut,
} from "@repo/tailwindcss/ui/command" ;
import { For, type JSXElement } from "solid-js" ;
type Option = {
icon : JSXElement ;
label : string ;
disabled : boolean ;
shortcut ?: JSXElement ;
};
type List = {
label : string ;
options : Option [];
};
export const commandData : List [] = [
{
label: "Suggestions" ,
options: [
{
icon : (
< svg
xmlns= "http://www.w3.org/2000/svg"
viewBox= "0 0 24 24"
class= "mr-2 h-4 w-4"
>
< path
fill= "none"
stroke= "currentColor"
stroke-linecap= "round"
stroke-linejoin= "round"
stroke-width= "2"
d= "M4 7a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2zm12-4v4M8 3v4m-4 4h16m-9 4h1m0 0v3"
/>
</ svg >
),
label: "Calendar" ,
disabled: false ,
},
{
icon : (
< svg
xmlns= "http://www.w3.org/2000/svg"
class= "mr-2 h-4 w-4"
viewBox= "0 0 24 24"
>
< g
fill= "none"
stroke= "currentColor"
stroke-linecap= "round"
stroke-linejoin= "round"
stroke-width= "2"
>
< path d= "M3 12a9 9 0 1 0 18 0a9 9 0 1 0-18 0m6-2h.01M15 10h.01" />
< path d= "M9.5 15a3.5 3.5 0 0 0 5 0" />
</ g >
</ svg >
),
label: "Search emoji" ,
disabled: false ,
},
{
icon : (
< svg
xmlns= "http://www.w3.org/2000/svg"
class= "mr-2 h-4 w-4"
viewBox= "0 0 24 24"
>
< g
fill= "none"
stroke= "currentColor"
stroke-linecap= "round"
stroke-linejoin= "round"
stroke-width= "2"
>
< path d= "M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3-5a9 9 0 0 0 6-8a3 3 0 0 0-3-3a9 9 0 0 0-8 6a6 6 0 0 0-5 3" />
< path d= "M7 14a6 6 0 0 0-3 6a6 6 0 0 0 6-3m4-8a1 1 0 1 0 2 0a1 1 0 1 0-2 0" />
</ g >
</ svg >
),
label: "Launch" ,
disabled: false ,
},
],
},
{
label: "Settings" ,
options: [
{
icon : (
< svg
xmlns= "http://www.w3.org/2000/svg"
class= "mr-2 h-4 w-4"
viewBox= "0 0 24 24"
>
< path
fill= "none"
stroke= "currentColor"
stroke-linecap= "round"
stroke-linejoin= "round"
stroke-width= "2"
d= "M8 7a4 4 0 1 0 8 0a4 4 0 0 0-8 0M6 21v-2a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v2"
/>
</ svg >
),
label: "Profile" ,
disabled: true ,
shortcut: < CommandShortcut > ⌘P </ CommandShortcut > ,
},
{
icon : (
< svg
xmlns= "http://www.w3.org/2000/svg"
class= "mr-2 h-4 w-4"
viewBox= "0 0 24 24"
>
< g
fill= "none"
stroke= "currentColor"
stroke-linecap= "round"
stroke-linejoin= "round"
stroke-width= "2"
>
< path d= "M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
< path d= "m3 7l9 6l9-6" />
</ g >
</ svg >
),
label: "Mail" ,
disabled: false ,
shortcut: < CommandShortcut > ⌘B </ CommandShortcut > ,
},
{
icon : (
< svg
xmlns= "http://www.w3.org/2000/svg"
class= "mr-2 h-4 w-4"
viewBox= "0 0 24 24"
>
< g
fill= "none"
stroke= "currentColor"
stroke-linecap= "round"
stroke-linejoin= "round"
stroke-width= "2"
>
< path d= "M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 0 0-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 0 0-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 0 0-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 0 0-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 0 0 1.066-2.573c-.94-1.543.826-3.31 2.37-2.37c1 .608 2.296.07 2.572-1.065" />
< path d= "M9 12a3 3 0 1 0 6 0a3 3 0 0 0-6 0" />
</ g >
</ svg >
),
label: "Setting" ,
disabled: false ,
shortcut: < CommandShortcut > ⌘S </ CommandShortcut > ,
},
],
},
];
const CommandDemo = () => {
return (
< Command class= "rounded-lg border shadow-md" >
< CommandInput placeholder= "Type a command or search..." />
< CommandList >
< CommandEmpty > No results found. </ CommandEmpty >
< For each={ commandData }>
{ (item) => (
< CommandGroup heading={ item.label }>
< For each={ item.options }>
{ (item) => (
< CommandItem disabled={ item.disabled }>
{ item.icon }
< span >{ item.label }</ span >
{ item.shortcut }
</ CommandItem >
) }
</ For >
</ CommandGroup >
) }
</ For >
</ CommandList >
</ Command >
);
};
export default CommandDemo;
Copy
Carousel
We’ve added a fully featured carousel component with motion, swipe gestures and keyboard support. Built on top of Embla Carousel .
It has support for infinite looping, autoplay, vertical orientation, and more.
import { Card, CardContent } from "@repo/tailwindcss/ui/card" ;
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@repo/tailwindcss/ui/carousel" ;
import { Index } from "solid-js" ;
const CarouselDemo = () => {
return (
< Carousel class= "w-full max-w-xs" >
< CarouselContent >
< Index each={ Array. from ({ length: 5 }) }>
{ (_, index) => (
< CarouselItem >
< div class= "p-1" >
< Card >
< CardContent class= "flex aspect-square items-center justify-center p-6" >
< span class= "text-4xl font-semibold" >{ index + 1 }</ span >
</ CardContent >
</ Card >
</ div >
</ CarouselItem >
) }
</ Index >
</ CarouselContent >
< CarouselPrevious />
< CarouselNext />
</ Carousel >
);
};
export default CarouselDemo;
Copy
We’ve added a pagination component with page navigation, previous and next buttons. Simple and flexible.
import {
Pagination,
PaginationEllipsis,
PaginationItem,
PaginationItems,
PaginationNext,
PaginationPrevious,
} from "@repo/tailwindcss/ui/pagination" ;
const PaginationDemo = () => {
return (
< Pagination
fixedItems
count={ 10 }
itemComponent={ (props) => (
< PaginationItem page={ props.page }>{ props.page }</ PaginationItem >
) }
ellipsisComponent={ () => < PaginationEllipsis />}
>
< PaginationPrevious />
< PaginationItems />
< PaginationNext />
</ Pagination >
);
};
export default PaginationDemo;
Copy
CLI updates
Icon library
We’re removed the icon library and using SVG for more flexibility.
Remove style
property
In this update, the style
property has been removed, but there’s a possibility of its return if additional styling features are introduced in future updates.
Support custom ui dir
You can use this config to customize the installation directory for your ui
components.
components.json {
"aliases" : {
"ui" : "@/ui"
}
}
Copy
Support custom Tailwind prefix
You can now configure a custom Tailwind prefix and the cli will automatically prefix your utility classes when adding components.
A drop-in for your existing design system with no conflict. 🔥
< AlertDialog class= " tw- grid tw- gap-4 tw- border tw- bg-background tw- shadow-lg" />
Copy
It works with cn
, cva
and CSS variables.
That’s it. Happy Lunar New Year.