mirror of
https://github.com/acid-info/lsd.git
synced 2025-01-27 09:15:38 +00:00
chore: update storybook docs
This commit is contained in:
parent
868ab6ca7a
commit
de21c474c3
@ -1,3 +1,4 @@
|
||||
import { Global, css } from '@emotion/react'
|
||||
import {
|
||||
Canvas,
|
||||
Controls,
|
||||
@ -7,11 +8,105 @@ import {
|
||||
useOf,
|
||||
} from '@storybook/blocks'
|
||||
import type { Preview } from '@storybook/react'
|
||||
import React from 'react'
|
||||
import clsx from 'clsx'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Dropdown, ThemeProvider, defaultThemes } from '../src'
|
||||
import { THEME_TYPOGRAPHY_FONT_CATEGORIES } from '../src/components/Theme/constants'
|
||||
import { docTheme, storybookThemes } from './themes'
|
||||
import { withTheme } from './withTheme.decorator'
|
||||
|
||||
const useGlobals = () => {
|
||||
const GLOBAL_PROPS = {
|
||||
themeColor: {
|
||||
defaultValue: 'Dark',
|
||||
description: 'Theme color',
|
||||
name: 'Theme color',
|
||||
toolbar: {
|
||||
icon: '',
|
||||
items: [
|
||||
{
|
||||
title: 'Dark',
|
||||
value: 'Dark',
|
||||
},
|
||||
{
|
||||
title: 'Light',
|
||||
value: 'Light',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
themeFont: {
|
||||
defaultValue: 'sans-serif',
|
||||
description: 'Theme font',
|
||||
name: 'Theme Font',
|
||||
toolbar: {
|
||||
icon: '',
|
||||
items: [
|
||||
{
|
||||
title: 'monospace',
|
||||
value: 'monospace',
|
||||
},
|
||||
{
|
||||
title: 'sans-serif',
|
||||
value: 'sans-serif',
|
||||
},
|
||||
{
|
||||
title: 'serif',
|
||||
value: 'serif',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const [updated, setUpdated] = useState(0)
|
||||
const [state, setState] = useState(
|
||||
Object.fromEntries(
|
||||
Object.entries(GLOBAL_PROPS).map(([name, prop]) => [
|
||||
name,
|
||||
(window as any).__STORYBOOK_STORY_STORE__?.globals?.globals?.[name] ??
|
||||
prop.defaultValue,
|
||||
]),
|
||||
),
|
||||
)
|
||||
|
||||
const updateGlobals = async (func: (globals: any) => void) => {
|
||||
const { __STORYBOOK_ADDONS_PREVIEW } = window as any
|
||||
const { channel } = __STORYBOOK_ADDONS_PREVIEW
|
||||
|
||||
const allGlobals = channel.data.updateGlobals
|
||||
|
||||
allGlobals.map((g) => func(g.globals))
|
||||
await Promise.all(
|
||||
allGlobals.map((globals, index) =>
|
||||
channel.events.updateGlobals[index](globals),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
updated > 0 &&
|
||||
updateGlobals((globals) => {
|
||||
Object.entries(state).forEach(([name, value]) => {
|
||||
globals[name] = value
|
||||
})
|
||||
})
|
||||
}, [updated, state])
|
||||
|
||||
return {
|
||||
props: Object.entries(GLOBAL_PROPS).map(([name, prop]) => ({
|
||||
key: name,
|
||||
name: prop.name,
|
||||
value: state[name],
|
||||
values: prop.toolbar?.items ?? [],
|
||||
set: (value: string) => {
|
||||
setState((s) => ({ ...s, [name]: value }))
|
||||
setUpdated((v) => v + 1)
|
||||
},
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
...storybookThemes.parameters,
|
||||
@ -44,6 +139,8 @@ const preview: Preview = {
|
||||
docs: {
|
||||
theme: docTheme,
|
||||
page: () => {
|
||||
const globals = useGlobals()
|
||||
|
||||
const resolvedOf = useOf('meta', ['meta'])
|
||||
const { stories, meta, moduleExports } = resolvedOf.csfFile
|
||||
|
||||
@ -51,14 +148,139 @@ const preview: Preview = {
|
||||
typeof meta?.parameters?.docs?.controls === 'undefined' ||
|
||||
meta?.parameters?.docs?.controls === true
|
||||
|
||||
const embedded =
|
||||
new URLSearchParams(window.location.search).get('embedded') === 'true'
|
||||
const globalControls =
|
||||
new URLSearchParams(window.location.search).get('globalControls') ===
|
||||
'true'
|
||||
const hideElements = (
|
||||
new URLSearchParams(window.location.search).get('hide') || ''
|
||||
).split(',')
|
||||
|
||||
const hideTitle = hideElements.includes('title')
|
||||
const hideSubtitle = hideElements.includes('subtitle')
|
||||
const hideDescription = hideElements.includes('description')
|
||||
const hideToolbar = hideElements.includes('toolbar')
|
||||
const hideControls = hideElements.includes('controls')
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title />
|
||||
<Subtitle />
|
||||
<Description />
|
||||
<Canvas sourceState="shown" />
|
||||
{controls && <Controls />}
|
||||
</>
|
||||
<ThemeProvider theme={defaultThemes.dark}>
|
||||
<div
|
||||
className={clsx(
|
||||
'docs-wrapper',
|
||||
embedded && 'docs-wrapper--embedded',
|
||||
hideElements.map((element) => `docs-wrapper--hide-${element}`),
|
||||
)}
|
||||
>
|
||||
{!hideTitle && <Title />}
|
||||
{!hideSubtitle && <Subtitle />}
|
||||
{!hideDescription && <Description />}
|
||||
{globalControls && (
|
||||
<div className="docs-global-controls">
|
||||
{globals.props.map((prop, index) => (
|
||||
<Dropdown
|
||||
key={index}
|
||||
menuProps={{ className: 'docs-dropdown-menu' }}
|
||||
value={prop.value}
|
||||
onChange={(value) => prop.set(value as string)}
|
||||
options={prop.values.map((i) => ({
|
||||
name: i.title,
|
||||
value: i.value,
|
||||
}))}
|
||||
triggerLabel={prop.name}
|
||||
label={prop.name}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<Canvas className="canvas" withToolbar={!hideToolbar} />
|
||||
{controls && !hideControls && <Controls />}
|
||||
</div>
|
||||
<Global
|
||||
styles={css`
|
||||
.docs-story,
|
||||
#lsd-presentation .docs-dropdown-menu {
|
||||
${defaultThemes.dark.cssVars}
|
||||
|
||||
background: rgb(var(--lsd-surface-primary));
|
||||
}
|
||||
|
||||
.docs-global-controls {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 16px;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.sbdocs-wrapper {
|
||||
.sbdocs-preview {
|
||||
// source code
|
||||
.docs-story + div {
|
||||
border-top: 1px solid;
|
||||
}
|
||||
|
||||
// toolbar
|
||||
> div:nth-child(1) {
|
||||
button:hover svg {
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.docblock-argstable-body {
|
||||
.rejt-tree {
|
||||
.rejt-name {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.rejt-value-node:hover > .rejt-value {
|
||||
color: #000 !important;
|
||||
background: #fff !important;
|
||||
}
|
||||
}
|
||||
|
||||
input[type='checkbox'] {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
input[type='radio'] + span {
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-wrapper--embedded {
|
||||
}
|
||||
|
||||
.docs-wrapper {
|
||||
&--hide-code {
|
||||
.docblock-code-toggle {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
&--hide-canvas-border {
|
||||
.sbdocs-preview {
|
||||
border: none;
|
||||
.docs-story > div:nth-child(1) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`}
|
||||
/>
|
||||
|
||||
{embedded && (
|
||||
<Global
|
||||
styles={css`
|
||||
.sbdocs-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
</ThemeProvider>
|
||||
)
|
||||
},
|
||||
},
|
||||
|
@ -4,6 +4,7 @@ import * as fsp from 'fs/promises'
|
||||
import { glob } from 'glob'
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
const DIRNAME = fileURLToPath(import.meta.url)
|
||||
const ROOT_DIR = path.resolve(DIRNAME, '../../../')
|
||||
@ -45,6 +46,11 @@ export const fromStories = async (
|
||||
const components: Record<
|
||||
string,
|
||||
{
|
||||
component: {
|
||||
title: string
|
||||
subtitle: string
|
||||
description: string
|
||||
}
|
||||
stories: StoryInfo[]
|
||||
argTypes: ArgTypes
|
||||
__docgenInfo: any
|
||||
@ -57,7 +63,17 @@ export const fromStories = async (
|
||||
const mod = await import(file)
|
||||
const { title, component, argTypes } = mod.default
|
||||
|
||||
const componentTitle = mod.default.title || title
|
||||
const componentSubtitle = mod.default.parameters?.componentSubtitle || ''
|
||||
const componentDescription =
|
||||
mod.default.parameters?.docs?.description?.component || ''
|
||||
|
||||
components[component.displayName] = {
|
||||
component: {
|
||||
title: componentTitle,
|
||||
subtitle: componentSubtitle,
|
||||
description: componentDescription,
|
||||
},
|
||||
argTypes,
|
||||
stories: stories.filter((story) => story.kind === title),
|
||||
__docgenInfo: component.__docgenInfo,
|
||||
|
@ -29,19 +29,23 @@ export const withTheme: Decorator = (Story, context) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ThemeProvider theme={theme} injectCssVars={true}>
|
||||
<StoryComponent />
|
||||
{isDoc && (
|
||||
<ThemeProvider theme={theme} injectCssVars={false}>
|
||||
<div className="story-wrapper">
|
||||
<StoryComponent />
|
||||
</div>
|
||||
{
|
||||
<Global
|
||||
styles={css`
|
||||
.docs-story {
|
||||
.story-wrapper,
|
||||
#lsd-presentation {
|
||||
${theme.cssVars}
|
||||
|
||||
background: rgb(var(--lsd-surface-primary));
|
||||
}
|
||||
.docs-story {
|
||||
background: rgb(${theme.palette.surface.primary});
|
||||
}
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
}
|
||||
</ThemeProvider>
|
||||
</div>
|
||||
)
|
||||
|
@ -28,7 +28,7 @@ export default {
|
||||
|
||||
export const Root: StoryObj<NumberInputProps> = {
|
||||
render: ({ ...args }) => {
|
||||
return <NumberInput {...args} />
|
||||
return <NumberInput {...args} defaultValue="2" />
|
||||
},
|
||||
|
||||
args: {
|
||||
|
@ -1,16 +1,11 @@
|
||||
import styled from '@emotion/styled'
|
||||
import { Meta, StoryObj } from '@storybook/react'
|
||||
import { get } from 'lodash'
|
||||
import React from 'react'
|
||||
import { Typography } from '../Typography'
|
||||
import { ThemeProvider, ThemeProviderProps } from './ThemeProvider'
|
||||
import { Theme, TypographyVariants } from './types'
|
||||
import { useTheme } from './useTheme'
|
||||
import {
|
||||
ColorDesignTokens,
|
||||
TypographyDesignTokens,
|
||||
SpacingDesignTokens,
|
||||
TypographyDesignTokens,
|
||||
} from '../../docs/components/DesignTokens'
|
||||
import { Typography } from '../Typography'
|
||||
import { ThemeProvider, ThemeProviderProps } from './ThemeProvider'
|
||||
|
||||
const subtitle = ``
|
||||
const description = ``
|
||||
|
Loading…
x
Reference in New Issue
Block a user