From f069eef8a8ad17d7c13a0d8019fcc3f748422205 Mon Sep 17 00:00:00 2001 From: devilreef Date: Thu, 30 Apr 2026 09:34:49 +0600 Subject: [PATCH] feat(frontend): add Tape presentational component --- frontend/src/components/Tape.tsx | 30 +++++++++++++++++++++++++ frontend/src/styles/components/tape.css | 23 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 frontend/src/components/Tape.tsx create mode 100644 frontend/src/styles/components/tape.css diff --git a/frontend/src/components/Tape.tsx b/frontend/src/components/Tape.tsx new file mode 100644 index 0000000..c154e6c --- /dev/null +++ b/frontend/src/components/Tape.tsx @@ -0,0 +1,30 @@ +import type { Station } from '@lib/types'; + +interface Props { + station: Station; + index: number; + active: boolean; + onSelect: (id: string) => void; + listeners?: number | null; +} + +export function Tape({ station, index, active, onSelect, listeners }: Props) { + return ( + + ); +} diff --git a/frontend/src/styles/components/tape.css b/frontend/src/styles/components/tape.css new file mode 100644 index 0000000..db5cdcb --- /dev/null +++ b/frontend/src/styles/components/tape.css @@ -0,0 +1,23 @@ +.tape { + font-family: var(--f-mono); + background: var(--cream); color: var(--ink); + padding: 10px 12px 12px; + border: 2px solid var(--ink); + box-shadow: 3px 3px 0 var(--ink); + cursor: pointer; text-align: left; + transition: transform 120ms ease-out, box-shadow 120ms ease-out; + width: 100%; +} +.tape:hover { transform: translate(-2px,-2px); box-shadow: 5px 5px 0 var(--ink); } +.tape.active { + background: var(--pink); color: var(--cream); + transform: translate(-3px,-3px) rotate(-1deg); + box-shadow: 6px 6px 0 var(--lemon); +} +.tape-num { font-family: var(--f-mono); font-size: 10px; opacity: 0.65; letter-spacing: 1.5px; } +.tape-name { font-family: var(--f-pixel); font-size: 16px; line-height: 1.1; margin-top: 2px; } +.tape-jp { font-family: var(--f-pixel); font-size: 11px; opacity: 0.85; letter-spacing: 1.5px; margin-top: 2px; } +.tape-meta { font-family: var(--f-mono); font-size: 10px; margin-top: 6px; display: flex; justify-content: space-between; opacity: 0.75; } +.tape-holes { display: flex; gap: 4px; margin-top: 6px; } +.tape-holes span { width: 14px; height: 14px; border-radius: 50%; background: var(--ink); box-shadow: inset 0 0 0 3px var(--cream); } +.tape.active .tape-holes span { box-shadow: inset 0 0 0 3px var(--pink); }