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: stack component #18

Merged
merged 1 commit into from
Nov 18, 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
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