Skip to content

Commit

Permalink
feat(button-groups): adds button groups
Browse files Browse the repository at this point in the history
  • Loading branch information
dvcol committed Nov 8, 2024
1 parent 6a33674 commit 92c23bf
Show file tree
Hide file tree
Showing 18 changed files with 654 additions and 149 deletions.
31 changes: 13 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,23 @@
Neomorphic ui library for svelte 5

## TODO
- buttons
- toggle
- skeleton
- border loading
- tags
- badge
- navbar
- card
- border loading
- skeleton
- images
- videos
- carousel
- avatar
- badge
- tags
- badge
- button groups
- card
- border loading
- skeleton
- images
- videos
- carousel
- navbar
- switch
- loading
- border loading
- skeleton
- radio
- checkbox
- tooltip
- popconfirm
- popselect
- Inputs
- validation
- loading
Expand All @@ -46,12 +38,15 @@ Neomorphic ui library for svelte 5
- time/date
- floating label


- Progress/Loading
- bar
- circle
- border
- background
- tooltip
- popconfirm
- popselect

- Alerts
- notification
- simple message
Expand Down
116 changes: 69 additions & 47 deletions demo/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,84 @@
import '~/styles/reset.scss';
import '~/styles/theme.scss';
import DemoButtons from './components/DemoButtons.svelte';
import { wait } from '@dvcol/common-utils/common/promise';
import { RouterView } from '@dvcol/svelte-simple-router/components';
import { fade } from 'svelte/transition';
import { router } from './router/router.js';
import { Route } from './router/routes';
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';
let transitionIn = $state(false);
let transitionOut = $state(false);
const onTransition = () => {
transitionOut = true;
setTimeout(() => {
transitionOut = false;
transitionIn = true;
setTimeout(() => {
transitionIn = false;
}, 750);
}, 750);
const transition: TransitionProps = {
in: fade,
out: fade,
params: { in: { delay: 200, duration: 200 }, out: { duration: 200 } },
skipFirst: true,
};
const active = $derived(router.route?.name);
let transitioning = $state(false);
const onChange = async () => {
transitioning = true;
await wait(150);
};
const onLoaded = async () => {
await wait(350);
transitioning = false;
};
let dark = $state(window.matchMedia('(prefers-color-scheme: dark)').matches);
const initial = localStorage.getItem('theme');
let dark = $state(initial ? initial === 'dark' : window.matchMedia('(prefers-color-scheme: dark)').matches);
let remember = $state(!!localStorage.getItem('theme'));
$effect(() => {
if (dark) {
document.documentElement.setAttribute('theme', 'dark');
} else {
document.documentElement.setAttribute('theme', 'light');
}
const theme = dark ? 'dark' : 'light';
document.documentElement.setAttribute('theme', theme);
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">
<NeoButton onclick={onTransition}>transition</NeoButton>
<NeoButton toggle bind:checked={dark}>
{#snippet icon()}
{#if dark}
<IconMoon />
{:else}
<IconSun />
{/if}
{/snippet}
<span>{dark ? 'Dark' : 'Light'} Theme</span>
</NeoButton>
<NeoButtonGroup>
{#each routes as route}
<NeoButton checked={active === route} onclick={() => router.push({ name: route })}>
{route}
</NeoButton>
{/each}
</NeoButtonGroup>

<NeoButtonGroup>
<NeoButton toggle bind:checked={dark}>
{#snippet icon()}
{#if dark}
<IconMoon />
{:else}
<IconSun />
{/if}
{/snippet}
<span>{dark ? 'Dark' : 'Light'} Theme</span>
</NeoButton>
<NeoButton toggle bind:checked={remember}>Remember</NeoButton>
</NeoButtonGroup>
</div>

<div class="row" class:transition-in={transitionIn} class:transition-out={transitionOut}>
<DemoButtons />
</div>
<main class="row view" class:transition={transitioning}>
<RouterView {router} {transition} {onChange} {onLoaded} />
</main>
</div>

<style lang="scss">
Expand All @@ -61,26 +90,19 @@
@include flex.row($center: true, $gap: var(--gap-xl));
}
.view {
min-height: 70vh;
}
.container {
@include flex.column($gap: var(--gap-xl));
padding: 1rem;
:global(.transition-out *),
:global(.transition-out *::before),
:global(.transition-out *::after) {
:global(.transition *),
:global(.transition *::before),
:global(.transition *::after) {
box-shadow: var(--box-shadow-flat) !important;
transition:
all 0.5s ease,
box-shadow 0.5s ease-in-out;
}
:global(.transition-in *),
:global(.transition-in *::before),
:global(.transition-in *::after) {
transition:
all 0.5s ease,
box-shadow 0.5s ease-in-out;
}
:global(.rotate) {
Expand Down
154 changes: 154 additions & 0 deletions demo/components/DemoButtonGroups.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<script lang="ts">
import { useWatchMedia } from '@dvcol/svelte-utils/media';
import SphereBackdrop from '../utils/SphereBackdrop.svelte';
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 { matches } = useWatchMedia('(max-width: 1550px)');
const vertical = $derived.by(matches);
</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>

<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>

<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="column">
<span class="label">Pulse</span>
<NeoButtonGroup {skeleton} pulse>
<NeoButton onclick={onClick}>Button</NeoButton>
<NeoButton toggle onclick={onClick}>Toggle</NeoButton>
<NeoButton {loading} onclick={onLoading} {icon} />
</NeoButtonGroup>

<span class="label">Coalesce</span>
<NeoButtonGroup {skeleton} coalesce>
<NeoButton onclick={onClick}>Button</NeoButton>
<NeoButton disabled onclick={onClick}>Disabled</NeoButton>
<NeoButton {loading} onclick={onLoading}>Loading</NeoButton>
</NeoButtonGroup>
</div>
</div>

<style lang="scss">
@use 'src/lib/styles/common/flex' as flex;
.column {
@include flex.column($center: true, $gap: var(--gap-lg));
}
.row {
@include flex.row($gap: var(--gap-xl));
}
@media (width > 1550px) {
.column {
@include flex.row($gap: var(--gap-xxl));
}
.row {
@include flex.column($center: true, $gap: var(--gap-xl));
}
.label {
min-width: 4.5rem;
}
}
</style>
6 changes: 3 additions & 3 deletions demo/components/DemoButtons.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@
@use 'src/lib/styles/common/flex' as flex;
.column {
@include flex.column($center: true, $gap: var(--gap-md));
@include flex.column($center: true, $gap: var(--gap-lg));
}
.row {
@include flex.row;
@include flex.row($gap: var(--gap-xl));
}
@media (width > 1550px) {
Expand All @@ -140,7 +140,7 @@
}
.row {
@include flex.column($center: true, $gap: var(--gap-lg));
@include flex.column($center: true, $gap: var(--gap-xl));
}
.label {
Expand Down
5 changes: 5 additions & 0 deletions demo/router/router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Router } from '@dvcol/svelte-simple-router';

import { options } from './routes.js';

export const router = new Router(options);
Loading

0 comments on commit 92c23bf

Please sign in to comment.