Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: switch #49

Merged
merged 1 commit into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/docs/components/ExampleLayout.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
<script lang="ts">
import Examples from '$docs/components/Examples.svelte';
import { Theme, type ExampleItem } from '$docs/constants.js';
import { Scrollable, Stack } from '@immich/ui';
import { Heading, Scrollable, Stack } from '@immich/ui';
import type { Snippet } from 'svelte';

type Props = {
name: string;
examples: ExampleItem[];
children?: Snippet;
};

const { name, examples }: Props = $props();
const { name, examples, children }: Props = $props();
</script>

<div class="flex h-full flex-col">
Expand All @@ -25,8 +27,10 @@
</div>
</nav>

<Scrollable>
<Stack gap={4} class="max-w-screen-lg p-4">
<Scrollable class="p-4">
<Heading size="large">{name}</Heading>
{@render children?.()}
<Stack gap={4} class="mt-4 max-w-screen-md">
<Examples theme={Theme.Dark} {examples} />
</Stack>
</Scrollable>
Expand Down
21 changes: 14 additions & 7 deletions src/docs/components/Lorem.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
<script lang="ts">
type Props = { count?: number };
const { count = 1 }: Props = $props();

const lorem =
'Lorem ipsum dolor sit amet consectetur adipisicing elit. A ipsam tenetur accusantium impedit beatae omnis necessitatibus. Voluptatum blanditiis libero impedit, harum eius inventore nihil, officia voluptate dolorum error consequatur animi.';

const make = (value: number) => {
let content = '';
for (let i = 0; i < value; i++) {
content += lorem;
}
return content;
};

const text = $derived(make(count));
</script>

{#each Array(count) as i}
<p data-index={i}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. A ipsam tenetur accusantium impedit
beatae omnis necessitatibus. Voluptatum blanditiis libero impedit, harum eius inventore nihil,
officia voluptate dolorum error consequatur animi.
</p>
{/each}
{text}
4 changes: 4 additions & 0 deletions src/docs/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import {
mdiListBoxOutline,
mdiMenu,
mdiNumeric,
mdiPanVertical,
mdiPartyPopper,
mdiToggleSwitch,
mdiViewSequential,
} from '@mdi/js';
import type { Component } from 'svelte';
Expand Down Expand Up @@ -47,6 +49,7 @@ export const componentGroups = [
{ name: 'AppShell', icon: mdiApplicationOutline },
{ name: 'Card', icon: mdiCardOutline },
{ name: 'Navbar', icon: mdiMenu },
{ name: 'Scrollable', icon: mdiPanVertical },
{ name: 'Stack', icon: mdiViewSequential },
],
},
Expand All @@ -61,6 +64,7 @@ export const componentGroups = [
{ name: 'Input', icon: mdiFormTextbox },
{ name: 'LoadingSpinner', icon: mdiDotsCircle },
{ name: 'PasswordInput', icon: mdiFormTextboxPassword },
{ name: 'Switch', icon: mdiToggleSwitch },
],
},
{
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/AppShell/AppShellSidebar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<Child for={ChildKey.AppShell} as={ChildKey.AppShellSidebar}>
<Scrollable
class={cleanClass(
'hidden h-full shrink-0 border-gray-200 dark:border-gray-700 lg:block',
'hidden h-full w-min shrink-0 border-gray-200 dark:border-gray-700 lg:block',
className,
noBorder || 'border-r',
)}
Expand Down
3 changes: 2 additions & 1 deletion src/lib/components/Scrollable/Scrollable.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@
const { class: className, children }: Props = $props();
</script>

<div class={cleanClass('immich-scrollbar overflow-y-auto', className)}>
<div class={cleanClass('immich-scrollbar h-full w-full overflow-auto', className)}>
{@render children?.()}
</div>

<style>
/* width */
.immich-scrollbar::-webkit-scrollbar {
width: 8px;
height: 8px;
}

/* Track */
Expand Down
99 changes: 99 additions & 0 deletions src/lib/components/Switch/Switch.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<script lang="ts">
import { getFieldContext } from '$lib/common/context.svelte.js';
import type { Color } from '$lib/types.js';
import { cleanClass } from '$lib/utils.js';
import type { HTMLInputAttributes } from 'svelte/elements';
import { tv } from 'tailwind-variants';

type Props = {
checked?: boolean;
color?: Color;
disabled?: boolean;
class?: string;
onToggle?: ((checked: boolean) => void) | undefined;
} & HTMLInputAttributes;

let {
checked = $bindable(false),
class: className,
color = 'primary',
onToggle = undefined,
...restProps
}: Props = $props();

const {
label,
readOnly = false,
required = false,
disabled = false,
} = $derived(getFieldContext());

const enabled = $derived(checked && !disabled);

const handleToggle = (event: Event) => onToggle?.((event.target as HTMLInputElement).checked);

const wrapper = tv({
base: 'relative flex flex-col justify-center',
variants: {
disabled: {
true: 'cursor-not-allowed',
false: 'cursor-pointer',
},
},
});

const bar = tv({
base: 'w-12 h-3 my-2 rounded-full border border-transparent',
variants: {
fillColor: {
default: 'bg-gray-400',
primary: 'bg-primary/50',
secondary: 'bg-dark/50',
success: 'bg-success/50',
danger: 'bg-danger/50',
warning: 'bg-warning/50',
info: 'bg-info/50',
},
},
});

const dot = tv({
base: 'absolute transition-colors h-6 w-6 rounded-full transition-transform duration-[400ms]',
variants: {
checked: {
true: 'translate-x-6',
false: '',
},
fillColor: {
default: 'bg-gray-600',
primary: 'bg-primary',
secondary: 'bg-dark',
success: 'bg-success',
danger: 'bg-danger',
warning: 'bg-warning',
info: 'bg-info',
},
},
});
</script>

<label class={cleanClass(className)}>
{label}
<span class={wrapper({ disabled })}>
<input
class="hidden"
type="checkbox"
bind:checked
onclick={handleToggle}
{required}
aria-required={required}
{disabled}
aria-disabled={disabled}
readonly={readOnly}
aria-readonly={readOnly}
{...restProps}
/>
<span class={bar({ fillColor: enabled ? color : 'default' })}> </span>
<span class={dot({ checked: enabled, fillColor: enabled ? color : 'default' })}></span>
</span>
</label>
1 change: 1 addition & 0 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export { default as HStack } from '$lib/components/Stack/HStack.svelte';
export { default as Stack } from '$lib/components/Stack/Stack.svelte';
export { default as VStack } from '$lib/components/Stack/VStack.svelte';
export { default as SupporterBadge } from '$lib/components/SupporterBadge/SupporterBadge.svelte';
export { default as Switch } from '$lib/components/Switch/Switch.svelte';
export { default as Text } from '$lib/components/Text/Text.svelte';
export * from '$lib/types.js';
export * from '$lib/utilities/byte-units.js';
5 changes: 4 additions & 1 deletion src/routes/components/button/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import ExampleLayout from '$docs/components/ExampleLayout.svelte';
import { Text } from '@immich/ui';
import BasicExample from './BasicExample.svelte';
import basicExample from './BasicExample.svelte?raw';
import ColorExample from './ColorExample.svelte';
Expand Down Expand Up @@ -35,4 +36,6 @@
];
</script>

<ExampleLayout name="Button" {examples} />
<ExampleLayout name="Button" {examples}>
<Text>A button component, which can also be used to render links</Text>
</ExampleLayout>
5 changes: 4 additions & 1 deletion src/routes/components/field/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
<script lang="ts">
import ExampleLayout from '$docs/components/ExampleLayout.svelte';
import { Text } from '@immich/ui';
import BasicExample from './BasicExample.svelte';
import basicExample from './BasicExample.svelte?raw';

const examples = [{ title: 'Basic', code: basicExample, component: BasicExample }];
</script>

<ExampleLayout name="Field" {examples} />
<ExampleLayout name="Field" {examples}>
<Text>A metadata component for tracking common form field information</Text>
</ExampleLayout>
2 changes: 1 addition & 1 deletion src/routes/components/navbar/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
];
</script>

<ExampleLayout name="Basic" {examples} />
<ExampleLayout name="Navbar" {examples} />
2 changes: 1 addition & 1 deletion src/routes/components/navbar/BasicExample.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
import { mdiHome } from '@mdi/js';
</script>

<div class="w-[200px]">
<div class="max-w-[200px]">
<NavbarItem icon={mdiHome} title="Home" href="#" active />
</div>
3 changes: 1 addition & 2 deletions src/routes/components/navbar/GroupExample.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script lang="ts">
import NavbarGroup from '$lib/components/Navbar/NavbarGroup.svelte';
import { NavbarItem } from '@immich/ui';
import { NavbarGroup, NavbarItem } from '@immich/ui';
import { mdiButtonPointer, mdiCardOutline, mdiHome } from '@mdi/js';
</script>

Expand Down
9 changes: 9 additions & 0 deletions src/routes/components/scrollable/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script lang="ts">
import ExampleLayout from '$docs/components/ExampleLayout.svelte';
import BasicExample from './BasicExample.svelte';
import basicExample from './BasicExample.svelte?raw';

const examples = [{ title: 'Basic', code: basicExample, component: BasicExample }];
</script>

<ExampleLayout name="Scrollable" {examples} />
22 changes: 22 additions & 0 deletions src/routes/components/scrollable/BasicExample.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="ts">
import Lorem from '$docs/components/Lorem.svelte';
import { Heading, Scrollable, Stack, Text } from '@immich/ui';
</script>

<Stack gap={4}>
<Heading size="tiny">Vertical</Heading>
<div class="h-64 w-32">
<Scrollable>
<Text>
<Lorem count={5} />
</Text>
</Scrollable>
</div>

<Heading size="tiny">Horizontal</Heading>
<Scrollable>
<Text class="h-8 w-[2000px]">
<Lorem />
</Text>
</Scrollable>
</Stack>
20 changes: 20 additions & 0 deletions src/routes/components/switch/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script lang="ts">
import ExampleLayout from '$docs/components/ExampleLayout.svelte';
import { Text } from '@immich/ui';
import BasicExample from './BasicExample.svelte';
import basicExample from './BasicExample.svelte?raw';
import ColorExample from './ColorExample.svelte';
import colorExample from './ColorExample.svelte?raw';
import FormExample from './FormExample.svelte';
import formExample from './FormExample.svelte?raw';

const examples = [
{ title: 'Basic', code: basicExample, component: BasicExample },
{ title: 'Colors', code: colorExample, component: ColorExample },
{ title: 'Form', code: formExample, component: FormExample },
];
</script>

<ExampleLayout name="Switch" {examples}>
<Text>A boolean input element</Text>
</ExampleLayout>
11 changes: 11 additions & 0 deletions src/routes/components/switch/BasicExample.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script>
import { Field, Stack, Switch } from '@immich/ui';
</script>

<Stack>
<Switch />
<Switch checked />
<Field disabled>
<Switch />
</Field>
</Stack>
12 changes: 12 additions & 0 deletions src/routes/components/switch/ColorExample.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script lang="ts">
import { Stack, Switch } from '@immich/ui';
</script>

<Stack>
<Switch color="primary" checked />
<Switch color="secondary" checked />
<Switch color="success" checked />
<Switch color="info" checked />
<Switch color="warning" checked />
<Switch color="danger" checked />
</Stack>
17 changes: 17 additions & 0 deletions src/routes/components/switch/FormExample.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script>
import { Field, Stack, Switch, Text } from '@immich/ui';
</script>

<Stack>
<Field label="Support Immich">
<Switch class="flex justify-between" checked />
</Field>
<Field label="Advanced features">
<Switch class="flex justify-between" />
</Field>
<Field label="Sell my privacy" disabled>
<Switch class="flex justify-between">
<Text>Disabled</Text>
</Switch>
</Field>
</Stack>
Loading