diff --git a/README.md b/README.md index c8e57d7..9abb795 100644 --- a/README.md +++ b/README.md @@ -32,3 +32,9 @@ To run for a different platform, use the `--platform platform` flag. E.g. dx serve --platform desktop ``` +### UI 组件文档 + +`src/components/ui` 提供了一套基于 Dioxus 0.7 的 shadcn 风格组件: + +- 扩展指南见 `src/components/ui/README.md` +- 使用示例与 props 说明见 `src/components/ui/USAGE.md` diff --git a/src/components/ui/USAGE.md b/src/components/ui/USAGE.md new file mode 100644 index 0000000..c2ed40b --- /dev/null +++ b/src/components/ui/USAGE.md @@ -0,0 +1,1167 @@ +# UI 组件使用手册 + +本手册针对 `src/components/ui` 下的 **Dioxus 0.7** 组件库,按分类说明每个组件(含子组件)与配套数据结构的用途、关键属性以及推荐写法。示例全部基于 `#[component]` 与 `Signal` 状态模型,确保可以直接粘贴到项目中演练。 + +- [基础展示组件](#基础展示组件) +- [布局与容器](#布局与容器) +- [表单与输入控件](#表单与输入控件) +- [导航与结构](#导航与结构) +- [数据展示与日期](#数据展示与日期) +- [反馈与浮层](#反馈与浮层) + +--- + +## 基础展示组件 + +### Button / ButtonVariant / ButtonSize + +主按钮组件,视觉样式与 shadcn 保持一致。 + +- **关键 props**:`variant: ButtonVariant`(Default/Secondary/Destructive/Outline/Ghost/Link/Icon)、`size: ButtonSize`(Default/Sm/Lg/Icon)、`on_click`. +- 使用 `disabled` 控制禁用,`class` 可追加自定义类。 + +```rust +use crate::components::ui::{Button, ButtonSize, ButtonVariant}; +use dioxus::prelude::*; + +#[component] +fn ButtonSamples() -> Element { + rsx! { + div { class: "ui-stack gap-2", + Button { "保存" } + Button { variant: ButtonVariant::Destructive, "删除" } + Button { size: ButtonSize::Icon, "⚙" } + } + } +} +``` + +### Badge / BadgeVariant + +用于展示状态或标签。 + +- `variant`(Default/Secondary/Outline/Destructive)映射到 `data-variant`。 +- 直接包裹文本或图标即可。 + +```rust +use crate::components::ui::{Badge, BadgeVariant}; + +#[component] +fn BadgeSamples() -> Element { + rsx! { + div { class: "ui-cluster gap-2", + Badge { "默认" } + Badge { variant: BadgeVariant::Outline, "草稿" } + Badge { variant: BadgeVariant::Destructive, "危险" } + } + } +} +``` + +### Avatar + +头像组件,可在图片加载失败时展示缩写。 + +- `src` 为头像地址,`fallback` 显示自定义文本(默认取 `alt` 首字母)。 +- 会监听 `img` 的 `onerror`/`onload` 自动切换。 + +```rust +use crate::components::ui::Avatar; + +#[component] +fn AvatarSample() -> Element { + rsx! { + Avatar { + src: Some("https://example.com/me.png".into()), + alt: Some("Jane Doe".into()), + } + } +} +``` + +### Alert / AlertVariant + +状态提示块。 + +- `variant`:Default 或 Destructive。 +- 可选 `title`,正文通过 `children`。 + +```rust +use crate::components::ui::{Alert, AlertVariant}; + +#[component] +fn AlertSample() -> Element { + rsx! { + Alert { + variant: AlertVariant::Destructive, + title: Some("发布失败".into()), + "请检查网络或稍后再试。" + } + } +} +``` + +### Progress + +线性进度条。 + +- 传入 `value` 与 `max`,组件内部计算百分比。 +- 可用 `class` 替换样式。 + +```rust +use crate::components::ui::Progress; + +#[component] +fn ProgressSample() -> Element { + rsx! { Progress { value: 32.0, max: 100.0 } } +} +``` + +### Skeleton + +骨架屏占位。 + +- 可传 `width`/`height`/`radius`(CSS 长度或百分比)。 + +```rust +use crate::components::ui::Skeleton; + +#[component] +fn SkeletonSample() -> Element { + rsx! { + Skeleton { + width: Some("240px".into()), + height: Some("48px".into()), + radius: Some("12px".into()), + } + } +} +``` + +### Separator / SeparatorOrientation + +分割线。 + +- `orientation` 控制横向或纵向(Horizontal/Vertical)。 +- `style` 追加内联样式。 + +```rust +use crate::components::ui::{Separator, SeparatorOrientation}; + +#[component] +fn SeparatorSample() -> Element { + rsx! { + div { class: "ui-stack gap-2", + "上方内容" + Separator {} + "下方内容" + Separator { + orientation: SeparatorOrientation::Vertical, + style: Some("height: 40px;".into()), + } + } + } +} +``` + +### AspectRatio + +用于固定宽高比的媒体容器。`ratio` 默认 1:1,内部子元素会自动伸缩。 + +```rust +use crate::components::ui::AspectRatio; + +#[component] +fn AspectRatioSample() -> Element { + rsx! { + AspectRatio { ratio: 16.0 / 9.0, + img { + src: "https://picsum.photos/800/450", + alt: "示例图片", + style: "width: 100%; height: 100%; object-fit: cover;", + } + } + } +} +``` + +--- + +## 布局与容器 + +### Card 系列(Card / CardHeader / CardTitle / CardDescription / CardContent / CardFooter) + +卡片容器,子组件负责分区。 + +```rust +use crate::components::ui::{Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Button}; + +#[component] +fn CardSample() -> Element { + rsx! { + Card { + CardHeader { + CardTitle { "团队概览" } + CardDescription { "本月新增 24 位成员" } + } + CardContent { + p { "更多内容放在这里…" } + } + CardFooter { + Button { "查看详情" } + } + } + } +} +``` + +### ScrollArea + +限制高度并展示滚动条。 + +- 通过 `max_height` 或 `style` 设置滚动容器大小。 + +```rust +use crate::components::ui::ScrollArea; + +#[component] +fn ScrollAreaSample() -> Element { + rsx! { + ScrollArea { max_height: Some("200px".into()), + ul { + for i in 1..=20 { + li { "列表项 #{i}" } + } + } + } + } +} +``` + +### ResizablePanels + +可拖拽的双列布局。 + +- `initial`/`min`/`max` 控制百分比分布;`orientation` 可设 Horizontal / Vertical。 +- `on_resize` 回调返回当前主面板占比。 + +```rust +use crate::components::ui::{ResizableOrientation, ResizablePanels}; +use dioxus::prelude::*; + +#[component] +fn ResizableSample() -> Element { + rsx! { + ResizablePanels { + orientation: ResizableOrientation::Horizontal, + first: rsx! { div { class: "ui-pane-muted", "左侧面板" } }, + second: rsx! { div { class: "ui-pane-surface", "右侧面板" } }, + } + } +} +``` + +### Sidebar 体系 + +包含构建侧边导航所需的所有子组件。 + +- `Sidebar` 控制折叠态,`SidebarTrigger` 提供折叠按钮。 +- `SidebarLayout` + `SidebarInset` 布局主体与内容。 +- `SidebarMenu`/`SidebarMenuItem`/`SidebarMenuButton` 组合导航项,可传 `description`、`badge`、`icon`、`href`。 +- 其他辅助块:`SidebarRail`、`SidebarHeader`、`SidebarContent`、`SidebarFooter`、`SidebarSeparator`、`SidebarGroup`(含 `SidebarGroupLabel`、`SidebarGroupContent`)、`SidebarMenuBadge`。 + +```rust +use crate::components::ui::*; +use dioxus::prelude::*; + +#[component] +fn SidebarSample() -> Element { + let mut collapsed = use_signal(|| false); + + rsx! { + SidebarLayout { + Sidebar { + collapsed: collapsed(), + SidebarHeader { "LOGO" } + SidebarContent { + SidebarGroup { + SidebarGroupLabel { "管理" } + SidebarGroupContent { + SidebarMenu { + SidebarMenuItem { + SidebarMenuButton { + label: "仪表盘", + icon: Some("🏠".into()), + active: true, + } + } + SidebarMenuItem { + SidebarMenuButton { + label: "订单", + description: Some("最新交易记录".into()), + badge: Some("8".into()), + } + } + } + } + } + } + SidebarFooter { + SidebarSeparator {} + SidebarMenuBadge { text: "v1.2.0" } + } + } + SidebarInset { + header { + SidebarTrigger { + collapsed: collapsed(), + on_toggle: move |next| collapsed.set(!next), + } + } + main { class: "ui-surface p-6", "右侧内容区" } + } + } + } +} +``` + +--- + +## 表单与输入控件 + +### Input + +标准文本输入框。 + +- 支持受控与非受控:传 `value` 或 `default_value`。 +- 常用属性:`placeholder`、`r#type`、`disabled`、`readonly`、`on_input`、`on_change`。 + +```rust +use crate::components::ui::Input; +use dioxus::prelude::*; + +#[component] +fn InputSample() -> Element { + let mut name = use_signal(|| "Alice".to_string()); + + rsx! { + Input { + value: Some(name()), + placeholder: Some("请输入姓名".into()), + on_input: move |event| name.set(event.value()), + } + } +} +``` + +### Label + +配合表单控件使用的 `