refactor: Phase 6 — Migrate feature modules to SUMI tokens

- auth: Replace gray-* with muted/border tokens, text-foreground
- settings: TwoFactorSettings + NotificationSettings text-foreground
- chat: ChatInput, ConversationItem, ChatPage — text-foreground,
  remove kodo references
- player: PlayerExpanded, PlayerQueue, PlayerControls — text-foreground,
  remove cyan/magenta gradients
- playlists: All components — text-foreground for badges/headings
- tracks: TrackCard, TrackListRow — text-foreground, remove glow effects
- studio: FileGridCard — text-foreground
- library: LibraryPageGrid — remove hover-glow-cyan, shadow-card-glow-cyan
- profile: UserProfilePageHeader — text-foreground

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
senke 2026-02-12 02:06:28 +01:00
parent 3c2e3fdf4f
commit 69e40e3c04
20 changed files with 51 additions and 51 deletions

View file

@ -19,9 +19,9 @@ export const Default: Story = {
subtitle: 'Please sign in to continue',
children: (
<div className="space-y-4">
<div className="h-10 bg-gray-100 rounded w-full border border-gray-200 flex items-center px-3 text-gray-400">Email</div>
<div className="h-10 bg-gray-100 rounded w-full border border-gray-200 flex items-center px-3 text-gray-400">Password</div>
<div className="h-10 bg-primary rounded w-full flex items-center justify-center text-white">Sign In</div>
<div className="h-10 bg-muted rounded w-full border border-border flex items-center px-3 text-muted-foreground">Email</div>
<div className="h-10 bg-muted rounded w-full border border-border flex items-center px-3 text-muted-foreground">Password</div>
<div className="h-10 bg-primary rounded w-full flex items-center justify-center text-foreground">Sign In</div>
</div>
),
footerLinks: [

View file

@ -135,7 +135,7 @@ export const ChatInput: React.FC = () => {
{attachments.map((att, i) => (
<div
key={i}
className="relative group flex items-center gap-2 p-2 bg-white/5 rounded-lg border border-white/10 text-xs text-white min-w-36"
className="relative group flex items-center gap-2 p-2 bg-white/5 rounded-lg border border-white/10 text-xs text-foreground min-w-36"
>
{att.file_type.startsWith('image') ? (
<ImageIcon size={14} className="text-primary" />
@ -160,7 +160,7 @@ export const ChatInput: React.FC = () => {
type="button"
variant="ghost"
size="icon"
className="text-muted-foreground hover:text-white hover:bg-white/5"
className="text-muted-foreground hover:text-foreground hover:bg-white/5"
onClick={() => fileInputRef.current?.click()}
>
<Paperclip size={20} />
@ -172,7 +172,7 @@ export const ChatInput: React.FC = () => {
variant="ghost"
size="icon"
className={cn(
'text-muted-foreground hover:text-white hover:bg-white/5',
'text-muted-foreground hover:text-foreground hover:bg-white/5',
showEmojiPicker && 'text-muted-foreground bg-white/5',
)}
onClick={() => setShowEmojiPicker(!showEmojiPicker)}
@ -214,7 +214,7 @@ export const ChatInput: React.FC = () => {
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="Broadcast message..."
className="w-full bg-white/5 border border-white/10 rounded-xl px-4 py-2.5 text-white placeholder:text-muted-foreground/50 focus:outline-none focus:border-border/50 focus:ring-1 focus:ring-border/50 transition-all font-mono text-sm"
className="w-full bg-white/5 border border-white/10 rounded-xl px-4 py-2.5 text-foreground placeholder:text-muted-foreground/50 focus:outline-none focus:border-border/50 focus:ring-1 focus:ring-border/50 transition-all font-mono text-sm"
disabled={!currentConversationId || isUploading}
/>
{message.length === 0 && !isUploading && (
@ -222,7 +222,7 @@ export const ChatInput: React.FC = () => {
type="button"
variant="ghost"
size="icon"
className="absolute right-1 top-1/2 -translate-y-1/2 h-8 w-8 text-muted-foreground/30 hover:text-white"
className="absolute right-1 top-1/2 -translate-y-1/2 h-8 w-8 text-muted-foreground/30 hover:text-foreground"
>
<Mic className="w-4 h-4" />
</Button>

View file

@ -131,7 +131,7 @@ export function ConversationItem({
'w-8 h-8 rounded-lg flex items-center justify-center transition-colors shrink-0',
isSelected
? 'bg-primary text-foreground'
: 'bg-white/5 text-muted-foreground group-hover:text-white',
: 'bg-white/5 text-muted-foreground group-hover:text-foreground',
)}
>
<Hash size={14} />
@ -167,7 +167,7 @@ export function ConversationItem({
size="sm"
className={cn(
'h-6 w-6 p-0 opacity-0 group-hover:opacity-100 transition-opacity shrink-0',
isSelected ? 'text-primary hover:bg-primary/20' : 'text-muted-foreground hover:text-white',
isSelected ? 'text-primary hover:bg-primary/20' : 'text-muted-foreground hover:text-foreground',
)}
>
<MoreVertical className="h-4 w-4" />

View file

@ -53,7 +53,7 @@ export const ChatPage: React.FC = () => {
<div className="flex flex-col items-center justify-center h-layout-chat">
<Card variant="glass" className="p-8 text-center max-w-md border-primary/20">
<AlertCircle className="w-12 h-12 text-primary mx-auto mb-4 opacity-50" />
<h2 className="text-xl font-bold text-white mb-2">Access Restricted</h2>
<h2 className="text-xl font-bold text-foreground mb-2">Access Restricted</h2>
<p className="mb-6 text-muted-foreground">Encrypted channel access requires authorization.</p>
<Button onClick={() => (window.location.href = '/login')}>Initialize Handshake</Button>
</Card>
@ -76,7 +76,7 @@ export const ChatPage: React.FC = () => {
<div className="flex flex-col items-center justify-center h-layout-chat">
<Card variant="glass" className="p-8 text-center max-w-md border-destructive/30">
<AlertCircle className="w-12 h-12 text-destructive mb-4" />
<h2 className="text-xl font-bold text-white mb-2">Connection Terminated</h2>
<h2 className="text-xl font-bold text-foreground mb-2">Connection Terminated</h2>
<p className="text-destructive/80 mb-4">{(tokenError as any).message || 'Secure handshake failed.'}</p>
<Button variant="outline" onClick={() => window.location.reload()}>Retry Connection</Button>
</Card>

View file

@ -37,9 +37,9 @@ export function LibraryPageGrid({
tabIndex={0}
role="button"
className={cn(
'group relative aspect-[4/5] overflow-hidden cursor-pointer hover:-translate-y-2 transition-all duration-[var(--duration-normal)] border-white/5 bg-black/20 backdrop-blur-xl hover-glow-cyan focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background',
'group relative aspect-[4/5] overflow-hidden cursor-pointer hover:-translate-y-2 transition-all duration-[var(--duration-normal)] border-white/5 bg-black/20 backdrop-blur-xl focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background',
isSelected
? 'border-primary ring-1 ring-primary shadow-card-glow-cyan'
? 'border-primary ring-1 ring-primary'
: 'hover:border-primary/30'
)}
onClick={() => onToggleSelection(track.id)}
@ -49,7 +49,7 @@ export function LibraryPageGrid({
{isSelected ? (
<CheckCircle2 className="w-6 h-6 text-primary fill-background drop-shadow-md" />
) : (
<Circle className="w-6 h-6 text-white/70 hover:text-white drop-shadow-md" />
<Circle className="w-6 h-6 text-white/70 hover:text-foreground drop-shadow-md" />
)}
</div>
<div className="h-3/5 w-full bg-gradient-to-br from-background to-black/40 flex items-center justify-center relative group-hover:from-background/80 group-hover:to-black/60 transition-all">
@ -70,7 +70,7 @@ export function LibraryPageGrid({
}}
className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-all duration-[var(--duration-normal)] scale-90 group-hover:scale-100 focus:opacity-100 focus:scale-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-inset"
>
<div className="w-14 h-14 rounded-full bg-primary text-primary-foreground flex items-center justify-center shadow-button-primary-glow hover:scale-110 transition-transform duration-[var(--duration-fast)]">
<div className="w-14 h-14 rounded-full bg-primary text-primary-foreground flex items-center justify-center hover:scale-110 transition-transform duration-[var(--duration-fast)]">
<Play className="w-6 h-6 ml-1 fill-current" />
</div>
</button>

View file

@ -50,7 +50,7 @@ export const Active: Story = {
<>
<StoreInitializer active={true} />
<div className="min-h-screen bg-gray-900 relative p-10">
<div className="mb-20 text-white">Main Content Area</div>
<div className="mb-20 text-foreground">Main Content Area</div>
<Story />
</div>
</>
@ -64,7 +64,7 @@ export const Idle: Story = {
<>
<StoreInitializer active={false} />
<div className="min-h-screen bg-gray-900 relative p-10">
<div className="mb-20 text-white">Main Content Area</div>
<div className="mb-20 text-foreground">Main Content Area</div>
<Story />
</div>
</>

View file

@ -47,7 +47,7 @@ export function PlayerControls({
size,
shuffle
? "text-primary bg-primary/10 shadow-queue-item-current"
: "text-muted-foreground hover:text-white hover:bg-white/5"
: "text-muted-foreground hover:text-foreground hover:bg-white/5"
)}
>
<Shuffle className={cn("w-4 h-4", isExpanded && "w-5 h-5")} />
@ -56,7 +56,7 @@ export function PlayerControls({
<button
onClick={onPrevious}
className={cn(iconBtnClass, size, "text-white hover:text-primary hover:bg-white/5")}
className={cn(iconBtnClass, size, "text-foreground hover:text-primary hover:bg-white/5")}
>
<SkipBack className={cn(iconSize, "fill-current")} />
</button>
@ -77,7 +77,7 @@ export function PlayerControls({
<button
onClick={onNext}
className={cn(iconBtnClass, size, "text-white hover:text-primary hover:bg-white/5")}
className={cn(iconBtnClass, size, "text-foreground hover:text-primary hover:bg-white/5")}
>
<SkipForward className={cn(iconSize, "fill-current")} />
</button>
@ -91,7 +91,7 @@ export function PlayerControls({
"relative",
repeat !== 'off'
? "text-primary bg-primary/10 shadow-queue-item-current"
: "text-muted-foreground hover:text-white hover:bg-white/5"
: "text-muted-foreground hover:text-foreground hover:bg-white/5"
)}
>
<Repeat className={cn("w-4 h-4", isExpanded && "w-5 h-5")} />

View file

@ -67,11 +67,11 @@ export function PlayerExpanded({ isOpen, onClose, currentTime, duration, onSeek,
{/* Header */}
<div className="relative z-10 flex items-center justify-between p-6">
<Button variant="ghost" className="text-white hover:bg-white/10 rounded-full" onClick={onClose}>
<Button variant="ghost" className="text-foreground hover:bg-white/10 rounded-full" onClick={onClose}>
<ChevronDown className="w-6 h-6" />
</Button>
<span className="text-xs font-bold tracking-widest uppercase text-white/50">Following the Signal</span>
<Button variant="ghost" className="text-white hover:bg-white/10 rounded-full">
<Button variant="ghost" className="text-foreground hover:bg-white/10 rounded-full">
<MoreHorizontal className="w-6 h-6" />
</Button>
</div>
@ -86,7 +86,7 @@ export function PlayerExpanded({ isOpen, onClose, currentTime, duration, onSeek,
"relative group transition-all duration-[var(--duration-slow)]",
showLyrics ? "w-full max-w-md md:max-w-sm aspect-square" : "w-full max-w-md md:max-w-xl aspect-square"
)}>
<div className="absolute inset-0 bg-gradient-to-br from-cyan-500/20 to-magenta-500/20 rounded-xl blur-2xl transform group-hover:scale-105 transition-transform duration-700" />
<div className="absolute inset-0 bg-gradient-to-br from-primary/20 to-secondary/20 rounded-xl blur-2xl transform group-hover:scale-105 transition-transform duration-700" />
<img
src={currentTrack.cover || '/placeholder.svg'}
alt={currentTrack.title}
@ -99,7 +99,7 @@ export function PlayerExpanded({ isOpen, onClose, currentTime, duration, onSeek,
<div className="flex items-end justify-between">
<div className="space-y-2">
<h2 className="text-4xl md:text-5xl font-heading font-bold text-white leading-tight">
<h2 className="text-4xl md:text-5xl font-heading font-bold text-foreground leading-tight">
{currentTrack.title}
</h2>
<p className="text-xl md:text-2xl text-muted-foreground font-medium">
@ -165,14 +165,14 @@ export function PlayerExpanded({ isOpen, onClose, currentTime, duration, onSeek,
</div>
<div className="flex items-center gap-4">
<Button size="icon" variant="ghost" className="text-muted-foreground hover:text-white">
<Button size="icon" variant="ghost" className="text-muted-foreground hover:text-foreground">
<Share2 className="w-5 h-5" />
</Button>
<Tooltip content={showLyrics ? "Hide lyrics" : "Show lyrics"}>
<Button
size="icon"
variant="ghost"
className={cn("transition-colors", showLyrics ? "text-primary" : "text-muted-foreground hover:text-white")}
className={cn("transition-colors", showLyrics ? "text-primary" : "text-muted-foreground hover:text-foreground")}
onClick={() => setShowLyrics(!showLyrics)}
>
<Mic2 className="w-5 h-5" />
@ -217,8 +217,8 @@ export function PlayerExpanded({ isOpen, onClose, currentTime, duration, onSeek,
<p
key={i}
className={cn(
"text-xl md:text-2xl font-bold transition-all duration-[var(--duration-slow)] cursor-pointer hover:text-white",
isActive ? "text-white scale-105" : "text-white/20"
"text-xl md:text-2xl font-bold transition-all duration-[var(--duration-slow)] cursor-pointer hover:text-foreground",
isActive ? "text-foreground scale-105" : "text-white/20"
)}
onClick={() => onSeek(line.time)}
>

View file

@ -33,7 +33,7 @@ export function PlayerQueue({ isOpen, onClose, currentTrackId, onPlay }: PlayerQ
{/* Header */}
<div className="flex items-center justify-between p-4 border-b border-white/5 bg-white/5">
<div className="flex items-center gap-2">
<h3 className="text-white font-bold font-heading tracking-wide">Play Queue</h3>
<h3 className="text-foreground font-bold font-heading tracking-wide">Play Queue</h3>
<Badge variant="outline" className="border-primary/20 text-primary bg-primary/10">
{queue.length} Tracks
</Badge>
@ -41,13 +41,13 @@ export function PlayerQueue({ isOpen, onClose, currentTrackId, onPlay }: PlayerQ
<div className="flex items-center gap-2">
<button
onClick={clearQueue}
className="px-3 py-1.5 text-xs text-muted-foreground hover:text-white hover:bg-white/10 rounded-md transition-colors duration-[var(--duration-fast)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background"
className="px-3 py-1.5 text-xs text-muted-foreground hover:text-foreground hover:bg-white/10 rounded-md transition-colors duration-[var(--duration-fast)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background"
>
Clear
</button>
<button
onClick={onClose}
className="p-1.5 text-muted-foreground hover:text-white hover:bg-white/10 rounded-full transition-colors duration-[var(--duration-fast)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background"
className="p-1.5 text-muted-foreground hover:text-foreground hover:bg-white/10 rounded-full transition-colors duration-[var(--duration-fast)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background"
>
<X className="w-5 h-5" />
</button>
@ -103,7 +103,7 @@ export function PlayerQueue({ isOpen, onClose, currentTrackId, onPlay }: PlayerQ
>
<h4 className={cn(
"text-sm font-medium truncate transition-colors",
isCurrent ? "text-primary" : "text-white group-hover:text-white"
isCurrent ? "text-primary" : "text-foreground group-hover:text-foreground"
)}>
{track.title}
</h4>

View file

@ -99,7 +99,7 @@ function PlaylistCardComponent({
'touch-manipulation min-h-6 min-w-6',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background',
selected
? 'bg-primary border-primary text-white'
? 'bg-primary border-primary text-foreground'
: 'bg-white/90 dark:bg-muted/90 border-border dark:border-border text-transparent hover:border-border/50',
)}
aria-label={
@ -118,7 +118,7 @@ function PlaylistCardComponent({
<div className="absolute top-2 right-2">
{playlist.is_public ? (
<div
className="bg-success/80 text-white px-2 py-1 rounded-full text-xs flex items-center gap-1"
className="bg-success/80 text-foreground px-2 py-1 rounded-full text-xs flex items-center gap-1"
aria-label="Playlist publique"
>
<Users className="w-3 h-3" aria-hidden="true" />
@ -126,7 +126,7 @@ function PlaylistCardComponent({
</div>
) : (
<div
className="bg-muted/80 text-white px-2 py-1 rounded-full text-xs flex items-center gap-1"
className="bg-muted/80 text-foreground px-2 py-1 rounded-full text-xs flex items-center gap-1"
aria-label="Playlist privée"
>
<Lock className="w-3 h-3" aria-hidden="true" />

View file

@ -53,7 +53,7 @@ export function PlaylistHeader({ playlist, className }: PlaylistHeaderProps) {
<div className="absolute top-3 right-3">
{playlist.is_public ? (
<div
className="bg-success/90 text-white px-4 py-1.5 rounded-full text-sm flex items-center gap-2"
className="bg-success/90 text-foreground px-4 py-1.5 rounded-full text-sm flex items-center gap-2"
aria-label="Playlist publique"
>
<Users className="w-4 h-4" aria-hidden="true" />
@ -61,7 +61,7 @@ export function PlaylistHeader({ playlist, className }: PlaylistHeaderProps) {
</div>
) : (
<div
className="bg-muted/90 text-white px-4 py-1.5 rounded-full text-sm flex items-center gap-2"
className="bg-muted/90 text-foreground px-4 py-1.5 rounded-full text-sm flex items-center gap-2"
aria-label="Playlist privée"
>
<Lock className="w-4 h-4" aria-hidden="true" />

View file

@ -127,7 +127,7 @@ export function PlaylistTrackItem({
{/* Track Info - Mobile optimized */}
<div className="flex-1 min-w-0">
<div className="font-medium text-sm sm:text-base text-foreground dark:text-white truncate">
<div className="font-medium text-sm sm:text-base text-foreground dark:text-foreground truncate">
{track.title}
</div>
<div className="text-xs sm:text-sm text-muted-foreground dark:text-muted-foreground truncate">

View file

@ -123,7 +123,7 @@ export function PlaylistListPage() {
<Filter className="mr-2 h-4 w-4" />
Filters
{hasActiveFilters && (
<span className="ml-2 bg-primary text-white rounded-full px-2 py-0.5 text-xs">
<span className="ml-2 bg-primary text-foreground rounded-full px-2 py-0.5 text-xs">
Active
</span>
)}

View file

@ -48,7 +48,7 @@ export function PlaylistDetailPageCoverAndInfo({ playlist }: PlaylistDetailPageC
</span>
</div>
<h1 className="text-4xl md:text-6xl font-heading font-bold text-white mb-4 tracking-tight drop-shadow-lg">
<h1 className="text-4xl md:text-6xl font-heading font-bold text-foreground mb-4 tracking-tight drop-shadow-lg">
{playlist.title}
</h1>

View file

@ -114,7 +114,7 @@ export function UserProfilePageHeader({
className="w-4 h-4 mx-auto mb-1.5 text-muted-foreground group-hover/stat:text-primary transition-colors duration-[var(--duration-fast)]"
aria-hidden
/>
<AnimatedNumber value={stat.value} className="text-2xl font-bold font-heading text-white" />
<AnimatedNumber value={stat.value} className="text-2xl font-bold font-heading text-foreground" />
<div className="text-xs uppercase tracking-wider text-muted-foreground font-bold">
{stat.label}
</div>

View file

@ -22,7 +22,7 @@ const meta = {
},
decorators: [
(Story) => (
<div className="max-w-xl mx-auto p-6 border rounded-lg bg-white dark:bg-card dark:text-white">
<div className="max-w-xl mx-auto p-6 border rounded-lg bg-white dark:bg-card dark:text-foreground">
<Story />
</div>
),

View file

@ -63,7 +63,7 @@ export const TwoFactorSettings: React.FC = () => {
<div className="flex items-center gap-3 p-4 bg-success/10 border border-success/20 rounded-lg">
<ShieldCheck className="h-8 w-8 text-success" />
<div>
<h4 className="font-bold text-white">2FA is enabled</h4>
<h4 className="font-bold text-foreground">2FA is enabled</h4>
<p className="text-xs text-muted-foreground">Your account is protected by an additional security layer.</p>
</div>
</div>
@ -82,7 +82,7 @@ export const TwoFactorSettings: React.FC = () => {
<div className="flex items-center gap-3 p-4 bg-orange-500/5 border border-orange-500/10 rounded-lg">
<ShieldAlert className="h-8 w-8 text-orange-500" />
<div>
<h4 className="font-bold text-white">2FA is not enabled</h4>
<h4 className="font-bold text-foreground">2FA is not enabled</h4>
<p className="text-xs text-muted-foreground">We highly recommend enabling 2FA to protect your music and assets.</p>
</div>
</div>

View file

@ -84,7 +84,7 @@ export function FileGridCard({
</div>
<div className="w-full min-w-0">
<h4
className="font-bold text-white text-sm truncate w-full"
className="font-bold text-foreground text-sm truncate w-full"
title={file.name}
>
{file.name}

View file

@ -155,7 +155,7 @@ function TrackCardComponent({
size="icon"
showCount={false}
compact
className="text-white hover:text-destructive"
className="text-foreground hover:text-destructive"
/>
<button
aria-label={`Plus d'options pour ${track.title}`}
@ -166,7 +166,7 @@ function TrackCardComponent({
onMore?.(track);
}
}}
className="text-white hover:text-primary transition-colors duration-[var(--duration-normal)] p-1 focus:outline-none focus:ring-2 focus:ring-primary rounded-full"
className="text-foreground hover:text-primary transition-colors duration-[var(--duration-normal)] p-1 focus:outline-none focus:ring-2 focus:ring-primary rounded-full"
>
<span aria-hidden="true"></span>
<span className="sr-only">Plus d'options</span>

View file

@ -163,7 +163,7 @@ export function TrackListRow({
<button
onClick={handlePlay}
aria-label={isPlaying ? 'Mettre en pause' : 'Lire'}
className="text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-sm"
className="text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-sm"
>
{PlayIcon}
</button>
@ -253,7 +253,7 @@ export function TrackListRow({
<button
aria-label={isPlaying ? 'Mettre en pause' : 'Lire'}
onClick={handlePlay}
className="text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-sm"
className="text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-sm"
>
{PlayIcon}
</button>