refactor(auth): use icon library for provider icons

This commit is contained in:
2026-06-17 16:58:24 +08:00
parent 08d512d9d6
commit b34533b242
8 changed files with 64 additions and 86 deletions
+3 -2
View File
@@ -29,6 +29,7 @@
"pino": "^10.3.1",
"react": "19.2.4",
"react-dom": "19.2.4",
"react-icons": "^5.6.0",
"stripe": "^22.2.1",
"unstorage": "^1.17.5",
"xstate": "^5",
@@ -36,8 +37,6 @@
},
"devDependencies": {
"@serwist/turbopack": "^9.0.0",
"esbuild": "^0.25.0",
"serwist": "^9.0.0",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
@@ -45,9 +44,11 @@
"@vitest/coverage-v8": "^4.1.8",
"@vitest/ui": "^4.1.8",
"barrelsby": "^2.8.1",
"esbuild": "^0.25.0",
"eslint": "^9",
"eslint-config-next": "16.2.7",
"jsdom": "^29.1.1",
"serwist": "^9.0.0",
"tailwindcss": "^4",
"typescript": "^5",
"vitest": "^4.1.8"
+12
View File
@@ -47,6 +47,9 @@ importers:
react-dom:
specifier: 19.2.4
version: 19.2.4(react@19.2.4)
react-icons:
specifier: ^5.6.0
version: 5.6.0(react@19.2.4)
stripe:
specifier: ^22.2.1
version: 22.2.1(@types/node@20.19.41)
@@ -2698,6 +2701,11 @@ packages:
peerDependencies:
react: ^19.2.4
react-icons@5.6.0:
resolution: {integrity: sha512-RH93p5ki6LfOiIt0UtDyNg/cee+HLVR6cHHtW3wALfo+eOHTp8RnU2kRkI6E+H19zMIs03DyxUG/GfZMOGvmiA==}
peerDependencies:
react: '*'
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@@ -5890,6 +5898,10 @@ snapshots:
react: 19.2.4
scheduler: 0.27.0
react-icons@5.6.0(react@19.2.4):
dependencies:
react: 19.2.4
react-is@16.13.1: {}
react@19.2.4: {}
@@ -21,6 +21,7 @@ import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context";
import { AuthErrorMessage } from "./auth-error-message";
import { AuthLegalText } from "./auth-legal-text";
import { AuthOtherOptionsDialog } from "./auth-other-options-dialog";
import { AuthProviderIcon } from "./auth-provider-icon";
import styles from "./auth-facebook-panel.module.css";
export interface AuthFacebookPanelProps {
@@ -70,9 +71,7 @@ export function AuthFacebookPanel({ onSwitchToEmail }: AuthFacebookPanelProps) {
<span className={styles.spinner} aria-hidden="true" />
) : (
<span className={styles.facebookIcon} aria-hidden="true">
<svg width="20" height="20" viewBox="0 0 24 24" fill="#1877f2">
<path d="M13 22v-8h3l1-4h-4V7.5c0-1.2.4-2 2-2h2V2.2C16.6 2.1 15.5 2 14.3 2 11.5 2 9.5 3.7 9.5 7v3h-3v4h3v8h3.5z" />
</svg>
<AuthProviderIcon provider="facebook" />
</span>
)}
<span className={styles.facebookLabel}>
@@ -14,9 +14,11 @@
* - Cancel 文本按钮
*/
import type { ReactNode } from "react";
import { Mail } from "lucide-react";
import { BottomSheet } from "@/app/_components/core/bottom-sheet";
import { AuthProviderIcon } from "./auth-provider-icon";
import { AuthSocialButton } from "./auth-social-button";
import styles from "./auth-other-options-dialog.module.css";
@@ -53,17 +55,7 @@ export function AuthOtherOptionsDialog({
{mode === "facebook" ? (
<AuthSocialButton
icon={
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="currentColor"
aria-hidden="true"
>
<path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4-8 5-8-5V6l8 5 8-5v2z" />
</svg>
}
icon={<Mail size={20} aria-hidden="true" />}
onClick={() => {
onClose();
onEmail();
@@ -73,17 +65,7 @@ export function AuthOtherOptionsDialog({
</AuthSocialButton>
) : (
<AuthSocialButton
icon={
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="var(--color-facebook-blue)"
aria-hidden="true"
>
<path d="M13 22v-8h3l1-4h-4V7.5c0-1.2.4-2 2-2h2V2.2C16.6 2.1 15.5 2 14.3 2 11.5 2 9.5 3.7 9.5 7v3h-3v4h3v8h3.5z" />
</svg>
}
icon={<AuthProviderIcon provider="facebook" />}
onClick={() => {
onClose();
onFacebook();
@@ -97,26 +79,7 @@ export function AuthOtherOptionsDialog({
<div className={styles.googleSlot}>{googleSlot}</div>
) : (
<AuthSocialButton
icon={
<svg width="20" height="20" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M22 12.2c0-.7-.1-1.4-.2-2H12v3.8h5.6c-.2 1.3-1 2.4-2 3.1v2.6h3.2c1.9-1.7 2.9-4.2 2.9-7.5z"
fill="#4285F4"
/>
<path
d="M12 22c2.7 0 4.9-.9 6.5-2.4l-3.2-2.5c-.9.6-2 1-3.3 1-2.6 0-4.7-1.7-5.5-4.1H3.2v2.5C4.8 19.7 8.1 22 12 22z"
fill="#34A853"
/>
<path
d="M6.5 14a6 6 0 010-3.9V7.5H3.2a10 10 0 000 9l3.3-2.5z"
fill="#FBBC05"
/>
<path
d="M12 5.9c1.5 0 2.8.5 3.8 1.5l2.9-2.9C16.9 2.9 14.7 2 12 2 8.1 2 4.8 4.3 3.2 7.5L6.5 10c.8-2.4 2.9-4.1 5.5-4.1z"
fill="#EA4335"
/>
</svg>
}
icon={<AuthProviderIcon provider="google" />}
onClick={() => {
onClose();
onGoogle();
+2 -13
View File
@@ -3,6 +3,7 @@
* 认证面板:顶层 switchFacebook / Email+ 悬浮返回按钮
*/
import { useRouter } from "next/navigation";
import { ChevronLeft } from "lucide-react";
import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context";
@@ -36,19 +37,7 @@ export function AuthPanel() {
onClick={handleBack}
aria-label="Back"
>
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2.5"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
>
<path d="M15 18l-6-6 6-6" />
</svg>
<ChevronLeft size={20} strokeWidth={2.5} aria-hidden="true" />
</button>
{state.authPanelMode === "facebook" ? (
@@ -0,0 +1,35 @@
"use client";
import { FaApple, FaFacebookF } from "react-icons/fa6";
import { FcGoogle } from "react-icons/fc";
export type AuthProviderIconName = "facebook" | "google" | "apple";
export interface AuthProviderIconProps {
provider: AuthProviderIconName;
size?: number;
className?: string;
}
export function AuthProviderIcon({
provider,
size = 20,
className,
}: AuthProviderIconProps) {
if (provider === "google") {
return <FcGoogle size={size} className={className} aria-hidden="true" />;
}
if (provider === "apple") {
return <FaApple size={size} className={className} aria-hidden="true" />;
}
return (
<FaFacebookF
size={size}
className={className}
color="var(--color-facebook-blue)"
aria-hidden="true"
/>
);
}
@@ -8,6 +8,7 @@
*/
import { type ReactNode } from "react";
import { AuthProviderIcon } from "./auth-provider-icon";
import styles from "./auth-social-buttons.module.css";
export interface AuthSocialButtonsProps {
@@ -37,10 +38,7 @@ export function AuthSocialButtons({
disabled={loadingProvider !== null && loadingProvider !== "facebook"}
>
<span className={styles.icon} aria-hidden="true">
{/* Facebook "f" logo placeholder */}
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
<path d="M13 22v-8h3l1-4h-4V7.5c0-1.2.4-2 2-2h2V2.2C16.6 2.1 15.5 2 14.3 2 11.5 2 9.5 3.7 9.5 7v3h-3v4h3v8h3.5z" />
</svg>
<AuthProviderIcon provider="facebook" />
</span>
<span>Continue with Facebook</span>
</button>
@@ -55,25 +53,7 @@ export function AuthSocialButtons({
disabled={loadingProvider !== null && loadingProvider !== "google"}
>
<span className={styles.icon} aria-hidden="true">
{/* Google "G" logo placeholder */}
<svg width="20" height="20" viewBox="0 0 24 24">
<path
d="M22 12.2c0-.7-.1-1.4-.2-2H12v3.8h5.6c-.2 1.3-1 2.4-2 3.1v2.6h3.2c1.9-1.7 2.9-4.2 2.9-7.5z"
fill="#4285F4"
/>
<path
d="M12 22c2.7 0 4.9-.9 6.5-2.4l-3.2-2.5c-.9.6-2 1-3.3 1-2.6 0-4.7-1.7-5.5-4.1H3.2v2.5C4.8 19.7 8.1 22 12 22z"
fill="#34A853"
/>
<path
d="M6.5 14a6 6 0 010-3.9V7.5H3.2a10 10 0 000 9l3.3-2.5z"
fill="#FBBC05"
/>
<path
d="M12 5.9c1.5 0 2.8.5 3.8 1.5l2.9-2.9C16.9 2.9 14.7 2 12 2 8.1 2 4.8 4.3 3.2 7.5L6.5 10c.8-2.4 2.9-4.1 5.5-4.1z"
fill="#EA4335"
/>
</svg>
<AuthProviderIcon provider="google" />
</span>
<span>Continue with Google</span>
</button>
@@ -87,9 +67,7 @@ export function AuthSocialButtons({
disabled={loadingProvider !== null && loadingProvider !== "apple"}
>
<span className={styles.icon} aria-hidden="true">
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
<path d="M16.4 1.5c0 1.1-.4 2.1-1.1 2.9-.8.8-1.8 1.4-2.8 1.3-.1-1.1.4-2.2 1.1-3 .8-.8 1.9-1.3 2.8-1.2zM20 17.4c-.5 1.2-1.1 2.3-1.9 3.3-1 1.3-2.4 2.9-4.1 2.9-1.5 0-1.9-1-3.9-1-2 0-2.4 1-4 1-1.7 0-3-1.5-4-2.8-2.7-3.6-3-7.8-1.3-10 1.2-1.5 3-2.4 4.8-2.4 1.8 0 2.9 1 4.4 1 1.4 0 2.3-1 4.4-1 1.6 0 3.3.9 4.5 2.4-4 2.1-3.3 7.7.1 8.6z" />
</svg>
<AuthProviderIcon provider="apple" />
</span>
<span>Continue with Apple</span>
</button>
+1
View File
@@ -11,6 +11,7 @@ export * from "./auth-legal-text";
export * from "./auth-other-options-dialog";
export * from "./auth-panel";
export * from "./auth-primary-button";
export * from "./auth-provider-icon";
export * from "./auth-social-button";
export * from "./auth-social-buttons";
export * from "./auth-text-field";