Design System 重构继续完成

This commit is contained in:
2026-02-10 04:58:50 +08:00
parent 73d0b0d5fe
commit b8cb884e9e
56 changed files with 403 additions and 1033 deletions

View File

@@ -3,11 +3,11 @@
import { useState, useEffect, useCallback } from "react";
import { useTranslations } from "next-intl";
import { Letter, SupportedAlphabets } from "@/lib/interfaces";
import { IconClick, CircleToggleButton, CircleButton, PrimaryButton } from "@/components/ui/buttons";
import { IconClick, CircleToggleButton, CircleButton, PrimaryButton } from "@/design-system/base/button";
import { IMAGES } from "@/config/images";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { PageLayout } from "@/components/ui/PageLayout";
import { Card } from "@/components/ui/Card";
import { Card } from "@/design-system/base/card";
interface AlphabetCardProps {
alphabet: Letter[];
@@ -103,7 +103,7 @@ export function AlphabetCard({ alphabet, alphabetType, onBack }: AlphabetCardPro
{/* 右上角返回按钮 - outside the white card */}
<div className="flex justify-end mb-4">
<IconClick
size={32}
size="lg"
alt="close"
src={IMAGES.close}
onClick={onBack}
@@ -185,7 +185,7 @@ export function AlphabetCard({ alphabet, alphabetType, onBack }: AlphabetCardPro
<div className="flex justify-between items-center">
{/* 上一个按钮 */}
<CircleButton onClick={goToPrevious} aria-label="上一个字母">
<ChevronLeft size={24} />
<ChevronLeft size={20} />
</CircleButton>
{/* 中间区域:随机按钮 */}
@@ -202,7 +202,7 @@ export function AlphabetCard({ alphabet, alphabetType, onBack }: AlphabetCardPro
{/* 下一个按钮 */}
<CircleButton onClick={goToNext} aria-label="下一个字母">
<ChevronRight size={24} />
<ChevronRight size={20} />
</CircleButton>
</div>
</Card>

View File

@@ -1,5 +1,5 @@
import { LightButton } from "@/components/ui/buttons";
import { IconClick } from "@/components/ui/buttons";
import { LightButton } from "@/design-system/base/button";
import { IconClick } from "@/design-system/base/button";
import { IMAGES } from "@/config/images";
import { Letter, SupportedAlphabets } from "@/lib/interfaces";
import {
@@ -45,10 +45,10 @@ export function MemoryCard({
className="w-full flex justify-center items-center"
onKeyDown={(e: KeyboardEvent<HTMLDivElement>) => e.preventDefault()}
>
<div className="m-4 p-4 w-full md:w-[60dvw] flex-col rounded-2xl shadow border-gray-200 border flex justify-center items-center">
<div className="m-4 p-4 w-full md:w-[60dvw] flex-col rounded-lg shadow border-gray-200 border flex justify-center items-center">
<div className="w-full flex justify-end items-center">
<IconClick
size={32}
size="lg"
alt="close"
src={IMAGES.close}
onClick={() => setChosenAlphabet(null)}
@@ -64,13 +64,13 @@ export function MemoryCard({
</div>
<div className="flex flex-row mt-32 items-center justify-center gap-2">
<IconClick
size={48}
size="lg"
alt="refresh"
src={IMAGES.refresh}
onClick={refresh}
></IconClick>
<IconClick
size={48}
size="lg"
alt="more"
src={IMAGES.more_horiz}
onClick={() => setMore(!more)}

View File

@@ -4,7 +4,7 @@ import { useState, useEffect } from "react";
import { useTranslations } from "next-intl";
import { Letter, SupportedAlphabets } from "@/lib/interfaces";
import { PageLayout } from "@/components/ui/PageLayout";
import { LightButton } from "@/components/ui/buttons";
import { LightButton } from "@/design-system/base/button";
import { AlphabetCard } from "./AlphabetCard";
export default function Alphabet() {

View File

@@ -1,7 +1,7 @@
"use client";
import { LightButton } from "@/components/ui/buttons";
import { Input } from "@/components/ui/Input";
import { LightButton } from "@/design-system/base/button";
import { Input } from "@/design-system/base/input";
import { useTranslations } from "next-intl";
import { useState } from "react";
import { useRouter } from "next/navigation";

View File

@@ -1,7 +1,7 @@
"use client";
import { Plus, RefreshCw } from "lucide-react";
import { CircleButton, LightButton } from "@/components/ui/buttons";
import { CircleButton, LightButton } from "@/design-system/base/button";
import { toast } from "sonner";
import { actionCreatePair } from "@/modules/folder/folder-aciton";
import { TSharedItem } from "@/shared/dictionary-type";

View File

@@ -6,7 +6,7 @@ import Link from "next/link";
import { Folder as Fd } from "lucide-react";
import { TSharedFolderWithTotalPairs } from "@/shared/folder-type";
import { PageLayout } from "@/components/ui/PageLayout";
import { PrimaryButton } from "@/components/ui/buttons";
import { PrimaryButton } from "@/design-system/base/button";
interface FolderSelectorProps {
folders: TSharedFolderWithTotalPairs[];
@@ -37,7 +37,7 @@ const FolderSelector: React.FC<FolderSelectorProps> = ({ folders }) => {
{t("selectFolder")}
</h1>
{/* 文件夹列表 */}
<div className="border border-gray-200 rounded-2xl max-h-96 overflow-y-auto">
<div className="border border-gray-200 rounded-lg max-h-96 overflow-y-auto">
{folders
.toSorted((a, b) => a.id - b.id)
.map((folder) => (
@@ -50,7 +50,7 @@ const FolderSelector: React.FC<FolderSelectorProps> = ({ folders }) => {
>
{/* 文件夹图标 */}
<div className="shrink-0">
<Fd className="text-gray-600" size={24} />
<Fd className="text-gray-600" size="md" />
</div>
{/* 文件夹信息 */}
<div className="flex-1">

View File

@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import { LinkButton, CircleToggleButton, LightButton } from "@/components/ui/buttons";
import { LinkButton, CircleToggleButton, LightButton } from "@/design-system/base/button";
import { useAudioPlayer } from "@/hooks/useAudioPlayer";
import { getTTSUrl, TTS_SUPPORTED_LANGUAGES } from "@/lib/bigmodel/tts";
import { useTranslations } from "next-intl";
@@ -29,7 +29,7 @@ const Memorize: React.FC<MemorizeProps> = ({ textPairs }) => {
if (textPairs.length === 0) {
return (
<PageLayout maxWidth="md">
<PageLayout>
<p className="text-gray-700 text-center">{t("noTextPairs")}</p>
</PageLayout>
);

View File

@@ -1,6 +1,6 @@
import { useState, useRef, forwardRef, useEffect, useCallback } from "react";
import { SubtitleDisplay } from "./SubtitleDisplay";
import { LightButton } from "@/components/ui/buttons";
import { LightButton } from "@/design-system/base/button";
import { RangeInput } from "@/components/ui/RangeInput";
import { getIndex, parseSrt, getNearistIndex } from "../subtitle";
import { useTranslations } from "next-intl";

View File

@@ -1,7 +1,7 @@
"use client";
import React, { useRef } from "react";
import { Button } from "@/components/ui/Button";
import { Button } from "@/design-system/base/button";
import { FileInputProps } from "../../types/controls";
interface FileInputComponentProps extends FileInputProps {

View File

@@ -2,7 +2,7 @@
import React from "react";
import { useTranslations } from "next-intl";
import { LightButton } from "@/components/ui/buttons";
import { LightButton } from "@/design-system/base/button";
import { PlayButtonProps } from "../../types/player";
export function PlayButton({ isPlaying, onToggle, disabled, className }: PlayButtonProps) {

View File

@@ -1,7 +1,7 @@
"use client";
import React from "react";
import { LightButton } from "@/components/ui/buttons";
import { LightButton } from "@/design-system/base/button";
import { SpeedControlProps } from "../../types/player";
import { getPlaybackRateOptions, getPlaybackRateLabel } from "../../utils/timeUtils";

View File

@@ -3,7 +3,7 @@
import React from "react";
import { useTranslations } from "next-intl";
import { ChevronLeft, ChevronRight, RotateCcw, Pause } from "lucide-react";
import { LightButton } from "@/components/ui/buttons";
import { LightButton } from "@/design-system/base/button";
import { ControlBarProps } from "../../types/controls";
import { PlayButton } from "../atoms/PlayButton";
import { SpeedControl } from "../atoms/SpeedControl";

View File

@@ -4,7 +4,7 @@ import React from "react";
import { useTranslations } from "next-intl";
import { toast } from "sonner";
import { Video, FileText } from "lucide-react";
import { LightButton } from "@/components/ui/buttons";
import { LightButton } from "@/design-system/base/button";
import { FileUploadProps } from "../../types/controls";
import { useFileUpload } from "../../hooks/useFileUpload";

View File

@@ -15,7 +15,7 @@ import { SubtitleArea } from "./components/compounds/SubtitleArea";
import { ControlBar } from "./components/compounds/ControlBar";
import { UploadZone } from "./components/compounds/UploadZone";
import { SeekBar } from "./components/atoms/SeekBar";
import { LightButton } from "@/components/ui/buttons";
import { LightButton } from "@/design-system/base/button";
export default function SrtPlayerPage() {
const t = useTranslations("home");
@@ -119,7 +119,7 @@ export default function SrtPlayerPage() {
</div>
{/* 视频播放器区域 */}
<div className="aspect-video bg-black relative rounded-xl overflow-hidden">
<div className="aspect-video bg-black relative rounded-md overflow-hidden">
{(!state.video.url || !state.subtitle.url || state.subtitle.data.length === 0) && (
<div className="absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-75 z-10">
<div className="text-center text-white">

View File

@@ -6,7 +6,7 @@ import {
TextSpeakerArraySchema,
TextSpeakerItemSchema,
} from "@/lib/interfaces";
import { IconClick } from "@/components/ui/buttons";
import { IconClick } from "@/design-system/base/button";
import { IMAGES } from "@/config/images";
import { useTranslations } from "next-intl";
import { getLocalStorageOperator } from "@/lib/browser/localStorageOperators";
@@ -24,7 +24,7 @@ function TextCard({ item, handleUse, handleDel }: TextCardProps) {
handleDel(item);
};
return (
<div className="p-2 border-b border-gray-200 rounded-2xl bg-gray-100 m-2 grid grid-cols-8">
<div className="p-2 border-b border-gray-200 rounded-lg bg-gray-100 m-2 grid grid-cols-8">
<div className="col-span-7" onClick={onUseClick}>
<div className="max-h-26 hover:cursor-pointer text-3xl overflow-y-auto">
{item.text}
@@ -39,7 +39,7 @@ function TextCard({ item, handleUse, handleDel }: TextCardProps) {
alt="delete"
onClick={onDelClick}
className="place-self-center"
size={42}
size="lg"
></IconClick>
</div>
</div>
@@ -81,7 +81,7 @@ export function SaveList({ show = false, handleUse }: SaveListProps) {
if (show)
return (
<div
className="my-4 p-2 mx-4 md:mx-32 border border-gray-200 rounded-2xl"
className="my-4 p-2 mx-4 md:mx-32 border border-gray-200 rounded-lg"
style={{ fontFamily: "Times New Roman, serif" }}
>
<div className="flex flex-row justify-center gap-8 items-center">
@@ -89,14 +89,14 @@ export function SaveList({ show = false, handleUse }: SaveListProps) {
src={IMAGES.refresh}
alt="refresh"
onClick={refresh}
size={48}
size="lg"
className=""
></IconClick>
<IconClick
src={IMAGES.delete}
alt="delete"
onClick={handleDeleteAll}
size={48}
size="lg"
className=""
></IconClick>
</div>

View File

@@ -1,7 +1,7 @@
"use client";
import { LightButton } from "@/components/ui/buttons";
import { IconClick } from "@/components/ui/buttons";
import { LightButton } from "@/design-system/base/button";
import { IconClick } from "@/design-system/base/button";
import { IMAGES } from "@/config/images";
import { useAudioPlayer } from "@/hooks/useAudioPlayer";
import {
@@ -222,7 +222,7 @@ export default function TextSpeakerPage() {
<PageLayout className="items-start py-4">
{/* 文本输入区域 */}
<div
className="border border-gray-200 rounded-2xl"
className="border border-gray-200 rounded-lg"
style={{ fontFamily: "Times New Roman, serif" }}
>
{/* 文本输入框 */}
@@ -242,37 +242,37 @@ export default function TextSpeakerPage() {
<div className="p-4 relative w-full flex flex-row flex-wrap gap-2 justify-center items-center">
{/* 速度调节面板 */}
{showSpeedAdjust && (
<div className="bg-white p-6 rounded-2xl border-gray-200 border-2 shadow-2xl absolute left-1/2 -translate-x-1/2 -translate-y-full -top-4 flex flex-row flex-wrap gap-2 justify-center items-center z-10">
<div className="bg-white p-6 rounded-lg border-gray-200 border-2 shadow-2xl absolute left-1/2 -translate-x-1/2 -translate-y-full -top-4 flex flex-row flex-wrap gap-2 justify-center items-center z-10">
<IconClick
size={45}
size="lg"
onClick={letMeSetSpeed(0.5)}
src={IMAGES.speed_0_5x}
alt="0.5x"
className={speed === 0.5 ? "bg-gray-200" : ""}
></IconClick>
<IconClick
size={45}
size="lg"
onClick={letMeSetSpeed(0.7)}
src={IMAGES.speed_0_7x}
alt="0.7x"
className={speed === 0.7 ? "bg-gray-200" : ""}
></IconClick>
<IconClick
size={45}
size="lg"
onClick={letMeSetSpeed(1)}
src={IMAGES.speed_1x}
alt="1x"
className={speed === 1 ? "bg-gray-200" : ""}
></IconClick>
<IconClick
size={45}
size="lg"
onClick={letMeSetSpeed(1.2)}
src={IMAGES.speed_1_2_x}
alt="1.2x"
className={speed === 1.2 ? "bg-gray-200" : ""}
></IconClick>
<IconClick
size={45}
size="lg"
onClick={letMeSetSpeed(1.5)}
src={IMAGES.speed_1_5x}
alt="1.5x"
@@ -282,7 +282,7 @@ export default function TextSpeakerPage() {
)}
{/* 播放/暂停按钮 */}
<IconClick
size={45}
size="lg"
onClick={speak}
src={pause ? IMAGES.play_arrow : IMAGES.pause}
alt="playorpause"
@@ -290,7 +290,7 @@ export default function TextSpeakerPage() {
></IconClick>
{/* 自动暂停按钮 */}
<IconClick
size={45}
size="lg"
onClick={() => {
setAutopause(!autopause);
if (objurlRef) {
@@ -303,7 +303,7 @@ export default function TextSpeakerPage() {
></IconClick>
{/* 速度调节按钮 */}
<IconClick
size={45}
size="lg"
onClick={() => setShowSpeedAdjust(!showSpeedAdjust)}
src={IMAGES.speed}
alt="speed"
@@ -311,7 +311,7 @@ export default function TextSpeakerPage() {
></IconClick>
{/* 保存按钮 */}
<IconClick
size={45}
size="lg"
onClick={save}
src={IMAGES.save}
alt="save"
@@ -338,7 +338,7 @@ export default function TextSpeakerPage() {
</div>
{/* 保存列表 */}
{showSaveList && (
<div className="mt-4 border border-gray-200 rounded-2xl overflow-hidden">
<div className="mt-4 border border-gray-200 rounded-lg overflow-hidden">
<SaveList show={showSaveList} handleUse={handleUseItem}></SaveList>
</div>
)}

View File

@@ -1,7 +1,6 @@
"use client";
import { LightButton, PrimaryButton } from "@/components/ui/buttons";
import { IconClick } from "@/components/ui/buttons";
import { LightButton, PrimaryButton, IconClick } from "@/design-system/base/button";
import { IMAGES } from "@/config/images";
import { useAudioPlayer } from "@/hooks/useAudioPlayer";
import { useTranslations } from "next-intl";
@@ -101,7 +100,7 @@ export default function TranslatorPage() {
{/* Card Component - Left Side */}
<div className="w-full md:w-1/2 flex flex-col-reverse gap-2">
{/* ICard1 Component */}
<div className="border border-gray-200 rounded-2xl w-full h-64 p-2">
<div className="border border-gray-200 rounded-lg w-full h-64 p-2">
<textarea
className="resize-none h-8/12 w-full focus:outline-0"
ref={taref}
@@ -147,7 +146,7 @@ export default function TranslatorPage() {
{/* Card Component - Right Side */}
<div className="w-full md:w-1/2 flex flex-col-reverse gap-2">
{/* ICard2 Component */}
<div className="bg-gray-100 rounded-2xl w-full h-64 p-2">
<div className="bg-gray-100 rounded-lg w-full h-64 p-2">
<div className="h-2/3 w-full overflow-y-auto">{translationResult?.translatedText || ""}</div>
<div className="ipa w-full h-1/6 overflow-y-auto text-gray-600">
{translationResult?.targetIpa || ""}
@@ -213,7 +212,8 @@ export default function TranslatorPage() {
<PrimaryButton
onClick={translate}
disabled={processing}
className="text-xl h-16 px-8"
size="lg"
className="text-xl"
>
{t("translate")}
</PrimaryButton>