Specialized components
UI framework
Storybook integration
22 min
overview storybook integration provides a dedicated environment for developing, documenting, and testing ui components in isolation it serves as an interactive component catalog that allows developers to view and interact with components outside the main application context the ir engine ui framework leverages storybook extensively to showcase component variations, document usage patterns, and ensure visual consistency this approach accelerates development by enabling focused work on individual components and facilitates collaboration by providing a shared reference for designers and developers core concepts stories stories are the fundamental building blocks of storybook each story represents a single state or variation of a component a story captures a specific component configuration (props, state, context) multiple stories can exist for a single component to demonstrate different variations stories serve as both examples and documentation stories can include interactive controls to manipulate component properties component isolation storybook renders components in isolation from the main application components are displayed in a controlled environment each component can be viewed and tested independently the rendering environment can be configured to provide necessary context isolation helps identify issues that might be masked in the full application addons storybook's functionality can be extended through addons controls allow interactive manipulation of component props actions log and display event handler calls accessibility perform automated accessibility checks docs generate documentation from component code and stories viewport test responsive behavior across different screen sizes implementation story files each component in the ui framework typically has an associated stories tsx file that defines its stories // from src/primitives/tailwind/button/index stories tsx import react from 'react'; import type { meta, storyobj } from '@storybook/react'; import button from ' /index'; import { sendmd, settingsmd } from ' / / /icons'; // define metadata for this component const meta meta\<typeof button> = { title 'primitives/button', // location in storybook sidebar component button, // the component being documented tags \['autodocs'], // generate automatic documentation argtypes { variant { control 'select', options \['primary', 'secondary', 'tertiary', 'green', 'red'], description 'the visual style of the button' }, size { control 'select', options \['xs', 'sm', 'l', 'xl'], description 'the size of the button' }, disabled { control 'boolean', description 'whether the button is disabled' } } }; export default meta; type story = storyobj\<typeof button>; // define individual stories export const primary story = { args { variant 'primary', children 'primary button' } }; export const secondary story = { args { variant 'secondary', children 'secondary button' } }; export const withicon story = { args { variant 'primary', children 'send message', starticon \<sendmd classname="w 4 h 4" /> } }; // additional stories for other variations this file defines metadata about the button component specifies which props can be controlled in the storybook ui creates individual stories for different button variations demonstrates how to use icons with buttons storybook configuration the storybook environment is configured through files in the storybook directory main configuration // from storybook/main ts import type { storybookconfig } from '@storybook/react vite'; import { join, dirname } from 'path'; function getabsolutepath(value string) string { return dirname(require resolve(join(value, 'package json'))); } const config storybookconfig = { // define where to find story files stories \[ ' /src/primitives/tailwind/ / stories @(js|jsx|ts|tsx)', ' /src/components/editor/ / stories @(js|jsx|ts|tsx)', ' /src/icons/ / stories @(js|jsx|ts|tsx)', ' /src/pages/ / stories @(js|jsx|ts|tsx)' ], // configure addons addons \[ getabsolutepath('@storybook/addon links'), getabsolutepath('@storybook/addon essentials'), getabsolutepath('@storybook/addon interactions'), getabsolutepath('@storybook/addon a11y') ], // use vite as the build tool framework { name getabsolutepath('@storybook/react vite'), options {} }, // additional configuration }; export default config; this configuration specifies where to find story files in the project configures which addons to use sets up the build framework (vite in this case) preview configuration // from storybook/preview\ tsx import react from 'react'; import { i18nextprovider } from 'react i18next'; import { dndprovider } from 'react dnd'; import { html5backend } from 'react dnd html5 backend'; import i18n from ' /i18n'; import { themeprovider } from '@ir engine/client core'; // global decorators wrap every story export const decorators = \[ (story) => ( \<themeprovider> \<i18nextprovider i18n={i18n}> \<dndprovider backend={html5backend}> \<div classname="p 4 bg ui background"> \<story /> \</div> \</dndprovider> \</i18nextprovider> \</themeprovider> ), ]; // default parameters for all stories export const parameters = { actions { argtypesregex '^on\[a z] ' }, controls { matchers { color /(background|color)$/i, date /date$/, }, }, layout 'centered', }; this configuration provides global decorators that wrap every story sets up necessary context providers (theme, i18n, drag and drop) configures default parameters for all stories internationalization setup // from storybook/i18n ts import i18n from 'i18next'; import { initreacti18next } from 'react i18next'; import entranslation from ' /src/locales/en/translation json'; i18n use(initreacti18next) init({ resources { en { translation entranslation } }, lng 'en', fallbacklng 'en', interpolation { escapevalue false } }); export default i18n; this configuration sets up internationalization for storybook loads translation resources configures language settings example stories ui primitives the basic ui primitives have straightforward stories that demonstrate their variations // from src/primitives/tailwind/input/index stories tsx import react from 'react'; import type { meta, storyobj } from '@storybook/react'; import input from ' /index'; import { searchmd } from ' / / /icons'; const meta meta\<typeof input> = { title 'primitives/input', component input, tags \['autodocs'], argtypes { placeholder { control 'text' }, disabled { control 'boolean' }, error { control 'boolean' } } }; export default meta; type story = storyobj\<typeof input>; export const default story = { args { placeholder 'enter text ' } }; export const withicon story = { args { placeholder 'search ', starticon \<searchmd classname="w 4 h 4 text text secondary" /> } }; export const disabled story = { args { placeholder 'disabled input', disabled true } }; export const witherror story = { args { placeholder 'error state', error true } }; complex components more complex components often have stories that demonstrate interactive behavior // from src/components/editor/audiovolumevisualizer/index stories tsx import react from 'react'; import type { meta, storyobj } from '@storybook/react'; import { audiovolumevisualizer } from ' /index'; const meta meta\<typeof audiovolumevisualizer> = { title 'editor/audiovolumevisualizer', component audiovolumevisualizer, parameters { layout 'centered', } }; export default meta; type story = storyobj\<typeof audiovolumevisualizer>; export const default story = { args { volume 0 5, onchange (value) => console log('volume changed ', value) } }; export const interactive story = { render () => { const \[volume, setvolume] = react usestate(0 5); return ( \<div classname="p 4 flex flex col items center gap 4"> \<audiovolumevisualizer volume={volume} onchange={setvolume} /> \<div classname="text sm"> current volume {math round(volume 100)}% \</div> \</div> ); } }; icon gallery the icon system has a special story that displays all available icons // from src/icons/index stories tsx import react from 'react'; import type { meta } from '@storybook/react'; import as icons from ' /index'; const meta meta = { title 'icons/gallery', parameters { layout 'centered', } }; export default meta; export const icongallery = () => { const iconentries = object entries(icons); return ( \<div classname="grid grid cols 4 gap 4 max w 4xl"> {iconentries map((\[name, icon]) => ( \<div key={name} classname="flex flex col items center p 4 border border ui outline rounded" \> \<icon classname="w 8 h 8 mb 2 text ui primary" /> \<div classname="text xs text center">{name}\</div> \<code classname="text xs mt 1 text text secondary"> {`import { ${name} } from '@ir engine/ui/icons'`} \</code> \</div> ))} \</div> ); }; storybook workflow the process of using storybook follows this workflow sequencediagram participant dev as developer participant cli as storybook cli participant config as storybook config participant stories as component stories participant browser as web browser dev >>cli npm run storybook cli >>config load configuration config >>cli provide settings cli >>stories discover and load stories stories >>cli return story definitions cli >>browser serve storybook ui browser >>dev display interactive component catalog dev >>browser select component/story browser >>browser render isolated component dev >>browser adjust controls browser >>browser re render with new props benefits storybook integration provides several key benefits for the ui framework development benefits focused development work on components in isolation without the complexity of the full application rapid iteration see changes immediately without navigating through the application edge case testing easily test unusual prop combinations or states visual regression detection identify unintended visual changes documentation benefits living documentation always up to date with the actual implementation interactive examples demonstrate component behavior through interaction prop exploration understand available props and their effects usage patterns show recommended ways to use components collaboration benefits design development bridge shared reference for designers and developers onboarding tool help new team members understand the component library review aid facilitate ui reviews with isolated components communication tool discuss specific components without ambiguity conclusion storybook integration is a vital part of the ir engine ui framework, providing a dedicated environment for component development, documentation, and testing by enabling isolated component work and interactive exploration, it accelerates development and improves collaboration the comprehensive story catalog serves as both a development tool and living documentation, ensuring that the ui framework remains maintainable and accessible to all team members this concludes our exploration of the ir engine ui framework throughout these chapters, we've covered the foundational ui primitives, specialized editor components, the icon system, the chat feature module, state management with hyperflux, and now storybook integration together, these systems provide a robust foundation for building complex, interactive user interfaces for the ir engine