@jsway/jui
v3.0.6
Published
JUI is a minimalistic yet powerful React component library that provides everything needed to build modern web applications. It combines a utility-first styling approach (similar to Tailwind CSS) with fully typed, composable components.
Readme
JUI - Just User Interface
JUI is a minimalistic yet powerful React component library that provides everything needed to build modern web applications. It combines a utility-first styling approach (similar to Tailwind CSS) with fully typed, composable components.
Installation
npm install @jsway/juiCore Concepts
Utility-First Styling with useBoxItem
JUI uses a prop-based styling system that transforms style props into CSS classes. This approach provides the flexibility of inline styles with the performance of CSS classes.
import { Box, Text } from '@jsway/jui';
// Style props are converted to optimized CSS classes
<Box padding="m" background="grey-1" radius="2">
<Text size="l" weight="bold" color="accent-6">
Hello World
</Text>
</Box>;Responsive Design
All style props support responsive modifiers:
// Different widths at different breakpoints
<Box width="100 50@md 33@lg">Responsive content</Box>Hover States
Style props can include hover variants:
<Box background="grey-1 grey-2@hover" cursor="pointer">
Hover me
</Box>Color System
JUI provides a carefully designed color palette:
Base Colors
white,black,transparent
Color Scales (1-6)
- Grey:
grey-1togrey-6(1 is darkest, 6 is lightest) - Dark:
dark-1todark-6(1 is darkest, 6 is lightest) - Light:
light-1tolight-6(1 is lightest, 6 is darkest) - Accent:
accent-1toaccent-6(1 is darkest, 6 is lightest)
Semantic Colors
- Green:
green-1,green-2 - Red:
red-1,red-2
Components
Layout Components
Box
The fundamental layout component with flexbox and grid support.
<Box horizontal spacing="m" justify="between" alignItems="center">
<Box>Left content</Box>
<Box>Right content</Box>
</Box>
// Grid layout
<Box grid="columns" columns={3} spacing="m">
<Box>Item 1</Box>
<Box>Item 2</Box>
<Box>Item 3</Box>
</Box>Box Props:
Layout & Sizing:
flex- Flex grow value:'0','1','2','3','4'or width valuesshrink- Flex shrink:'0','1','2','3','4'width- Width values with breakpoint supportheight- Height valuesmaxWidth- Max width:'s','m','l','xl'maxHeight- Max height:'xxs','xs','s','m','l','auto'aspect- Aspect ratio:'1-1','1-2','2-1','3-4','4-3','16-9'
Spacing:
margin- Margin:'0','xs','s','m','l','xl'(supports 1-4 values)padding- Padding: same values as margin
Colors & Appearance:
color- Text color from color systembackground- Background color from color systemopacity- Opacity:'100','90','80','70','60','50','40','30','20','10','0'
Visibility:
visible- Visibility control with breakpoint supportinline- Display inline
Borders & Styling:
border- Border width/style by sides or'inset-1','inset-2','inset-3','inset-5'borderColor- Border color by sidesradius- Border radius:'0','1','2','3','round'shadow- Box shadow:boolean,'1','2','3'
Positioning:
position- Various position values including sticky and absolute positionszIndex- Z-index:'0'to'10'overlay- Overlay positioningalign- Alignment:'right','top','center','bottom'
Flexbox Layout:
horizontal,vertical- Layout directionwrap- Flex wrapspacing- Gap between children:'xs','s','m','l','xl'justify- Justify content:'space','start','center','end'alignItems- Align items:'start','end','center','baseline','stretch'
Grid Layout:
grid- Grid type:'columns','template'columns- Number of columns:1,2,3,4gridRows,gridColumns- CSS grid template values
Container:
as- HTML element typefixed- Fixed positioningstretch- Stretch to fill containeroverflow- Overflow:'hidden','auto'fullScreen- Full screen modeseparator- Separator line stylecursor- Cursor style:'pointer','auto','move','grab','not-allowed'hoverable- Add hover effect
Typography
Text
Flexible text component with semantic HTML support.
<Text h1 size="4xl" weight="bold">Main Heading</Text>
<Text size="l" color="grey-6">Subtitle text</Text>
<Text caps size="s" color="accent-4">SMALL CAPS LABEL</Text>
<Text monospace background="light-1" padding="xs s">code snippet</Text>Text Props:
Typography:
size- Text size:'s','m','l','xl','xxl','3xl','4xl','5xl'weight- Font weight:'normal','medium','bold'leading- Line height:'s','m','l'
Semantic Elements:
h1throughh5- Header levelsas- HTML element:'p','span','strong','em', etc.link- Style as linkhref- Link URL
Text Styling:
caps- Uppercase textmonospace- Monospace fontunderline- Underline textsmall,large- Quick size modifiersstrong- Medium font weightsup,sub- Superscript/subscript
Text Layout:
block- Block displayright,center- Text alignmenttruncate- Truncate with ellipsislineClamp- Clamp lines:boolean,'2'-'8'line- Single line display
Icons:
icon- Icon nameiconPosition- Icon position:'before','after'
Plus all Box props for layout and styling
Data Display
List
Standard list with selection, keyboard navigation, and drag support.
const items = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
];
<List
data={items}
itemKey={(item) => item.id}
itemContent={(item) => <Text>{item.name}</Text>}
onAction={(item) => console.log('Selected:', item)}
/>;List Props:
data- Array of itemsitemKey- Function to get unique keyitemContent- Render function for itemsitemProps- Props for item stylingselectable,multiselect- Selection modesonAction,onSelect- Event handlerskeyboard- Enable keyboard navigationdraggable- Enable drag and drop
LazyList
Virtualized list for large datasets with excellent performance.
<LazyList
data={largeDataset}
itemHeight={40}
height={400}
itemKey={(item) => item.id}
itemContent={(item) => <Text>{item.name}</Text>}
onLoadMore={loadNextPage}
/>LazyList Props:
- All List props
itemHeight- Height of each item (for virtualization)height- Container heightonLoadMore- Infinite scroll callbackthreshold- Scroll threshold for loading more
Form Components
Field
Unified field component that handles various input types with validation and autocomplete.
// Text input with validation
<Field
label="Email"
type="text"
value={email}
onChange={setEmail}
validators={[
{ required: true, message: 'Email is required' },
{ pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: 'Invalid email' }
]}
/>
// Numeric input
<Field
label="Age"
type="numeric"
value={age}
onChange={setAge}
min={0}
max={120}
/>
// Select field
<Field
label="Country"
type="select"
value={country}
onChange={setCountry}
data={countries}
itemKey={c => c.code}
itemContent={c => c.name}
/>
// Autocomplete field
<Field
label="Search Users"
type="suggest"
value={user}
onChange={setUser}
data={async (search) => await searchUsers(search)}
itemKey={u => u.id}
itemContent={u => u.name}
debounce={300}
/>Field Props:
label- Field labeltype-'text','numeric','date','select','suggest'value,onChange- Controlled component propsvalidators- Array of validation rulesdata- Options for select/suggest (can be async function)prefix,suffix- Icons or contentdebounce- Debounce delay for suggestplaceholder,hint- Helper textyearRange- Year range for date picker (default: 5)- All BoxItem props for styling
TextInput
Basic text input component.
<TextInput
value={text}
onChange={setText}
placeholder="Enter text..."
prefix={<Icon name="search" />}
clearable
/>Select
Dropdown select component.
<Select
value={selected}
onChange={setSelected}
data={options}
itemKey={(opt) => opt.id}
itemContent={(opt) => opt.label}
placeholder="Choose an option"
/>Suggest
Autocomplete component with search.
<Suggest
value={selected}
onChange={setSelected}
data={async (search) => await searchAPI(search)}
itemKey={(item) => item.id}
itemContent={(item) => item.name}
debounce={300}
clearable
/>DateInput
Date picker with calendar popup.
<DateInput
value={date}
onChange={setDate}
locale="en-US"
yearRange={10}
placeholder="Select date"
/>DateInput Props:
value- Date | string | nullonChange- (value: Date | null) => voidlocale- Locale for formatting (string or locale object)yearRange- Years to show before/after current year (default: 5)toggle- Allow calendar toggle (default: false)- Dynamic positioning - Calendar opens above input when no space below
- Inherits all TextInput props except 'onChange' and 'value'
Dropdown
Low-level dropdown component for custom implementations.
<Dropdown
opener={<Button>Open Menu</Button>}
content={
<Box padding="s" background="white" shadow="2">
<Text>Dropdown content</Text>
</Box>
}
/>Other Components
Button
<Button primary size="m" onClick={handleClick}>
Primary Button
</Button>
<Button variant="secondary" icon="add">
With Icon
</Button>Icon
<Icon name="settings" size="m" color="accent-4" />Checkbox & Radio
<Checkbox value={checked} onChange={setChecked}>
Accept terms
</Checkbox>
<Radio value={option} onChange={setOption} options={[
{ value: 'a', label: 'Option A' },
{ value: 'b', label: 'Option B' },
]} />Theming
JUI supports multiple themes that can be switched dynamically.
import { Theme } from '@jsway/jui';
<Theme theme="ascii">
<App />
</Theme>;Available themes:
default- Modern, clean designascii- Terminal-style ASCII themerects- Rectangular, minimalist theme
Advanced Features
Width System
JUI provides a comprehensive width system:
- Semantic:
'auto','fit','screen','xxs','xs','s','m','l','xl','xxl' - Percentages:
'0','3','5','7','10','15','20','25','30','33','35','40','50','60','70','80','90','100' - Fixed:
'1px','5px','10px','1em','2em','3em','5em'
Spacing System
- Values:
'0','xs','s','m','l','xl' - Axis-based:
"s m"for vertical/horizontal - Side-based:
"s m l xl"for top/right/bottom/left
Custom Styling with BoxItem Props
Almost all components accept BoxItem props for custom styling:
<TextInput
padding="m"
background="accent-1"
border="1 dark-6"
radius="2"
value={text}
onChange={setText}
/>Responsive Utilities
// Hide on mobile, show on desktop
<Box visible="false true@md">
Desktop only content
</Box>
// Different spacing on different screen sizes
<Box padding="s m@md l@lg">
Responsive padding
</Box>TypeScript Support
JUI is built with TypeScript and provides full type safety:
interface User {
id: string;
name: string;
email: string;
}
<List<User>
data={users}
itemKey={(user) => user.id}
itemContent={(user) => <Text>{user.name}</Text>}
onAction={(user) => console.log(user.email)}
/>;License
MIT © Oleg V. Richards
