Skip to content

Commit

Permalink
feat(tabs): adds base tab bar component
Browse files Browse the repository at this point in the history
  • Loading branch information
dvcol committed Nov 8, 2024
1 parent 92c23bf commit 9864b86
Show file tree
Hide file tree
Showing 23 changed files with 827 additions and 222 deletions.
33 changes: 22 additions & 11 deletions demo/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,50 @@
import { router } from './router/router.js';
import { Route } from './router/routes';
import { routes } from './router/routes.js';
import type { Routes } from './router/routes.js';
import type { TransitionProps } from '@dvcol/svelte-simple-router/models';
import NeoButton from '~/buttons/NeoButton.svelte';
import NeoButtonGroup from '~/buttons/NeoButtonGroup.svelte';
import IconMoon from '~/icons/IconMoon.svelte';
import IconSun from '~/icons/IconSun.svelte';
import NeoTab from '~/nav/NeoTab.svelte';
import NeoTabs from '~/nav/NeoTabs.svelte';
const transition: TransitionProps = {
in: fade,
out: fade,
params: { in: { delay: 200, duration: 200 }, out: { duration: 200 } },
params: { in: { delay: 100, duration: 100 }, out: { duration: 100 } },
props: { container: { style: 'display: flex; justify-content: center; align-items: center; overflow:hidden;' } },
skipFirst: true,
};
const active = $derived(router.route?.name);
let transitioning = $state(false);
let first = true;
const onChange = async () => {
if (first) return;
transitioning = true;
await wait(150);
await wait(200);
};
const onLoaded = async () => {
await wait(350);
if (active && first) {
first = false;
return;
}
await wait(200);
transitioning = false;
};
const onClick = (id?: Routes) => {
if (id === undefined || id === active) return;
router.push({ name: id });
};
const initial = localStorage.getItem('theme');
let dark = $state(initial ? initial === 'dark' : window.matchMedia('(prefers-color-scheme: dark)').matches);
let remember = $state(!!localStorage.getItem('theme'));
Expand All @@ -48,19 +63,15 @@
if (remember) localStorage.setItem('theme', dark ? 'dark' : 'light');
else localStorage.removeItem('theme');
});
const routes = [Route.Buttons, Route.ButtonGroups];
</script>

<div class="container">
<div class="row">
<NeoButtonGroup>
<NeoTabs {active} onchange={onClick}>
{#each routes as route}
<NeoButton checked={active === route} onclick={() => router.push({ name: route })}>
{route}
</NeoButton>
<NeoTab tabId={route}>{route}</NeoTab>
{/each}
</NeoButtonGroup>
</NeoTabs>

<NeoButtonGroup>
<NeoButton toggle bind:checked={dark}>
Expand Down
133 changes: 42 additions & 91 deletions demo/components/DemoButtonGroups.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,112 +3,63 @@
import SphereBackdrop from '../utils/SphereBackdrop.svelte';
import { useButtonState } from '../utils/use-button-state.svelte';
import type { NeoButtonGroupContext } from '~/buttons/neo-button-group.model';
import NeoButton from '~/buttons/NeoButton.svelte';
import NeoButtonGroup from '~/buttons/NeoButtonGroup.svelte';
import IconAccount from '~/icons/IconAccount.svelte';
const onClick = (...args: any) => {
console.info(...args);
};
let loading = $state(false);
const onLoading = (e: MouseEvent, checked?: boolean, duration = 5000) => {
loading = !loading;
setTimeout(() => {
loading = !loading;
}, duration);
onClick(e);
};
let skeleton = $state(false);
const onSkeleton = (e: MouseEvent, checked?: boolean, duration = 5000) => {
skeleton = !skeleton;
setTimeout(() => {
skeleton = !skeleton;
}, duration);
onClick(e);
};
const { onClick, loading: loading$, onLoading, skeleton: skeleton$, onSkeleton } = useButtonState('DemoGroupClicked');
const loading = $derived.by(loading$);
const skeleton = $derived.by(skeleton$);
const { matches } = useWatchMedia('(max-width: 1550px)');
const vertical = $derived.by(matches);
const columns = [
{ label: 'Default' },
{ label: 'Rounded', props: { rounded: true } },
{ label: 'Flat', props: { flat: true } },
{ label: 'Text', props: { text: true } },
{ label: 'Glass', props: { glass: true } },
];
</script>

{#snippet icon()}
<IconAccount />
{/snippet}

<div class="row">
<div class="column">
<span class="label">Default</span>
<NeoButtonGroup {vertical} {skeleton}>
<NeoButton onclick={onClick}>Button</NeoButton>
<NeoButton toggle onclick={onClick}>Toggle</NeoButton>
<NeoButton disabled onclick={onClick}>Disabled</NeoButton>
<NeoButton {loading} onclick={onLoading}>Loading</NeoButton>
<NeoButton {loading} onclick={onLoading} {icon} />
<NeoButton onclick={onClick} {icon}>Icon</NeoButton>
<NeoButton reverse onclick={onClick} {icon}>Reversed</NeoButton>
<NeoButton {skeleton} onclick={onSkeleton}>Skeleton</NeoButton>
</NeoButtonGroup>
</div>

<div class="column">
<span class="label">Rounded</span>
<NeoButtonGroup {vertical} {skeleton} rounded>
<NeoButton onclick={onClick}>Button</NeoButton>
<NeoButton toggle onclick={onClick}>Toggle</NeoButton>
<NeoButton disabled onclick={onClick}>Disabled</NeoButton>
<NeoButton {loading} onclick={onLoading}>Loading</NeoButton>
<NeoButton {loading} onclick={onLoading} {icon} />
<NeoButton onclick={onClick} {icon}>Icon</NeoButton>
<NeoButton reverse onclick={onClick} {icon}>Reversed</NeoButton>
<NeoButton {skeleton} onclick={onSkeleton}>Skeleton</NeoButton>
</NeoButtonGroup>
</div>

<div class="column">
<span class="label">Flat</span>
<NeoButtonGroup {vertical} {skeleton} flat>
<NeoButton flat onclick={onClick}>Button</NeoButton>
<NeoButton flat toggle onclick={onClick}>Toggle</NeoButton>
<NeoButton flat disabled onclick={onClick}>Disabled</NeoButton>
<NeoButton flat {loading} onclick={onLoading}>Loading</NeoButton>
<NeoButton flat {loading} onclick={onLoading} {icon} />
<NeoButton flat onclick={onClick} {icon}>Icon</NeoButton>
<NeoButton flat reverse onclick={onClick} {icon}>Reversed</NeoButton>
<NeoButton flat {skeleton} onclick={onSkeleton}>Skeleton</NeoButton>
</NeoButtonGroup>
</div>
{#snippet buttons()}
<NeoButton onclick={onClick}>Button</NeoButton>
<NeoButton toggle onclick={onClick}>Toggle</NeoButton>
<NeoButton disabled onclick={onClick}>Disabled</NeoButton>
<NeoButton {loading} onclick={onLoading}>Loading</NeoButton>
<NeoButton {loading} onclick={onLoading} {icon} />
<NeoButton onclick={onClick} {icon}>Icon</NeoButton>
<NeoButton reverse onclick={onClick} {icon}>Reversed</NeoButton>
<NeoButton {skeleton} onclick={onSkeleton}>Skeleton</NeoButton>
{/snippet}

<div class="column">
<span class="label">Text</span>
<NeoButtonGroup {vertical} {skeleton} text>
<NeoButton text onclick={onClick}>Button</NeoButton>
<NeoButton text toggle onclick={onClick}>Toggle</NeoButton>
<NeoButton text disabled onclick={onClick}>Disabled</NeoButton>
<NeoButton text {loading} onclick={onLoading}>Loading</NeoButton>
<NeoButton text {loading} onclick={onLoading} {icon} />
<NeoButton text onclick={onClick} {icon}>Icon</NeoButton>
<NeoButton text reverse onclick={onClick} {icon}>Reversed</NeoButton>
<NeoButton text {skeleton} onclick={onSkeleton}>Skeleton</NeoButton>
</NeoButtonGroup>
</div>
{#snippet group(props: NeoButtonGroupContext = {})}
<NeoButtonGroup {vertical} {skeleton} {...props}>
{@render buttons()}
</NeoButtonGroup>
{/snippet}

<div class="column">
<span class="label">Glass</span>
<SphereBackdrop>
<NeoButtonGroup {vertical} {skeleton} glass>
<NeoButton onclick={onClick}>Button</NeoButton>
<NeoButton toggle onclick={onClick}>Toggle</NeoButton>
<NeoButton disabled onclick={onClick}>Disabled</NeoButton>
<NeoButton {loading} onclick={onLoading}>Loading</NeoButton>
<NeoButton {loading} onclick={onLoading} {icon} />
<NeoButton onclick={onClick} {icon}>Icon</NeoButton>
<NeoButton reverse onclick={onClick} {icon}>Reversed</NeoButton>
<NeoButton {skeleton} onclick={onSkeleton}>Skeleton</NeoButton>
</NeoButtonGroup>
</SphereBackdrop>
</div>
<div class="row">
{#each columns as { label, props }}
<div class="column">
<span class="label">{label}</span>

{#if props?.glass}
<SphereBackdrop>{@render group(props)}</SphereBackdrop>
{:else}
{@render group(props)}
{/if}
</div>
{/each}

<div class="column">
<span class="label">Pulse</span>
Expand Down
107 changes: 32 additions & 75 deletions demo/components/DemoButtons.svelte
Original file line number Diff line number Diff line change
@@ -1,92 +1,49 @@
<script lang="ts">
import SphereBackdrop from '../utils/SphereBackdrop.svelte';
import { useButtonState } from '../utils/use-button-state.svelte';
import type { NeoButtonProps } from '~/buttons/neo-button.model';
import NeoButton from '~/buttons/NeoButton.svelte';
import IconAccount from '~/icons/IconAccount.svelte';
const onClick = (...args: any) => {
console.info(...args);
};
const { onClick, loading: loading$, onLoading, skeleton: skeleton$, onSkeleton } = useButtonState('DemoButtonClick');
const loading = $derived.by(loading$);
const skeleton = $derived.by(skeleton$);
let loading = $state(false);
const onLoading = (e: MouseEvent, checked?: boolean, duration = 5000) => {
loading = !loading;
setTimeout(() => {
loading = !loading;
}, duration);
onClick(e);
};
let skeleton = $state(false);
const onSkeleton = (e: MouseEvent, checked?: boolean, duration = 5000) => {
skeleton = !skeleton;
setTimeout(() => {
skeleton = !skeleton;
}, duration);
onClick(e);
};
const columns = [
{ label: 'Default' },
{ label: 'Rounded', props: { rounded: true } },
{ label: 'Flat', props: { flat: true } },
{ label: 'Text', props: { text: true } },
];
</script>

{#snippet icon()}
<IconAccount />
{/snippet}

<div class="row">
<div class="column">
<span class="label">Default</span>
<NeoButton onclick={onClick}>Button</NeoButton>
<NeoButton toggle onclick={onClick}>Toggle</NeoButton>
<NeoButton disabled onclick={onClick}>Disabled</NeoButton>
<NeoButton {loading} onclick={onLoading}>Loading</NeoButton>
<NeoButton {loading} onclick={onLoading} {icon} />
<NeoButton onclick={onClick} {icon}>Icon</NeoButton>
<NeoButton reverse onclick={onClick} {icon}>Reversed</NeoButton>
<NeoButton {loading} pulse onclick={onLoading}>Pulse</NeoButton>
<NeoButton coalesce onclick={onClick}>Coalesce</NeoButton>
<NeoButton {skeleton} onclick={onSkeleton}>Skeleton</NeoButton>
</div>

<div class="column">
<span class="label">Rounded</span>
<NeoButton rounded onclick={onClick}>Button</NeoButton>
<NeoButton rounded toggle onclick={onClick}>Toggle</NeoButton>
<NeoButton rounded disabled onclick={onClick}>Disabled</NeoButton>
<NeoButton rounded {loading} onclick={onLoading}>Loading</NeoButton>
<NeoButton rounded {loading} onclick={onLoading} {icon} />
<NeoButton rounded onclick={onClick} {icon}>Icon</NeoButton>
<NeoButton rounded reverse onclick={onClick} {icon}>Reversed</NeoButton>
<NeoButton rounded {loading} pulse onclick={onLoading}>Pulse</NeoButton>
<NeoButton rounded coalesce onclick={onClick}>Coalesce</NeoButton>
<NeoButton {skeleton} onclick={onSkeleton}>Skeleton</NeoButton>
</div>

<div class="column">
<span class="label">Flat</span>
<NeoButton flat onclick={onClick}>Button</NeoButton>
<NeoButton flat toggle onclick={onClick}>Toggle</NeoButton>
<NeoButton flat disabled onclick={onClick}>Disabled</NeoButton>
<NeoButton flat {loading} onclick={onLoading}>Loading</NeoButton>
<NeoButton flat {loading} onclick={onLoading} {icon} />
<NeoButton flat onclick={onClick} {icon}>Icon</NeoButton>
<NeoButton flat reverse onclick={onClick} {icon}>Reversed</NeoButton>
<NeoButton flat {loading} pulse onclick={onLoading}>Pulse</NeoButton>
<NeoButton flat coalesce onclick={onClick}>Coalesce</NeoButton>
<NeoButton flat {skeleton} onclick={onSkeleton}>Skeleton</NeoButton>
</div>
{#snippet buttons(opts: NeoButtonProps = {})}
<NeoButton {...opts} onclick={onClick}>Button</NeoButton>
<NeoButton {...opts} toggle onclick={onClick}>Toggle</NeoButton>
<NeoButton {...opts} disabled onclick={onClick}>Disabled</NeoButton>
<NeoButton {...opts} {loading} onclick={onLoading}>Loading</NeoButton>
<NeoButton {...opts} {loading} onclick={onLoading} {icon} />
<NeoButton {...opts} onclick={onClick} {icon}>Icon</NeoButton>
<NeoButton {...opts} reverse onclick={onClick} {icon}>Reversed</NeoButton>
<NeoButton {...opts} {loading} pulse onclick={onLoading}>Pulse</NeoButton>
<NeoButton {...opts} coalesce onclick={onClick}>Coalesce</NeoButton>
<NeoButton {...opts} {skeleton} onclick={onSkeleton}>Skeleton</NeoButton>
{/snippet}

<div class="column">
<span class="label">Text</span>
<NeoButton text onclick={onClick}>Button</NeoButton>
<NeoButton text toggle onclick={onClick}>Toggle</NeoButton>
<NeoButton text disabled onclick={onClick}>Disabled</NeoButton>
<NeoButton text {loading} onclick={onLoading}>Loading</NeoButton>
<NeoButton text {loading} onclick={onLoading} {icon} />
<NeoButton text onclick={onClick} {icon}>Icon</NeoButton>
<NeoButton text reverse onclick={onClick} {icon}>Reversed</NeoButton>
<NeoButton text {loading} pulse onclick={onLoading}>Pulse</NeoButton>
<NeoButton text coalesce onclick={onClick}>Coalesce</NeoButton>
<NeoButton text {skeleton} onclick={onSkeleton}>Skeleton</NeoButton>
</div>
<div class="row">
{#each columns as { label, props }}
<div class="column">
<span class="label">{label}</span>
{@render buttons(props)}
</div>
{/each}

<div class="column">
<span class="label">Glass</span>
Expand Down
Loading

0 comments on commit 9864b86

Please sign in to comment.