更新日志
最新的更新和公告。
2024年9月 - 新组件
导航菜单
用于网站导航的链接集合。
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;
2024年6月 - 新组件
数字字段
允许用户使用键盘输入自定义数字的数字输入框。
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;
OTP 字段
一个功能齐全的 OTP 输入组件。 支持所有默认按键绑定,并且是可访问的。支持 Android 和 iOS 的复制、粘贴、剪切以及更多功能。 构建于 @corvu/otp-field
之上。 这是来自 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;
菜单栏
一种在桌面应用程序中常见的、视觉上持久存在的菜单,提供对一组一致命令的快速访问。
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;
日历
新的 Calendar
演示。
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;
2024年5月 - CLI 和组件更新
CLI 更新
diff
使用 diff
跟踪上游组件的更新。
运行 diff
命令以获取具有可用更新的组件列表
npx shadcn-solid diff
┌ shadcn-solid
│
◇ The following components have updates avaiable
│
● alert - path\to\my-ap\components\ui\alert.tsx
│
● card - path\to\my-ap\components\ui\card.tsx
│
└ Run diff <component> to see the changes
然后运行 diff [component]
以查看更改
npx shadcn-solid diff alert
const alertVariants = cva(
- "relative w-full rounded-lg border",
+ "relative w-full pl-12 rounded-lg border"
)
add
添加多个组件或使用 --all 会更快
Schema 更新
components.json
schema 已更新
{
"$schema": "https://zh.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"
}
}
组件更新
我们已经向 shadcn-solid 添加了新组件。
- Toggle Group - 一组可以切换为开启(按下)或关闭(未按下)状态的双状态按钮。
- Sonner - 一个为 Solid 而设计的 toast 组件。
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;
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;
已转换两个现有组件,Splitter 和 Command,以分别使用来自 corvu 的新 Resizable 和 cmdk 的 solid 移植版本。
2024年4月 - UnoCSS。
我们很高兴地宣布支持 UnoCSS,一种即时原子 CSS 引擎。
框架选择
您可以使用 init
命令在项目设置期间选择您首选的 CSS 框架
◆ Which CSS framework would you like to use?
│ ○ TailwindCSS
│ ● UnoCSS
组件安装
一个新的 --all
选项已添加到 add
命令中。 此增强简化了一次安装所有可用组件的过程。
2024年3月 - Drawer。
- Drawer - 一个可拖动的对话框,可以附加到视口的任何一侧。
Drawer
2024年3月 - 更新了文档、UI 并修复了错误。
2024年2月 - 新组件、CLI 及更多
我们已经向 shadcn-solid 添加了新组件,并对 CLI 进行了改进。
以下是新增功能的快速概述
- Carousel - 一个具有动画、滑动和键盘支持的轮播组件。
- Pagination - 一个分页组件,允许用户从一系列页面中选择特定页面。
- Command - 一个可组合的命令菜单组件。
- Date Picker - 一个允许用户从日历中选择日期的组件。
- CLI 更新 - 支持自定义 Tailwind 前缀,删除
style
等。
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;
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;
Carousel
我们添加了一个功能齐全的轮播组件,具有动画、滑动和键盘支持。 构建于 Embla Carousel 之上。
它支持无限循环、自动播放、垂直方向等。
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;
Pagination
我们添加了一个带有页面导航、上一个和下一个按钮的分页组件。 简单且灵活。
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;
CLI 更新
-
图标库
我们已删除图标库并使用 SVG 以获得更大的灵活性。
-
删除
style
属性在此更新中,
style
属性已被删除,但如果未来的更新中引入其他样式功能,则有可能返回。 -
支持自定义 ui 目录
您可以使用此配置来自定义
ui
组件的安装目录。components.json { "aliases": { "ui": "@/ui" } }
-
支持自定义 Tailwind 前缀
您现在可以配置自定义 Tailwind 前缀,并且 cli 在添加组件时会自动为您的实用程序类添加前缀。
无需冲突,即可作为现有设计系统的直接替代品。 🔥
<AlertDialog class="tw-grid tw-gap-4 tw-border tw-bg-background tw-shadow-lg" />
它与
cn
、cva
和 CSS 变量一起使用。
就这样。 新年快乐。