Storybook-esque component directory, embed right into SvelteKit
Please give it a try, but setting up is a PITA right now. It also only supports SvelteKit from ^1.0.0-next.250
Setting up Storybooks with SvelteKit is a daunting task that's overkill for static / content-focused websites.
TaleNote doesn't run a separate server — instead, it is embedded into SvelteKit's routes directory directly & relies on Vite's glob import to access other components.
Install talenote:
npm install talenote
In routes, create the following structure:
routes
└─ talenote
├─ __layout.reset.svelte
├─ _tales.json
├─ component.svelte
├─ index.svelte
└─ tales.js
Directory & filenames are currently hardcoded. There's an example of what these files look like here
__layout.reset.svelteJust to reset the parent layout, if any.
<slot />
_tales.jsonThis is where all the props snapshots will be stored. For starter, just leave this in:
{}
I'm 90% confident that
lowdbwould just create one if there's none, please let me know if it doesn't.
component.svelteTalenote will mount a Svelte component into this page & load it into an iframe. This is the place to pass in components & any wrapper components.
<script context="module">
// Write a glob to get your handsome components here. Are they in `lib`? or maybe `components`?
const modules = import.meta.globEager('/src/lib/**/*.svelte');
</script>
<script>
import { DisplayComponent } from 'talenote';
</script>
<DisplayComponent {modules} />
index.svelteThis is where Talenote UI lives.
<script lang="ts">
import { TaleNote } from 'talenote';
// not required, just something to get the component name instead of the full file path
const getComponentName = (name: string) => name.split('/src/lib/')[1].split('.svelte')[0];
</script>
<TaleNote {getComponentName} />
tales.js (or .ts)Talenote uses lowdb to write snapshots of your component props into a local json file. This file exports the required HTTP operations.
import path from 'path';
import { createAPI } from 'talenote';
// __dirname is not a thing with ESM, emulates it with import.meta.url
const taleDir = path.join(import.meta.url, '..').replace('file:', '');
const pathToJson = path.join(taleDir, '_tales.json');
const { post, get, del } = createAPI({ pathToJson });
export { post, get, del };
Note: I always run into strange ESM errors after launching
/talenotefor the first time. Hard refresh and / or reinstallingnode_modulesa few times usually fixes them... let me know if you have an idea how to improve this.
Because Talenote doesn't run any static code analysis, the only way to recognize a component's default props is to export them from that component.
<script context="module">
export const defaultProps = { name: 'Eri' };
</script>
<script>
export let name = defaultProps.name;
</script>
<h1>Hello {name}</h1>
When viewing small components such as a button, it's helpful to have them centered on the screen. From within a component, export a taleWrapper with the id of the wrapper. Valid defaults are center and none.
<script context="module">
export const defaultProps = { name: 'Eri' };
// center this component
export const taleWrapper = 'center';
// alternatively, dont use any wrapper
export const taleWrapper = 'none';
</script>
<script>
export let name = defaultProps.name;
</script>
<h1>Hello {name}</h1>
Additional wrappers can be passed into talenote/component.svelte:
<script context="module">
const modules = import.meta.globEager('/src/components/**/*.svelte');
</script>
<script>
import { DisplayComponent } from 'talenote';
import CustomWrapper from './_CustomWrapper.svelte';
const wrappers = {
custom: CustomWrapper,
// set the component above as the default for all components
default: 'custom'
};
</script>
// talenote/component.svelte
<DisplayComponent {modules} {wrappers} />
Starting from 1.0.0-next.249, kit.routes is available in svelte.config.js to filter out unwanted paths.
// svelte.config.js
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: preprocess(),
kit: {
adapter: adapter(),
target: '#svelte',
routes: (filepath) => {
return process.env.NODE_ENV === 'production' ? !filepath.includes('talenote') : true;
}
}
};
Because component props are serialized & passed back & forth via window.postMessage, functions props are excluded.
Tales (component props snapshot) can only be viewed locally, though the component directory can still be shipped.
Ideas, PRs, contributions, forks are all welcomed! Built by dereknguyen