Skip to content

Commit

Permalink
feat: stack component
Browse files Browse the repository at this point in the history
  • Loading branch information
jrasm91 committed Nov 18, 2024
1 parent 0371a53 commit 546a7f7
Show file tree
Hide file tree
Showing 18 changed files with 695 additions and 531 deletions.
43 changes: 43 additions & 0 deletions src/docs/components/DecorativeBlock.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script lang="ts">
import type { Color, Size } from '$lib/types.js';
import { cleanClass } from '$lib/utils.js';
import { tv } from 'tailwind-variants';
type Props = {
color?: Color;
width?: Size;
height?: Size;
};
const { width = 'medium', height = 'medium', color = 'primary' }: Props = $props();
const styles = tv({
base: '',
variants: {
color: {
primary: 'bg-primary',
secondary: 'bg-dark',
success: 'bg-success',
danger: 'bg-danger',
warning: 'bg-warning',
info: 'bg-info',
},
width: {
tiny: 'w-4',
small: 'w-8',
medium: 'w-16',
large: 'w-32',
giant: 'w-64',
},
height: {
tiny: 'h-4',
small: 'h-8',
medium: 'h-16',
large: 'h-32',
giant: 'h-64',
},
},
});
</script>

<div class={cleanClass(styles({ width, height, color }))}></div>
5 changes: 4 additions & 1 deletion src/docs/components/DualThemeLayout.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { DisplayOption, Theme } from '$docs/constants.js';
import { Icon } from '$lib/index.js';
import { VStack } from '@immich/ui';
import { mdiCompare, mdiWeatherNight, mdiWeatherSunny } from '@mdi/js';
import type { Snippet } from 'svelte';
Expand Down Expand Up @@ -60,7 +61,9 @@
{#each displayThemes as theme}
<div class="flex flex-col gap-4 {theme} h-full bg-light p-8">
<h2 class="text-2xl capitalize text-dark">{theme}</h2>
{@render component({ theme })}
<VStack gap={4}>
{@render component({ theme })}
</VStack>
</div>
{/each}
</div>
Expand Down
1 change: 1 addition & 0 deletions src/docs/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ export const routes: Route[] = [
{ name: 'Heading', link: '/examples/heading' },
{ name: 'IconButton', link: '/examples/icon-button' },
{ name: 'Logo', link: '/examples/logo' },
{ name: 'Stack', link: '/examples/stack' },
{ name: 'Text', link: '/examples/text' },
];
2 changes: 1 addition & 1 deletion src/lib/components/Card/Card.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script lang="ts">
import { withChildrenSnippets } from '$lib/common/use-context.svelte.js';
import IconButton from '$lib/components/IconButton/IconButton.svelte';
import { ContextKey } from '$lib/constants.js';
import type { Color, Shape } from '$lib/types.js';
import { cleanClass } from '$lib/utils.js';
import { IconButton } from '@immich/ui';
import { mdiChevronDown } from '@mdi/js';
import { type Snippet } from 'svelte';
import type { HTMLAttributes } from 'svelte/elements';
Expand Down
10 changes: 10 additions & 0 deletions src/lib/components/Stack/HStack.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script lang="ts">
import Stack from '$lib/components/Stack/Stack.svelte';
import type { HStackProps } from '$lib/types.js';
const { class: className, children, ...props }: HStackProps = $props();
</script>

<Stack direction="row" class={className} {...props}>
{@render children()}
</Stack>
68 changes: 68 additions & 0 deletions src/lib/components/Stack/Stack.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<script lang="ts">
import type { StackProps } from '$lib/types.js';
import { cleanClass } from '$lib/utils.js';
import { tv } from 'tailwind-variants';
const {
align,
direction = 'column',
wrap = false,
class: className,
gap = 2,
children,
}: StackProps = $props();
const styles = tv({
base: 'flex gap-2',
variants: {
direction: {
row: 'flex-row',
column: 'flex-col',
},
align: {
start: 'items-start',
center: 'items-center',
end: 'items-end',
},
fullWidth: {
true: 'w-full',
false: '',
},
fullHeight: {
true: 'h-full',
false: '',
},
gap: {
0: 'gap-0',
1: 'gap-1',
2: 'gap-2',
3: 'gap-3',
4: 'gap-4',
5: 'gap-5',
6: 'gap-6',
7: 'gap-7',
8: 'gap-8',
},
wrap: {
true: 'flex-wrap',
false: '',
},
},
});
</script>

<div
class={cleanClass(
styles({
align,
direction,
gap,
wrap,
fullWidth: direction === 'row',
fullHeight: direction === 'column',
}),
className,
)}
>
{@render children()}
</div>
10 changes: 10 additions & 0 deletions src/lib/components/Stack/VStack.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script lang="ts">
import Stack from '$lib/components/Stack/Stack.svelte';
import type { VStackProps } from '$lib/types.js';
const { class: className, children, ...props }: VStackProps = $props();
</script>

<Stack direction="column" class={className} {...props}>
{@render children()}
</Stack>
3 changes: 3 additions & 0 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ export { default as Heading } from '$lib/components/Heading/Heading.svelte';
export { default as Icon } from '$lib/components/Icon/Icon.svelte';
export { default as IconButton } from '$lib/components/IconButton/IconButton.svelte';
export { default as Logo } from '$lib/components/Logo/Logo.svelte';
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 Text } from '$lib/components/Text/Text.svelte';
export * from '$lib/types.js';
16 changes: 16 additions & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { Snippet } from 'svelte';
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';

export type Color = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info';
export type Size = 'tiny' | 'small' | 'medium' | 'large' | 'giant';
export type HeadingSize = Size | 'title';
export type Shape = 'rectangle' | 'semi-round' | 'round';
export type Variants = 'filled' | 'outline' | 'ghost' | 'hero';
export type Gap = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;

type ButtonOrAnchor =
| ({ href?: never } & HTMLButtonAttributes)
Expand Down Expand Up @@ -35,3 +37,17 @@ export type IconProps = {

export type IconButtonProps = ButtonBaseProps & IconProps;
export type ButtonProps = ButtonBaseProps & { fullWidth?: boolean };

type StackBaseProps = {
class?: string;
children: Snippet;
align?: 'start' | 'center' | 'end';
gap?: Gap;
wrap?: boolean;
};

export type StackProps = StackBaseProps & {
direction?: 'row' | 'column';
};
export type HStackProps = StackBaseProps;
export type VStackProps = StackBaseProps;
114 changes: 50 additions & 64 deletions src/routes/examples/alert/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,78 +2,64 @@
import DualThemeLayout from '$docs/components/DualThemeLayout.svelte';
import Lorem from '$docs/components/Lorem.svelte';
import { colors } from '$docs/constants.js';
import Card from '$lib/components/Card/Card.svelte';
import CardBody from '$lib/components/Card/CardBody.svelte';
import CardHeader from '$lib/components/Card/CardHeader.svelte';
import CardTitle from '$lib/components/Card/CardTitle.svelte';
import { Alert } from '@immich/ui';
import { Alert, Card, CardBody, CardHeader, CardTitle, VStack } from '@immich/ui';
import { mdiHelpCircleOutline } from '@mdi/js';
</script>

<DualThemeLayout name="Alert">
{#snippet component()}
<div class="flex flex-col gap-4">
<section class="flex flex-col gap-4">
<Card>
<CardHeader>
<CardTitle>Basic</CardTitle>
</CardHeader>
<CardBody>
<div class="flex flex-wrap gap-4">
{#each colors as color}
<Alert {color} title="This is an alert" />
{/each}
</div>
</CardBody>
</Card>
</section>
<Card>
<CardHeader>
<CardTitle>Basic</CardTitle>
</CardHeader>
<CardBody>
<VStack>
{#each colors as color}
<Alert {color} title="This is an alert" />
{/each}
</VStack>
</CardBody>
</Card>

<section class="flex flex-col gap-4">
<Card>
<CardHeader>
<CardTitle>Colors</CardTitle>
</CardHeader>
<CardBody>
<div class="flex flex-wrap gap-4">
{#each colors as color}
<Alert {color} title="This is an alert">
<Lorem />
</Alert>
{/each}
</div>
</CardBody>
</Card>
</section>

<section class="flex flex-col gap-4">
<Card>
<CardHeader>
<CardTitle>Custom icon</CardTitle>
</CardHeader>
<CardBody>
<Alert icon={mdiHelpCircleOutline} title="This is an alert">
<Card>
<CardHeader>
<CardTitle>Colors</CardTitle>
</CardHeader>
<CardBody>
<VStack>
{#each colors as color}
<Alert {color} title="This is an alert">
<Lorem />
</Alert>
</CardBody>
</Card>
</section>
{/each}
</VStack>
</CardBody>
</Card>

<Card>
<CardHeader>
<CardTitle>Custom icon</CardTitle>
</CardHeader>
<CardBody>
<Alert icon={mdiHelpCircleOutline} title="This is an alert">
<Lorem />
</Alert>
</CardBody>
</Card>

<section class="flex flex-col gap-4">
<Card>
<CardHeader>
<CardTitle>Colors</CardTitle>
</CardHeader>
<CardBody>
<div class="flex flex-wrap gap-4">
{#each colors as color}
<Alert {color} title="This is an alert">
<Lorem />
</Alert>
{/each}
</div>
</CardBody>
</Card>
</section>
</div>
<Card>
<CardHeader>
<CardTitle>Colors</CardTitle>
</CardHeader>
<CardBody>
<VStack>
{#each colors as color}
<Alert {color} title="This is an alert">
<Lorem />
</Alert>
{/each}
</VStack>
</CardBody>
</Card>
{/snippet}
</DualThemeLayout>
Loading

0 comments on commit 546a7f7

Please sign in to comment.