Specialized components
UI framework
UI primitives & styling (Tailwind)
20 min
overview the ui primitives system forms the foundation of the ir engine user interface framework it provides a standardized set of reusable ui components that maintain consistent styling throughout the application these primitives serve as the basic building blocks for constructing more complex ui elements and interfaces, ensuring visual coherence and reducing development time the styling of these components is implemented using tailwind css, a utility first css framework that enables efficient and consistent design application core concepts ui primitives ui primitives are fundamental, reusable interface components that serve as the basic building blocks for constructing the application's user interface the ir engine ui framework includes several essential primitives button for triggering actions input for text and numeric entry checkbox for boolean selections select for dropdown option selection text for displaying labels and content these primitives are designed to be reusable each component can be used in multiple contexts throughout the application consistent all instances of a component maintain the same visual style configurable components accept props to modify their appearance and behavior accessible components follow accessibility best practices tailwind css tailwind css is a utility first css framework that provides low level utility classes to build custom designs without leaving your html (or jsx) instead of writing custom css rules, developers apply pre defined utility classes directly to elements click me click me key benefits of tailwind in the ir engine ui framework consistency predefined color scales, spacing values, and other design tokens ensure visual consistency development speed no need to write and maintain custom css files flexibility easy to create variations without writing new css bundle size optimization only the utility classes actually used are included in the final css implementation component structure ui primitives are organized in the codebase as follows src/ ├── primitives/ │ └── tailwind/ │ ├── button/ │ │ └── index tsx │ ├── input/ │ │ └── index tsx │ ├── checkbox/ │ │ └── index tsx │ └── └── index ts (exports all primitives) each primitive is implemented as a react component that applies tailwind utility classes based on its props button component the button component is a fundamental ui primitive that demonstrates the implementation pattern used throughout the system // simplified from src/primitives/tailwind/button/index tsx import react from 'react'; import { twmerge } from 'tailwind merge'; // define style variants const variants = { primary 'bg ui primary text text primary button hover\ bg ui hover primary', secondary 'bg \[#4d84bf33] dark\ bg ui secondary text ui primary', // additional variants }; const button = ({ variant = 'primary', // default variant children, // button content classname, // additional classes props // other html button props }) => { // combine base styles, variant styles, and custom classes const buttonclasses = twmerge( 'flex items center justify center px 4 py 1 text sm font medium', // base styles variants\[variant], // variant specific styles classname // custom classes (override if needed) ); return ( \<button classname={buttonclasses} { props}> {children} \</button> ); }; export default react forwardref(button); this implementation defines style variants as collections of tailwind classes accepts a variant prop to select the appropriate style uses twmerge to intelligently combine multiple sets of tailwind classes renders a standard html button with the combined classes forwards the react ref to the underlying button element input component the input component follows a similar pattern // simplified from src/primitives/tailwind/input/index tsx import react from 'react'; import { twmerge } from 'tailwind merge'; // define height variants const heights = { l 'h 8 py 1 5 px 2', // other size options }; const input = ({ height = 'l', classname, props }) => { return ( \<input classname={twmerge( 'rounded md border \[0 5px] border ui outline', 'text xs placeholder text tertiary dark\ bg ui background', heights\[height], // focus and disabled states classname )} { props} /> ); }; export default react forwardref(input); component exports all ui primitives are exported from a central index ts file, making them easily accessible throughout the application // from src/index ts export { default as button } from ' /primitives/tailwind/button'; export type { buttonprops } from ' /primitives/tailwind/button'; export { default as input } from ' /primitives/tailwind/input'; export type { inputprops } from ' /primitives/tailwind/input'; // additional exports this approach allows developers to import components with a clean, consistent syntax import { button, input } from '@ir engine/ui'; tailwind configuration configuration file the tailwind configuration defines the design system's colors, spacing, typography, and other design tokens // from tailwind config js import tailwindconfig from ' / /tailwind config' module exports = { tailwindconfig } the ui framework inherits its tailwind configuration from a shared config file, ensuring consistency across the entire ir engine ecosystem custom theme values the shared configuration defines custom theme values like colors and spacing // conceptual content of the shared tailwind config js module exports = { theme { extend { colors { 'ui primary' '#007bff', 'text primary button' '#ffffff', 'ui hover primary' '#0069d9', 'ui outline' '#e2e8f0', // additional custom colors }, // typography, spacing, and other theme extensions }, }, // plugins and other configuration }; postcss processing tailwind classes are processed into standard css using postcss // from postcss config js module exports = { plugins { tailwindcss import('tailwindcss'), autoprefixer import('autoprefixer'), }, } this configuration uses the tailwind plugin to generate css from utility classes applies autoprefixer to ensure cross browser compatibility usage examples basic button import { button } from '@ir engine/ui'; function confirmdialog() { const handleconfirm = () => { console log("action confirmed"); }; return ( \<div> \<p>are you sure you want to proceed?\</p> \<button variant="primary" onclick={handleconfirm}> confirm \</button> \</div> ); } form with multiple primitives import { button, input, checkbox } from '@ir engine/ui'; function settingsform() { const \[name, setname] = usestate(''); const \[enabled, setenabled] = usestate(false); return ( \<form> \<div classname="mb 4"> \<label>name\</label> \<input value={name} onchange={(e) => setname(e target value)} placeholder="enter name" /> \</div> \<div classname="mb 4"> \<checkbox checked={enabled} onchange={(e) => setenabled(e target checked)} label="enable feature" /> \</div> \<button variant="primary" type="submit"> save settings \</button> \</form> ); } styling workflow the process of styling a component using the ui primitives and tailwind follows this workflow sequencediagram participant dev as developer participant comp as component participant prim as ui primitive participant tw as tailwind config participant build as build process participant browser dev >>comp creates component using ui primitives comp >>prim uses primitive with variant prop prim >>prim selects tailwind classes based on variant prim >>tw references custom theme values note over build during build time build >>tw reads configuration build >>prim scans for tailwind classes build >>build generates optimized css prim >>browser renders with appropriate classes browser >>browser applies generated css next steps with an understanding of the ui primitives and tailwind styling system, the next chapter explores how these building blocks are used to create more complex ui structures for editing properties in the ir engine editor next editor properties ui (nodeeditor components) docid\ lzijkd55ed idsqh3l ug