Replace legacy hardcoded bg-kodo-steel (RGB 59,69,84, theme-unaware)
with semantic bg-muted token across 46 user-facing components.
This completes the kodo-steel elimination from source files: text, border,
and background variants are now all on semantic design system tokens.
Co-authored-by: Cursor <cursoragent@cursor.com>
Eliminate all remaining text-kodo-content-dim from user-facing source files.
This legacy token (hardcoded Gray-400) is now fully replaced by the
theme-aware text-muted-foreground token across UI primitives, settings,
social features, playlists, modals, inventory, and admin views.
Only story files (.stories.tsx) retain the old token for reference.
Total migration: ~345 instances across 87 files (this + previous commit).
Co-authored-by: Cursor <cursoragent@cursor.com>
Ensure smooth hover background transitions on interactive elements that
were snapping instead of transitioning:
- QueuePanel: queue list items now smooth-transition on hover
- Header: mobile sidebar toggle button smooth-transitions on hover
Co-authored-by: Cursor <cursoragent@cursor.com>
SearchPageResults: add tabIndex, role="button", focus-visible ring, and
onKeyDown (Enter/Space) to all interactive Card elements across all tabs.
UserCard: convert clickable div/h3 to semantic <button> elements with
focus-visible ring. Migrate hardcoded text-white/text-kodo-content-dim
to design system tokens (text-foreground/text-muted-foreground).
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace hardcoded red-500/red-400 color references with the semantic
`destructive` design token. This ensures error and danger states adapt
correctly to theme changes and maintain consistency across the UI.
Files: PlayerExpanded, PlayerQueue, WebhooksView, RolesPage, ChatPage,
AdminDashboardStatCard, NotificationsViewItem/Header, AnalyticsViewTopTracks,
AdminDashboardTabs, AdminDashboardHeader.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace bare text "No X found" messages with the shared EmptyState
component (icon + title + description + optional action). This gives
empty moments a designed, intentional feel instead of a raw fallback.
- EmptyState: use design system tokens (text-foreground, text-muted-foreground)
- MarketplaceHome: EmptyState with ShoppingBag icon
- MarketplaceViewGrid: EmptyState with clear filters action
- ProfileViewTracksTab: EmptyState with Music icon
- ProfileViewPlaylistsTab: EmptyState with ListMusic icon
- PurchasesViewList: EmptyState with ShoppingCart icon
- SessionManagement: centered empty text with padding
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace raw `animate-pulse bg-muted` divs with the `<Skeleton>` component
across all major page and section skeletons. Every loading state now uses
the premium sweeping shimmer animation instead of the basic pulse.
Files: TrackDetailPageSkeleton, LibraryPageSkeleton, PlaylistDetailPageSkeleton,
DiscoverViewSkeleton, PlaybackDashboardSkeleton, StudioViewSkeleton,
MonitoringDashboardSkeleton, LibraryManagerSkeleton, UploadViewSkeleton,
FileManagerViewSkeleton, TrackSearchFiltersSkeleton, TrackListPaginationSkeleton,
TrackFiltersSkeleton, TrackHistorySkeleton, PlaylistActionsSkeleton, TrackGrid.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace static animate-pulse with a sweeping gradient shimmer overlay
for a premium loading experience (Spotify/Discord-like).
Skeleton: bg-kodo-steel/50 → bg-muted/50 (design system token), adds
a child div with .skeleton-shimmer class for the gradient sweep.
index.css: add .skeleton-shimmer utility class with linear-gradient
animation (1.8s ease-in-out infinite). Respects prefers-reduced-motion
by disabling animation.
Existing inline skeletons using animate-pulse are unaffected.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Remove transition-opacity that was overriding Card's shadow/color
transitions (hover:shadow-xl was not animating)
- Add focus-visible ring to selectable wrapper and Link wrapper
- Replace ring-blue-500 (arbitrary color) with ring-primary (design system)
for selected state
Co-authored-by: Cursor <cursoragent@cursor.com>
Rewrite fixDisplayIssues.ts from 719 → 70 lines. Removed:
- Nuclear CSS injection (background-image: none !important on *,
border removal on all non-input elements, display: none on narrow
elements)
- MutationObserver watching all DOM mutations
- setInterval(1000ms) scanning every element in the document
- 50+ debug log statements
Kept: grid overlay removal (harmless), 3 opt-in diagnostic console
commands (__enableCleanMode, __disableCleanMode, __findVerticalLines).
Also reduce aggressiveVisualFix.ts to a documented no-op (was already
disabled but still contained ~190 lines of dead code).
The original vertical line issue was fixed at the CSS source
(global-effects.css gradient removal + input focus styles).
Co-authored-by: Cursor <cursoragent@cursor.com>
Remove duplicate scrollbar definitions from:
- global-effects.css: replaced cyan scrollbar block with comment pointing
to index.css as the single source
- fixDisplayIssues.ts: removed JS-injected scrollbar override that
conflicted with the CSS source of truth
The canonical scrollbar definition (6px, white/12 thumb, transparent
track) now lives exclusively in index.css @layer base.
Co-authored-by: Cursor <cursoragent@cursor.com>
DashboardLayout: add min-w-0 to flex child (prevents overflow), use
max-lg:ml-0 for responsive specificity, absolute-positioned player at
bottom of content area.
Header: bg-background/80 → bg-transparent with backdrop-blur-md for a
seamless Spotify-like header that blends with the page content below.
Co-authored-by: Cursor <cursoragent@cursor.com>
Dark mode: oklch(0.65) → oklch(0.70) — closer to Spotify/Discord secondary text.
Light mode: oklch(0.45) → oklch(0.42) — stronger contrast on white backgrounds.
Sidebar-foreground synced with muted-foreground for consistency.
Also includes previously integrated but uncommitted token work:
- Modal max-height tokens and utility classes (max-h-layout-modal*)
- Lyrics height tokens (h-layout-lyrics*)
- Responsive lg: margin-left / left utility classes for shell
- prefers-reduced-motion support for transition-shell and player-bar-entrance
- Main offset-bottom adjusted to 9rem (144px) for player clearance
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add playwright.config.storybook.ts: runs against storybook-static on :6007
- Add e2e/tests/storybook/storybook-all.spec.ts: one test per story (load iframe, no errors)
- Add scripts/serve-storybook-static.cjs: serves build or stub (empty index) when no build
- npm run test:storybook:playwright (after build-storybook) for full coverage
- Storybook decorator: use bg-background / design tokens for dark (#121212)
- Preview: default dark background #121212
- Button: secondary/ghost/glass aligned to Spotify/Discord (white/5, white/10 hover)
- KodoEmptyState: softer orbs, compact copy, primary CTA without heavy glow
Co-authored-by: Cursor <cursoragent@cursor.com>