feat: add color variables and use them acros the project

This commit is contained in:
Ilia Mashkov
2026-02-10 23:19:27 +03:00
parent 8aad8942fc
commit d749f86edc
20 changed files with 134 additions and 77 deletions

View File

@@ -44,7 +44,7 @@ let {
<SliderPrimitive.Thumb
data-slot="slider-thumb"
index={thumb}
class="border-primary ring-ring/50 block size-4 shrink-0 rounded-full border bg-white shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
class="border-primary ring-ring/50 block size-4 shrink-0 rounded-full border bg-background shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
/>
{/each}
{/snippet}

View File

@@ -103,7 +103,7 @@ const handleSliderChange = (newValue: number) => {
<Button
{...props}
variant="ghost"
class="hover:bg-white/50 hover:font-bold bg-white/20 border-none duration-150 will-change-transform active:scale-95 cursor-pointer"
class="hover:bg-background-50 hover:font-bold bg-background-20 border-none duration-150 will-change-transform active:scale-95 cursor-pointer"
size="icon"
aria-label={controlLabel}
>

View File

@@ -110,7 +110,7 @@ function calculateScale(index: number): number | string {
<div
class={cn(
'flex gap-4 sm:py-4 sm:px-1 rounded-xl transition-all duration-300',
'backdrop-blur-md',
'',
orientation === 'horizontal' ? 'flex-row items-end w-full' : 'flex-col items-center h-full',
className,
)}
@@ -130,10 +130,10 @@ function calculateScale(index: number): number | string {
orientation === 'horizontal' ? 'flex-col' : 'flex-row',
)}
>
<span class="font-mono text-[0.375rem] text-gray-400 tabular-nums">
<span class="font-mono text-[0.375rem] text-text-muted tabular-nums">
{calculateScale(i)}
</span>
<div class={cn('bg-gray-300', orientation === 'horizontal' ? 'w-px h-1' : 'h-px w-1')}>
<div class={cn('bg-border-muted', orientation === 'horizontal' ? 'w-px h-1' : 'h-px w-1')}>
</div>
</div>
{/each}
@@ -163,9 +163,9 @@ function calculateScale(index: number): number | string {
{#if label}
<div class="flex items-center gap-2 opacity-70">
<div class="w-1 h-1 rounded-full bg-gray-900"></div>
<div class="w-px h-2 bg-gray-400/50"></div>
<span class="font-mono text-[8px] uppercase tracking-[0.2em] text-gray-500 font-medium">
<div class="w-1 h-1 rounded-full bg-foreground"></div>
<div class="w-px h-2 bg-text-muted/50"></div>
<span class="font-mono text-[8px] uppercase tracking-[0.2em] text-text-subtle font-medium">
{label}
</span>
</div>
@@ -195,7 +195,7 @@ function calculateScale(index: number): number | string {
<Button
{...props}
variant="ghost"
class="hover:bg-white/50 hover:font-bold bg-white/20 border-none duration-150 will-change-transform active:scale-95 cursor-pointer"
class="hover:bg-background-50 hover:font-bold bg-background-20 border-none duration-150 will-change-transform active:scale-95 cursor-pointer"
size="icon"
aria-label={controlLabel}
>

View File

@@ -199,8 +199,8 @@ $effect(() => {
class={cn(
'relative p-0.5 sm:p-2 rounded-lg sm:rounded-2xl border transition-all duration-250 ease-out flex flex-col gap-1.5 backdrop-blur-lg',
expanded
? 'bg-white/5 border-indigo-400/40 shadow-[0_30px_70px_-10px_rgba(99,102,241,0.25)]'
: ' bg-white/25 border-white/40 shadow-[0_12px_40px_-12px_rgba(0,0,0,0.12)]',
? 'bg-background-20 border-indigo-400/40 shadow-[0_30px_70px_-10px_rgba(99,102,241,0.25)]'
: 'bg-background-40 border-background-40 shadow-[0_12px_40px_-12px_rgba(0,0,0,0.12)]',
disabled && 'opacity-80 grayscale-[0.2]',
containerClassName,
)}

View File

@@ -17,7 +17,8 @@ interface Props {
const { children, class: className, render }: Props = $props();
const baseClasses = 'font-mono text-[0.5625rem] sm:text-[0.625rem] uppercase tracking-[0.2em] text-gray-500 opacity-60';
const baseClasses =
'font-mono text-[0.5625rem] sm:text-[0.625rem] uppercase tracking-[0.2em] text-text-soft opacity-60';
const combinedClasses = cn(baseClasses, className);
</script>

View File

@@ -29,7 +29,7 @@ let { rotation = 'clockwise', icon, ...rest }: Props = $props();
variant="ghost"
class="
group relative border-none size-9
bg-white/20 hover:bg-white/60
bg-background-20 hover:bg-background-60
backdrop-blur-3xl
transition-all duration-200 ease-out
will-change-transform
@@ -43,7 +43,7 @@ let { rotation = 'clockwise', icon, ...rest }: Props = $props();
>
{@render icon({
className: cn(
'size-4 transition-all duration-200 stroke-[1.5] stroke-gray-500 group-hover:stroke-gray-900 group-hover:scale-110 group-hover:stroke-3 group-active:scale-90 group-disabled:stroke-transparent',
'size-4 transition-all duration-200 stroke-[1.5] stroke-text-muted group-hover:stroke-foreground group-hover:scale-110 group-hover:stroke-3 group-active:scale-90 group-disabled:stroke-transparent',
rotation === 'clockwise' ? 'group-active:rotate-6' : 'group-active:-rotate-6',
),
})}

View File

@@ -35,19 +35,19 @@ const isGhost = $derived(variant === 'ghost');
class={cn(
'h-12 sm:h-14 md:h-16 w-full text-sm sm:text-base',
'backdrop-blur-md',
isGhost ? 'bg-transparent' : 'bg-white/80',
'border border-gray-300/50',
isGhost ? 'border-transparent' : 'border-gray-300/50',
isGhost ? 'bg-transparent' : 'bg-background-80',
'border border-border-muted',
isGhost ? 'border-transparent' : 'border-border-muted',
isGhost ? 'shadow-none' : 'shadow-[0_1px_3px_rgba(0,0,0,0.04)]',
'focus-visible:border-gray-400/60',
'focus-visible:border-border-soft',
'focus-visible:outline-none',
'focus-visible:ring-1',
'focus-visible:ring-gray-400/30',
'focus-visible:bg-white/90',
'hover:bg-white/90',
'hover:border-gray-400/60',
'text-gray-900',
'placeholder:text-gray-400',
'focus-visible:ring-border-muted/30',
'focus-visible:bg-background-95',
'hover:bg-background-95',
'hover:border-border-soft',
'text-foreground',
'placeholder:text-text-muted',
'placeholder:font-mono',
'placeholder:text-xs sm:placeholder:text-sm',
'placeholder:tracking-wide',

View File

@@ -31,7 +31,7 @@ let { size = 20, class: className = '', message = 'analyzing_data' }: Props = $p
out:fade={{ duration: 300 }}
>
<div style:width="{size}px" style:height="{size}px">
<svg class="stroke-gray-900 stroke-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<svg class="stroke-foreground stroke-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(12, 12)">
<!-- Four corner brackets rotating -->
<g>
@@ -68,10 +68,10 @@ let { size = 20, class: className = '', message = 'analyzing_data' }: Props = $p
</svg>
</div>
<!-- Divider -->
<div class="w-px h-3 bg-gray-400/50"></div>
<div class="w-px h-3 bg-text-muted/50"></div>
<!-- Message -->
<span class="font-mono text-[10px] uppercase tracking-[0.2em] text-gray-600 font-medium">
<span class="font-mono text-[10px] uppercase tracking-[0.2em] text-text-subtle font-medium">
{message}
</span>
</div>

View File

@@ -105,8 +105,8 @@ $effect(() => {
<div class="flex flex-col gap-2 sm:gap-3" bind:this={titleContainer}>
<div class="flex items-center gap-2 sm:gap-3">
{#if icon}
{@render icon({ className: 'size-3 sm:size-4 stroke-gray-900 stroke-1 opacity-60' })}
<div class="w-px h-2.5 sm:h-3 bg-gray-300/60"></div>
{@render icon({ className: 'size-3 sm:size-4 stroke-foreground stroke-1 opacity-60' })}
<div class="w-px h-2.5 sm:h-3 bg-border-subtle"></div>
{/if}
{#if description}
<Footnote>
@@ -124,7 +124,7 @@ $effect(() => {
{#if title}
{@render title({
className:
'text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-semibold tracking-tighter text-gray-900 leading-[0.9]',
'text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-semibold tracking-tighter text-foreground leading-[0.9]',
})}
{/if}
</div>

View File

@@ -30,7 +30,7 @@ const { Story } = defineMeta({
}}
>
<div class="flex flex-col gap-4 p-4 w-full">
<div class="flex flex-col gap-2 p-4 border rounded-xl border-gray-200/50 bg-white/40">
<div class="flex flex-col gap-2 p-4 border rounded-xl border-border-subtle bg-background-40">
<div class="flex items-center justify-between mb-4">
<Skeleton class="h-8 w-1/3" />
<Skeleton class="h-8 w-8 rounded-full" />

View File

@@ -18,7 +18,7 @@ let { class: className, animate = true, ...rest }: Props = $props();
<div
class={cn(
'rounded-md bg-gray-100/50 backdrop-blur-sm',
'rounded-md bg-background-subtle/50 backdrop-blur-sm',
animate && 'animate-pulse',
className,
)}

View File

@@ -43,11 +43,11 @@ let { value = $bindable(), orientation = 'horizontal', class: className, ...rest
{#snippet children(props)}
<span
{...props}
class={cn('relative bg-gray-200 rounded-full', orientation === 'horizontal' ? 'w-full h-px' : 'h-full w-px')}
class={cn('relative bg-background-muted rounded-full', orientation === 'horizontal' ? 'w-full h-px' : 'h-full w-px')}
>
<!-- Filled range with NO transition -->
<Slider.Range
class={cn('absolute bg-gray-900 rounded-full', orientation === 'horizontal' ? 'h-full' : 'w-full')}
class={cn('absolute bg-foreground rounded-full', orientation === 'horizontal' ? 'h-full' : 'w-full')}
/>
<Slider.Thumb
@@ -56,7 +56,7 @@ let { value = $bindable(), orientation = 'horizontal', class: className, ...rest
'group/thumb relative block',
orientation === 'horizontal' ? '-top-1 w-2 h-2.25' : '-left-1 h-2 w-2.25',
'rounded-sm',
'bg-gray-900',
'bg-foreground',
// Glow shadow
'shadow-[0_0_6px_rgba(0,0,0,0.4)]',
// Smooth transitions only for size/position
@@ -76,7 +76,7 @@ let { value = $bindable(), orientation = 'horizontal', class: className, ...rest
<div
class="
absolute inset-0 rounded-sm
bg-white/20
bg-background-20
opacity-0 group-hover/thumb:opacity-100
transition-opacity duration-200
"
@@ -89,8 +89,8 @@ let { value = $bindable(), orientation = 'horizontal', class: className, ...rest
'absolute',
orientation === 'horizontal' ? '-top-8 left-1/2 -translate-x-1/2' : 'left-5 top-1/2 -translate-y-1/2',
'px-1.5 py-0.5 rounded-md',
'bg-gray-900/90 backdrop-blur-sm',
'font-mono text-[0.625rem] font-medium text-white ',
'bg-foreground/90 backdrop-blur-sm',
'font-mono text-[0.625rem] font-medium text-background',
'opacity-0 group-hover/thumb:opacity-100',
'transition-all duration-300',
'pointer-events-none',