Skip to content

Commit a7ed436

Browse files
Merge pull request #16 from MasterFrontEndYu/main
fix:some
2 parents 8329e8c + 4bf22a6 commit a7ed436

File tree

10 files changed

+276
-146
lines changed

10 files changed

+276
-146
lines changed

app/doc/astro.config.mjs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @ts-check
2-
import { defineConfig } from 'astro/config';
3-
import starlight from '@astrojs/starlight';
2+
import { defineConfig } from "astro/config";
3+
import starlight from "@astrojs/starlight";
44
import mdx from "@astrojs/mdx";
55
import solidJs from "@astrojs/solid-js";
66
import tailwindcss from "@tailwindcss/vite";
@@ -34,6 +34,10 @@ export default defineConfig({
3434
label: "布局",
3535
autogenerate: { directory: "layout" },
3636
},
37+
{
38+
label: "导航",
39+
autogenerate: { directory: "navigation" },
40+
},
3741
],
3842
customCss: ["./src/styles/global.css"],
3943
plugins: [starlightThemeRapide()],

app/doc/src/content/docs/components/button.mdx

Lines changed: 68 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@ description: A reference page in my new Starlight docs site.
77

88
五种 variant 按钮
99

10-
- default、outline、dashed、filled、text、link
11-
10+
- default、outline、dashed、filled、text、link
1211

1312
四种 颜色 按钮
1413

15-
- primary、success、 warning、error
16-
14+
- primary、success、 warning、error
1715

18-
19-
import { Button } from "solid-element-ui";
16+
import { Button, ButtonGroup } from "solid-element-ui";
2017

2118
<div class="display-flex">
2219
<Button variant="default">default</Button>
@@ -28,40 +25,79 @@ import { Button } from "solid-element-ui";
2825
</div>
2926
<div class="display-flex">
3027
<Button color="primary">primary</Button>
31-
<Button variant="outline" color="primary">primary</Button>
32-
<Button variant="dashed" color="primary">primary</Button>
33-
<Button variant="filled" color="primary">primary</Button>
34-
<Button variant="text" color="primary">primary</Button>
35-
<Button variant="link" color="primary">primary</Button>
36-
28+
<Button variant="outline" color="primary">
29+
primary
30+
</Button>
31+
<Button variant="dashed" color="primary">
32+
primary
33+
</Button>
34+
<Button variant="filled" color="primary">
35+
primary
36+
</Button>
37+
<Button variant="text" color="primary">
38+
primary
39+
</Button>
40+
<Button variant="link" color="primary">
41+
primary
42+
</Button>
3743
</div>
3844
<div class="display-flex">
3945
<Button color="success">success</Button>
40-
<Button variant="outline" color="success">primary</Button>
41-
<Button variant="dashed" color="success">primary</Button>
42-
<Button variant="filled" color="success">primary</Button>
43-
<Button variant="text" color="success">primary</Button>
44-
<Button variant="link" color="success">primary</Button>
45-
46+
<Button variant="outline" color="success">
47+
primary
48+
</Button>
49+
<Button variant="dashed" color="success">
50+
primary
51+
</Button>
52+
<Button variant="filled" color="success">
53+
primary
54+
</Button>
55+
<Button variant="text" color="success">
56+
primary
57+
</Button>
58+
<Button variant="link" color="success">
59+
primary
60+
</Button>
4661
</div>
4762
<div class="display-flex">
4863
<Button color="warning">warning</Button>
49-
<Button variant="outline" color="warning">primary</Button>
50-
<Button variant="dashed" color="warning">primary</Button>
51-
<Button variant="filled" color="warning">primary</Button>
52-
<Button variant="text" color="warning">primary</Button>
53-
<Button variant="link" color="warning">primary</Button>
64+
<Button variant="outline" color="warning">
65+
primary
66+
</Button>
67+
<Button variant="dashed" color="warning">
68+
primary
69+
</Button>
70+
<Button variant="filled" color="warning">
71+
primary
72+
</Button>
73+
<Button variant="text" color="warning">
74+
primary
75+
</Button>
76+
<Button variant="link" color="warning">
77+
primary
78+
</Button>
5479
</div>
5580
<div class="display-flex">
5681
<Button color="error">error</Button>
57-
<Button variant="outline" color="error">primary</Button>
58-
<Button variant="dashed" color="error">primary</Button>
59-
<Button variant="filled" color="error">primary</Button>
60-
<Button variant="text" color="error">primary</Button>
61-
<Button variant="link" color="error">primary</Button>
82+
<Button variant="outline" color="error">
83+
primary
84+
</Button>
85+
<Button variant="dashed" color="error">
86+
primary
87+
</Button>
88+
<Button variant="filled" color="error">
89+
primary
90+
</Button>
91+
<Button variant="text" color="error">
92+
primary
93+
</Button>
94+
<Button variant="link" color="error">
95+
primary
96+
</Button>
6297
</div>
6398

64-
65-
<Button >error</Button>
66-
67-
99+
<ButtonGroup>
100+
<Button>primary</Button>
101+
<Button color="primary">primary</Button>
102+
<Button variant="outline">outline</Button>
103+
</ButtonGroup>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
title: Anchor
3+
description: A reference page in my new Starlight docs site.
4+
---
5+
6+
import { Anchor, AnchorLink } from "solid-element-ui";
7+
8+
<div class="flex p-10 gap-10">
9+
<div class="p-20">
10+
<Anchor client:load class="w-40">
11+
<AnchorLink href="#test" title="测试链接 1" />
12+
<AnchorLink href="#test2" title="测试链接 2" />
13+
</Anchor>
14+
15+
</div>
16+
<div class="h-screen">
17+
<div id="test" class="h-screen">
18+
内容1
19+
</div>
20+
<div id="test2" class="h-screen">
21+
内容2
22+
</div>
23+
</div>
24+
25+
</div>

packages/solid-element-ui/components/anchor/anchor-link.tsx

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,24 @@
1-
import { useContext, type Component } from "solid-js";
2-
import { type AnchorLinkProps, AnchorContext } from "./setting";
3-
import { cn } from "@solid-element-ui/utils/cn";
1+
import { onMount, onCleanup, createMemo, type Component } from "solid-js";
2+
import { type AnchorLinkProps, anchorVariants, useAnchor } from "./setting";
43

5-
export const SeAnchorLink: Component<AnchorLinkProps> = (props) => {
6-
const ctx = useContext(AnchorContext);
7-
if (!ctx) return null;
4+
export const AnchorLink: Component<AnchorLinkProps> = (props) => {
5+
const ctx = useAnchor();
86

9-
const handleClick = (e: MouseEvent) => {
10-
e.preventDefault();
11-
ctx.scrollTo(props.href);
12-
};
7+
// 注册逻辑仅在浏览器端运行
8+
onMount(() => ctx?.registerLink(props.href));
9+
onCleanup(() => ctx?.unregisterLink(props.href));
1310

14-
const isActive = () => ctx.activeLink() === props.href;
11+
const isActive = createMemo(() => ctx?.activeLink() === props.href);
12+
const styles = createMemo(() => anchorVariants({ active: isActive() }));
1513

1614
return (
1715
<a
1816
href={props.href}
19-
onClick={handleClick}
20-
class={cn(
21-
"block py-1 pl-4 text-sm transition-all border-l-2 -ml-0.5",
22-
isActive()
23-
? "text-blue-600 border-blue-600 font-medium"
24-
: "text-gray-500 border-transparent hover:text-gray-900"
25-
)}
17+
onClick={(e) => {
18+
e.preventDefault();
19+
ctx?.scrollTo(props.href);
20+
}}
21+
class={styles().link({ class: props.class })}
2622
>
2723
{props.title}
2824
</a>

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

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,75 +3,77 @@ import {
33
onMount,
44
onCleanup,
55
splitProps,
6-
type ParentComponent,
6+
createMemo,
77
} from "solid-js";
8-
import { type AnchorProps, AnchorContext } from "./setting";
9-
import { cn } from "@solid-element-ui/utils/cn";
8+
import { isServer } from "solid-js/web";
9+
import {
10+
type AnchorProps,
11+
type AnchorContextValue, // 这里引用了接口
12+
AnchorContext,
13+
anchorVariants,
14+
} from "./setting";
1015

11-
export const SeAnchor: ParentComponent<AnchorProps> = (props) => {
16+
export const Anchor = (props: AnchorProps) => {
1217
const [local, others] = splitProps(props, [
1318
"target",
1419
"offset",
1520
"class",
1621
"children",
1722
]);
1823
const [activeLink, setActiveLink] = createSignal("");
24+
const [links, setLinks] = createSignal<string[]>([]);
1925

20-
// 收集所有链接
21-
const links: string[] = [];
26+
const styles = createMemo(() => anchorVariants());
2227

2328
const handleScroll = () => {
29+
if (isServer) return;
2430
const offset = local.offset ?? 0;
2531
let currentActive = "";
26-
27-
for (const link of links) {
28-
const el = document.querySelector(link);
29-
if (el) {
30-
const rect = el.getBoundingClientRect();
31-
// 如果元素顶部达到了 offset 阈值
32-
if (rect.top <= offset + 10) {
33-
currentActive = link;
32+
for (const link of links()) {
33+
try {
34+
const el = document.querySelector(link);
35+
if (el instanceof HTMLElement) {
36+
if (el.getBoundingClientRect().top <= offset + 20) {
37+
currentActive = link;
38+
}
3439
}
35-
}
40+
} catch (e) {}
3641
}
3742
setActiveLink(currentActive);
3843
};
3944

4045
const scrollTo = (link: string) => {
46+
if (isServer) return;
4147
const el = document.querySelector(link);
42-
if (el) {
48+
if (el instanceof HTMLElement) {
4349
const offset = local.offset ?? 0;
44-
const elementPosition =
45-
el.getBoundingClientRect().top + window.scrollY;
46-
47-
window.scrollTo({
48-
top: elementPosition - offset,
49-
behavior: "smooth",
50-
});
50+
const scrollTarget = local.target?.() || window;
51+
const top =
52+
el.getBoundingClientRect().top + window.scrollY - offset;
53+
scrollTarget.scrollTo({ top, behavior: "smooth" });
54+
setActiveLink(link);
5155
}
5256
};
5357

5458
onMount(() => {
55-
const scrollTarget = local.target?.() || window;
56-
scrollTarget.addEventListener("scroll", handleScroll);
57-
// 初始化计算
59+
const target = local.target?.() || window;
60+
target.addEventListener("scroll", handleScroll, { passive: true });
5861
handleScroll();
59-
onCleanup(() =>
60-
scrollTarget.removeEventListener("scroll", handleScroll)
61-
);
62+
onCleanup(() => target.removeEventListener("scroll", handleScroll));
6263
});
6364

65+
// 显式标注类型以确保匹配
66+
const contextValue: AnchorContextValue = {
67+
activeLink,
68+
scrollTo,
69+
registerLink: (link) => setLinks((p) => [...new Set([...p, link])]),
70+
unregisterLink: (link) => setLinks((p) => p.filter((l) => l !== link)),
71+
};
72+
6473
return (
65-
<AnchorContext.Provider value={{ activeLink, scrollTo }}>
66-
<div
67-
class={cn(
68-
"anchor-wrapper relative border-l-2 border-gray-200",
69-
local.class
70-
)}
71-
{...others}
72-
>
73-
{/* 动态指示条 */}
74-
<div class="flex flex-col">{local.children}</div>
74+
<AnchorContext.Provider value={contextValue}>
75+
<div {...others} class={styles().base({ class: local.class })}>
76+
<div class={styles().list()}>{local.children}</div>
7577
</div>
7678
</AnchorContext.Provider>
7779
);
Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,53 @@
1-
import { createContext, type JSX } from "solid-js";
1+
import { createContext, useContext, type JSX } from "solid-js";
2+
import { isServer } from "solid-js/web";
3+
import { tv, type VariantProps } from "tailwind-variants";
24

3-
// 定义组件的 Props 类型
4-
// TODO: 根据需要修改继承的 HTML 元素类型
5+
// 1. 定义样式
6+
export const anchorVariants = tv({
7+
slots: {
8+
base: "relative border-l-2 border-gray-200 ml-0.5 h-fit",
9+
list: "flex flex-col relative",
10+
link: "block py-1 pl-4 text-sm transition-all border-l-2 -ml-[2px] no-underline cursor-pointer",
11+
},
12+
variants: {
13+
active: {
14+
true: { link: "text-primary border-primary font-medium" },
15+
false: {
16+
link: "text-gray-500 border-transparent hover:text-gray-700",
17+
},
18+
},
19+
},
20+
});
21+
22+
// 2. 【关键】导出 Context 接口
23+
export interface AnchorContextValue {
24+
activeLink: () => string;
25+
scrollTo: (link: string) => void;
26+
registerLink: (link: string) => void;
27+
unregisterLink: (link: string) => void;
28+
}
29+
30+
// 3. 导出 Props 接口
531
export interface AnchorProps extends JSX.HTMLAttributes<HTMLDivElement> {
6-
target?: () => HTMLElement | Window; // 滚动容器
7-
offset?: number; // 距离顶部的偏移量(触发高亮的阈值)
8-
bounds?: number; // 锚点区域边界
32+
target?: () => HTMLElement | Window;
33+
offset?: number;
34+
children?: JSX.Element;
935
}
1036

1137
export interface AnchorLinkProps {
12-
href: string; // 锚点链接(如 #section1)
13-
title: JSX.Element; // 显示文字或图标
38+
href: string;
39+
title: JSX.Element;
40+
class?: string;
1441
}
1542

43+
// 4. 导出 Context 实例
44+
export const AnchorContext = createContext<AnchorContextValue>();
1645

17-
export const AnchorContext = createContext<{
18-
activeLink: () => string;
19-
scrollTo: (link: string) => void;
20-
}>();
46+
// 5. 导出 Hook
47+
export const useAnchor = () => {
48+
const ctx = useContext(AnchorContext);
49+
if (!ctx && !isServer) {
50+
console.warn("SeAnchorLink 必须在 SeAnchor 内部使用");
51+
}
52+
return ctx;
53+
};

0 commit comments

Comments
 (0)