Skip to content

Commit 8329e8c

Browse files
author
sanguogege
committed
add Divider
1 parent 93129e5 commit 8329e8c

File tree

8 files changed

+186
-103
lines changed

8 files changed

+186
-103
lines changed

app/doc/astro.config.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,13 @@ export default defineConfig({
2727
],
2828
},
2929
{
30-
label: "components",
30+
label: "通用",
3131
autogenerate: { directory: "components" },
3232
},
33+
{
34+
label: "布局",
35+
autogenerate: { directory: "layout" },
36+
},
3337
],
3438
customCss: ["./src/styles/global.css"],
3539
plugins: [starlightThemeRapide()],
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
title: Divider
3+
description: Divider.
4+
---
5+
6+
7+
import { Divider } from "solid-element-ui";
8+
9+
<div>
10+
<p>
11+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
12+
probare, quae sunt a te dicta? Refert tamen, quo modo.
13+
</p>
14+
<Divider />
15+
<p>
16+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
17+
probare, quae sunt a te dicta? Refert tamen, quo modo.
18+
</p>
19+
<Divider dashed />
20+
<p>
21+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
22+
probare, quae sunt a te dicta? Refert tamen, quo modo.
23+
</p>
24+
</div>
25+
26+
27+
<div>
28+
29+
<p>
30+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
31+
probare, quae sunt a te dicta? Refert tamen, quo modo.
32+
</p>
33+
<Divider>Text</Divider>
34+
<p>
35+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
36+
probare, quae sunt a te dicta? Refert tamen, quo modo.
37+
</p>
38+
<Divider contentPosition="left">Left Text</Divider>
39+
<p>
40+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
41+
probare, quae sunt a te dicta? Refert tamen, quo modo.
42+
</p>
43+
<Divider contentPosition="center">center Text</Divider>
44+
<p>
45+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
46+
probare, quae sunt a te dicta? Refert tamen, quo modo.
47+
</p>
48+
<Divider contentPosition="right" >
49+
right Text
50+
</Divider>
51+
<p>
52+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
53+
probare, quae sunt a te dicta? Refert tamen, quo modo.
54+
</p>
55+
</div>

packages/solid-element-ui/components/button/button.tsx

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,32 @@
1-
import { splitProps, JSX } from "solid-js";
2-
import {
3-
buttonVariants,
4-
ButtonProps,
5-
} from "./setting";
6-
7-
// 扩展 Props
8-
1+
import { splitProps, createMemo } from "solid-js";
2+
import { buttonVariants, type ButtonProps } from "./setting";
93

104
export const Button = (props: ButtonProps) => {
115
// 1. 拆分参数
6+
// local: 内部使用的属性
7+
// variantProps: 传给 TV 生成样式的属性
8+
// others: 传给原生 button 标签的属性 (如 type, onClick, disabled 等)
129
const [local, variantProps, others] = splitProps(
1310
props,
1411
["class", "style", "children", "loading"],
15-
["variant","color", "size"]
12+
["variant", "color", "size"]
1613
);
1714

18-
// 2. 调用 TV (传入 variant 和自定义 class)
19-
// TV 会自动把 local.class 合并到 base 槽位
20-
const styles = () =>
15+
// 2. 使用 createMemo 保证响应式
16+
// 注意:TV 的多插槽(slots)模式下,调用 styles() 会返回一个包含各个 slot 函数的对象
17+
const styles = createMemo(() =>
2118
buttonVariants({
2219
...variantProps,
2320
loading: local.loading,
24-
class: local.class,
25-
});
21+
})
22+
);
2623

27-
console.log("local",local);
28-
console.log("variantProps", variantProps);
29-
console.log("others", others);
30-
console.log(styles().base());
3124
return (
3225
<button
33-
class={styles().base()} // 使用 base 槽位生成的类名
26+
// styles().base({ class: ... }) 会自动合并外部传入的 class 到 base 槽位
27+
class={styles().base({ class: local.class })}
3428
style={local.style}
29+
// 只要是 loading 状态或外部传入了 disabled,按钮就禁用
3530
disabled={local.loading || others.disabled}
3631
{...others}
3732
>

packages/solid-element-ui/components/button/setting.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { tv, type VariantProps } from "tailwind-variants";
33

44
export const buttonVariants = tv(
55
{
6-
// slots: 定义组件内部多个部分的样式
76
slots: {
87
base: "inline-flex items-center cursor-pointer justify-center rounded-sm text-sm font-medium transition-all duration-200 active:scale-[0.98] focus:outline-none disabled:opacity-50 disabled:pointer-events-none",
98
icon: "animate-spin -ml-1 mr-2 h-4 w-4 text-current",

packages/solid-element-ui/components/divider/divider.tsx

Lines changed: 47 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,67 @@
1-
import { splitProps, Show, type ParentComponent, createMemo } from "solid-js";
2-
import { type DividerProps } from "./setting";
3-
import { cn } from "@solid-element-ui/utils/cn";
1+
import { splitProps, Show, createMemo } from "solid-js";
2+
import { dividerVariants, type DividerProps } from "./setting";
43

5-
// 1. 定义预设颜色映射(对应你 Tailwind v4 的主题配置)
6-
const COLOR_MAP: Record<string, string> = {
7-
primary: "border-primary text-primary",
8-
success: "border-green-500 text-green-500",
9-
warning: "border-yellow-500 text-yellow-500",
10-
danger: "border-red-500 text-red-500",
11-
info: "border-gray-400 text-gray-400",
12-
};
13-
14-
const customAttributes = [
15-
"direction",
16-
"contentPosition",
17-
"dashed",
18-
"color",
19-
"class",
20-
"children",
21-
] as const;
4+
// 对应 Tailwind 主题配置的预设名
5+
const PRESET_COLORS = ["primary", "success", "warning", "danger", "info"];
226

23-
export const SeDivider: ParentComponent<DividerProps> = (
24-
props: DividerProps
25-
) => {
26-
const [local, others] = splitProps(props, customAttributes);
7+
export const Divider = (props: DividerProps) => {
8+
// 1. 拆分参数:style 必须分到 local 中以修复 TS2339
9+
const [local, variantProps, others] = splitProps(
10+
props,
11+
["class", "style", "children", "color"],
12+
["direction", "contentPosition", "dashed"]
13+
);
2714

28-
const isVertical = () => local.direction === "vertical";
29-
const contentPos = () => local.contentPosition || "center";
15+
const isVertical = () => variantProps.direction === "vertical";
3016

31-
// 2. 核心判断逻辑
17+
// 2. 判断是否为自定义颜色(如 #fff, rgb...)
3218
const isCustomColor = createMemo(
33-
() => local.color && !COLOR_MAP[local.color]
19+
() => local.color && !PRESET_COLORS.includes(local.color)
3420
);
35-
const presetColorClass = createMemo(() =>
36-
local.color ? COLOR_MAP[local.color] : ""
21+
22+
// 3. 生成 TV 样式类
23+
const styles = createMemo(() =>
24+
dividerVariants({
25+
...variantProps,
26+
// 如果是预设色,传给 TV;如果是自定义色,TV 不处理
27+
color: !isCustomColor() ? (local.color as any) : undefined,
28+
hasChildren: !!local.children && !isVertical(),
29+
})
3730
);
3831

39-
// 3. 动态样式处理
32+
// 4. 处理 Style 逻辑:合并自定义颜色
4033
const resolveStyles = createMemo(() => {
41-
if (!isCustomColor()) return others.style || {};
42-
return {
43-
"border-color": local.color,
44-
color: local.color,
45-
...(others.style as any),
46-
};
34+
const baseStyle = typeof local.style === "object" ? local.style : {};
35+
36+
if (isCustomColor()) {
37+
return {
38+
"border-color": local.color,
39+
color: local.color, // 让 text-inherit 和 border-inherit 生效
40+
...baseStyle,
41+
};
42+
}
43+
44+
// 无颜色且无文字时的默认兜底色(Tailwind v4 默认透明,需指定)
45+
if (!local.color && !local.children) {
46+
return {
47+
"border-color": "var(--color-gray-200, #e5e7eb)",
48+
...baseStyle,
49+
};
50+
}
51+
52+
return baseStyle;
4753
});
4854

4955
return (
5056
<div
5157
{...others}
5258
role="separator"
53-
style={resolveStyles()}
54-
class={cn(
55-
"relative transition-colors duration-200",
56-
// 如果没有颜色且没有文字,给一个默认边框色
57-
!local.color && !local.children && "border-gray-200",
58-
// 应用预设类名
59-
presetColorClass(),
60-
61-
!isVertical()
62-
? [
63-
"flex items-center w-full my-6",
64-
// 关键:带文字时父容器不能有 border,否则会穿透文字
65-
local.children ? "border-none" : "border-t",
66-
]
67-
: "inline-block mx-2 h-[0.9em] align-middle border-l",
68-
69-
local.dashed && "border-dashed",
70-
local.class
71-
)}
59+
style={resolveStyles() as any}
60+
class={styles().base({ class: local.class })}
7261
>
7362
<Show when={!isVertical() && local.children}>
74-
<div
75-
class={cn(
76-
"flex items-center w-full text-sm font-medium",
77-
// 必须包含 border-inherit,让 before/after 线条继承父级的预设类名颜色或内联样式颜色
78-
"before:content-[''] before:border-t before:border-inherit",
79-
"after:content-[''] after:border-t after:border-inherit",
80-
local.dashed &&
81-
"before:border-dashed after:border-dashed",
82-
// 位置逻辑
83-
contentPos() === "center" &&
84-
"before:flex-1 after:flex-1",
85-
contentPos() === "left" && "before:w-6 after:flex-1",
86-
contentPos() === "right" && "before:flex-1 after:w-6"
87-
)}
88-
>
89-
<span class="px-4 whitespace-nowrap text-inherit">
90-
{local.children}
91-
</span>
63+
<div class={styles().container()}>
64+
<span class={styles().text()}>{local.children}</span>
9265
</div>
9366
</Show>
9467
</div>

packages/solid-element-ui/components/divider/setting.ts

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,71 @@
11
import { type JSX } from "solid-js";
2+
import { tv, type VariantProps } from "tailwind-variants";
23

3-
export interface DividerProps extends JSX.HTMLAttributes<HTMLDivElement> {
4+
export const dividerVariants = tv({
5+
slots: {
6+
base: "relative transition-colors duration-200",
7+
// container 负责文字两侧的线条,通过 border-inherit 继承父级颜色
8+
container:
9+
"flex items-center w-full text-sm font-medium before:content-[''] after:content-[''] before:border-t after:border-t before:border-inherit after:border-inherit",
10+
text: "px-4 whitespace-nowrap text-inherit",
11+
},
12+
variants: {
13+
direction: {
14+
horizontal: {
15+
base: "flex items-center w-full my-6",
16+
},
17+
vertical: {
18+
base: "inline-block mx-2 h-[0.9em] align-middle border-l",
19+
},
20+
},
21+
dashed: {
22+
true: {
23+
base: "border-dashed",
24+
container: "before:border-dashed after:border-dashed",
25+
},
26+
},
27+
contentPosition: {
28+
left: { container: "before:w-6 after:flex-1" },
29+
center: { container: "before:flex-1 after:flex-1" },
30+
right: { container: "before:flex-1 after:w-6" },
31+
},
32+
color: {
33+
primary: { base: "border-primary text-primary" },
34+
success: { base: "border-green-500 text-green-500" },
35+
warning: { base: "border-yellow-500 text-yellow-500" },
36+
danger: { base: "border-red-500 text-red-500" },
37+
info: { base: "border-gray-400 text-gray-400" },
38+
},
39+
40+
hasChildren: {
41+
true: {},
42+
false: {},
43+
},
44+
},
45+
compoundVariants: [
46+
{
47+
direction: "horizontal",
48+
hasChildren: false,
49+
class: {
50+
base: "border-t",
51+
},
52+
},
53+
],
54+
defaultVariants: {
55+
direction: "horizontal",
56+
contentPosition: "center",
57+
},
58+
});
59+
60+
export type DividerVariantProps = VariantProps<typeof dividerVariants>;
61+
62+
export interface DividerProps
63+
extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "color"> {
464
direction?: "horizontal" | "vertical";
565
contentPosition?: "left" | "center" | "right";
666
dashed?: boolean;
7-
8-
/** 新增:颜色属性,支持主题色名或自定义 */
9-
1067
color?: "primary" | "success" | "warning" | "danger" | "info" | string;
68+
children?: JSX.Element;
69+
class?: string;
70+
style?: JSX.CSSProperties | string;
1171
}
12-
13-

packages/solid-element-ui/css/index.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,3 @@
2929
}
3030
}
3131

32-
@source "../components/button/settings.ts";

packages/solid-element-ui/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export { SeBreadcrumbItem } from "./components/breadcrumb/breadcrumb-item.tsx";
1818
export { SeAnchor } from "./components/anchor/anchor.tsx";
1919
export { SeAnchorLink } from "./components/anchor/anchor-link.tsx";
2020

21-
export { SeDivider } from "./components/divider/divider.tsx";
21+
export { Divider } from "./components/divider/divider.tsx";
2222

2323
export { SeAutocomplete } from "./components/autocomplete/autocomplete.tsx";
2424

0 commit comments

Comments
 (0)