feat: storybook

This commit is contained in:
2026-05-31 17:11:42 +03:00
parent 2f937e94b1
commit 67993ae3ec
17 changed files with 764 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
import type { StorybookConfig } from 'storybook-react-rsbuild';
/* Dev-only playground. Never shipped — package `files` is ["dist"]. */
const config: StorybookConfig = {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(ts|tsx)'],
addons: ['@storybook/addon-docs'],
framework: {
name: 'storybook-react-rsbuild',
options: {},
},
typescript: {
// Prop tables in autodocs come from the components' TS types.
reactDocgen: 'react-docgen-typescript',
reactDocgenTypescriptOptions: {
shouldExtractLiteralValuesFromEnum: true,
// Keep our own props; drop the noise inherited from node_modules.
propFilter: (prop) =>
prop.parent ? !/node_modules/.test(prop.parent.fileName) : true,
},
},
};
export default config;
+4
View File
@@ -0,0 +1,4 @@
import { addons } from 'storybook/manager-api';
import theme from './theme';
addons.setConfig({ theme });
+19
View File
@@ -0,0 +1,19 @@
/* Calm dark canvas. Uses the felt's subtle radial glow (no heavy fixed
grain) so the story sits on-brand without flooding the frame. The
--bg-glow / --ink tokens come from the imported stylesheet and react
to the data-theme toggle automatically. */
.sb-show-main {
background-color: var(--ink);
background-image: var(--bg-glow);
background-size: cover;
background-repeat: no-repeat;
background-attachment: fixed;
}
/* Autodocs preview blocks: same dark surface as the canvas. */
.docs-story,
.sbdocs-preview {
background-color: var(--ink) !important;
background-image: var(--bg-glow);
background-size: cover;
}
+60
View File
@@ -0,0 +1,60 @@
import { useEffect, type ReactNode } from 'react';
import type { Preview, Decorator } from 'storybook-react-rsbuild';
import { Tooltip } from 'radix-ui';
/* The shipped library surface, exactly as a consumer would load it. */
import '../src/styles/fonts.css';
import '../src/styles/index.css';
/* Storybook-only canvas styling (background, docs blocks). */
import './preview.css';
import theme from './theme';
/* Toolbar theme switch → drives `data-theme` on <html>, same lever as the
library's ThemeProvider. The frame stays content-sized; the dark canvas
comes from preview.css, so stories never balloon to full-viewport. */
function ThemeFrame({ theme, children }: { theme: string; children: ReactNode }) {
useEffect(() => {
document.documentElement.setAttribute('data-theme', theme);
}, [theme]);
return <Tooltip.Provider delayDuration={200}>{children}</Tooltip.Provider>;
}
const withModernSk: Decorator = (Story, context) => (
<ThemeFrame theme={(context.globals.theme as string) ?? 'dark'}>
<Story />
</ThemeFrame>
);
const preview: Preview = {
tags: ['autodocs'],
decorators: [withModernSk],
parameters: {
layout: 'centered',
backgrounds: { disable: true },
docs: { theme },
controls: {
matchers: { color: /(background|color)$/i, date: /Date$/i },
},
options: {
storySort: { order: ['Getting Started', 'Inputs', 'Selection', 'Feedback', 'Overlays', 'Data Display', 'Layout'] },
},
},
globalTypes: {
theme: {
description: 'ModernSK theme',
defaultValue: 'dark',
toolbar: {
title: 'Theme',
icon: 'contrast',
items: [
{ value: 'dark', title: 'Dark', icon: 'moon' },
{ value: 'light', title: 'Light', icon: 'sun' },
],
dynamicTitle: true,
},
},
},
};
export default preview;
+39
View File
@@ -0,0 +1,39 @@
import { create } from 'storybook/theming';
/* Dark, lime-accented chrome so the Storybook UI + autodocs match the
components instead of framing them in stock white. */
export default create({
base: 'dark',
brandTitle: 'ModernSK',
colorPrimary: '#bef264',
colorSecondary: '#bef264',
// App
appBg: '#0f100d',
appContentBg: '#0f100d',
appPreviewBg: '#0f100d',
appBorderColor: '#2a2c22',
appBorderRadius: 10,
// Typography
fontBase: "'Onest', system-ui, -apple-system, 'Segoe UI', sans-serif",
fontCode: "'Geist Mono', ui-monospace, 'SF Mono', Menlo, monospace",
// Text
textColor: '#f3f4ee',
textInverseColor: '#0f100d',
textMutedColor: '#9a9c8c',
// Toolbar / sidebar bars
barBg: '#16170f',
barTextColor: '#9a9c8c',
barSelectedColor: '#bef264',
barHoverColor: '#bef264',
// Inputs
inputBg: '#1c1d16',
inputBorder: '#2a2c22',
inputTextColor: '#f3f4ee',
inputBorderRadius: 8,
});