1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
use dioxus::prelude::*;
/// 演示框组件 - 用于展示组件示例和代码
#[component]
pub fn DemoBox(
/// 示例标题
#[props(default = String::new())]
title: String,
/// 示例描述
#[props(default = String::new())]
description: String,
/// 代码示例
code: String,
/// 示例内容
children: Element,
) -> Element {
let mut show_code = use_signal(|| false);
let mut copied = use_signal(|| false);
rsx! {
div {
class: "mb-8 border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden transition-colors",
// 标题和描述
if !title.is_empty() || !description.is_empty() {
div {
class: "px-6 pt-6 pb-2",
if !title.is_empty() {
h3 {
class: "text-lg font-semibold text-gray-900 dark:text-white mb-2",
"{title}"
}
}
if !description.is_empty() {
p {
class: "text-sm text-gray-600 dark:text-gray-400",
"{description}"
}
}
}
}
// 示例展示区域
div {
class: "p-6 bg-white dark:bg-gray-800 transition-colors",
{children}
}
// 分隔线
div {
class: "border-t border-gray-200 dark:border-gray-700"
}
// 代码切换按钮
div {
class: "px-6 py-3 bg-gray-50 dark:bg-gray-900 flex items-center justify-between transition-colors",
button {
class: "flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white transition-colors",
onclick: move |_| {
show_code.set(!show_code());
},
// 代码图标
svg {
class: "w-4 h-4",
xmlns: "http://www.w3.org/2000/svg",
view_box: "0 0 24 24",
fill: "none",
stroke: "currentColor",
stroke_width: "2",
path {
d: "M16 18L22 12L16 6M8 6L2 12L8 18"
}
}
span {
if *show_code.read() {
"隐藏代码"
} else {
"显示代码"
}
}
// 展开/收起图标
svg {
class: if *show_code.read() { "w-4 h-4 transform rotate-180 transition-transform" } else { "w-4 h-4 transition-transform" },
xmlns: "http://www.w3.org/2000/svg",
view_box: "0 0 24 24",
fill: "currentColor",
path {
d: "M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"
}
}
}
// 复制按钮
button {
class: "flex items-center gap-1 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white transition-colors",
onclick: move |_| {
let code_to_copy = code.clone();
spawn(async move {
#[cfg(feature = "web")]
{
let js_code = format!(
r#"navigator.clipboard.writeText(`{}`)"#,
code_to_copy.replace('`', "\\`").replace('\\', "\\\\")
);
let _ = dioxus::document::eval(&js_code);
}
copied.set(true);
// 2秒后重置复制状态
gloo_timers::future::TimeoutFuture::new(2000).await;
copied.set(false);
});
},
if *copied.read() {
// 已复制图标
svg {
class: "w-4 h-4 text-green-500",
xmlns: "http://www.w3.org/2000/svg",
view_box: "0 0 24 24",
fill: "currentColor",
path {
d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"
}
}
span { class: "text-green-500", "已复制" }
} else {
// 复制图标
svg {
class: "w-4 h-4",
xmlns: "http://www.w3.org/2000/svg",
view_box: "0 0 24 24",
fill: "none",
stroke: "currentColor",
stroke_width: "2",
path {
d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
}
}
}
}
}
// 代码展示区域(可折叠)
if *show_code.read() {
div {
class: "border-t border-gray-200 dark:border-gray-700",
pre {
class: "p-6 bg-gray-900 dark:bg-gray-950 text-gray-100 text-sm overflow-x-auto transition-colors",
code {
class: "language-rust",
"{code}"
}
}
}
}
}
}
}