chore: upgrade to tailwindcss v4

This commit is contained in:
Shibo Lyu 2025-03-17 00:25:07 +08:00
parent 88551053d9
commit cd0bf37a68
22 changed files with 434 additions and 694 deletions

View file

@ -19,9 +19,9 @@
"@sveltejs/adapter-auto": "^3.3.1",
"@sveltejs/kit": "^2.9.0",
"@sveltejs/vite-plugin-svelte": "^3.1.2",
"@tailwindcss/postcss": "^4.0.14",
"@tailwindcss/typography": "^0.5.15",
"@types/eslint": "^9.6.1",
"autoprefixer": "^10.4.21",
"eslint": "^9.22.0",
"eslint-config-prettier": "^10.1.1",
"eslint-plugin-svelte": "^2.46.1",
@ -31,7 +31,7 @@
"prettier-plugin-tailwindcss": "^0.6.11",
"svelte": "^4.2.19",
"svelte-check": "^4.1.5",
"tailwindcss": "^3.4.15",
"tailwindcss": "^4.0.14",
"typescript": "^5.8.2",
"typescript-eslint": "^8.26.1",
"vite": "^5.1.8",

934
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,5 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {}
'@tailwindcss/postcss': {},
}
};

View file

@ -1,34 +1,77 @@
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
@import 'tailwindcss';
@plugin '@tailwindcss/typography';
@custom-variant dark {
@media (prefers-color-scheme: dark) {
&:not([data-weblah-color-scheme='light'] *) {
@slot;
}
}
&:is([data-weblah-color-scheme='dark'] *) {
@slot;
}
}
@theme {
--color-accent-50: #eff6ff;
--color-accent-100: #dbeafe;
--color-accent-200: #bfdbfe;
--color-accent-300: #93c5fd;
--color-accent-400: #60a5fa;
--color-accent-500: #3b82f6;
--color-accent-600: #2563eb;
--color-accent-700: #1d4ed8;
--color-accent-800: #1e40af;
--color-accent-900: #1e3a8a;
--color-accent-950: #172554;
--color-sb-overlay: var(--weblah-color-sb-overlay);
--color-sb-primary: var(--weblah-color-sb-primary);
--color-sb-secondary: var(--weblah-color-sb-secondary);
--color-sb-tertiary: var(--weblah-color-sb-tertiary);
--color-sf-primary: var(--weblah-color-sf-primary);
--color-sf-secondary: var(--weblah-color-sf-secondary);
--color-sf-tertiary: var(--weblah-color-sf-tertiary);
--color-ss-primary: var(--weblah-color-ss-primary);
--color-ss-secondary: var(--weblah-color-ss-secondary);
}
@utility rich-text {
@apply prose prose-slate max-w-none dark:prose-invert;
@apply prose-p:my-0 prose-p:leading-tight prose-code:before:content-[''] prose-code:after:content-[''];
@apply [&_span[data-weblah-brt=underline]]:underline;
}
@layer base {
.weblah-light-theme {
--weblah-color-sb-overlay: theme(colors.white);
--weblah-color-sb-primary: theme(colors.slate.50);
--weblah-color-sb-secondary: theme(colors.slate.100);
--weblah-color-sb-tertiary: theme(colors.slate.200);
--weblah-color-sb-overlay: var(--color-white);
--weblah-color-sb-primary: var(--color-slate-50);
--weblah-color-sb-secondary: var(--color-slate-100);
--weblah-color-sb-tertiary: var(--color-slate-200);
--weblah-color-sf-primary: theme(colors.slate.900);
--weblah-color-sf-secondary: theme(colors.slate.500);
--weblah-color-sf-tertiary: theme(colors.slate.400);
--weblah-color-sf-primary: var(--color-slate-900);
--weblah-color-sf-secondary: var(--color-slate-500);
--weblah-color-sf-tertiary: var(--color-slate-400);
--weblah-color-ss-primary: theme(colors.slate.300);
--weblah-color-ss-secondary: theme(colors.slate.300 / 60%);
--weblah-color-ss-primary: var(--color-slate-300);
--weblah-color-ss-secondary: --theme(--color-slate-300 / 60%);
}
.weblah-dark-theme {
--weblah-color-sb-overlay: theme(colors.slate.800);
--weblah-color-sb-primary: theme(colors.slate.900);
--weblah-color-sb-secondary: theme(colors.slate.950);
--weblah-color-sb-tertiary: theme(colors.black);
--weblah-color-sb-overlay: var(--color-slate-800);
--weblah-color-sb-primary: var(--color-slate-900);
--weblah-color-sb-secondary: var(--color-slate-950);
--weblah-color-sb-tertiary: var(--color-black);
--weblah-color-sf-primary: theme(colors.slate.100);
--weblah-color-sf-secondary: theme(colors.slate.400);
--weblah-color-sf-tertiary: theme(colors.slate.500);
--weblah-color-sf-primary: var(--color-slate-100);
--weblah-color-sf-secondary: var(--color-slate-400);
--weblah-color-sf-tertiary: var(--color-slate-500);
--weblah-color-ss-primary: theme(colors.slate.700);
--weblah-color-ss-secondary: theme(colors.slate.700 / 60%);
--weblah-color-ss-primary: var(--color-slate-700);
--weblah-color-ss-secondary: --theme(--color-slate-700 / 60%);
}
:root {
@ -49,11 +92,3 @@
}
}
}
@layer utilities {
.rich-text {
@apply prose prose-slate max-w-none dark:prose-invert;
@apply prose-p:my-0 prose-p:leading-tight prose-code:before:content-[''] prose-code:after:content-[''];
@apply [&_span[data-weblah-brt=underline]]:underline;
}
}

View file

@ -19,12 +19,12 @@
this={href ? 'a' : 'button'}
{href}
class={tw(
'inline-flex cursor-default items-center justify-center rounded-md px-2 py-1 text-sf-secondary shadow-sm ring-1 ring-ss-secondary',
'inline-flex cursor-default items-center justify-center rounded-md px-2 py-1 text-sf-secondary shadow-xs ring-1 ring-ss-secondary',
'font-normal transition-shadow duration-200 hover:ring-ss-primary active:shadow-inner',
variant === 'primary' && [
'relative text-slate-50 ring-0 duration-200',
'before:absolute before:-inset-px before:rounded-[7px]',
'before:bg-gradient-to-b before:from-accent-400 before:from-40% before:to-accent-500 before:ring-1 before:ring-inset before:ring-black/10',
'before:bg-linear-to-b before:from-accent-400 before:from-40% before:to-accent-500 before:ring-1 before:ring-inset before:ring-black/10',
'before:transition-shadow active:before:shadow-inner dark:before:from-accent-500 dark:before:to-accent-600'
],
className
@ -35,7 +35,7 @@
tabindex="0"
>
{#if variant === 'primary'}
<div class="z-10 drop-shadow-[0_-1px_0_theme(colors.black/0.2)]"><slot /></div>
<div class="z-10 drop-shadow-[0_-1px_0_--theme(--color-black/0.2)]"><slot /></div>
{:else}
<slot />
{/if}

View file

@ -5,7 +5,7 @@
</script>
<DropdownMenu.Item
class="cursor-default rounded px-1.5 py-0.5 text-sf-primary transition-colors duration-200 hover:bg-accent-50 group-has-[[data-melt-dropdown-menu-radio-group]]:ps-6 dark:hover:bg-white/5"
class="cursor-default rounded-sm px-1.5 py-0.5 text-sf-primary transition-colors duration-200 hover:bg-accent-50 group-has-data-melt-dropdown-menu-radio-group:ps-6 dark:hover:bg-white/5"
on:click
{...$$restProps}
>

View file

@ -8,7 +8,7 @@
</script>
<DropdownMenu.RadioItem
class="flex cursor-default items-center gap-1 rounded px-1.5 py-0.5 text-sf-primary transition-colors duration-200 hover:bg-accent-50 dark:hover:bg-white/5"
class="flex cursor-default items-center gap-1 rounded-sm px-1.5 py-0.5 text-sf-primary transition-colors duration-200 hover:bg-accent-50 dark:hover:bg-white/5"
{value}
{...$$props}
>

View file

@ -1,5 +1,5 @@
<label
class="flex gap-2 px-4 py-3 font-medium text-sf-primary [align-items:first_baseline] [&>input]:flex-1 [&>input]:bg-transparent [&>input]:text-end [&>input]:outline-none [&>input]:placeholder:opacity-50"
class="flex gap-2 px-4 py-3 font-medium text-sf-primary [align-items:first_baseline] [&>input]:flex-1 [&>input]:bg-transparent [&>input]:text-end [&>input]:outline-hidden [&>input]:placeholder:opacity-50"
>
<slot />
</label>

View file

@ -5,7 +5,7 @@
</h3>
{/if}
<div
class="divide-y-[0.5px] divide-ss-secondary overflow-hidden rounded-lg border-[0.5px] border-ss-secondary bg-sb-primary shadow-sm"
class="divide-y-[0.5px] divide-ss-secondary overflow-hidden rounded-lg border-[0.5px] border-ss-secondary bg-sb-primary shadow-xs"
>
<slot />
</div>

View file

@ -7,7 +7,7 @@
<label
class={tw(
'flex items-center gap-1 rounded-md bg-sb-primary px-2 py-1.5 caret-accent-500 shadow-[inset_0_1px_2px_0_rgb(0_0_0/0.05)] ring-1 ring-ss-secondary transition-shadow duration-200 has-[input,textarea,[contenteditable]]:cursor-text has-[:focus]:ring-ss-primary',
'flex items-center gap-1 rounded-md bg-sb-primary px-2 py-1.5 caret-accent-500 shadow-[inset_0_1px_2px_0_rgb(0_0_0/0.05)] ring-1 ring-ss-secondary transition-shadow duration-200 has-[input,textarea,[contenteditable]]:cursor-text has-focus:ring-ss-primary',
className
)}
>

View file

@ -7,7 +7,7 @@
<header
class={tw(
'flex min-h-[calc(3rem+1px)] cursor-default items-center border-b border-ss-secondary bg-sb-primary p-2 text-center font-semibold text-sf-primary shadow-sm',
'flex min-h-[calc(3rem+1px)] cursor-default items-center border-b border-ss-secondary bg-sb-primary p-2 text-center font-semibold text-sf-primary shadow-xs',
className
)}
>

View file

@ -13,7 +13,7 @@
<span class="sr-only">{account.profile.signee.payload.name}</span>
{:else}
<div
class="box-border size-[--weblah-profile-pic-size] rounded-full border-2 border-dashed border-ss-primary"
class="box-border size-(--weblah-profile-pic-size) rounded-full border-2 border-dashed border-ss-primary"
style:--weblah-profile-pic-size={`${size}px`}
aria-hidden
/>

View file

@ -50,7 +50,7 @@
</script>
<div
class="rich-text relative w-full outline-none before:absolute before:hidden before:leading-tight before:opacity-50 before:content-[attr(data-weblah-placeholder)] data-[weblah-is-empty]:before:block"
class="rich-text relative w-full outline-hidden before:absolute before:hidden before:leading-tight before:opacity-50 before:content-[attr(data-weblah-placeholder)] data-weblah-is-empty:before:block"
use:asRoot={editor}
data-weblah-is-empty={!delta || (delta.ops.length === 1 && delta.ops[0].insert === '\n')
? 'true'

View file

@ -7,7 +7,7 @@
<div
class={tw(
'backdrop mx-4 inline-block cursor-default rounded-full px-2 py-0.5 text-center text-sm text-sf-secondary backdrop-blur-sm',
'backdrop mx-4 inline-block cursor-default rounded-full px-2 py-0.5 text-center text-sm text-sf-secondary backdrop-blur-xs',
className
)}
>

View file

@ -27,7 +27,7 @@
data-weblah-main-visible={mainVisible ? 'true' : undefined}
>
<aside
class="relative h-[100dvh] min-h-0 overflow-hidden border-ss-primary bg-sb-primary shadow-lg [view-transition-name:chat-list] after:pointer-events-none after:absolute after:inset-0 after:size-full after:bg-transparent group-data-[weblah-main-visible]:after:bg-black/30 sm:w-1/3 sm:border-e sm:after:hidden lg:w-1/4"
class="relative h-[100dvh] min-h-0 overflow-hidden border-ss-primary bg-sb-primary shadow-lg [view-transition-name:chat-list] after:pointer-events-none after:absolute after:inset-0 after:size-full after:bg-transparent group-data-weblah-main-visible:after:bg-black/30 sm:w-1/3 sm:border-e sm:after:hidden lg:w-1/4"
>
<ChatList />
{#if isSettings}

View file

@ -17,7 +17,7 @@
}
</script>
<header class="flex items-center justify-stretch gap-2 border-b border-ss-secondary p-2 shadow-sm">
<header class="flex items-center justify-stretch gap-2 border-b border-ss-secondary p-2 shadow-xs">
<a
class={tw(
'transition-[opacity,transform] duration-200',
@ -34,7 +34,7 @@
<input
type="search"
placeholder="Search"
class="w-full flex-1 bg-transparent text-sm leading-4 text-sf-primary focus:outline-none"
class="w-full flex-1 bg-transparent text-sm leading-4 text-sf-primary focus:outline-hidden"
bind:value={searchQuery}
bind:this={inputElement}
on:focus={() => {

View file

@ -10,7 +10,7 @@
</script>
<div
class="relative z-10 box-border flex min-h-[calc(3rem+1px)] w-full items-center gap-2 border-b border-ss-secondary bg-sb-primary p-2 shadow-sm"
class="relative z-10 box-border flex min-h-[calc(3rem+1px)] w-full items-center gap-2 border-b border-ss-secondary bg-sb-primary p-2 shadow-xs"
>
<Button href="/" class="rounded-full sm:hidden">
<Icon src={ChevronLeft} />

View file

@ -28,7 +28,7 @@
</script>
<form
class="flex w-full items-end gap-2 border-t border-ss-secondary bg-sb-primary p-2 shadow-sm"
class="flex w-full items-end gap-2 border-t border-ss-secondary bg-sb-primary p-2 shadow-xs"
bind:this={form}
on:submit|preventDefault={submit}
>

View file

@ -13,22 +13,22 @@
class={tw(
'relative flex-1',
isMyself
? '[--weblah-chat-bubble-bg:theme(colors.accent.100)] [--weblah-chat-bubble-stroke:theme(colors.accent.200)] dark:[--weblah-chat-bubble-bg:theme(colors.accent.900)] dark:[--weblah-chat-bubble-stroke:theme(colors.accent.950)]'
: '[--weblah-chat-bubble-bg:theme(colors.sb.primary)] [--weblah-chat-bubble-stroke:theme(colors.ss.secondary)]',
? '[--weblah-chat-bubble-bg:var(--color-accent-100)] [--weblah-chat-bubble-stroke:var(--color-accent-200)] dark:[--weblah-chat-bubble-bg:var(--color-accent-900)] dark:[--weblah-chat-bubble-stroke:var(--color-accent-950)]'
: '[--weblah-chat-bubble-bg:var(--color-sb-primary)] [--weblah-chat-bubble-stroke:var(--color-ss-secondary)]',
isMyself && 'text-end'
)}
>
<div
class={tw(
`relative inline-block max-w-[85%] rounded-2xl bg-[--weblah-chat-bubble-bg] shadow-sm ring-1 ring-[--weblah-chat-bubble-stroke]`,
`relative inline-block max-w-[85%] rounded-2xl bg-(--weblah-chat-bubble-bg) shadow-xs ring-1 ring-(--weblah-chat-bubble-stroke)`,
showBubbleTail && [
// ::before: Fill of chat bubble tail
'before:absolute before:-bottom-[1px] before:box-content before:h-6 before:w-5 before:border-[--weblah-chat-bubble-bg] before:text-[--weblah-chat-bubble-stroke]',
'before:absolute before:-bottom-[1px] before:box-content before:h-6 before:w-5 before:border-(--weblah-chat-bubble-bg) before:text-(--weblah-chat-bubble-stroke)',
isMyself
? 'before:-end-5 before:rounded-es-[16px_12px] before:border-s-[10px] before:drop-shadow-[1px_0]'
: `before:-start-5 before:rounded-ee-[16px_12px] before:border-e-[10px] before:drop-shadow-[-1px_0]`,
// ::after: Stroke of chat bubble tail
'after:absolute after:-bottom-[1px] after:-z-10 after:box-content after:h-6 after:w-5 after:text-[--weblah-chat-bubble-stroke]',
'after:absolute after:-bottom-[1px] after:-z-10 after:box-content after:h-6 after:w-5 after:text-(--weblah-chat-bubble-stroke)',
isMyself
? 'after:-end-5 after:rounded-es-[16px_12px] after:border-s-[10px] after:drop-shadow-[0_1px]'
: `after:-start-5 after:rounded-ee-[16px_12px] after:border-e-[10px] after:drop-shadow-[0_1px]`

View file

@ -89,7 +89,7 @@
bind:value={name}
placeholder="Your Name"
disabled={isBusy}
class="ms-3 flex-1 bg-transparent text-lg leading-loose caret-accent-500 outline-none placeholder:opacity-50"
class="ms-3 flex-1 bg-transparent text-lg leading-loose caret-accent-500 outline-hidden placeholder:opacity-50"
/>
</GroupedListItem>
</GroupedListSection>

View file

@ -6,17 +6,17 @@
<h2 class="my-2 text-xl">{title}</h2>
<div class="flex gap-4">
<div class="w-32 rounded-md border border-ss-primary bg-sb-primary py-3 text-center">
<div class="mb-3 border-b border-ss-secondary pb-3 shadow-sm">Primary BG</div>
<div class="mb-3 border-b border-ss-secondary pb-3 shadow-xs">Primary BG</div>
<p class="text-sf-secondary">Secondary FG</p>
<p class="text-sf-tertiary">Tertiary FG</p>
</div>
<div class="w-32 rounded-md border border-ss-primary bg-sb-secondary py-3 text-center">
<div class="mb-3 border-b border-ss-secondary pb-3 shadow-sm">Secondary BG</div>
<div class="mb-3 border-b border-ss-secondary pb-3 shadow-xs">Secondary BG</div>
<p class="text-sf-secondary">Secondary FG</p>
<p class="text-sf-tertiary">Tertiary FG</p>
</div>
<div class="w-32 rounded-md border border-ss-primary bg-sb-tertiary py-3 text-center">
<div class="mb-3 border-b border-ss-secondary pb-3 shadow-sm">Tertiary BG</div>
<div class="mb-3 border-b border-ss-secondary pb-3 shadow-xs">Tertiary BG</div>
<p class="text-sf-secondary">Secondary FG</p>
<p class="text-sf-tertiary">Tertiary FG</p>
</div>

View file

@ -1,42 +0,0 @@
import type { Config } from 'tailwindcss';
import colors from 'tailwindcss/colors';
export default {
content: ['./src/**/*.{html,js,svelte,ts}'],
darkMode: [
'variant',
[
'@media (prefers-color-scheme: dark) { &:not([data-weblah-color-scheme="light"] *) }',
'&:is([data-weblah-color-scheme="dark"] *)'
]
],
theme: {
extend: {
colors: {
accent: colors.blue,
// Semantic Background
sb: {
overlay: 'var(--weblah-color-sb-overlay)',
primary: 'var(--weblah-color-sb-primary)',
secondary: 'var(--weblah-color-sb-secondary)',
tertiary: 'var(--weblah-color-sb-tertiary)'
},
// Semantic Foreground
sf: {
primary: 'var(--weblah-color-sf-primary)',
secondary: 'var(--weblah-color-sf-secondary)',
tertiary: 'var(--weblah-color-sf-tertiary)'
},
// Semantic Stroke
ss: {
primary: 'var(--weblah-color-ss-primary)',
secondary: 'var(--weblah-color-ss-secondary)'
}
}
}
},
plugins: [require('@tailwindcss/typography')]
} as Config;