2626 * is intentionally stateless and render-only.
2727 */
2828
29-
3029// src/components/labnotes/LabNoteCard.tsx
31- import React from "react" ;
3230import { Link } from "react-router-dom" ;
33- const { i18n } = useTranslation ( "labNotesPage" ) ;
3431import { useTranslation } from "react-i18next" ;
3532import type { LabNote } from "@/lib/labNotes" ;
3633
@@ -69,7 +66,7 @@ const allStyles: Record<string, DeptStyle> = {
6966} ;
7067
7168// 🧬 Explicitly map potential YAML names to our style keys
72- function getDeptKey ( id : string ) : string {
69+ function getDeptKey ( id ? : string ) : keyof typeof allStyles {
7370 const normalized = ( id || "scms" ) . toLowerCase ( ) ;
7471 if ( normalized === "alignment" || normalized === "coda" ) return "coda" ;
7572 if ( normalized === "shadow" || normalized === "vesper" ) return "vesper" ;
@@ -84,18 +81,21 @@ type Props = {
8481} ;
8582
8683export function LabNoteCard ( { note, index } : Props ) {
84+ const { t, i18n } = useTranslation ( "labNotesPage" ) ;
8785 const locale = i18n . language || "en" ;
88- const { t } = useTranslation ( "labNotesPage" ) ;
86+
8987 // Prefer canonical department_id; dept is optional label
90- const deptKey = ( note . dept ?? note . department_id ?? "scms" ) . toLowerCase ( ) ;
91- const style = allStyles [ deptKey ] ?? allStyles . scms ;
88+ const deptKey = getDeptKey ( note . dept ?? note . department_id ) ;
89+ const styles = allStyles [ deptKey ] ?? allStyles . scms ;
90+
9291 // Better label fallback now that type exists
9392 const tag = note . tags ?. [ 0 ] || ( note . type ? note . type . toUpperCase ( ) : "NOTE" ) ;
93+
9494 // Clamp shadow density to 0–10
9595 const shadow = Math . max ( 0 , Math . min ( 10 , Math . round ( note . shadow_density ?? 0 ) ) ) ;
96+
9697 const teaser = note . subtitle ?? note . summary ?? "" ;
97- const styles = allStyles [ deptKey ] || allStyles . scms ;
98-
98+
9999 return (
100100 < article
101101 style = { { animationDelay : `${ index * 100 } ms` , opacity : 0 } }
@@ -156,33 +156,33 @@ export function LabNoteCard({ note, index }: Props) {
156156 { /* Default: excerpt */ }
157157 < p
158158 className = "
159- text-sm text-slate-400 leading-relaxed line-clamp-3
160- transition-all duration-500 ease-out
161- group-hover:opacity-0 group-hover:-translate-y-1
162- "
159+ text-sm text-slate-400 leading-relaxed line-clamp-3
160+ transition-all duration-500 ease-out
161+ group-hover:opacity-0 group-hover:-translate-y-1
162+ "
163163 >
164164 { note . summary }
165165 </ p >
166166
167167 { /* Hover: concept signals */ }
168168 < div
169169 className = "
170- absolute inset-0
171- opacity-0 translate-y-1
172- transition-all duration-500 ease-out delay-75
173- group-hover:opacity-100 group-hover:translate-y-0
174- "
170+ absolute inset-0
171+ opacity-0 translate-y-1
172+ transition-all duration-500 ease-out delay-75
173+ group-hover:opacity-100 group-hover:translate-y-0
174+ "
175175 >
176176 < div className = "space-y-3" >
177177 < div className = "flex items-center justify-between" >
178- < span className = "text-[10px] font-mono uppercase tracking-[0.3em] text-slate-500" >
179- Concept Load
180- </ span >
178+ < span className = "text-[10px] font-mono uppercase tracking-[0.3em] text-slate-500" >
179+ Concept Load
180+ </ span >
181181
182182 { note . safer_landing && (
183183 < span className = "text-[10px] font-mono uppercase tracking-widest text-lyric/80" >
184- Safer ✓
185- </ span >
184+ Safer ✓
185+ </ span >
186186 ) }
187187 </ div >
188188
@@ -195,9 +195,13 @@ export function LabNoteCard({ note, index }: Props) {
195195 < span
196196 key = { i }
197197 className = { `
198- w-1 rounded-sm transition-all duration-500
199- ${ active ? "bg-vesper shadow-[0_0_8px_rgba(110,0,255,0.55)]" : "bg-slate-800" }
200- ` }
198+ w-1 rounded-sm transition-all duration-500
199+ ${
200+ active
201+ ? "bg-vesper shadow-[0_0_8px_rgba(110,0,255,0.55)]"
202+ : "bg-slate-800"
203+ }
204+ ` }
201205 style = { { height : `${ 6 + i } px` } }
202206 />
203207 ) ;
@@ -206,27 +210,26 @@ export function LabNoteCard({ note, index }: Props) {
206210
207211 { /* Tag pills */ }
208212 < div className = "flex flex-wrap gap-2" >
209- { ( note . tags ?? [ ] ) . slice ( 0 , 3 ) . map ( ( tag ) => (
213+ { ( note . tags ?? [ ] ) . slice ( 0 , 3 ) . map ( ( tagItem ) => (
210214 < span
211- key = { tag }
215+ key = { tagItem }
212216 className = "px-2 py-0.5 rounded border border-slate-800 bg-slate-900/40
213217 text-[10px] font-mono uppercase tracking-wider text-slate-400"
214218 >
215- { tag }
216- </ span >
219+ { tagItem }
220+ </ span >
217221 ) ) }
218222
219223 { /* fallback if tags empty */ }
220224 { ( ! note . tags || note . tags . length === 0 ) && (
221225 < span className = "text-[10px] font-mono uppercase tracking-wider text-slate-600" >
222- No tags registered
223- </ span >
226+ No tags registered
227+ </ span >
224228 ) }
225229 </ div >
226230 </ div >
227231 </ div >
228232 </ div >
229-
230233 </ div >
231234 ) }
232235 </ div >
0 commit comments