Files
TUIkit/docs/app/components/Icon.tsx
T
phranck bdb6d0c3f9 Chore: Fourth-pass optimization — bug fix, auto test counts, ESLint clean, constant extraction
- Fix: parseTerminalFormatting used undefined 'key' instead of 'partKey' (TS error)
- Fix: ESLint setState-in-effect errors (4→0) via cleanup patterns and hydration-sync
- Feat: Auto test/suite counts from Swift project at build-time (prebuild script + env vars)
- Refactor: ArchHighlight sub-component eliminates 4× duplicated pattern in page.tsx
- Refactor: BTN_PRIMARY/BTN_SECONDARY constants replace duplicated button classes
- Refactor: CRT geometry object centralizes repeated calc() layer positions
- Refactor: 13 magic numbers → named constants in TerminalScreen (timings, delays)
- Refactor: Icon component extended with custom SVG support (copy icon)
- Refactor: cloudGradient() helper replaces 6× duplicated radial-gradient strings
- Refactor: HIGHLIGHT constants object for syntax highlighter colors
- Refactor: text-glow CSS utility replaces duplicated textShadow inline styles
2026-02-02 15:38:33 +01:00

79 lines
2.0 KiB
TypeScript

"use client";
import {
SFSymbol,
SFAppleTerminalFill,
SFPaintbrushFill,
SFKeyboardFill,
SFSquareStack3dUpFill,
SFBoltFill,
SFDocumentFill,
SFEyeFill,
SFArrowLeftArrowRight,
SFSwift,
SFCheckmarkCircleFill,
SFBookFill,
SFChevronLeftForwardslashChevronRight,
} from "sf-symbols-lib/hierarchical";
/** Maps of icon names to SF Symbol constants for type-safe usage. */
const sfIcons = {
terminal: SFAppleTerminalFill,
paintbrush: SFPaintbrushFill,
keyboard: SFKeyboardFill,
stack: SFSquareStack3dUpFill,
bolt: SFBoltFill,
document: SFDocumentFill,
eye: SFEyeFill,
arrows: SFArrowLeftArrowRight,
swift: SFSwift,
checkmark: SFCheckmarkCircleFill,
book: SFBookFill,
code: SFChevronLeftForwardslashChevronRight,
} as const;
/** Custom SVG icons not available in SF Symbols. */
const customIcons = {
/** Two overlapping rectangles — standard copy-to-clipboard metaphor. */
copy: (size: number) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={size}
height={size}
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
</svg>
),
} as const;
export type IconName = keyof typeof sfIcons | keyof typeof customIcons;
interface IconProps {
name: IconName;
size?: number;
className?: string;
}
/** Decorative icon wrapper — hidden from screen readers since adjacent text conveys meaning. */
export default function Icon({ name, size = 20, className }: IconProps) {
if (name in customIcons) {
return (
<span aria-hidden="true" className={className}>
{customIcons[name as keyof typeof customIcons](size)}
</span>
);
}
return (
<span aria-hidden="true">
<SFSymbol name={sfIcons[name as keyof typeof sfIcons]} size={size} className={className} />
</span>
);
}