Set global icon stroke width and remove per-icon strokeWidth props

This commit is contained in:
2026-09-23 21:55:00 +02:00
parent 26bb8a50a3
commit cbbde95773
17 changed files with 27 additions and 28 deletions
+1 -1
View File
@@ -55,7 +55,7 @@ The design system lives in `src/routes/layout.css` (`@theme` tokens plus `@utili
- **Colors:** always use `--mf-*`/`text-*`/`bg-*`/`border-*` from `theme.css`/`tokens.ts`. Never a literal hex or `rgba()` inside a `.svelte` file; those literals only belong in `theme.css`/`tokens.ts` as the source of truth. - **Colors:** always use `--mf-*`/`text-*`/`bg-*`/`border-*` from `theme.css`/`tokens.ts`. Never a literal hex or `rgba()` inside a `.svelte` file; those literals only belong in `theme.css`/`tokens.ts` as the source of truth.
- **Inline `style="…"` and arbitrary `-[…]` values:** only the ones whitelisted in `scripts/check-tokens.mjs` (the stagger variable `--i`, tile hue, menu position, progress width, `text-[clamp(…)]`, `leading-[…]` on login's display type, `grid-cols-[auto_1fr]`, `max-h-[85dvh]`, `my-`/`py-[Ndvh]` for vertical centering, `transition-[filter]` on genre tiles, and `bg-[image:var(--mf-*)]`). Everything else should become a token. - **Inline `style="…"` and arbitrary `-[…]` values:** only the ones whitelisted in `scripts/check-tokens.mjs` (the stagger variable `--i`, tile hue, menu position, progress width, `text-[clamp(…)]`, `leading-[…]` on login's display type, `grid-cols-[auto_1fr]`, `max-h-[85dvh]`, `my-`/`py-[Ndvh]` for vertical centering, `transition-[filter]` on genre tiles, and `bg-[image:var(--mf-*)]`). Everything else should become a token.
- Reach for these base components before creating a new one: `Artwork`, `Avatar`, `ListRow`, `MediaIdentity`, `TrackList`, `MediaCard`, `PageHeader`, `ContextMenu`, `ConfirmDialog`, `PlayButton`, `Slider`, `Logo`, `Chip`, `SegmentedControl`, `CoverForm`. - Reach for these base components before creating a new one: `Artwork`, `Avatar`, `ListRow`, `MediaIdentity`, `TrackList`, `MediaCard`, `PageHeader`, `ContextMenu`, `ConfirmDialog`, `PlayButton`, `Slider`, `Logo`, `Chip`, `SegmentedControl`, `CoverForm`.
- Known and accepted gap (documented in `scripts/check-tokens.mjs`): icon `strokeWidth={n}` isn't unified yet. There are 13 different values spread across almost every component, and migrating them to `stroke-thin/regular/bold` recipes safely would require visually confirming that `lucide-svelte` actually respects `stroke-width` through CSS, so that was left out of the last pass. - **Icon stroke:** one global rule (`svg.lucide { stroke-width: 1.25 }` in `layout.css`) sets the stroke for every icon. Never pass `strokeWidth` to an icon, since any CSS rule overrides the SVG attribute and it would do nothing. For a different stroke on one icon, use a Tailwind `stroke-*` utility.
## Motion ## Motion
@@ -44,7 +44,7 @@
</AccountMenu> </AccountMenu>
{:else} {:else}
<IconButton href="/auth/login" reload label="Iniciar sesión" shape="round" size="md"> <IconButton href="/auth/login" reload label="Iniciar sesión" shape="round" size="md">
<LogIn class="size-icon-lg" strokeWidth={2} /> <LogIn class="size-icon-lg" />
</IconButton> </IconButton>
{/if} {/if}
</header> </header>
@@ -48,7 +48,7 @@
? 'bg-surface-2 text-fg' ? 'bg-surface-2 text-fg'
: 'text-fg-2 hover:bg-hover hover:text-fg'}" : 'text-fg-2 hover:bg-hover hover:text-fg'}"
> >
<link.icon class="size-icon-md shrink-0" strokeWidth={1.5} /> <link.icon class="size-icon-md shrink-0" />
<span class="flex-1 truncate">{link.label}</span> <span class="flex-1 truncate">{link.label}</span>
{#if link.count} {#if link.count}
<span class="text-xs text-fg-2 tabular-nums">{link.count}</span> <span class="text-xs text-fg-2 tabular-nums">{link.count}</span>
@@ -68,7 +68,7 @@
size="xs" size="xs"
onclick={() => createPlaylistModal.show()} onclick={() => createPlaylistModal.show()}
> >
<Plus class="size-icon-sm text-fg-2" strokeWidth={1.25} /> <Plus class="size-icon-sm text-fg-2" />
</IconButton> </IconButton>
{/if} {/if}
</div> </div>
@@ -93,7 +93,7 @@
onclick={() => createPlaylistModal.show()} onclick={() => createPlaylistModal.show()}
class="flex items-center gap-2 rounded-control px-3 py-2 text-xs text-fg-2 transition-colors hover:bg-hover hover:text-fg-2" class="flex items-center gap-2 rounded-control px-3 py-2 text-xs text-fg-2 transition-colors hover:bg-hover hover:text-fg-2"
> >
<Plus class="size-3.5" strokeWidth={1.8} /> <Plus class="size-3.5" />
Crear tu primera lista Crear tu primera lista
</button> </button>
{/each} {/each}
@@ -30,7 +30,7 @@
? 'text-fg' ? 'text-fg'
: 'text-fg-2'}" : 'text-fg-2'}"
> >
<link.icon class="size-4" strokeWidth={1.6} /> <link.icon class="size-4" />
<span class="text-xs font-medium">{link.label}</span> <span class="text-xs font-medium">{link.label}</span>
</a> </a>
{/each} {/each}
@@ -62,14 +62,14 @@
size="xs" size="xs"
onclick={() => history.back()} onclick={() => history.back()}
> >
<ChevronLeft class="size-icon-sm" strokeWidth={1.9} /> <ChevronLeft class="size-icon-sm" />
</IconButton> </IconButton>
<form onsubmit={onSubmit} class="max-w-search min-w-0 flex-1"> <form onsubmit={onSubmit} class="max-w-search min-w-0 flex-1">
<label <label
class="flex h-9.5 w-full items-center gap-2.5 rounded-control bg-surface-2 px-3.5 transition focus-within:bg-surface-hover" class="flex h-9.5 w-full items-center gap-2.5 rounded-control bg-surface-2 px-3.5 transition focus-within:bg-surface-hover"
> >
<Search class="size-4 shrink-0 text-fg-2" strokeWidth={1.8} /> <Search class="size-4 shrink-0 text-fg-2" />
<input <input
type="text" type="text"
bind:this={searchInput} bind:this={searchInput}
@@ -57,11 +57,11 @@
onclick={() => player.toggleMute()} onclick={() => player.toggleMute()}
> >
{#if player.muted || player.volume === 0} {#if player.muted || player.volume === 0}
<VolumeX class="size-icon-sm" strokeWidth={1.8} /> <VolumeX class="size-icon-sm" />
{:else if player.volume < 50} {:else if player.volume < 50}
<Volume1 class="size-icon-sm" strokeWidth={1.8} /> <Volume1 class="size-icon-sm" />
{:else} {:else}
<Volume2 class="size-icon-sm" strokeWidth={1.8} /> <Volume2 class="size-icon-sm" />
{/if} {/if}
</IconButton> </IconButton>
<Slider <Slider
@@ -78,7 +78,7 @@
pressed={queuePanel.open} pressed={queuePanel.open}
onclick={() => queuePanel.toggle()} onclick={() => queuePanel.toggle()}
> >
<ListMusic class="size-icon-sm" strokeWidth={1.8} /> <ListMusic class="size-icon-sm" />
</IconButton> </IconButton>
</div> </div>
</div> </div>
@@ -56,11 +56,11 @@
<IconButton <IconButton
label={isLiked ? 'Quitar de Me gusta' : 'Añadir a Me gusta'} label={isLiked ? 'Quitar de Me gusta' : 'Añadir a Me gusta'}
tone="plain" tone="plain"
size="xs" size="md"
pressed={isLiked} pressed={isLiked}
onclick={toggleLike} onclick={toggleLike}
> >
<Heart class="size-icon-md" fill={isLiked ? 'currentColor' : 'none'} strokeWidth={1.25} /> <Heart class="size-icon-md" fill={isLiked ? 'currentColor' : 'none'} />
</IconButton> </IconButton>
{/if} {/if}
</div> </div>
@@ -26,7 +26,7 @@
aria-label="Aleatorio" aria-label="Aleatorio"
class="transition-colors hover:text-fg {player.shuffle ? 'text-accent' : 'text-fg-2'}" class="transition-colors hover:text-fg {player.shuffle ? 'text-accent' : 'text-fg-2'}"
> >
<Shuffle class="size-4" strokeWidth={1.8} /> <Shuffle class="size-4" />
</button> </button>
{/if} {/if}
@@ -58,7 +58,7 @@
aria-label="Repetir" aria-label="Repetir"
class="transition-colors hover:text-fg {player.repeat ? 'text-accent' : 'text-fg-2'}" class="transition-colors hover:text-fg {player.repeat ? 'text-accent' : 'text-fg-2'}"
> >
<Repeat class="size-4" strokeWidth={1.8} /> <Repeat class="size-4" />
</button> </button>
{/if} {/if}
</div> </div>
@@ -68,6 +68,6 @@
class="h-full w-full object-cover" class="h-full w-full object-cover"
/> />
{:else} {:else}
<Icon class="size-icon-xl {gradient ? 'text-on-art/70' : 'text-fg-2'}" strokeWidth={1.3} /> <Icon class="size-icon-xl {gradient ? 'text-on-art/70' : 'text-fg-2'}" />
{/if} {/if}
</label> </label>
@@ -95,7 +95,7 @@
style="--mf-track-cols:{gridColumns}; --mf-track-cols-mobile:{gridColumnsMobile}" style="--mf-track-cols:{gridColumns}; --mf-track-cols-mobile:{gridColumnsMobile}"
> >
{#if index} {#if index}
<Hash size={16} strokeWidth={1.5} /> <Hash size={16} />
{/if} {/if}
<span>Título</span> <span>Título</span>
{#each columns as column (column)} {#each columns as column (column)}
@@ -24,7 +24,7 @@
> >
{#if tone === 'danger'} {#if tone === 'danger'}
<span class="mb-4 grid size-10 place-items-center rounded-full bg-danger/12 text-danger-fg"> <span class="mb-4 grid size-10 place-items-center rounded-full bg-danger/12 text-danger-fg">
<CircleAlert class="size-icon-md" strokeWidth={2} /> <CircleAlert class="size-icon-md" />
</span> </span>
{/if} {/if}
<h2 class="text-display-3 text-fg">{title}</h2> <h2 class="text-display-3 text-fg">{title}</h2>
@@ -22,7 +22,6 @@
/> />
<Check <Check
class="pointer-events-none absolute size-3.5 text-ink opacity-0 transition peer-checked:opacity-100" class="pointer-events-none absolute size-3.5 text-ink opacity-0 transition peer-checked:opacity-100"
strokeWidth={3}
/> />
</span> </span>
<span class="cursor-pointer">{@render children()}</span> <span class="cursor-pointer">{@render children()}</span>
@@ -15,7 +15,7 @@
<div class="flex flex-col items-center rounded-panel px-6 py-16 text-center {klass}"> <div class="flex flex-col items-center rounded-panel px-6 py-16 text-center {klass}">
{#if Icon} {#if Icon}
<Icon class="size-icon-xl text-fg-2" strokeWidth={1.25} /> <Icon class="size-icon-xl text-fg-2" />
{/if} {/if}
{#if title} {#if title}
<h3 class="mt-6 text-display-3 text-fg"> <h3 class="mt-6 text-display-3 text-fg">
@@ -27,7 +27,7 @@
{#snippet actions()} {#snippet actions()}
{#if items.length > 0} {#if items.length > 0}
<Button onclick={() => (creating = true)}> <Button onclick={() => (creating = true)}>
<Plus class="size-4" strokeWidth={2.5} /> <Plus class="size-4" />
Nuevo álbum Nuevo álbum
</Button> </Button>
{/if} {/if}
@@ -39,7 +39,7 @@
<div <div
class="grid size-cover-hero shrink-0 place-items-center rounded-art-lg bg-[image:var(--mf-liked-grad)] sm:size-cover-hero-sm" class="grid size-cover-hero shrink-0 place-items-center rounded-art-lg bg-[image:var(--mf-liked-grad)] sm:size-cover-hero-sm"
> >
<Heart class="size-icon-xl text-on-art/90" fill="currentColor" strokeWidth={0} /> <Heart class="size-icon-xl text-on-art/90" fill="currentColor" />
</div> </div>
{/snippet} {/snippet}
{#snippet actions()} {#snippet actions()}
@@ -130,7 +130,7 @@
: 'bg-accent-btn text-accent-soft'}" : 'bg-accent-btn text-accent-soft'}"
> >
{#if stepStates[i] === 'done'} {#if stepStates[i] === 'done'}
<Check class="size-3.5" strokeWidth={2.5} /> <Check class="size-3.5" />
{:else} {:else}
{i + 1} {i + 1}
{/if} {/if}
@@ -146,7 +146,7 @@
{#if status === 'done'} {#if status === 'done'}
<Surface padding="lg" class="mt-10 bg-accent-tint text-center"> <Surface padding="lg" class="mt-10 bg-accent-tint text-center">
<span class="mx-auto grid size-14 place-items-center rounded-full bg-accent-soft text-ink"> <span class="mx-auto grid size-14 place-items-center rounded-full bg-accent-soft text-ink">
<Check class="size-7" strokeWidth={2.5} /> <Check class="size-7" />
</span> </span>
<h2 class="mt-6 font-display text-2xl font-semibold tracking-display text-fg">¡Subida!</h2> <h2 class="mt-6 font-display text-2xl font-semibold tracking-display text-fg">¡Subida!</h2>
<p class="mt-3 text-sm text-fg-2"> <p class="mt-3 text-sm text-fg-2">
@@ -207,9 +207,9 @@
aria-label="Seleccionar archivo de audio" aria-label="Seleccionar archivo de audio"
/> />
{#if audioName === ''} {#if audioName === ''}
<Headphones class="size-9 text-fg-2 sm:size-10" strokeWidth={1.4} /> <Headphones class="size-9 text-fg-2 sm:size-10" />
{:else} {:else}
<Music class="size-9 text-accent-soft sm:size-10" strokeWidth={1.4} /> <Music class="size-9 text-accent-soft sm:size-10" />
{/if} {/if}
{#if audioName === ''} {#if audioName === ''}
<p class="mt-4 text-sm font-medium text-fg"> <p class="mt-4 text-sm font-medium text-fg">
+1 -1
View File
@@ -261,7 +261,7 @@
@layer base { @layer base {
svg.lucide { svg.lucide {
stroke-width: 1.8; stroke-width: 1.5;
} }
} }