mirror of
https://github.com/immich-app/immich.git
synced 2024-12-29 15:11:58 +00:00
feat: add storybook
This commit is contained in:
parent
e0ec75119f
commit
146f24eaae
9 changed files with 8659 additions and 333 deletions
|
@ -6,6 +6,7 @@ module.exports = {
|
|||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:svelte/recommended',
|
||||
'plugin:unicorn/recommended',
|
||||
'plugin:storybook/recommended',
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint'],
|
||||
|
|
2
web/.gitignore
vendored
2
web/.gitignore
vendored
|
@ -6,3 +6,5 @@ node_modules
|
|||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
*storybook.log
|
||||
|
|
17
web/.storybook/main.ts
Normal file
17
web/.storybook/main.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import type { StorybookConfig } from '@storybook/sveltekit';
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx|svelte)'],
|
||||
addons: [
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
'@chromatic-com/storybook',
|
||||
'@storybook/addon-interactions',
|
||||
'@storybook/addon-svelte-csf',
|
||||
],
|
||||
framework: {
|
||||
name: '@storybook/sveltekit',
|
||||
options: {},
|
||||
},
|
||||
};
|
||||
export default config;
|
15
web/.storybook/preview.ts
Normal file
15
web/.storybook/preview.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import type { Preview } from '@storybook/svelte';
|
||||
import '../src/app.css';
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default preview;
|
8838
web/package-lock.json
generated
8838
web/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -20,11 +20,22 @@
|
|||
"test": "vitest --run",
|
||||
"test:cov": "vitest --coverage",
|
||||
"test:watch": "vitest dev",
|
||||
"prepare": "svelte-kit sync"
|
||||
"prepare": "svelte-kit sync",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"build-storybook": "storybook build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@chromatic-com/storybook": "^1.5.0",
|
||||
"@faker-js/faker": "^8.4.1",
|
||||
"@socket.io/component-emitter": "^3.1.0",
|
||||
"@storybook/addon-essentials": "^8.1.5",
|
||||
"@storybook/addon-interactions": "^8.1.5",
|
||||
"@storybook/addon-links": "^8.1.5",
|
||||
"@storybook/addon-svelte-csf": "^4.1.3",
|
||||
"@storybook/blocks": "^8.1.5",
|
||||
"@storybook/svelte": "^8.1.5",
|
||||
"@storybook/sveltekit": "^8.1.5",
|
||||
"@storybook/test": "^8.1.5",
|
||||
"@sveltejs/adapter-static": "^3.0.1",
|
||||
"@sveltejs/enhanced-img": "^0.2.0",
|
||||
"@sveltejs/kit": "^2.5.2",
|
||||
|
@ -42,6 +53,7 @@
|
|||
"autoprefixer": "^10.4.17",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-storybook": "^0.8.0",
|
||||
"eslint-plugin-svelte": "^2.35.1",
|
||||
"eslint-plugin-unicorn": "^53.0.0",
|
||||
"factory.ts": "^1.4.1",
|
||||
|
@ -50,6 +62,7 @@
|
|||
"prettier-plugin-organize-imports": "^3.2.4",
|
||||
"prettier-plugin-svelte": "^3.2.1",
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"storybook": "^8.1.5",
|
||||
"svelte": "^4.2.12",
|
||||
"svelte-check": "^3.6.5",
|
||||
"tailwindcss": "^3.4.1",
|
||||
|
@ -74,8 +87,8 @@
|
|||
"lodash-es": "^4.17.21",
|
||||
"luxon": "^3.4.4",
|
||||
"socket.io-client": "^4.7.4",
|
||||
"svelte-local-storage-store": "^0.6.4",
|
||||
"svelte-i18n": "^4.0.0",
|
||||
"svelte-local-storage-store": "^0.6.4",
|
||||
"svelte-maplibre": "^0.9.0",
|
||||
"thumbhash": "^0.1.1"
|
||||
},
|
||||
|
|
68
web/src/lib/ui/Button.svelte
Normal file
68
web/src/lib/ui/Button.svelte
Normal file
|
@ -0,0 +1,68 @@
|
|||
<script lang="ts">
|
||||
import type { Color, OnBlur, OnClick, OnFocus, Shape, Size } from '$lib/ui/types';
|
||||
import type { HTMLButtonAttributes } from 'svelte/elements';
|
||||
|
||||
export let type: HTMLButtonAttributes['type'] = 'button';
|
||||
export let color: Color = 'primary';
|
||||
export let size: Size = 'md';
|
||||
export let shape: Shape = 'rounded';
|
||||
export let disabled = false;
|
||||
|
||||
export let onClick: OnClick | undefined;
|
||||
export let onFocus: OnFocus | undefined;
|
||||
export let onBlur: OnBlur | undefined;
|
||||
|
||||
let className = '';
|
||||
export { className as class };
|
||||
|
||||
const sizes: Record<Size, string> = {
|
||||
xs: 'p-0 ml-2 mr-0 align-top font-small',
|
||||
sm: 'px-4 py-2 text-sm font-medium',
|
||||
md: 'px-6 py-3 font-medium',
|
||||
lg: 'px-6 py-4 font-semibold',
|
||||
xl: 'px-8 py-6 font-large font-semibold',
|
||||
};
|
||||
|
||||
const colors: Record<Color, string> = {
|
||||
primary:
|
||||
'bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray enabled:dark:hover:bg-immich-dark-primary/80 enabled:hover:bg-immich-primary/90',
|
||||
secondary:
|
||||
'bg-gray-500 dark:bg-gray-200 text-white dark:text-immich-dark-gray enabled:hover:bg-gray-500/90 enabled:dark:hover:bg-gray-200/90',
|
||||
success: '',
|
||||
danger: '',
|
||||
warning: '',
|
||||
info: '',
|
||||
};
|
||||
|
||||
const rounded = {
|
||||
xs: 'rounded-xs',
|
||||
sm: 'rounded-sm',
|
||||
md: 'rounded-md',
|
||||
lg: 'rounded-lg',
|
||||
xl: 'rounded-xl',
|
||||
};
|
||||
|
||||
const getClasses = () => {
|
||||
const classes = [className, sizes[size], colors[color]];
|
||||
if (shape === 'rounded') {
|
||||
classes.push(rounded[size]);
|
||||
}
|
||||
|
||||
if (shape === 'circle') {
|
||||
classes.push('rounded-full');
|
||||
}
|
||||
|
||||
return classes.join(' ');
|
||||
};
|
||||
</script>
|
||||
|
||||
<button
|
||||
{type}
|
||||
{disabled}
|
||||
on:click={onClick}
|
||||
on:focus={onFocus}
|
||||
on:blur={onBlur}
|
||||
class="inline-flex items-center justify-center transition-colors disabled:cursor-not-allowed disabled:opacity-60 {getClasses()}"
|
||||
>
|
||||
<slot />
|
||||
</button>
|
9
web/src/lib/ui/types.ts
Normal file
9
web/src/lib/ui/types.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
export type Color = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info';
|
||||
|
||||
export type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
|
||||
export type Shape = 'rounded' | 'circle';
|
||||
|
||||
export type OnClick = () => void;
|
||||
export type OnBlur = () => void;
|
||||
export type OnFocus = () => void;
|
25
web/src/stories/Button.stories.svelte
Normal file
25
web/src/stories/Button.stories.svelte
Normal file
|
@ -0,0 +1,25 @@
|
|||
<script context="module">
|
||||
import Button from '$lib/ui/Button.svelte';
|
||||
import { Template } from '@storybook/addon-svelte-csf';
|
||||
export const meta = {
|
||||
title: 'Button',
|
||||
component: Button,
|
||||
};
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { Story } from '@storybook/addon-svelte-csf';
|
||||
</script>
|
||||
|
||||
<Template let:args>
|
||||
<Button {...args}>{args.text ?? 'Click me'}</Button>
|
||||
</Template>
|
||||
|
||||
<Story name="Primary" args={{}} />
|
||||
<Story name="Secondary" args={{ color: 'secondary' }} />
|
||||
|
||||
<Story name="Size: tiny" args={{ size: 'xs' }} />
|
||||
<Story name="Size: sm" args={{ size: 'sm' }} />
|
||||
<Story name="Size: base" args={{ size: 'md' }} />
|
||||
<Story name="Size: lg" args={{ size: 'lg' }} />
|
||||
<Story name="Size: xl" args={{ size: 'xl' }} />
|
Loading…
Reference in a new issue