mirror of
https://github.com/Blah-IM/Weblah.git
synced 2025-04-30 16:21:09 +00:00
refactor: Refactor Button and GroupedListItem components
Improve component typing with more specific HTML attribute types and implement conditional rendering based on properties. Use Svelte snippets to avoid code duplication and enhance component flexibility.
This commit is contained in:
parent
9e79b29c69
commit
c379933787
3 changed files with 67 additions and 47 deletions
9
.zed/settings.json
Normal file
9
.zed/settings.json
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"lsp": {
|
||||||
|
"tailwindcss-language-server": {
|
||||||
|
"settings": {
|
||||||
|
"classFunctions": ["tw"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,45 +1,40 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { tw } from '$lib/tw';
|
import { tw } from '$lib/tw';
|
||||||
import type { HTMLAttributes } from 'svelte/elements';
|
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
variant?: 'primary' | 'secondary';
|
variant?: 'primary' | 'secondary';
|
||||||
class?: string;
|
class?: string;
|
||||||
children?: import('svelte').Snippet;
|
children?: import('svelte').Snippet;
|
||||||
[key: string]: unknown;
|
} & Omit<HTMLAnchorAttributes | HTMLButtonAttributes, 'class'>;
|
||||||
} & (
|
|
||||||
| ({
|
|
||||||
href: string;
|
|
||||||
} & HTMLAttributes<HTMLAnchorElement>)
|
|
||||||
| ({
|
|
||||||
href?: undefined;
|
|
||||||
} & HTMLAttributes<HTMLButtonElement>)
|
|
||||||
);
|
|
||||||
|
|
||||||
let { variant = 'secondary', class: className = '', href, children, ...rest }: Props = $props();
|
let { variant = 'secondary', class: externalClass, children, ...rest }: Props = $props();
|
||||||
|
|
||||||
|
const className = $derived(
|
||||||
|
tw(
|
||||||
|
'text-sf-secondary bg-sb-primary ring-ss-secondary inline-flex cursor-default items-center justify-center rounded-md px-2.5 py-1 shadow-xs ring-1',
|
||||||
|
'hover:ring-ss-primary font-normal transition-shadow duration-200 active:shadow-inner',
|
||||||
|
variant === 'primary' && [
|
||||||
|
'relative text-slate-50 ring-0 duration-200',
|
||||||
|
'before:absolute before:-inset-px before:rounded-[7px]',
|
||||||
|
'before:from-accent-400 before:to-accent-500 before:bg-linear-to-b before:from-40% before:ring-1 before:ring-black/10 before:ring-inset',
|
||||||
|
'dark:before:from-accent-500 dark:before:to-accent-600 before:transition-shadow active:before:shadow-inner'
|
||||||
|
],
|
||||||
|
externalClass
|
||||||
|
)
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:element
|
{#snippet content()}
|
||||||
this={href ? 'a' : 'button'}
|
|
||||||
{href}
|
|
||||||
class={tw(
|
|
||||||
'text-sf-secondary bg-sb-primary ring-ss-secondary inline-flex cursor-default items-center justify-center rounded-md px-2.5 py-1 shadow-xs ring-1',
|
|
||||||
'hover:ring-ss-primary font-normal transition-shadow duration-200 active:shadow-inner',
|
|
||||||
variant === 'primary' && [
|
|
||||||
'relative text-slate-50 ring-0 duration-200',
|
|
||||||
'before:absolute before:-inset-px before:rounded-[7px]',
|
|
||||||
'before:from-accent-400 before:to-accent-500 before:bg-linear-to-b before:from-40% before:ring-1 before:ring-black/10 before:ring-inset',
|
|
||||||
'dark:before:from-accent-500 dark:before:to-accent-600 before:transition-shadow active:before:shadow-inner'
|
|
||||||
],
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
{...rest}
|
|
||||||
>
|
|
||||||
{#if variant === 'primary'}
|
{#if variant === 'primary'}
|
||||||
<div class="z-10 drop-shadow-[0_-1px_0_--theme(--color-black/0.2)]">{@render children?.()}</div>
|
<div class="z-10 drop-shadow-[0_-1px_0_--theme(--color-black/0.2)]">{@render children?.()}</div>
|
||||||
{:else}
|
{:else}
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
{/if}
|
{/if}
|
||||||
</svelte:element>
|
{/snippet}
|
||||||
|
|
||||||
|
{#if 'href' in rest}
|
||||||
|
<a class={className} {...rest}>{@render content()}</a>
|
||||||
|
{:else}
|
||||||
|
<button class={className} {...rest}>{@render content()}</button>
|
||||||
|
{/if}
|
||||||
|
|
|
@ -1,29 +1,37 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { tw } from '$lib/tw';
|
import { tw } from '$lib/tw';
|
||||||
import { Icon, type IconSource } from 'svelte-hero-icons';
|
import { Icon, type IconSource } from 'svelte-hero-icons';
|
||||||
|
import type { HTMLAnchorAttributes, HTMLAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
interface Props {
|
type Props = {
|
||||||
href?: string | undefined;
|
|
||||||
icon?: IconSource | undefined;
|
icon?: IconSource | undefined;
|
||||||
selected?: boolean;
|
selected?: boolean;
|
||||||
children?: import('svelte').Snippet;
|
children?: import('svelte').Snippet;
|
||||||
onclick?: (e: MouseEvent) => void;
|
class?: string;
|
||||||
}
|
} & (
|
||||||
|
| ({ href: string } & Omit<HTMLAnchorAttributes, 'class' | 'href'>)
|
||||||
|
| ({ onclick: Required<HTMLButtonAttributes['onclick']> } & Omit<HTMLButtonAttributes, 'class'>)
|
||||||
|
| Omit<HTMLAttributes<HTMLDivElement>, 'onclick'>
|
||||||
|
);
|
||||||
|
|
||||||
let { href = undefined, icon = undefined, selected = false, children, onclick }: Props = $props();
|
let {
|
||||||
|
icon = undefined,
|
||||||
|
selected = false,
|
||||||
|
children,
|
||||||
|
class: externalClass,
|
||||||
|
...rest
|
||||||
|
}: Props = $props();
|
||||||
|
|
||||||
|
const className = $derived(
|
||||||
|
tw(
|
||||||
|
'text-sf-primary flex w-full cursor-default items-center gap-2 px-4 py-3 font-medium first:rounded-t-lg last:rounded-b-lg',
|
||||||
|
selected && 'bg-accent-500 dark:bg-accent-900 dark:text-sf-primary text-white shadow-inner',
|
||||||
|
externalClass
|
||||||
|
)
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:element
|
{#snippet content()}
|
||||||
this={href ? 'a' : 'button'}
|
|
||||||
{href}
|
|
||||||
class={tw(
|
|
||||||
'text-sf-primary flex w-full cursor-default items-center gap-2 px-4 py-3 font-medium first:rounded-t-lg last:rounded-b-lg',
|
|
||||||
selected && 'bg-accent-500 dark:bg-accent-900 dark:text-sf-primary text-white shadow-inner'
|
|
||||||
)}
|
|
||||||
tabindex="0"
|
|
||||||
role="button"
|
|
||||||
{onclick}
|
|
||||||
>
|
|
||||||
{#if icon}
|
{#if icon}
|
||||||
<Icon
|
<Icon
|
||||||
src={icon}
|
src={icon}
|
||||||
|
@ -34,4 +42,12 @@
|
||||||
<div class="min-w-0 truncate text-start">
|
<div class="min-w-0 truncate text-start">
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
</div>
|
</div>
|
||||||
</svelte:element>
|
{/snippet}
|
||||||
|
|
||||||
|
{#if 'href' in rest}
|
||||||
|
<a class={className} {...rest}>{@render content()}</a>
|
||||||
|
{:else if 'onclick' in rest}
|
||||||
|
<button class={className} {...rest}>{@render content()}</button>
|
||||||
|
{:else}
|
||||||
|
<div class={className} {...rest}>{@render content()}</div>
|
||||||
|
{/if}
|
||||||
|
|
Loading…
Add table
Reference in a new issue