mirror of
https://github.com/Lapikud/lapikud.github.io.git
synced 2026-08-08 22:19:14 +00:00
components and storybook for development svg previews
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -22,3 +22,6 @@ dist-ssr
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*storybook.log
|
||||
storybook-static
|
||||
|
||||
13
.storybook/main.js
Normal file
13
.storybook/main.js
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
|
||||
/** @type { import('@storybook/svelte-vite').StorybookConfig } */
|
||||
const config = {
|
||||
"stories": [
|
||||
"../src/**/*.stories.@(js|ts|svelte)"
|
||||
],
|
||||
"addons": [
|
||||
"@storybook/addon-svelte-csf"
|
||||
],
|
||||
"framework": "@storybook/svelte-vite"
|
||||
};
|
||||
export default config;
|
||||
13
.storybook/preview.js
Normal file
13
.storybook/preview.js
Normal file
@@ -0,0 +1,13 @@
|
||||
/** @type { import('@storybook/svelte-vite').Preview } */
|
||||
const preview = {
|
||||
parameters: {
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default preview;
|
||||
1532
package-lock.json
generated
1532
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -6,13 +6,18 @@
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"build-storybook": "storybook build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"svelte": "^5.43.8",
|
||||
"vite": "npm:rolldown-vite@7.2.5"
|
||||
"vite": "npm:rolldown-vite@7.2.5",
|
||||
"storybook": "^10.2.15",
|
||||
"@storybook/svelte-vite": "^10.2.15",
|
||||
"@storybook/addon-svelte-csf": "^5.0.11"
|
||||
},
|
||||
"overrides": {
|
||||
"vite": "npm:rolldown-vite@7.2.5"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<!--
|
||||
Multi-purpose image/SVG component with optional link wrapper,
|
||||
hover effects, size variants, and object-fit options.
|
||||
Multi-purpose image component with optional link wrapper,
|
||||
hover effects, size variants, and object-fit options. Includes support for WebP format with fallback to standard formats.
|
||||
-->
|
||||
|
||||
<script>
|
||||
export let src = "";
|
||||
export let webpSrc = ""; // Optional WebP source for browsers that support it
|
||||
export let src = ""; // Fallback (some devices don't support WebP) or primary source if webpSrc is not provided
|
||||
export let alt = "";
|
||||
export let href = null; // optional link URL
|
||||
export let target = "_blank";
|
||||
@@ -13,6 +14,12 @@ hover effects, size variants, and object-fit options.
|
||||
export let hover = false;
|
||||
export let className = "";
|
||||
|
||||
// optional srcset for responsive images (w descriptors means width-based, x descriptors means pixel density-based)
|
||||
// e.g. "image-400.jpg 400w, image-800.jpg 800w"
|
||||
export let srcSet = ""; // always set src if using this
|
||||
export let webpSrcSet = ""; // always set src if using this
|
||||
export let pictureClass = ""; // CSS/Tailwind classes applied to the <picture> element
|
||||
|
||||
$: objectFitClass = {
|
||||
contain: "object-contain",
|
||||
cover: "object-cover",
|
||||
@@ -25,22 +32,29 @@ hover effects, size variants, and object-fit options.
|
||||
</script>
|
||||
|
||||
{#if href}
|
||||
<a
|
||||
{href}
|
||||
{target}
|
||||
{rel}
|
||||
class="inline-block leading-none"
|
||||
>
|
||||
<a {href} {target} {rel} class="inline-block leading-none">
|
||||
<picture class={pictureClass}>
|
||||
{#if webpSrc || webpSrcSet}
|
||||
<source srcset={webpSrcSet || webpSrc} type="image/webp" />
|
||||
{/if}
|
||||
<img
|
||||
{src}
|
||||
{alt}
|
||||
srcset={srcSet || undefined}
|
||||
alt={alt}
|
||||
class="block h-auto max-w-full {objectFitClass} {hoverClasses} {className}"
|
||||
/>
|
||||
</picture>
|
||||
</a>
|
||||
{:else}
|
||||
<picture class={pictureClass}>
|
||||
{#if webpSrc || webpSrcSet}
|
||||
<source srcset={webpSrcSet || webpSrc} type="image/webp" />
|
||||
{/if}
|
||||
<img
|
||||
{src}
|
||||
{alt}
|
||||
srcset={srcSet || undefined}
|
||||
alt={alt}
|
||||
class="block h-auto max-w-full {objectFitClass} {hoverClasses} {className}"
|
||||
/>
|
||||
</picture>
|
||||
{/if}
|
||||
19
src/components/README.md
Normal file
19
src/components/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# SVG previews
|
||||
|
||||
use `npm run storybook` which opens a browser window with all the SVG variations. You can also edit the SVG properties in storybook controls.
|
||||
|
||||
# Components
|
||||
|
||||
under components are building blocks that are not layout related.
|
||||
|
||||
## details
|
||||
|
||||
- Button: a simple button component with some styling.
|
||||
- Dropdown: a dropdown component that can be used to show/hide content.
|
||||
- Slideshow: a simple slideshow component that can be used to show multiple images in a slideshow format. Includes options to enable/disable autoplay and to set the autoplay interval.
|
||||
- Svg: a component that renders different SVG icons based on the `type` prop. See the comment after the `type` prop in `Svg.svelte` for the available types.
|
||||
- Image: a component that renders an image with some styling. It accepts a lot of props. Main ones are `src` (the main image source that is used if anything else fails or not provided), `alt` (the alt text for the image), `srcSet` (a string of comma-separated image sources for different screen sizes, jpg or png files), `webpSrc` (the webp image source as a webp file), `webpSrcSet` (a string of comma-separated webp image sources for different screen sizes). We use 2 webp images: 400 and 800 width, and one jpg image 800 width as default src for fallback.
|
||||
|
||||
# Layout components
|
||||
|
||||
under components/layout are components that are used to structure the page, such as Container, Stack, Center, etc.
|
||||
54
src/components/Svg.svelte
Normal file
54
src/components/Svg.svelte
Normal file
@@ -0,0 +1,54 @@
|
||||
<script>
|
||||
export let type; // "connector", "mirrorV", "mirrorH", "mirrorVH", "branch"
|
||||
export let className = "";
|
||||
</script>
|
||||
|
||||
{#if type === "connector"}
|
||||
<svg viewBox="0 0 182 66" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 63.5H67.5L102.5 15.5H156" stroke="currentColor" stroke-width="5"/>
|
||||
<circle cx="166" cy="15.5" r="10" stroke="currentColor" stroke-width="5"/>
|
||||
</svg>
|
||||
|
||||
{:else if type === "mirrorV"}
|
||||
<svg viewBox="0 0 182 66" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="scale(1,-1) translate(0,-66)">
|
||||
<path d="M0 63.5H67.5L102.5 15.5H156" stroke="currentColor" stroke-width="5"/>
|
||||
<circle cx="166" cy="15.5" r="10" stroke="currentColor" stroke-width="5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
{:else if type === "mirrorH"}
|
||||
<svg viewBox="0 0 182 66" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="scale(-1,1) translate(-182,0)">
|
||||
<path d="M0 63.5H67.5L102.5 15.5H156" stroke="currentColor" stroke-width="5"/>
|
||||
<circle cx="166" cy="15.5" r="10" stroke="currentColor" stroke-width="5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
{:else if type === "mirrorVH"}
|
||||
<svg viewBox="0 0 182 66" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="scale(-1,-1) translate(-182,-66)">
|
||||
<path d="M0 63.5H67.5L102.5 15.5H156" stroke="currentColor" stroke-width="5"/>
|
||||
<circle cx="166" cy="15.5" r="10" stroke="currentColor" stroke-width="5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
{:else if type === "branch"}
|
||||
<svg viewBox="0 0 75 74" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 31.4784H46L68 1.47842M45.5 30.9784L66.5 63.9784"
|
||||
stroke="currentColor"
|
||||
stroke-width="5"/>
|
||||
</svg>
|
||||
|
||||
{:else if type === "branchH"}
|
||||
<svg viewBox="0 0 75 74" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="scale(-1,1) translate(-75,0)">
|
||||
<path d="M0 31.4784H46L68 1.47842M45.5 30.9784L66.5 63.9784"
|
||||
stroke="currentColor"
|
||||
stroke-width="5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
{:else}
|
||||
<div>Unknown type: {type}</div>
|
||||
{/if}
|
||||
@@ -1,3 +1,4 @@
|
||||
// layout components
|
||||
export { default as Container } from './layout/Container.svelte'
|
||||
export { default as Card } from './layout/Card.svelte'
|
||||
export { default as Stack } from './layout/Stack.svelte'
|
||||
@@ -5,6 +6,9 @@ export { default as Grid } from './layout/Grid.svelte'
|
||||
export { default as Center } from './layout/Center.svelte'
|
||||
export { default as Section } from './layout/Section.svelte'
|
||||
|
||||
// components
|
||||
export { default as Button } from './Button.svelte'
|
||||
export { default as Dropdown } from './Dropdown.svelte'
|
||||
export { default as Slideshow } from './Slideshow.svelte'
|
||||
export { default as Svg } from './Svg.svelte'
|
||||
export { default as Image } from './Image.svelte'
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
const paddingClasses = {
|
||||
none: "py-0",
|
||||
tight: "py-2 md:py-3",
|
||||
small: "py-4 md:py-8",
|
||||
normal: "py-12 max-md:py-8",
|
||||
large: "py-[clamp(3rem,8vw,6rem)] max-md:py-12",
|
||||
|
||||
@@ -105,9 +105,9 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<Section className="text-black" background="orange" padding="small">
|
||||
<Section className="text-black" background="orange" padding="tight">
|
||||
{#if $text && Object.keys($text).length > 0}
|
||||
<div class="flex items-center w-full relative min-h-16">
|
||||
<div class="flex items-center w-full relative min-h-12">
|
||||
<!-- Logo -->
|
||||
{#if currentPath !== "/"}
|
||||
<div class="absolute left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2 md:relative md:left-auto md:translate-x-0 md:top-auto md:translate-y-0">
|
||||
|
||||
51
src/stories/Icon.stories.js
Normal file
51
src/stories/Icon.stories.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import Icon from '../components/Svg.svelte';
|
||||
|
||||
export default {
|
||||
title: 'SVG/Icon',
|
||||
component: Icon,
|
||||
argTypes: {
|
||||
type: { control: { type: 'select', options: ['connector','mirrorV','mirrorH','mirrorVH','branch','branchH'] } },
|
||||
className: { control: 'text' },
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => ({
|
||||
Component: Icon,
|
||||
props: args,
|
||||
});
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
type: 'connector',
|
||||
className: 'w-64 text-cyan-500',
|
||||
};
|
||||
|
||||
export const MirrorV = Template.bind({});
|
||||
MirrorV.args = {
|
||||
type: 'mirrorV',
|
||||
className: 'w-64 text-green-500',
|
||||
};
|
||||
|
||||
export const MirrorH = Template.bind({});
|
||||
MirrorH.args = {
|
||||
type: 'mirrorH',
|
||||
className: 'w-64 text-yellow-500',
|
||||
};
|
||||
|
||||
export const MirrorVH = Template.bind({});
|
||||
MirrorVH.args = {
|
||||
type: 'mirrorVH',
|
||||
className: 'w-64 text-pink-500',
|
||||
};
|
||||
|
||||
export const Branch = Template.bind({});
|
||||
Branch.args = {
|
||||
type: 'branch',
|
||||
className: 'w-48 text-magenta-500',
|
||||
};
|
||||
|
||||
export const BranchH = Template.bind({});
|
||||
BranchH.args = {
|
||||
type: 'branchH',
|
||||
className: 'w-48 text-magenta-500',
|
||||
};
|
||||
Reference in New Issue
Block a user