refactor Tabs to separate components

This commit is contained in:
Benjamin Palko 2024-12-19 14:43:54 -05:00
parent e1816867f5
commit 0329e2f8ee
5 changed files with 87 additions and 32 deletions

View file

@ -0,0 +1,5 @@
<script lang="ts">
let { active, label, onclick } = $props();
</script>
<input aria-label={label} type="radio" role="tab" class="tab" class:tab-active={active} {onclick} />

View file

@ -0,0 +1,27 @@
<script module lang="ts">
import { defineMeta } from '@storybook/addon-svelte-csf';
import type { ComponentProps } from 'svelte';
import Tabs from './Tabs.svelte';
const { Story } = defineMeta({
title: 'Tabs',
component: Tabs,
tags: ['autodocs'],
argTypes: {
size: {
control: 'select',
options: ['xs', 'sm', 'rg', 'lg']
},
variant: {
control: 'select',
options: ['none', 'bordered', 'lifted', 'boxed']
}
}
});
</script>
{#snippet template(args: Partial<ComponentProps<typeof Tabs>>)}
<Tabs tabs={['Tab 1', 'Tab 2']} {...args} />
{/snippet}
<Story name="Default" args={{}} children={template} />

View file

@ -0,0 +1,36 @@
<script lang="ts">
import type { DaisySize } from '$lib/types';
import Tab from './Tab.svelte';
type Props = {
size?: DaisySize;
tabs: string[];
selected?: number;
variant?: 'none' | 'bordered' | 'lifted' | 'boxed';
};
let { size, tabs, selected: value = $bindable(0), variant = 'none' }: Props = $props();
</script>
<div
role="tablist"
class="tabs w-full"
class:tabs-xs={size === 'xs'}
class:tabs-sm={size === 'sm'}
class:tabs-lg={size === 'lg'}
class:tabs-bordered={variant === 'bordered'}
class:tabs-lifted={variant === 'lifted'}
class:tabs-boxed={variant === 'boxed'}
>
{#each tabs as tab, index}
{#key [tab, value]}
<Tab
active={index === value}
label={tab}
onclick={() => {
value = index;
}}
/>
{/key}
{/each}
</div>

View file

@ -0,0 +1,4 @@
import Tabs from './Tabs.svelte';
export default Tabs;
export { default as Tabs } from './Tabs.svelte';

View file

@ -2,10 +2,10 @@
import Button from '$lib/components/Button.svelte';
import Container from '$lib/components/common/Container.svelte';
import TextInput from '$lib/components/TextInput.svelte';
import Tabs from '$lib/components/common/Tabs';
import { fade } from 'svelte/transition';
let mode: 'register' | 'login' = $state('login');
let action = $derived(mode === 'login' ? '?/login' : '?/register');
let tab: 0 | 1 = $state(0);
</script>
{#snippet userIcon()}
@ -20,38 +20,21 @@
<i class="fi fi-rr-user"></i>
{/snippet}
<div class="page" transition:fade>
<Container>
<form class="flex w-full flex-col items-center gap-6" method="POST" {action}>
<h1 class="text-3xl">Hestia</h1>
<br />
<div role="tablist" class="tabs tabs-bordered tabs-lg w-full">
<button
type="button"
role="tab"
class="tab"
class:tab-active={mode === 'login'}
onclick={() => {
mode = 'login';
}}>Login</button
>
<button
type="button"
role="tab"
class="tab"
class:tab-active={mode === 'register'}
onclick={() => {
mode = 'register';
}}>Register</button
>
</div>
{#snippet form(variant: 'login' | 'register')}
<form class="flex w-full flex-col items-center gap-6" method="POST" action={`?/${variant}`}>
<TextInput start={userIcon} placeholder="Email" name="email" type="email" />
<TextInput start={passwordIcon} placeholder="Password" name="password" type="password" />
{#if mode === 'register'}
{#if variant === 'register'}
<TextInput start={nameIcon} placeholder="Name" name="name" fade />
{/if}
<Button block type="submit" label="Submit" outline />
</form>
{/snippet}
<div class="page" transition:fade>
<Container>
<Tabs variant="bordered" bind:selected={tab} tabs={['Login', 'Register']} />
{@render form(tab === 0 ? 'login' : 'register')}
</Container>
</div>