Skip to content

Commit c026f97

Browse files
committed
refactor(组件): 替换 Material Web 组件为自定义实现
重构多个组件,移除对 Material Web 组件的依赖,改用自定义样式和实现 - 将 md-icon 替换为 material-symbols-rounded 原生元素 - 重写 Button 组件实现自定义样式和交互效果 - 重构 LanguageSwitcher 为纯 HTML/CSS 实现 - 更新主题颜色和样式配置 - 优化下载按钮交互逻辑
1 parent 0c05f00 commit c026f97

9 files changed

Lines changed: 309 additions & 198 deletions

File tree

src/components/Button.astro

Lines changed: 100 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,113 @@
11
---
22
interface Props {
3-
variant?: "filled" | "tonal" | "outlined" | "text";
3+
variant?: "filled" | "outlined";
44
icon?: string;
55
label?: string;
66
href?: string;
77
}
88
99
const { variant = "filled", icon, label, href } = Astro.props;
1010
11-
const tagMap = {
12-
filled: "md-filled-button",
13-
tonal: "md-filled-tonal-button",
14-
outlined: "md-outlined-button",
15-
text: "md-text-button",
16-
} as const;
17-
18-
const Tag = tagMap[variant];
19-
const style =
20-
variant === "filled" || variant === "outlined"
21-
? "min-width: 140px"
22-
: undefined;
11+
const Tag = href ? "a" : "button";
2312
---
2413

25-
<Tag href={href} style={style}>
26-
{icon && <md-icon slot="icon">{icon}</md-icon>}
27-
<slot>{label}</slot>
14+
<Tag href={href} class={`premium-btn ${variant}`}>
15+
<div class="btn-bg"></div>
16+
<div class="btn-content">
17+
{icon && <span class="material-symbols-rounded icon">{icon}</span>}
18+
<span class="label"><slot>{label}</slot></span>
19+
</div>
2820
</Tag>
2921

30-
<script>
31-
import "@material/web/button/filled-button.js";
32-
import "@material/web/button/filled-tonal-button.js";
33-
import "@material/web/button/outlined-button.js";
34-
import "@material/web/button/text-button.js";
35-
import "@material/web/icon/icon.js";
36-
</script>
22+
<style>
23+
.premium-btn {
24+
position: relative;
25+
display: inline-flex;
26+
align-items: center;
27+
justify-content: center;
28+
padding: 12px 28px;
29+
font-family: "Outfit", sans-serif;
30+
font-weight: 600;
31+
font-size: 15px;
32+
letter-spacing: 0.5px;
33+
border-radius: 999px;
34+
cursor: pointer;
35+
text-decoration: none;
36+
outline: none;
37+
border: none;
38+
background: transparent;
39+
transition: all 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
40+
min-width: 140px;
41+
isolation: isolate;
42+
overflow: hidden;
43+
}
44+
45+
.btn-bg {
46+
position: absolute;
47+
inset: 0;
48+
border-radius: 999px;
49+
z-index: -1;
50+
transition: all 0.4s ease;
51+
}
52+
53+
.btn-content {
54+
display: flex;
55+
align-items: center;
56+
gap: 8px;
57+
z-index: 1;
58+
}
59+
60+
.icon {
61+
font-size: 20px;
62+
transition: transform 0.3s ease;
63+
}
64+
65+
.premium-btn:hover .icon {
66+
transform: translateX(2px);
67+
}
68+
69+
/* Filled Variant (Premium Glass/Neon) */
70+
.filled {
71+
color: #ffffff;
72+
box-shadow: 0 4px 16px rgba(168, 199, 250, 0.15);
73+
}
74+
75+
.filled .btn-bg {
76+
background: linear-gradient(135deg, rgba(168,199,250,0.8) 0%, rgba(218,195,246,0.8) 100%);
77+
backdrop-filter: blur(10px);
78+
-webkit-backdrop-filter: blur(10px);
79+
border: 1px solid rgba(255, 255, 255, 0.2);
80+
}
81+
82+
.filled:hover {
83+
box-shadow: 0 8px 24px rgba(168, 199, 250, 0.3), 0 0 12px rgba(218, 195, 246, 0.4);
84+
transform: translateY(-2px);
85+
}
86+
87+
.filled:hover .btn-bg {
88+
background: linear-gradient(135deg, rgba(168,199,250,1) 0%, rgba(218,195,246,1) 100%);
89+
}
90+
91+
/* Outlined Variant (Glassmorphism outline) */
92+
.outlined {
93+
color: #d6e3ff;
94+
}
95+
96+
.outlined .btn-bg {
97+
background: rgba(26, 29, 33, 0.4);
98+
backdrop-filter: blur(12px);
99+
-webkit-backdrop-filter: blur(12px);
100+
border: 1px solid rgba(168,199,250,0.3);
101+
}
102+
103+
.outlined:hover {
104+
color: #ffffff;
105+
transform: translateY(-2px);
106+
}
107+
108+
.outlined:hover .btn-bg {
109+
background: rgba(168,199,250,0.1);
110+
border-color: rgba(168,199,250,0.6);
111+
box-shadow: inset 0 0 16px rgba(168,199,250,0.1);
112+
}
113+
</style>

src/components/ContributorsSection.astro

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ const { t } = Astro.props;
2828
</section>
2929

3030
<script>
31-
import "@material/web/button/filled-button.js";
32-
import "@material/web/icon/icon.js";
33-
3431
const section = document.getElementById("contributors");
3532
if (!section) throw new Error("Missing #contributors");
3633
const contentElRaw = section.querySelector(".contributors-content");
@@ -126,7 +123,7 @@ const { t } = Astro.props;
126123
errorDiv.className = "error";
127124
errorDiv.textContent = t.error;
128125

129-
const retryButton = document.createElement("md-filled-button");
126+
const retryButton = document.createElement("button");
130127
retryButton.className = "retry-btn";
131128
retryButton.textContent = t.retry;
132129
retryButton.addEventListener("click", fetchContributors);
@@ -174,11 +171,29 @@ const { t } = Astro.props;
174171

175172
:global(.error) {
176173
display: flex;
174+
flex-direction: column;
177175
align-items: center;
178176
justify-content: center;
179-
gap: 12px;
177+
gap: 16px;
180178
}
181179

180+
:global(.retry-btn) {
181+
background: linear-gradient(135deg, rgba(168,199,250,0.8) 0%, rgba(218,195,246,0.8) 100%);
182+
color: #fff;
183+
border: none;
184+
padding: 10px 24px;
185+
border-radius: 999px;
186+
font-family: "Outfit", sans-serif;
187+
font-weight: 600;
188+
cursor: pointer;
189+
transition: all 0.3s ease;
190+
}
191+
192+
:global(.retry-btn:hover) {
193+
transform: translateY(-2px);
194+
box-shadow: 0 4px 12px rgba(168, 199, 250, 0.4);
195+
}
196+
182197
:global(.grid) {
183198
display: grid;
184199
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));

src/components/DownloadSection.astro

Lines changed: 20 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
---
2+
import Button from "./Button.astro";
3+
24
interface DownloadTranslations {
35
recommended: string;
46
title: string;
@@ -45,19 +47,13 @@ const FALLBACK = "https://github.com/LanRhyme/MicYou/releases/latest";
4547
<div class="card-glow"></div>
4648
<div class="badge" hidden>{t.recommended}</div>
4749
<div class="platform-icon">
48-
<md-icon>desktop_windows</md-icon>
50+
<span class="material-symbols-rounded" style="font-size: 36px;">desktop_windows</span>
4951
</div>
5052
<h3 class="platform-name">{t.winClient}</h3>
5153
<p class="platform-desc">{t.winReq}</p>
5254
<div class="store-buttons">
53-
<md-outlined-button data-url="exe" href={FALLBACK}>
54-
<md-icon slot="icon">download</md-icon>
55-
<span class="btn-label">{t.loading}</span>
56-
</md-outlined-button>
57-
<md-outlined-button data-url="zip" href={FALLBACK}>
58-
<md-icon slot="icon">download</md-icon>
59-
{t.btnWinZip}
60-
</md-outlined-button>
55+
<Button data-url="exe" href={FALLBACK} variant="outlined" icon="download" label={t.loading} />
56+
<Button data-url="zip" href={FALLBACK} variant="outlined" icon="download" label={t.btnWinZip} />
6157
</div>
6258
<div class="version-info">
6359
<span class="version-tag">Latest</span> &bull; {t.bit64}
@@ -69,15 +65,12 @@ const FALLBACK = "https://github.com/LanRhyme/MicYou/releases/latest";
6965
<div class="card-glow"></div>
7066
<div class="badge" hidden>{t.recommended}</div>
7167
<div class="platform-icon">
72-
<md-icon>smartphone</md-icon>
68+
<span class="material-symbols-rounded" style="font-size: 36px;">smartphone</span>
7369
</div>
7470
<h3 class="platform-name">{t.androidApp}</h3>
7571
<p class="platform-desc">{t.androidReq}</p>
7672
<div class="store-buttons">
77-
<md-outlined-button data-url="apk" href={FALLBACK}>
78-
<md-icon slot="icon">android</md-icon>
79-
{t.btnApk}
80-
</md-outlined-button>
73+
<Button data-url="apk" href={FALLBACK} variant="outlined" icon="android" label={t.btnApk} />
8174
</div>
8275
<div class="version-info">
8376
<span class="version-tag">Latest</span>
@@ -89,19 +82,13 @@ const FALLBACK = "https://github.com/LanRhyme/MicYou/releases/latest";
8982
<div class="card-glow"></div>
9083
<div class="badge" hidden>{t.recommended}</div>
9184
<div class="platform-icon">
92-
<md-icon>laptop_mac</md-icon>
85+
<span class="material-symbols-rounded" style="font-size: 36px;">laptop_mac</span>
9386
</div>
9487
<h3 class="platform-name">{t.macClient}</h3>
9588
<p class="platform-desc">{t.macReq}</p>
9689
<div class="store-buttons">
97-
<md-outlined-button data-url="dmg-arm" href={FALLBACK}>
98-
<md-icon slot="icon">download</md-icon>
99-
macOS (Apple Silicon)
100-
</md-outlined-button>
101-
<md-outlined-button data-url="dmg-x64" href={FALLBACK}>
102-
<md-icon slot="icon">download</md-icon>
103-
macOS (Intel x64)
104-
</md-outlined-button>
90+
<Button data-url="dmg-arm" href={FALLBACK} variant="outlined" icon="download" label="macOS (Apple Silicon)" />
91+
<Button data-url="dmg-x64" href={FALLBACK} variant="outlined" icon="download" label="macOS (Intel x64)" />
10592
</div>
10693
<div class="version-info">
10794
<span class="version-tag">Latest</span>
@@ -113,23 +100,16 @@ const FALLBACK = "https://github.com/LanRhyme/MicYou/releases/latest";
113100
<div class="card-glow"></div>
114101
<div class="badge" hidden>{t.recommended}</div>
115102
<div class="platform-icon">
116-
<md-icon>desktop_mac</md-icon>
103+
<span class="material-symbols-rounded" style="font-size: 36px;">desktop_mac</span>
117104
</div>
118105
<h3 class="platform-name">{t.linuxClient}</h3>
119106
<p class="platform-desc">{t.linuxReq}</p>
120107
<div class="store-buttons">
121-
<md-outlined-button data-url="deb" href={FALLBACK}>
122-
<md-icon slot="icon">download</md-icon>
123-
{t.btnLinuxDebian}
124-
</md-outlined-button>
125-
<md-outlined-button data-url="rpm" href={FALLBACK}>
126-
<md-icon slot="icon">download</md-icon>
127-
{t.btnLinuxRPM}
128-
</md-outlined-button>
129-
<md-outlined-button data-action="copy-aur">
130-
<md-icon slot="icon">content_copy</md-icon>
131-
{t.btnLinuxAUR}
132-
</md-outlined-button>
108+
<Button data-url="deb" href={FALLBACK} variant="outlined" icon="download" label={t.btnLinuxDebian} />
109+
<Button data-url="rpm" href={FALLBACK} variant="outlined" icon="download" label={t.btnLinuxRPM} />
110+
<span data-action="copy-aur">
111+
<Button variant="outlined" icon="content_copy" label={t.btnLinuxAUR} />
112+
</span>
133113
<div class="aur-message" hidden></div>
134114
</div>
135115
<div class="version-info">
@@ -141,9 +121,6 @@ const FALLBACK = "https://github.com/LanRhyme/MicYou/releases/latest";
141121
</section>
142122

143123
<script>
144-
import "@material/web/button/filled-button.js";
145-
import "@material/web/button/outlined-button.js";
146-
import "@material/web/icon/icon.js";
147124
import { detectDevice } from "../utils/device";
148125

149126
const section = document.getElementById("download")!;
@@ -217,14 +194,14 @@ const FALLBACK = "https://github.com/LanRhyme/MicYou/releases/latest";
217194
if (el) el.setAttribute("href", url);
218195
}
219196

220-
const exeLabel = section.querySelector("[data-url='exe'] .btn-label");
197+
const exeLabel = section.querySelector("[data-url='exe'] .label");
221198
if (exeLabel) exeLabel.textContent = t.btnWinDownload;
222199

223200
section.querySelectorAll(".version-tag").forEach((el) => {
224201
el.textContent = data.tag_name;
225202
});
226203
} catch {
227-
const exeLabel = section.querySelector("[data-url='exe'] .btn-label");
204+
const exeLabel = section.querySelector("[data-url='exe'] .label");
228205
if (exeLabel) exeLabel.textContent = t.btnWinDownload;
229206
}
230207
}
@@ -260,12 +237,8 @@ const FALLBACK = "https://github.com/LanRhyme/MicYou/releases/latest";
260237
if (key) {
261238
const btn = card.querySelector<HTMLElement>(`[data-url="${key}"]`);
262239
if (btn) {
263-
const filled = document.createElement("md-filled-button");
264-
for (const attr of Array.from(btn.attributes)) {
265-
filled.setAttribute(attr.name, attr.value);
266-
}
267-
filled.innerHTML = btn.innerHTML;
268-
btn.replaceWith(filled);
240+
btn.classList.remove("outlined");
241+
btn.classList.add("filled");
269242
}
270243
}
271244
} catch {
@@ -458,10 +431,6 @@ const FALLBACK = "https://github.com/LanRhyme/MicYou/releases/latest";
458431
box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 1px rgba(255,255,255,0.1);
459432
}
460433

461-
.platform-icon md-icon {
462-
font-size: 36px;
463-
}
464-
465434
.platform-name {
466435
font-family: "Outfit", sans-serif;
467436
font-size: 26px;

src/components/FeatureCard.astro

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,13 @@ const { icon, title, description, delay = 0 } = Astro.props;
1212
<div class="feature-card reveal-on-scroll" data-delay={delay}>
1313
<div class="card-glow"></div>
1414
<div class="icon-container">
15-
<md-icon class="feature-icon">{icon}</md-icon>
15+
<span class="material-symbols-rounded feature-icon">{icon}</span>
1616
</div>
1717
<h3 class="feature-title">{title}</h3>
1818
<p class="feature-description">{description}</p>
1919
</div>
2020

2121
<script>
22-
import "@material/web/icon/icon.js";
23-
2422
const observerOptions = {
2523
root: null,
2624
rootMargin: '0px',

src/components/Footer.astro

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const currentYear = new Date().getFullYear();
1616
<div class="footer-container">
1717
<div class="footer-content">
1818
<div class="footer-brand">
19-
<md-icon class="footer-logo">mic</md-icon>
19+
<span class="material-symbols-rounded footer-logo">mic</span>
2020
<span class="brand-name">MicYou</span>
2121
</div>
2222

@@ -39,10 +39,6 @@ const currentYear = new Date().getFullYear();
3939
</div>
4040
</footer>
4141

42-
<script>
43-
import "@material/web/icon/icon.js";
44-
</script>
45-
4642
<style>
4743
.footer {
4844
background-color: var(--md-sys-color-background);

src/components/HeroSection.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ const { t } = Astro.props;
192192
}
193193

194194
.hero-title-highlight {
195-
background: linear-gradient(135deg, #a8c7fa 0%, #dac3f6 50%, #d6e3ff 100%);
195+
background: linear-gradient(135deg, var(--md-sys-color-primary) 0%, var(--md-sys-color-secondary) 50%, var(--md-sys-color-tertiary) 100%);
196196
-webkit-background-clip: text;
197197
-webkit-text-fill-color: transparent;
198198
background-size: 200% auto;

0 commit comments

Comments
 (0)