import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Alert, Button, Grid, useTheme } from 'core' export const meta = { title: 'Alert', description: 'Show a message that stays in the page, with an optional title, icon and close button.', sidebar: 'components', group: 'Components', index: 54 } ## Alert Show a message that stays in the page, with an optional title, icon and close button. Your trial ends in 3 days. Pick a plan to keep your projects. Invoice 2041 is paid. You used 92% of your 10 GB. Your bank refused the payment. Update the card to retry. `} /> New features are on the way. New features are on the way. New features are on the way. New features are on the way. `} /> { const [open, setOpen] = React.useState(true) return open ? ( setOpen(false)}> Reload the page to get the latest changes. ) : ( ) } `} /> { const theme = useTheme() const icon = ( ) return (
Leave now and the last 4 edits are lost.
) } `} /> Alert.Props | Attribute | Description | Type | Accepted values | Default | | -------------- | --------------------------------------------- | ----------------------------------------------------------------------------- | --------------- | --------- | | **type** | color of the alert | `'default' \| 'primary' \| 'secondary' \| 'success' \| 'warning' \| 'error' \| 'info'` | - | `default` | | **title** | bold first line | `ReactNode` | - | - | | **icon** | element before the text | `ReactNode` | - | - | | **filled** | solid color | `boolean` | - | `false` | | **light** | tinted background | `boolean` | - | `false` | | **subtle** | text only, no border | `boolean` | - | `false` | | **onClose** | shows a close button and calls it on click | `() => void` | - | - | | **closeLabel** | accessible name of the close button | `string` | - | `Close` | | **role** | defaults to `alert` for errors and warnings, `status` otherwise | `string` | - | - | | ... | native props | `HTMLAttributes` | - | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Avatar, Grid, Text, Tag, Card } from 'core' export const meta = { title: 'Avatar', description: 'Avatars represent a user or a team. Stacked avatars represent a group of people.', sidebar: 'components', group: 'Components', index: 1 } ## Avatar Avatars represent a user or a team. Stacked avatars represent a group of people. `} /> `} /> `} /> {[ ['AL', 'Ada Lovelace', 'Owner'], ['GH', 'Grace Hopper', 'Editor'], ['LT', 'Linus Torvalds', 'Viewer'] ].map(([text, name, role]) => (
{name} {role}
))} `} /> Avatar.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | ---------------------------------- | ------------------- | ---------------------------------------- | ------- | | **src** | image src | `string` | - | - | | **stacked** | stacked display group | `boolean` | - | `false` | | **text** | display text when image is missing | `string` | - | - | | **isSquare** | avatar shape | `boolean` | - | `false` | | ... | native props | `ImgHTMLAttributes` | `'alt', 'crossOrigin', 'className', ...` | - | Avatar.Group.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------------ | ---------------- | -------------------------------- | ------- | | **count** | show total members | `number` | - | - | | ... | native props | `HTMLAttributes` | `'id', 'name', 'className', ...` | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Badge, Grid, Avatar, Button, Link, useTheme } from 'core' export const meta = { title: 'Badge', description: 'Display an indicator that requires attention.', sidebar: 'components', group: 'Components', index: 2 } ## Badge Display an indicator that requires attention. Default `} /> Default Primary Secondary Success Warning Error Info `} /> For more colors, please refer to the{' '} color section . } scope={{ Grid, Badge, useTheme }} code={` () => { const theme = useTheme() return ( Success Light Alert Purple Violet ) } `} /> Recording Live `} /> 10 10 99+ Bolio UI Share Link `} /> Badge.Props | Attribute | Description | Type | Accepted values | Default | | --------- | --------------------------- | ---------------- | ------------------------------- | --------- | | **type** | badge type | `BadgeTypes` | [BadgeTypes](#badgetypes) | `default` | | **dot** | show dot and ignore content | `boolean` | - | `false` | | **pulse** | animated ring for live status | `boolean` | - | `false` | | **ghost** | outline variant: opposite color | `boolean` | - | `false` | | **light** | light variant: tinted background | `boolean` | - | `false` | | **subtle**| subtle variant: no background | `boolean` | - | `false` | | ... | native props | `HTMLAttributes` | `'alt', 'id', 'className', ...` | - | Badge.Anchor.Props | Attribute | Description | Type | Accepted values | Default | | ------------- | ---------------------- | ----------------- | ----------------------------------- | ---------- | | **placement** | fixe position of Badge | `AnchorPlacement` | [AnchorPlacement](#anchorplacement) | `topRight` | | ... | native props | `HTMLAttributes` | `'alt', 'id', 'className', ...` | - | BadgeTypes ```ts type BadgeTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` AnchorPlacement ```ts type AnchorPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Breadcrumbs, Grid } from 'core' import { useRouter } from 'next/navigation' import { Home, Settings } from '@bolio-ui/icons' export const meta = { title: 'Breadcrumbs', description: 'Show where users are in the application.', sidebar: 'components', group: 'Components', index: 3 } ## Breadcrumbs Show where users are in the application. Home Settings General `} /> Home Categories Add Home : Pages Default Index `} /> Settings General `} /> { const router = useRouter() const go = (url) => (event) => { event.preventDefault() router.push(url) } return ( Home Settings General ) } `} /> Breadcrumbs.Props | Attribute | Description | Type | Accepted values | Default | | ------------- | ---------------- | ---------------- | ------------------------ | ------- | | **separator** | separator string | `string` | - | `/` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Breadcrumbs.Item.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | ------------------ | ----------------------------- | ------------------------ | ------- | | **href** | link address | `string` | - | - | | **nextLink** | render as a link even without `href` | `boolean` | - | `false` | | **onClick** | click event | `(event: MouseEvent) => void` | - | - | | ... | native props | `AnchorHTMLAttributes` | `'id', 'className', ...` | - | Breadcrumbs.Separator.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | ------------------------ | ------- | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { ButtonDropdown, Grid } from 'core' import { Playground, Attributes } from 'src/components' import { Plus, Copy, FileText } from '@bolio-ui/icons' export const meta = { title: 'Button Dropdown', description: 'Display related but alternate actions for a button.', sidebar: 'components', group: 'Components', index: 5 } ## Button Dropdown Display related but alternate actions for a button. Default Button Secondary Button Tertiary Button `} /> Default Button Secondary Button Tertiary Button `} /> Default Button Secondary Button Tertiary Button `} /> Primary Button Secondary Button Tertiary Button Secondary Button Secondary Button Tertiary Button Success Button Secondary Button Tertiary Button Warning Button Secondary Button Tertiary Button Error Button Secondary Button Tertiary Button Info Button Secondary Button Tertiary Button `} /> Check Block Lock Destroy `} /> }> Check User Block User Lock User Destroy User `} /> }>Copy Markdown }>View as Markdown `} /> Start Secondary Button Center Secondary Button End Secondary Button `} /> ButtonDropdown.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | --------------------------- | ------------------------------ | ------------------------------------------- | -------------------- | | **type** | button type | `ButtonDropdownTypes` | [ButtonDropdownTypes](#buttondropdowntypes) | `default` | | **loading** | display loading indicator | `boolean` | - | `false` | | **auto** | autoscale width | `boolean` | - | `false` | | **align** | main button label alignment | `'start' \| 'center' \| 'end'` | - | `center` | | **disabled** | disable button | `boolean` | - | `false` | | **icon** | custom right icon | `ReactNode` | - | `ButtonDropdownIcon` | | ... | native props | `HTMLAttributes` | `'autoFocus', 'name', 'className', ...` | - | ButtonDropdown.Item.Props | Attribute | Description | Type | Accepted values | Default | | ----------- | --------------------- | ---------------------- | ------------------------------------------- | --------- | | **type** | button type | `ButtonDropdownTypes` | [ButtonDropdownTypes](#buttondropdowntypes) | `default` | | **main** | the main action | `boolean` | - | `false` | | **icon** | icon before the label | `ReactNode` | - | - | | **onClick** | event handler | `MouseEventHandler` | - | - | | ... | native props | `ButtonHTMLAttributes` | `'id', 'name', 'className', ...` | - | ButtonDropdownTypes ```ts type ButtonDropdownTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Button, Grid, ButtonGroup } from 'core' import { Bold, Italic, Underline } from '@bolio-ui/icons' export const meta = { title: 'Button Group', description: 'A set of related buttons.', sidebar: 'components', group: 'Components', index: 6 } ## Button Group A set of related buttons. `} /> `} /> `} /> `} /> `} /> { const [on, setOn] = React.useState({ bold: true, italic: false, underline: false }) const toggle = (key) => () => setOn((last) => ({ ...last, [key]: !last[key] })) const style = (key) => (on[key] ? 'primary' : 'default') return ( `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> { const [state, setState] = React.useState('idle') const save = () => { setState('saving') setTimeout(() => setState('saved'), 1500) } return ( ) } `} /> Button.Props | Attribute | Description | Type | Accepted values | Default | | ------------- | ----------------------------------------- | ----------------------------------------------- | --------------------------- | --------- | | **type** | button type | `ButtonTypes` | [ButtonTypes](#buttontypes) | `default` | | **ghost** | the opposite color | `boolean` | - | `false` | | **subtle** | no background, only the type's color | `boolean` | - | `false` | | **rounded** | rounded button | `boolean` | - | `false` | | **loading** | display loading indicator | `boolean` | - | `false` | | **shadow** | display shadow | `boolean` | - | `false` | | **auto** | autoscale width | `boolean` | - | `false` | | **effect** | display animation | `boolean` | - | `true` | | **spotlight** | glow that follows the pointer on hover | `boolean` | - | `false` | | **disabled** | disable button | `boolean` | - | `false` | | **onClick** | click handler | `MouseEventHandler` | - | - | | **icon** | show icon in button | `ReactNode` | - | - | | **iconRight** | show icon on the other side of the button | `ReactNode` | - | - | | **htmlType** | native type of button element | `ButtonHTMLAttributes.type` | - | `button` | | **ref** | forwardRef | Ref<HTMLButtonElement | null> | - | - | | ... | native props | `ButtonHTMLAttributes` | `'id', 'className', ...` | - | ButtonTypes ```ts type ButtonTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' | 'abort' | 'primary-light' | 'secondary-light' | 'success-light' | 'warning-light' | 'error-light' | 'info-light' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Calendar, Grid } from 'core' export const meta = { title: 'Calendar', description: 'A month grid to pick a day with the mouse or the keyboard.', sidebar: 'components', group: 'Components', index: 43 } ## Calendar A month grid to pick a day with the mouse or the keyboard. `DatePicker` uses it, and you can use it alone when the calendar should always be visible. In Next.js 16 with `cacheComponents` on, wrap a `Calendar` that is always visible in ``. It reads today's date while it renders, and Next does not prerender that. A `DatePicker` does not need it, because its calendar opens on a click. `} /> `} /> `} /> `} /> `} /> date.getDay() === 0 || date.getDay() === 6} /> `} /> `} /> `} /> Calendar.Props | Attribute | Description | Type | Accepted values | Default | | --------------------- | --------------------------------------------------------- | ------------------------------------------- | ------------------------------- | ---------------- | | **value** | selected day, days or range, to control the component | `Date` / `null`, `Date[]` or `[Date, Date]` | - | - | | **onChange** | called with what the user picked, in the shape of `value` | `(value) => void` | - | - | | **min** | first day that can be picked | `Date` | - | - | | **max** | last day that can be picked | `Date` | - | - | | **locale** | language of the month and weekday names | `string` | any `Intl` locale | `en-US` | | **weekStartsOn** | first day of the week, 0 is Sunday | `number` | `0` to `6` | `0` | | **mode** | how many days can be picked | `string` | `'single', 'multiple', 'range'` | `single` | | **maxSelected** | most days in `multiple` mode | `number` | - | - | | **shouldDisableDate** | disable the days where it returns `true` | `(date: Date) => boolean` | - | - | | **showOutsideDays** | show days of the neighbor months | `boolean` | - | `false` | | **numberOfMonths** | months shown side by side; hides the neighbor days if more than one | `number` | - | `1` | | **showWeekNumbers** | show the ISO week of each row | `boolean` | - | `false` | | **month** | visible month, to control it | `Date` | - | - | | **defaultMonth** | visible month at the start | `Date` | - | the selected day | | **onMonthChange** | called with the first day of the new month | `(month: Date) => void` | - | - | | **weekLabel** | name of the week number column | `string` | - | `Week` | | **autoFocus** | move the focus to the day when it is shown | `boolean` | - | `false` | | **previousLabel** | name of the previous month button | `string` | - | `Previous month` | | **nextLabel** | name of the next month button | `string` | - | `Next month` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Ref The `ref` points at the root element. Accessibility The days are a `grid` named by the month, with a single tab stop on the focused day. The selected day has `aria-selected` and today has `aria-current="date"`. | Key | Action | | ------------------------- | ----------------------------------------------- | | Arrow keys | Move by one day, or one week | | Home and End | Go to the first and to the last day of the week | | Page Up and Page Down | Go to the previous and to the next month | | Shift and Page Up or Down | Go to the previous and to the next year | | Enter and Space | Pick the day | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Capacity, Grid, Card, Text, useTheme } from 'core' export const meta = { title: 'Capacity', description: 'Display an capacity indicator.', sidebar: 'components', group: 'Components', index: 7 } ## Capacity Display an capacity indicator. `} /> { const theme = useTheme() return ( ) } `} /> {[ ['Projects', 3, 10], ['Members', 7, 10], ['Storage (GB)', 9.4, 10] ].map(([label, value, limit]) => ( {label} {value} of {limit} ))} `} /> Capacity.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ---------------- | ---------------- | ------------------ | ------- | | **value** | value number | `number` | - | 0 | | **limit** | max value | `number` | - | 100 | | **color** | css color string | `string` | - | - | | ... | native props | `HTMLAttributes` | `'className', ...` | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Card, Link, Image, Text, Divider, Code, Grid, Avatar, Button } from 'core' export const meta = { title: 'Card', description: 'A common container component.', sidebar: 'components', group: 'Components', index: 8 } ## Card A common container component. A default card. `} /> A hoverable default card. A hoverable primary card. A hoverable secondary card. `} /> A bordered default card. A bordered primary card. A bordered secondary card. `} /> A shadow default card. A shadow primary card. A shadow secondary card. `} /> { const types = ['default', 'primary', 'secondary', 'success', 'warning', 'error', 'info', 'dark', 'lite'] return ( {types.map((type) => ( {type} {type} ))} ) } `} /> Bolio UI More creative and fun with amazing features for React. Visit source code on GitHub. Bolio UI More creative and fun with amazing features for React. Visit source code on GitHub. `} /> Bolio UI More creative and fun with amazing features for React. Visit source code on GitHub. `} /> A Simple Component React components implement a render() method that takes input data and returns what to display. This example uses an XML-like syntax called JSX. Input data that is passed into the component can be accessed by render() via{' '} this.props. `} /> Default Move the pointer over the card. Primary The glow follows the card color. Dark Works on solid backgrounds too. `} /> Frosted The gradient shows through the card. Frosted dark Same effect with a dark tint. `} /> alert('Opened')}> Open project Click, or focus with Tab. With spotlight Combine variants freely. `} /> Revenue $48,200 +12.4% this month Active users 3,842 +4.1% this week Churn 1.8% +0.3% this month `} /> Free $0 1 project Community support Pro $12 Unlimited projects Priority support `} /> Ada Lovelace ada@example.com `} /> Card.Props | Attribute | Description | Type | Accepted values | Default | | ------------- | ------------------- | --------------------- | ----------------------- | --------- | | **hoverable** | add effect on hover | `boolean` | - | `false` | | **shadow** | show shadow | `boolean` | - | `false` | | **type** | card type | [CardType](#cardtype) | - | `default` | | **filled** | filled variant, solid background | `boolean` | - | `false` | | **ghost** | outline variant, always shows a border | `boolean` | - | `false` | | **subtle** | subtle variant, no background | `boolean` | - | `false` | | **spotlight** | glow that follows the pointer on hover | `boolean` | - | `false` | | **glass** | translucent background with blur | `boolean` | - | `false` | | **interactive** | pointer cursor, lift on hover and focus ring | `boolean` | - | `false` | | ... | native props | `HTMLAttributes` | `'id', className', ...` | - | Card.Content.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | ----------------------- | ------- | | ... | native props | `HTMLAttributes` | `'id', className', ...` | - | Card.Footer.Props | Attribute | Description | Type | Accepted values | Default | | --------------------- | ----------------------------- | ---------------- | ----------------------- | ------- | | **disableAutoMargin** | cancel automatic margin value | `boolean` | - | `false` | | ... | native props | `HTMLAttributes` | `'id', className', ...` | - | CardType ```ts type CardType = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' | 'dark' | 'lite' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Carousel, Card, Text, Avatar, Button, Grid, Image, useTheme } from 'core' export const meta = { title: 'Carousel', description: 'A row of slides that scrolls and snaps, with buttons and dots to move between them.', sidebar: 'components', group: 'Components', index: 64 } ## Carousel A row of slides that scrolls and snaps into place. It is plain scrolling with `scroll-snap`, so touch, trackpad and keyboard work as the browser does them, and the buttons and dots move the same scroll. {[ ['Themes', 'Dark and light, and your brand color in one line.'], ['Accessible', 'Keyboard and screen reader support in every component.'], ['Typed', 'Props and refs are typed for TypeScript.'] ].map(([title, text]) => ( {title} {text} ))} `} /> {['Free', 'Starter', 'Pro', 'Team', 'Business'].map((name, index) => ( {name} {'$' + index * 12 + ' a month'} ))} `} /> { const theme = useTheme() const photos = [ ['/img/jpg/docs/lake-sunrise.jpg', 'A mountain lake at sunrise', 'Lake at sunrise'], ['/img/jpg/docs/forest-lake.jpg', 'A forest lake under the clouds', 'Forest lake'], ['/img/jpg/docs/autumn-canyon.jpg', 'A river in a canyon in autumn', 'Autumn canyon'], ['/img/jpg/docs/mountain-reflection.jpg', 'Snowy mountains reflected in a lake', 'Mountain reflection'], ['/img/jpg/docs/moonlit-peaks.jpg', 'Snowy mountains under the moon', 'Moonlit peaks'] ] return ( {photos.map(([src, alt, caption]) => (
{alt} {caption}
))}
) } `} /> { const theme = useTheme() const photos = [ ['/img/jpg/docs/lake-sunrise.jpg', 'A mountain lake at sunrise'], ['/img/jpg/docs/forest-lake.jpg', 'A forest lake under the clouds'], ['/img/jpg/docs/autumn-canyon.jpg', 'A river in a canyon in autumn'], ['/img/jpg/docs/mountain-reflection.jpg', 'Snowy mountains reflected in a lake'], ['/img/jpg/docs/moonlit-peaks.jpg', 'Snowy mountains under the moon'] ] return ( {photos.map(([src, alt]) => ( {alt} ))} ) } `} /> { const theme = useTheme() const places = [ ['/img/jpg/docs/lake-sunrise.jpg', 'A mountain lake at sunrise', 'Lake at sunrise', 'From $420'], ['/img/jpg/docs/forest-lake.jpg', 'A forest lake under the clouds', 'Forest lake', 'From $380'], ['/img/jpg/docs/autumn-canyon.jpg', 'A river in a canyon in autumn', 'Autumn canyon', 'From $510'], ['/img/jpg/docs/mountain-reflection.jpg', 'Snowy mountains reflected in a lake', 'Mountain reflection', 'From $460'] ] return ( {places.map(([src, alt, name, price]) => ( {alt} {name} {price} ))} ) } `} /> { const [index, setIndex] = React.useState(0) return ( {['Create an account', 'Invite your team', 'Deploy', 'Share the link'].map((step) => ( {step} ))} Slide {index + 1} of 4 ) } `} /> {[ ['AL', 'Ada Lovelace', 'We shipped our dashboard in a week.'], ['GH', 'Grace Hopper', 'The best defaults I have used.'], ['LT', 'Linus Torvalds', 'Easy to theme, and the docs are clear.'] ].map(([text, name, quote]) => ( {quote}
{name}
))} `} /> Carousel.Props | Attribute | Description | Type | Accepted values | Default | | ------------------ | ----------------------------------------------------------------- | --------------------------------------------- | ------------------------- | ------------------- | | **slidesToShow** | slides in view at once | `number` | - | `1` | | **gap** | space between the slides | `string` | any CSS length | `1rem` | | **controls** | show the previous and next buttons | `boolean` | - | `true` | | **indicators** | show a dot for each position | `boolean` | - | `true` | | **value** | index of the first slide in view, to control it | `number` | - | - | | **initialValue** | index of the first slide in view on the first render | `number` | - | `0` | | **onChange** | called with the index of the slide the scroll rests on | `(index: number) => void` | - | - | | **previousLabel** | name of the previous button | `string` | - | `Previous slide` | | **nextLabel** | name of the next button | `string` | - | `Next slide` | | **slideLabel** | name of each slide for screen readers | `(index: number, count: number) => string` | - | `1 of 5` | | **indicatorLabel** | name of each dot | `(index: number) => string` | - | `Go to slide 1` | | ... | native props, passed to the root `div` | `HTMLAttributes` | `'aria-label', 'id', ...` | - | Behavior - • **Scroll**: swiping, the trackpad, the arrow keys on the focused list and the buttons all move the same scroll. `onChange` is called once the scroll stops, not on every pixel. - • **Motion**: the scroll is smooth, unless the user asked for less motion in the system. - • **Ends**: the buttons are disabled on the first and the last position. There is no loop. - • **Controls**: when every slide fits, the buttons and dots are not shown. Ref The `ref` points at the root `div`. Accessibility The root is a `region` with `aria-roledescription="carousel"`, and each slide is a `group` named by its position, like "2 of 5". Name the carousel with `aria-label`. The scrolling list can be focused, so the keyboard can scroll it, and the buttons and dots are real buttons with names you can translate. The dot of the current position has `aria-current`. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Checkbox, Grid, Code, Button } from 'core' export const meta = { title: 'Checkbox', description: 'Displays a boolean value.', sidebar: 'components', group: 'Components', index: 9 } ## Checkbox Displays a boolean value. Check option `} /> scale-0.25 scale-0.5 scale-0.75 `} /> Checkbox Default Checkbox Primary Checkbox Secondary Checkbox Success Checkbox Warning Checkbox Error Checkbox Info `} /> Checkbox option Checkbox option disabled `} /> { const handler = value => { console.log(value) } return ( Checkbox option 1 Checkbox option 2 Checkbox option 3 Checkbox option 4 ) } `} /> { const [accepted, setAccepted] = React.useState(false) return ( setAccepted(event.target.checked)}> I accept the terms of use ) } `} /> Checkbox.Props | Attribute | Description | Type | Accepted values | Default | | ------------------ | ------------------------------------------- | ---------------------------------------------- | ------------------------------- | --------- | | **checked** | checked or not | `boolean` | - | - | | **initialChecked** | checked or not on initial | `boolean` | - | `false` | | **onChange** | change event handler | `CheckboxEvent` | - | - | | **value** | unique identification value (only in group) | `string` | - | - | | **disabled** | disable checkbox | `boolean` | - | `false` | | **type** | current type | `CheckboxTypes` | [CheckboxTypes](#checkboxtypes) | `default` | | **ref** | forwardRef | Ref<HTMLInputElement | null> | - | - | | ... | native props | `LabelHTMLAttributes` | `'form' ...` | - | Checkbox.Group.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | ---------------------- | ---------------------------- | --------------- | ------- | | **value** | checked children | `Array` | - | `[]` | | **disabled** | disable checkbox group | `boolean` | - | `false` | | **onChange** | change event handler | `(values: string[]) => void` | - | - | | ... | native props | `HTMLAttributes` | `'id', ...` | - | CheckboxTypes ```ts type CheckboxTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` CheckboxEvent ```ts interface CheckboxEventTarget { checked: boolean } export interface CheckboxEvent { target: CheckboxEventTarget stopPropagation: () => void preventDefault: () => void nativeEvent: React.ChangeEvent } ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Chip, Card, Text, Grid } from 'core' export const meta = { title: 'Chip', description: 'Pick options from a row of pills, one or several at a time.', sidebar: 'components', group: 'Components', index: 55 } ## Chip Pick options from a row of pills, one or several at a time. Free shipping `} /> { const [stack, setStack] = React.useState(['react']) return ( <> React Vue Svelte Solid {stack.length ? stack.length + ' selected: ' + stack.join(', ') : 'Pick at least one framework.'} ) } `} /> { const [size, setSize] = React.useState(['m']) return ( S M L XL, sold out ) } `} /> { const posts = [ ['Ship a Tour in an afternoon', 'product'], ['Why we dropped styled-jsx', 'engineering'], ['Dark mode without gray mush', 'design'], ['Splitting a layout with CSS grid', 'engineering'], ['Reading an empty state', 'design'] ] const [topics, setTopics] = React.useState([]) const shown = topics.length ? posts.filter(([, topic]) => topics.includes(topic)) : posts return ( <> Product Engineering Design
{shown.map(([title, topic]) => ( {title} {topic} ))}
) } `} /> Chip.Props | Attribute | Description | Type | Accepted values | Default | | ------------------ | -------------------------------------------------------- | ----------------------------------------------------------------- | --------------- | --------- | | **value** | value the chip adds to or takes from its `Chip.Group` | `string` | - | - | | **checked** | checked state, to control the chip | `boolean` | - | - | | **initialChecked** | checked state at the start | `boolean` | - | `false` | | **onChange** | called with the new state when the chip is alone | `(checked: boolean) => void` | - | - | | **type** | color of a checked chip | `'primary' \| 'secondary' \| 'success' \| 'warning' \| 'error' \| 'info'` | - | `primary` | | **disabled** | block the chip | `boolean` | - | `false` | | ... | native props of the input | `InputHTMLAttributes` | - | - | Chip.Group.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | ------------------------------------------- | ----------------------------- | --------------- | ------- | | **value** | values of the checked chips, to control it | `string[]` | - | - | | **initialValue** | values checked at the start | `string[]` | - | `[]` | | **onChange** | called with the values of the checked chips | `(value: string[]) => void` | - | - | | **multiple** | allow several checked chips | `boolean` | - | `false` | | **disabled** | block every chip of the group | `boolean` | - | `false` | | ... | native props | `HTMLAttributes` | - | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Code, Text, Grid } from 'core' import { Playground, Attributes, ParsedCodes } from 'src/components' import WaitTime from 'core/MdxWidgets/ParsedCodes/WaitTime' export const meta = { title: 'Code', description: 'Show source code in a standardized way.', sidebar: 'components', group: 'Components', index: 10 } ## Code Show source code in a standardized way. Want to display shell code snippets? try [Snippet](/docs/components/snippet). Run npm i @bolio-ui/core to install. Or run yarn add @bolio-ui/core to install. `} /> `} /> {'yarn add @bolio-ui/core'} `} /> `} /> { const [active, setActive] = React.useState(0) const codes = [ "import { Button } from '@bolio-ui/core'", "import { Text } from '@bolio-ui/core'" ] return ( {codes[active]} ) } `} /> `} /> Code.Props | Attribute | Description | Type | Accepted values | Default | | --------------- | ------------------------------------------- | ------------------------- | ------------------ | ------- | | **block** | show code in `pre` | `boolean` | - | `false` | | **name** | text displayed at the top of the code block | `string` | - | - | | **classic** | display with classic style | `boolean` | - | `false` | | **tabs** | names of the tabs, in place of `name` | `string[]` | - | `[]` | | **activeTab** | index of the active tab | `number` | - | `0` | | **onTabChange** | called with the index of the chosen tab | `(index: number) => void` | - | - | | ... | native props | `HTMLAttributes` | `'className', ...` | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Row, Col, Card, Text } from 'core' export const meta = { title: 'Col', description: 'A column inside a Row, sized in twelfths.', sidebar: 'components', group: 'Components', index: 47 } ## Col A column inside a Row, sized in twelfths of the row. span 4 span 8 `} /> span 4, offset 4 `} /> Settings Profile Billing Team Profile Update your name, photo and the email we use to contact you. `} /> Col.Props | Attribute | Description | Type | Accepted values | Default | | ------------- | ------------------------------------------ | ----------------------------- | ----------------------------- | ------- | | **span** | how many twelfths of the row it takes | `number` | `1` to `12` | `12` | | **offset** | how many twelfths to leave before it | `number` | `0` to `11` | `0` | | **component** | the element to render | `keyof JSX.IntrinsicElements` | `'div', 'li', 'section', ...` | `div` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Ref The `ref` points at the root element. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Collapse, Grid, Text } from 'core' export const meta = { title: 'Collapse', description: 'Display large amounts of text in collapsible sections. Commonly referred to as an accordion.', sidebar: 'components', group: 'Components', index: 11 } ## Collapse Display large amounts of text in collapsible sections. Commonly referred to as an accordion. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. `} /> Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. `} /> Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. More description about Lorem ipsum 2 } > Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. `} /> Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum `} /> { const [visible, setVisible] = React.useState(true) return ( The section is {visible ? 'open' : 'closed'}. Nobody sees this. ) } `} /> Collapse.Props | Attribute | Description | Type | Accepted values | Default | | ------------------- | ---------------- | ---------------- | -------------------------------- | ------- | | **title**(required) | collapse title | `string` | - | - | | **subtitle** | description | `string` | - | - | | **initialVisible** | initial expanded | `boolean` | - | `false` | | **visible** | expanded, to control it | `boolean` | - | - | | **onVisibleChange** | called with the next state when the header is clicked | `(visible: boolean) => void` | - | - | | **disabled** | the section cannot be toggled | `boolean` | - | `false` | | **shadow** | show shadow card | `boolean` | - | `false` | | ... | native props | `HTMLAttributes` | `'id', 'name', 'className', ...` | - | Collapse.Group.Props | Attribute | Description | Type | Accepted values | Default | | ------------- | -------------- | ---------------- | -------------------------------- | ------- | | **accordion** | accordion mode | `boolean` | - | `true` | | ... | native props | `HTMLAttributes` | `'id', 'name', 'className', ...` | - | Accessibility The title is a heading with a real button inside, so a screen reader announces it as a heading and as a button that is expanded or collapsed, and `aria-controls` points at the content. Enter and Space toggle a section. In a `Collapse.Group`, the Up and Down arrows move focus between the titles, wrapping at the ends, and Home and End go to the first and the last. Disabled sections are skipped. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { ColorInput, Grid, useTheme } from 'core' export const meta = { title: 'Color Input', description: 'A field for a hex color, with a swatch that opens a color picker in a popover.', sidebar: 'components', group: 'Components', index: 66 } ## Color Input A field for a hex color. The swatch on the left shows the color and opens a Color Picker in a popover. You can also type the code. Brand color `} /> `} /> { const theme = useTheme() const [primary, setPrimary] = React.useState('#2563eb') const [secondary, setSecondary] = React.useState('#7c3aed') return ( Primary Secondary
) } `} /> `} /> `} /> ColorInput.Props | Attribute | Description | Type | Accepted values | Default | | ----------------- | -------------------------------------------------------- | ----------------------- | -------------------------------------------------------------------------- | -------------- | | **value** | the color, to control the component | `string` | `'#rrggbb'`, `'#rgb'` | - | | **initialValue** | the color on the first render | `string` | `'#rrggbb'`, `'#rgb'` | `#000000` | | **onChange** | called with the color as `#rrggbb` in lowercase | `(hex: string) => void` | - | - | | **swatches** | colors to pick with one click in the popover | `string[]` | - | - | | **placeholder** | text shown when the field is empty | `string` | - | `#000000` | | **pickerLabel** | name of the swatch button and of the dialog | `string` | - | `Choose color` | | **disabled** | disable the component | `boolean` | - | `false` | | **type** | color of the field | `NormalTypes` | `'default', 'primary', 'secondary', 'success', 'warning', 'error', 'info'` | `default` | | **rounded** | round the corners | `boolean` | - | `false` | | **filled** | filled variant | `boolean` | - | `false` | | **light** | light variant | `boolean` | - | `false` | | **ghost** | outline variant | `boolean` | - | `false` | | **subtle** | subtle variant | `boolean` | - | `false` | | ... | native props, passed to the input | `InputHTMLAttributes` | `'aria-label', 'name', ...` | - | Typing The color changes as soon as the text holds six digits, with or without the `#`. A short code like `#abc` is read when the field loses the focus, and becomes `#aabbcc`. Any other text is dropped on blur, and the field goes back to the current color. The field always holds a color, so it cannot be left empty. Ref The `ref` points at the `input`. Accessibility The field is named by its label, or by `aria-label`. The swatch is a button with `aria-haspopup="dialog"` and `aria-expanded`, named by `pickerLabel`. The picker opens in a dialog with the focus on its square. Escape closes it and puts the focus back on the swatch. The code is also a text in the field, so the color is not conveyed by the swatch alone. See Color Picker for the keys. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { ColorPicker, Grid, Text, Button, useTheme } from 'core' export const meta = { title: 'Color Picker', description: 'A panel to pick a color by saturation, brightness and hue, with a hex field and optional swatches.', sidebar: 'components', group: 'Components', index: 65 } ## Color Picker A panel to pick a color. Drag in the square for the saturation and the brightness, use the bar for the hue, or type the hex code. For a field that opens this panel in a popover, see Color Input. `} /> `} /> { const theme = useTheme() const [color, setColor] = React.useState('#f59e0b') return (
{color}
) } `} /> `} /> ColorPicker.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | ------------------------------------------------------------ | ----------------------- | ------------------------- | ----------------------------- | | **value** | the color, to control the component | `string` | `'#rrggbb'`, `'#rgb'` | - | | **initialValue** | the color on the first render | `string` | `'#rrggbb'`, `'#rgb'` | `#000000` | | **onChange** | called with the color as `#rrggbb` in lowercase | `(hex: string) => void` | - | - | | **swatches** | colors to pick with one click | `string[]` | - | - | | **hexInput** | show the field for the hex code | `boolean` | - | `true` | | **disabled** | disable the component | `boolean` | - | `false` | | **panelLabel** | name of the square, for screen readers | `string` | - | `Saturation and brightness` | | **hueLabel** | name of the hue bar | `string` | - | `Hue` | | **hexLabel** | name of the hex field | `string` | - | `Hex color` | | ... | native props, passed to the root `div` | `HTMLAttributes` | `'aria-label', 'id', ...` | - | Hex field The field changes the color as soon as it holds six digits, with or without the `#`. A short code like `#abc` is read when the field loses the focus, and becomes `#aabbcc`. Any other text is dropped on blur, and the field goes back to the current color. Ref The `ref` points at the root `div`. Accessibility The square is a `slider` named by `panelLabel`, whose value reads like "40% saturation, 80% brightness". With the focus on it, Left and Right change the saturation and Up and Down the brightness, by 1%, or by 10% with Shift. The hue bar is a native range input, and the swatches are buttons named by their code, with `aria-pressed` on the one in use. The color is never conveyed by the swatch alone, because the hex code is also a text. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Combobox, Grid, Code } from 'core' export const meta = { title: 'Combobox', description: 'An input that filters a list of options while you type and lets you pick one.', sidebar: 'components', group: 'Components', index: 42 } ## Combobox An input that filters a list of options while you type and lets you pick one. Use it when the list is long enough that a `Select` is hard to scan. `} /> `} /> `} /> `} /> `} /> `} /> Combobox.Props | Attribute | Description | Type | Accepted values | Default | | ----------------- | ---------------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------- | -------------------------- | | **options** | the options to choose from | `ComboboxOption[]` | [ComboboxOption](#comboboxoption) | - | | **value** | selected value, to control the component | `string` / `null` | - | - | | **initialValue** | selected value at the start | `string` / `null` | - | `null` | | **onChange** | called with the chosen value, or `null` when it is cleared | (value: string | null) => void | - | - | | **onInputChange** | called with the text while the user types | `(text: string) => void` | - | - | | **filter** | decides which options match the text | `(option, text) => boolean` | - | contains, case insensitive | | **placeholder** | text shown when the input is empty | `string` | - | - | | **emptyText** | text shown when no option matches | `string` | - | `No results` | | **disabled** | disable the component | `boolean` | - | `false` | | **rounded** | round the corners | `boolean` | - | `false` | | **filled** | filled variant | `boolean` | - | `false` | | **light** | light variant | `boolean` | - | `false` | | **ghost** | outline variant | `boolean` | - | `false` | | **subtle** | subtle variant | `boolean` | - | `false` | | **type** | color of the field | `NormalTypes` | `'default', 'primary', 'secondary', 'success', 'warning', 'error', 'info'` | `default` | | **rounded** | round the corners | `boolean` | - | `false` | | **filled** | filled variant | `boolean` | - | `false` | | **light** | light variant | `boolean` | - | `false` | | **ghost** | outline variant | `boolean` | - | `false` | | **subtle** | subtle variant | `boolean` | - | `false` | | ... | native props, passed to the input | `InputHTMLAttributes` | `'aria-label', 'name', 'id', ...` | - | ComboboxOption ```ts type ComboboxOption = { value: string label?: string // shown in the list and in the input, `value` when missing disabled?: boolean } ``` Ref The `ref` points at the `input`. Accessibility The input has `role="combobox"` and points at the active option with `aria-activedescendant`. The list is a `listbox` of `option` elements. | Key | Action | | ----------------- | ---------------------------------------------------- | | Arrow Down and Up | Open the list, and move between the options | | Enter | Choose the active option | | Escape | Close the list | | Tab | Close the list and restore the text of the selection | A screen reader hears how many options match while the user types. Give the input a name with `aria-label` or `aria-labelledby`. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Command, Button, Keyboard, useKeyboard, KeyCode, KeyMod, Grid, Text } from 'core' import { useState } from 'react' import { Home, Settings, Search, Plus, UserPlus, CreditCard, LogOut } from '@bolio-ui/icons' export const meta = { title: 'Command', description: 'A searchable list of actions, opened with a shortcut.', sidebar: 'components', group: 'Components', index: 57 } ## Command A searchable list of actions, opened with a shortcut. { const [open, setOpen] = useState(false) const items = [ { value: 'home', label: 'Go to home', icon: , onSelect: () => console.log('home') }, { value: 'settings', label: 'Open settings', icon: , hint: 'G S', onSelect: () => console.log('settings') }, { value: 'theme', label: 'Switch theme', hint: 'T', onSelect: () => console.log('theme') } ] return ( <> setOpen(false)} items={items} /> ) } `} /> { const [open, setOpen] = useState(false) useKeyboard( (event) => { event.preventDefault() setOpen(true) }, [KeyCode.KEY_K, KeyMod.CtrlCmd] ) const items = [ { value: 'new', label: 'New project', onSelect: () => console.log('new') }, { value: 'invite', label: 'Invite a teammate', onSelect: () => console.log('invite') } ] return ( <> K setOpen(false)} items={items} /> ) } `} /> { const [open, setOpen] = useState(false) const [last, setLast] = useState('nothing yet') const run = (name) => () => setLast(name) const items = [ { value: 'new', label: 'Create project', icon: , hint: 'N', onSelect: run('created a project') }, { value: 'invite', label: 'Invite a teammate', icon: , onSelect: run('opened the invite form') }, { value: 'billing', label: 'Go to billing', icon: , hint: 'G B', onSelect: run('went to billing') }, { value: 'settings', label: 'Open settings', icon: , hint: 'G S', onSelect: run('opened settings') }, { value: 'signout', label: 'Sign out', icon: , onSelect: run('signed out') } ] return ( <> Last action: {last} setOpen(false)} items={items} /> ) } `} /> Command.Props | Attribute | Description | Type | Accepted values | Default | | --------------- | ----------------------------------- | -------------------- | --------------- | ------------------------------ | | **visible** | show the palette | `boolean` | - | - | | **onClose** | called on Esc, backdrop or selection | `() => void` | - | - | | **items** | actions to list | `CommandItem[]` | - | - | | **placeholder** | placeholder of the search field | `string` | - | `Type a command or search` | | **emptyText** | shown when nothing matches | `string` | - | `No results. Try another word.` | CommandItem ```ts interface CommandItem { value: string label: string icon?: React.ReactNode hint?: React.ReactNode onSelect?: () => void } ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Container, Card, Text, Button, Grid } from 'core' export const meta = { title: 'Container', description: 'Limit the width of the page and center its content.', sidebar: 'components', group: 'Components', index: 45 } ## Container Limit the width of the page and center its content. Put a `Row` inside it to build the layout. See the page structure guide. The content of the page. `} /> This one has no maximum width. `} /> Build your interface faster Accessible components, themes that follow your brand and docs you can copy from. `} /> Container.Props | Attribute | Description | Type | Accepted values | Default | | ------------- | --------------------------------------------------------------- | --------------------- | --------------------------------------------- | ------- | | **fluid** | remove the maximum width | `boolean` | - | `false` | | **justify** | horizontal alignment, when the Container is a flex box | `string` | `start`, `end`, `center`, `space-around`, `space-between` | `start` | | **align** | vertical alignment, when the Container is a flex box | `string` | `top`, `middle`, `bottom` | `top` | | **component** | the element to render | `keyof JSX.IntrinsicElements` | `'div', 'main', 'section', ...` | `div` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | `justify` and `align` only have an effect when you make the Container a flex box, for example with `style={{ display: 'flex' }}`. Ref The `ref` points at the root element. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { ContextMenu, Menu, Card, Text, Grid } from 'core' export const meta = { title: 'Context Menu', description: 'A menu of actions that opens at the pointer when the user right clicks an area.', sidebar: 'components', group: 'Components', index: 67 } ## Context Menu A menu of actions that opens at the pointer when the user right clicks an area. It is a Menu placed at the cursor, so it has the same items, submenus and keys. Copy Paste Delete } > Right click anywhere in this card `} /> { const [last, setLast] = React.useState('Right click a file.') const files = ['Contract.pdf', 'Invoice.pdf', 'Photo.png'] return ( {files.map((file) => ( setLast('Opened ' + file)}>Open setLast('Renamed ' + file)}>Rename setLast('Emailed ' + file)}>Email setLast('Copied the link to ' + file)}>Copy link setLast('Deleted ' + file)}>Delete } > {file} ))} {last} ) } `} /> Never shown}> The menu of the browser opens here `} /> ContextMenu.Props | Attribute | Description | Type | Accepted values | Default | | ------------------- | --------------------------------------------------------------- | ---------------------------- | ---------------------------------------- | ------- | | **content** | the items of the menu | `ReactNode` | `Menu.Item`, `Menu.Sub`, `Menu.Divider`, ... | - | | **disabled** | leave the right click to the browser | `boolean` | - | `false` | | **onVisibleChange** | called with `true` when the menu opens and `false` when it closes | `(visible: boolean) => void` | - | - | | ... | native props, passed to the area `div` | `HTMLAttributes` | `'tabIndex', 'id', 'style', ...` | - | Behavior - • **Position**: the menu opens at the pointer and flips to the other side when there is no room. - • **Another right click** moves the menu to the new point. - • **Closing**: choosing an item, Escape, a click outside and a scroll of the page all close it. The focus goes back to the area. - • **Items** are the ones of Menu, with the same keys: arrows, Home, End, Enter, Space and the first letters. - • **onContextMenu**: a handler you pass to the area runs first, and calling `preventDefault` there keeps the menu closed. Ref The `ref` points at the area `div`. Accessibility The right click is not the only way in. The keyboard opens a context menu with Shift and F10, or with the menu key, on a focused element, and the browser sends the same event with the position of that element. For that, the area, or something inside it, has to be focusable: use `tabIndex={0}` on the area when it has nothing focusable. The menu is a `menu` with `menuitem` children, as in Menu. Touch screens have no right click, so keep a visible way to reach the same actions, like a button with a Menu. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { DatePicker, Grid, Code } from 'core' export const meta = { title: 'DatePicker', description: 'An input to type a date, with a calendar to pick it.', sidebar: 'components', group: 'Components', index: 44 } ## DatePicker An input to type a date, with a calendar to pick it. The text is a date in the `YYYY-MM-DD` format, which is the same in every country. `} /> `} /> `} /> `} /> `} /> `} /> DatePicker.Props | Attribute | Description | Type | Accepted values | Default | | ----------------- | -------------------------------------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------- | ------------- | | **value** | selected date, to control the component | `Date` / `null` | - | - | | **initialValue** | date at the start | `Date` / `null` | - | `null` | | **onChange** | called with the date, or `null` when the text is emptied | (date: Date | null) => void | - | - | | **min** | first date that can be picked | `Date` | - | - | | **max** | last date that can be picked | `Date` | - | - | | **locale** | language of the calendar | `string` | any `Intl` locale | `en-US` | | **weekStartsOn** | first day of the week in the calendar, 0 is Sunday | `number` | `0` to `6` | `0` | | **placeholder** | text shown when the input is empty | `string` | - | `YYYY-MM-DD` | | **calendarLabel** | name of the calendar button and of its dialog | `string` | - | `Choose date` | | **disabled** | disable the component | `boolean` | - | `false` | | **rounded** | round the corners | `boolean` | - | `false` | | **filled** | filled variant | `boolean` | - | `false` | | **light** | light variant | `boolean` | - | `false` | | **ghost** | outline variant | `boolean` | - | `false` | | **subtle** | subtle variant | `boolean` | - | `false` | | **type** | color of the field | `NormalTypes` | `'default', 'primary', 'secondary', 'success', 'warning', 'error', 'info'` | `default` | | **rounded** | round the corners | `boolean` | - | `false` | | **filled** | filled variant | `boolean` | - | `false` | | **light** | light variant | `boolean` | - | `false` | | **ghost** | outline variant | `boolean` | - | `false` | | **subtle** | subtle variant | `boolean` | - | `false` | | ... | native props, passed to the input | `InputHTMLAttributes` | `'aria-label', 'name', ...` | - | Typing The value changes only for a real date inside `min` and `max`. `2026-02-31` is not accepted. When the input loses the focus, it goes back to the last valid date. An empty text clears the value. Ref The `ref` points at the `input`. Accessibility The calendar button has `aria-haspopup="dialog"` and `aria-expanded`. The calendar opens in a dialog with the focus on the day of the current value. Escape closes it and puts the focus back on the button, and picking a day puts the focus on the input. See Calendar for the keys. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { DateRangePicker, Grid, Text, Code } from 'core' export const meta = { title: 'DateRangePicker', description: 'Two inputs to type a start and an end date, with one calendar to pick the range.', sidebar: 'components', group: 'Components', index: 60 } ## DateRangePicker Two inputs to type a start and an end date, with a calendar of two months to pick the range. When there is not room for two months, for example on a phone, it shows one. The text is a date in the `YYYY-MM-DD` format, which is the same in every country. `} /> `} /> { const [range, setRange] = React.useState([null, null]) const format = (date) => (date ? date.toDateString() : '...') return ( From {format(range[0])} to {format(range[1])}. ) } `} /> `} /> `} /> `} /> DateRangePicker.Props | Attribute | Description | Type | Accepted values | Default | | -------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------------- | | **value** | selected range, to control the component | [Date | null, Date | null] | - | - | | **initialValue** | range at the start | [Date | null, Date | null] | - | `[null, null]` | | **onChange** | called with `[start, end]`, with `end` as `null` while the range is picked | (range: [Date | null, Date | null]) => void | - | - | | **min** | first date that can be picked | `Date` | - | - | | **max** | last date that can be picked | `Date` | - | - | | **locale** | language of the calendar | `string` | any `Intl` locale | `en-US` | | **weekStartsOn** | first day of the week in the calendar, 0 is Sunday | `number` | `0` to `6` | `0` | | **startPlaceholder** | text shown when the start input is empty | `string` | - | `YYYY-MM-DD` | | **endPlaceholder** | text shown when the end input is empty | `string` | - | `YYYY-MM-DD` | | **startLabel** | name of the start input | `string` | - | `Start date` | | **endLabel** | name of the end input | `string` | - | `End date` | | **calendarLabel** | name of the calendar button and of its dialog | `string` | - | `Choose dates` | | **disabled** | disable the component | `boolean` | - | `false` | | **type** | color of the field | `NormalTypes` | `'default', 'primary', 'secondary', 'success', 'warning', 'error', 'info'` | `default` | | **rounded** | round the corners | `boolean` | - | `false` | | **filled** | filled variant | `boolean` | - | `false` | | **light** | light variant | `boolean` | - | `false` | | **ghost** | outline variant | `boolean` | - | `false` | | **subtle** | subtle variant | `boolean` | - | `false` | | ... | native props, passed to the group `div` | `HTMLAttributes` | `'aria-label', 'id', ...` | - | Typing Each input changes the range only for a real date inside `min` and `max`. The end cannot come before the start, so that text is not accepted. When an input loses the focus, it goes back to the last valid date. An empty text clears that edge of the range. Ref The `ref` points at the group `div`. Accessibility The group is named by `aria-label`, and each input has its own name, `Start date` and `End date`, which you can translate with `startLabel` and `endLabel`. The calendar button has `aria-haspopup="dialog"` and `aria-expanded`. The calendar opens in a dialog that shows two months side by side, or one month when there is not room, with the focus on the day of the start. Escape closes it and puts the focus back on the button, and picking the end puts the focus on the end input. See Calendar for the keys. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Description, Code, Grid, Card, Badge } from 'core' export const meta = { title: 'Description', description: 'Display brief information with a title and description.', sidebar: 'components', group: 'Components', index: 12 } ## Description Display brief information with a title and description. `} /> code about this section.

} />
`} /> Pro} /> `} /> Description.Props | Attribute | Description | Type | Accepted values | Default | | ----------- | ------------ | ---------------------- | --------------- | ------- | | **title** | title text | `ReactNode` / `string` | - | - | | **content** | title text | `ReactNode` / `string` | - | - | | ... | native props | `HTMLAttributes` | - | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Display, Code, Snippet, Image, Grid } from 'core' export const meta = { title: 'Display', description: 'To display important information or images in a central alignment.', sidebar: 'components', group: 'Components', index: 13 } ## Display To display important information or images in a central alignment. `} /> { const codes = \`{ "build": { "env": { "VARIABLE": "ENV_SECRET" } } }\` return ( {codes} ) } `} /> `} /> Browse bolio-ui.com.br for more information.

}>
`} /> Display.Props | Attribute | Description | Type | Accepted values | Default | | ----------- | ----------------------------- | ---------------------- | --------------- | ------- | | **caption** | description for display block | `ReactNode` / `string` | - | - | | **shadow** | show shadow | `boolean` | - | `false` | | ... | native props | `HTMLAttributes` | - | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Layout, Playground, Attributes } from 'src/components' import { Divider, Text, Grid } from 'core' export const meta = { title: 'Divider', description: 'A divider line separates different content.', sidebar: 'components', group: 'Components', index: 14 } ## Divider A divider line separates different content. React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Declarative views make your code more predictable and easier to debug. `} /> React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. A Simple Component React components implement a render() method that takes input data and returns what to display. This example uses an XML-like syntax called JSX. Input data that is passed into the component can be accessed by render() via this.props. A Stateful Component In addition to taking input data (accessed via this.props), a component can maintain internal state data (accessed via this.state). When a component’s state data changes, the rendered markup will be updated by re-invoking render(). `} /> React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. A Simple Component React components implement a render() method that takes input data and returns what to display. This example uses an XML-like syntax called JSX. Input data that is passed into the component can be accessed by render() via this.props. A Stateful Component In addition to taking input data (accessed via this.props), a component can maintain internal state data (accessed via this.state). When a component’s state data changes, the rendered markup will be updated by re-invoking render(). `} /> React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. A Simple Component React components implement a render() method that takes input data and returns what to display. This example uses an XML-like syntax called JSX. Input data that is passed into the component can be accessed by render() via this.props. A Stateful Component In addition to taking input data (accessed via this.props), a component can maintain internal state data (accessed via this.state). When a component’s state data changes, the rendered markup will be updated by re-invoking render(). `} /> Divider.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ----------------- | ----------------------------- | -------------------------------- | --------- | | **type** | type of divier | [DividerTypes](#dividertypes) | - | `default` | | **align** | alignment of text | [DividerAlign](#divideralign) | - | `center` | | ... | native props | `HTMLAttributes` | `'id', 'name', 'className', ...` | - | DividerTypes ```ts type DividerTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' | 'dark' | 'lite' ``` DividerAlign ```ts type DividerAlign = 'center' | 'start' | 'left' | 'end' | 'right' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Dot, Grid, Card } from 'core' export const meta = { title: 'Dot', description: 'Display an indicator of standardization status.', sidebar: 'components', group: 'Components', index: 15 } ## Dot Display an indicator of standardization status. `} /> Canceled Primary Secondary Ready Warning Error Info `} /> {[ ['success', 'API', 'Operational'], ['warning', 'Webhooks', 'Delayed by 4 minutes'], ['error', 'Payments', 'Down since 09:12'] ].map(([type, name, state]) => ( {name}: {state} ))} `} /> Dot.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | --------------------- | --------- | | **type** | dot type | `DotTypes` | [DotTypes](#dottypes) | `default` | | ... | native props | `HTMLAttributes` | - | - | DotTypes ```ts type DotTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Drawer, Button, Grid, Input, Spacer } from 'core' export const meta = { title: 'Drawer', description: 'An interactive element fixed to the edge of the screen.', sidebar: 'components', group: 'Components', index: 16 } ## Drawer An interactive element fixed to the edge of the screen. { const [state, setState] = React.useState(false) return ( setState(false)} placement="right" > Drawer Example of a drawer

Demo content for the drawer.

) } `} /> { const [state, setState] = React.useState(false) const [placement, setPlacement] = React.useState('') const open = (text) => { setPlacement(text) setState(true) } return ( setState(false)} placement={placement} > Drawer Example of a drawer

Demo content for the drawer.

) } `} /> { const [open, setOpen] = React.useState(false) return ( <> setOpen(false)} placement="right"> Edit profile Changes show on your public page. Name Email ) } `} /> Drawer.Props | Attribute | Description | Type | Accepted values | Default | | ------------------------ | -------------------------------- | ----------------------------------- | -------------------------- | ------- | | **visible** | open or close | `boolean` | - | `false` | | **onClose** | close event | `() => void` | - | - | | **onContentClick** | event from modal content | `(e: MouseEvent) => void` | - | - | | **wrapClassName** | className of the drawer dialog | `string` | - | - | | **keyboard** | press Esc to close drawer | `boolean` | - | `true` | | **disableBackdropClick** | click background and don't close | `boolean` | - | `false` | | **placement** | position of the drawer | [DrawerPlacement](#drawerplacement) | - | `right` | | ... | native props | `HTMLAttributes` | `'name', 'className', ...` | - | Drawer.Title.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | ------------------------ | ------- | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Drawer.Subtitle.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | ------------------------ | ------- | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Drawer.Content.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | ------------------------ | ------- | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | DrawerPlacement ```ts type DrawerPlacement = 'top' | 'bottom' | 'right' | 'left' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Dropzone, Grid, Text, Code } from 'core' export const meta = { title: 'Dropzone', description: 'An area to drop files or click to choose them, with limits for type, size and number.', sidebar: 'components', group: 'Components', index: 62 } ## Dropzone An area to drop files or click to choose them. It checks the type, the size and the number of files, and hands them to `onDrop`. Uploading and listing the files is up to you. { const [names, setNames] = React.useState([]) return ( setNames(accepted.map((file) => file.name))} /> {names.length ? names.join(', ') : 'No files yet.'} ) } `} /> { const [result, setResult] = React.useState('Drop up to 2 images of 1 MB.') const onDrop = (accepted, rejected) => setResult( accepted.length + ' accepted. ' + rejected.map((item) => item.file.name + ': ' + item.reason).join('; ') ) return ( Drop up to 2 images of 1 MB {result} ) } `} /> Drop images, PDFs, CSVs or ZIPs `} /> Upload your contract PDF, one file `} /> Uploads are off `} /> Dropzone.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | ------------------------------------------------------------------------ | --------------------------------------------------------- | --------------------------------------------- | ------- | | **onDrop** | called with the accepted files and the rejected ones, from a drop or from the picker | (accepted: File[], rejected: FileRejection[]) => void | - | - | | **accept** | types that pass, in the format of the `accept` of a file input | `string` | `'.pdf', 'image/*', 'image/png', ...`, separated by commas | - | | **multiple** | accepts more than one file | `boolean` | - | `false` | | **maxSize** | largest size of a file, in bytes | `number` | - | - | | **maxFiles** | most files in one drop, with `multiple` | `number` | - | - | | **thumbnails** | keeps the accepted files and shows them as tiles below the area | `boolean` | - | `false` | | **value** | the files shown with `thumbnails`, to control them | `File[]` | - | - | | **onChange** | called with the whole list when a file is added or removed, with `thumbnails` | (files: File[]) => void | - | - | | **removeLabel** | name of the remove button of a file, for screen readers | (file: File) => string | - | `Remove ` | | **disabled** | ignores drops and blocks the picker | `boolean` | - | `false` | | ... | native props, passed to the `input` | `InputHTMLAttributes` | `'name', 'aria-label', 'required', ...` | - | Rejected files `rejected` is a list of `{ file, reason }`. Each file gets only the first reason that applies, checked in this order: - • **file-type**: the file does not match `accept`. - • **file-too-large**: the file is bigger than `maxSize`. - • **too-many-files**: there are already as many accepted files as the limit, which is `1` without `multiple` and `maxFiles` with it. `onDrop` is called on every drop or choice, even when every file was rejected. The file picker is cleared after each choice, so the same file can be chosen again. Thumbnail behavior - • **Format**: the tile shows the extension of the file in capitals, like `PNG` or `PDF`. A file without an extension uses the subtype of its type. - • **Preview**: only images are shown as they are. Other formats, like PDF, CSV or ZIP, cannot be drawn by the browser, so they get a file icon. - • **Limits**: with `multiple`, new files are added to the ones already there, and `maxFiles` counts all of them. Without it, a new file replaces the current one. - • **Control**: the list is kept for you. Use `value` and `onChange` to own it, for example to clear it after an upload. `onDrop` is still called on every drop with the files of that drop. Ref The `ref` points at the file `input`. Extra props go to the `input` too, while `className` and `style` go to the wrapper of the area and the thumbnails. Accessibility The area is a label around a native file input, so it is reached with Tab and opened with Enter or Space, and its content names the input. A dragged file highlights the area, but the drag is only a shortcut: the picker does the same for people who use the keyboard or a screen reader. The thumbnails are a list, each with the name of the file as text and a remove button named after it, and the preview of an image is decorative. Show the result of `onDrop` as text on the page, for example the rejected files and why. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { EmptyState, Button, Card, Grid } from 'core' import { Inbox, Search, FolderPlus, AlertCircle } from '@bolio-ui/icons' export const meta = { title: 'Empty State', description: 'Explain an empty area and how to leave it.', sidebar: 'components', group: 'Components', index: 54 } ## Empty State Explain an empty area and how to leave it. } title="No messages yet" description="Messages from your team show up here. Invite someone to start a conversation." action={} /> `} /> } title="No results for “invoice”" description="Check the spelling or clear the filters to see every document." action={} /> `} /> } title="Create your first project" description="Projects keep your files, members and deploys in one place. It takes under a minute." action={ } /> `} /> } title="We could not load your invoices" description="Check your connection and try again. Your data is safe." action={} /> `} /> EmptyState.Props | Attribute | Description | Type | Accepted values | Default | | --------------- | ------------------------------ | ---------------- | --------------- | ------- | | **title** | what is empty | `ReactNode` | - | - | | **description** | how to leave the empty state | `ReactNode` | - | - | | **icon** | icon above the title | `ReactNode` | - | - | | **action** | usually a `Button` | `ReactNode` | - | - | | ... | native props | `HTMLAttributes` | - | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Card, Grid, Fieldset, Button, Text, Divider } from 'core' export const meta = { title: 'Fieldset', description: 'Display a collection of related information in a single unit.', sidebar: 'components', group: 'Components', index: 17 } ## Fieldset Display a collection of related information in a single unit.
Try React React has been designed from the start for gradual adoption, and you can use as little or as much React as you need. Whether you want to get a taste of React, add some interactivity to a simple HTML page, or start a complex React-powered app, the links in this section will help you get started. Try React
`} />
Add React to a Website You can add React to an HTML page in one minute. You can then either gradually expand its presence, or keep it contained to a few dynamic widgets An error has occurred.
`} /> { const handler = (v) => console.log(v) return (
Create a New React App When starting a React project, a simple HTML page with script tags might still be the best option. It only takes a minute to set up! Create a New React App
Learn React People come to React from different backgrounds and with different learning styles. Whether you prefer a more theoretical or a practical approach, we hope you’ll find this section helpful. Learn React
First Examples The React homepage contains a few small React examples with a live editor. Even if you don’t know anything about React yet, try changing their code and see how it affects the result. First Examples
) } `} />

React

For Beginners

If you feel that the React documentation goes at a faster pace than you’re comfortable with, check out this overview of React by Tania Rascia. It introduces the most important React concepts in a detailed, beginner-friendly way. Once you’re done, give the documentation another try!

JavaScript Resources
`} /> Fieldset.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | ---------------------------------- | ------------------------ | -------------------------- | ------- | | **value** | unique ident value (only in group) | `string` | - | - | | **label** | group tab text (only in group) | `string` | - | - | | **title** | title of fieldset | `ReactNode` / `string` | - | - | | **subtitle** | subtitle of fieldset | `ReactNode` / `string` | - | - | | ... | native props | `FieldsetHTMLAttributes` | `'name', 'className', ...` | - | Fieldset.Content.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | --------------- | ------- | | ... | native props | `HTMLAttributes` | - | - | Fieldset.Footer.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | --------------- | ------- | | ... | native props | `HTMLAttributes` | - | - | Fieldset.Group.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | ------------------ | ------------------------- | --------------- | ------- | | **value** | selected tab value | `string` | - | - | | **onChange** | change tab event | `(value: string) => void` | - | - | | ... | native props | `HTMLAttributes` | - | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, PlaygroundTitle, Attributes } from 'src/components' import { Grid, Card } from 'core' export const meta = { title: 'Grid', description: 'Powerful fluid style layout container.', sidebar: 'components', group: 'Components', index: 18 } ## Grid Powerful fluid style layout container. The `Grid` component uses **dynamic CSS media query** to implement responsive layout, It has ultra-high performance and very small size. Of course, it still supports dynamic props and custom breakpoints. `} /> `} /> `} /> `} /> `} /> ```tsx const breakpoints: BolioUIThemesBreakpoints = { xs: { min: '0', max: '650px' }, sm: { min: '650px', max: '900px' }, md: { min: '900px', max: '1280px' }, lg: { min: '1280px', max: '1920px' }, xl: { min: '1920px', max: '10000px' } } const App = () => { const myTheme = Themes.createFromLight({ type: 'myTheme', breakpoints }) return ( ) } ``` Grid.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | ----------------------------------------------------- | ---------------- | ----------------------------- | ------------ | | **justify** | CSS "justify-content" property | `Justify` | [Justify](#justify) | `flex-start` | | **alignItems** | CSS "align-items" property | `AlignItems` | [AlignItems](#alignitems) | `stretch` | | **alignContent** | CSS "align-content" property | `AlignContent` | [AlignContent](#aligncontent) | `flex-start` | | **direction** | CSS "flex-direction" property | `Direction` | [Direction](#direction) | `row` | | **xs** | width of grid, for `xs` breakpoints and wider screens | `number` | `0 - 24`, `boolean` | `false` | | **sm** | width of grid, for `sm` breakpoints and wider screens | `number` | `0 - 24`, `boolean` | `false` | | **md** | width of grid, for `md` breakpoints and wider screens | `number` | `0 - 24`, `boolean` | `false` | | **lg** | width of grid, for `lg` breakpoints and wider screens | `number` | `0 - 24`, `boolean` | `false` | | **xl** | width of grid, for `xl` breakpoints and wider screens | `number` | `0 - 24`, `boolean` | `false` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Grid.Container.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------------------ | ------------------ | ------------------------- | ------- | | **gap** | spacing of children | `number` / `float` | - | 0 | | **wrap** | CSS "flex-wrap" property | `Wrap` | [Wrap](#wrap) | `wrap` | | ... | Grid props | `Grid.Props` | [Grid.Props](#grid.props) | - | Justify ```ts type Justify = | 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly' ``` AlignItems ```ts type AlignItems = 'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline' ``` AlignContent ```ts type AlignContent = | 'stretch' | 'center' | 'flex-start' | 'flex-end' | 'space-between' | 'space-around' ``` Direction ```ts type Direction = 'row' | 'row-reverse' | 'column' | 'column-reverse' ``` Wrap ```ts type Wrap = 'nowrap' | 'wrap' | 'wrap-reverse' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Smile } from '@bolio-ui/icons' import { Grid } from 'core' import { Layout, Playground, PlaygroundTitle, Attributes, IconsGallery, PackageTabs } from 'src/components' export const meta = { title: 'Icons', description: 'Display semantic vector graphics in SVG format.', sidebar: 'components', group: 'Components', index: 19 } ## Icons Display semantic vector graphics in SVG format. `} /> `} /> `} /> Icon.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | ------------ | --------------- | -------------------------------- | ------- | | **color** | Icon color | `string` | - | - | | **fontSize** | Icon size | `number` | - | - | | ... | Native props | `SVGAttributes` | `'id', 'name', 'className', ...` | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { ImageZoom, Grid, useTheme } from 'core' export const meta = { title: 'Image Zoom', description: 'A picture that opens in a larger view above the page when it is clicked.', sidebar: 'components', group: 'Components', index: 69 } ## Image Zoom A picture that opens in a larger view above the page when it is clicked. The view is a native `dialog`: it keeps the focus inside, closes with Escape, and gives the focus back to the picture. { const theme = useTheme() return ( ) } `} /> { const theme = useTheme() return ( ) } `} /> { const theme = useTheme() const photos = [ ['/img/jpg/docs/forest-lake.jpg', 'A forest lake under the clouds'], ['/img/jpg/docs/mountain-reflection.jpg', 'Snowy mountains reflected in a lake'], ['/img/jpg/docs/moonlit-peaks.jpg', 'Snowy mountains under the moon'] ] return ( {photos.map(([src, alt]) => ( ))} ) } `} /> ImageZoom.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | ------------------------------------------------------------ | ----------- | -------------------------------- | ------- | | **src** | the picture | `string` | - | - | | **alt** | what the picture shows, and the name of the button | `string` | - | - | | **zoomSrc** | a larger version, loaded when the view opens | `string` | - | `src` | | **caption** | text under the picture in the view | `ReactNode` | - | - | | **closeLabel** | name of the close button | `string` | - | `Close` | | ... | the props of Image, like `width`, `height` and `style` | `ImageProps` | - | - | Behavior - • **Closing**: Escape, the close button and a click on the dark area close it. A click on the picture does not. - • **Page**: it does not scroll while the view is open. - • **Size**: the picture in the view fits the screen, in the proportion it has. Ref The `ref` points at the button that opens the view. Accessibility The picture is a button with `aria-haspopup="dialog"`, named by `alt`. The view is a modal `dialog` named by the same text. The focus goes to the close button when it opens, stays inside while it is open, and goes back to the picture when it closes. Always write a useful `alt`: it is what a screen reader reads for both the thumbnail and the larger picture. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Image, Display, Code, Grid } from 'core' export const meta = { title: 'Image', description: 'Display image content.', sidebar: 'components', group: 'Components', index: 19 } ## Image Display image content. `} /> `} /> `} /> `} /> Reduce the possibility of page rendering by setting{' '} height

} >
`} /> { const svg = \` \` return ( ) } `} /> Image.Props | Attribute | Description | Type | Accepted values | Default | | --------------------- | --------------------------------------- | ------------------- | ------------------------- | ------- | | **src** | image src | `string` | - | - | | **disableSkeleton** | disable skeleton animation when loading | `boolean` | - | `false` | | **disableAutoResize** | disable zooming when width is too small | `boolean` | - | `false` | | **maxDelay**(ms) | max duration of animation | `number` | - | `3000` | | ... | native props | `ImgHTMLAttributes` | `'alt', 'className', ...` | - | Image.Browser.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | ------------------------------------- | ---------------------- | ------------------------ | ------- | | **title** | show text title (when "url" is unset) | `string` | - | - | | **url** | show url on browser address input | `string` | - | - | | **showFullLink** | show full url | `boolean` | - | `false` | | **invert** | invert colors | `boolean` | - | `false` | | **anchorProps** | props of element `a` | `AnchorHTMLAttributes` | - | `{}` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Instagram, Facebook } from '@bolio-ui/icons' import { Input, Grid, Button, Code, Text, Dot, Spacer } from 'core' export const meta = { title: 'Input', description: 'Retrieve text input from a user.', sidebar: 'components', group: 'Components', index: 20 } ## Input Retrieve text input from a user. The Input contain an additional Hooks, see subsection [useInput](/docs/hooks/use-input) for details. `} /> Email Email `} /> `} /> `} /> `} /> `} /> Block Label Block Label `} /> `} /> `} /> `} /> } placeholder="Instagram" /> } placeholder="Facebook" /> `} /> `} /> `} /> { const [value, setValue] = React.useState() const handler = (e) => { setValue(e.target.value) console.log(e.target.value) } return ( ) } `} /> Date Time Date and time `} /> { const ref = React.useRef(null) const setChange = () => { ref && (ref.current.value = Math.random().toString(32)) } return ( console.log(e.target.value)} ref={ref} /> ) } `} /> { const [email, setEmail] = React.useState('') const [submitted, setSubmitted] = React.useState(false) const invalid = submitted && !/^\\S+@\\S+\\.\\S+$/.test(email) return (
{ event.preventDefault() setSubmitted(true) }} > setEmail(event.target.value)}> Email {invalid && Enter an email like name@company.com.} Password ) } `} /> Input.Props | Attribute | Description | Type | Accepted values | Default | | ----------------- | ----------------------------- | ---------------------------------------------------- | --------------------------------- | --------- | | **value** | input value | `string` | - | - | | **initialValue** | initial value | `string` | - | - | | **placeholder** | placeholder | `string` | - | - | | **type** | current type | `InputTypes` | [InputTypes](#inputtypes) | `default` | | **htmlType** | native type attr | `string` | - | `text` | | **readOnly** | native attr | `boolean` | - | `false` | | **disabled** | disable input | `boolean` | - | `false` | | **clearable** | show clear icon | `boolean` | - | `false` | | **filled** | filled variant | `boolean` | - | `false` | | **light** | light variant | `boolean` | - | `false` | | **ghost** | outline variant | `boolean` | - | `false` | | **subtle** | subtle variant | `boolean` | - | `false` | | **label** | text label for input | `string` | - | - | | **labelRight** | text label at right for input | `string` | - | - | | **floating** | label inside the field that moves up on focus | `boolean` | - | `false` | | **icon** | icon for input | `React.ReactNode` | - | - | | **iconRight** | icon at right for input | `React.ReactNode` | - | - | | **iconClickable** | icons are clickable | `boolean` | - | `false` | | **onIconClick** | click icon event | `(e: React.ChangeEvent) => void` | - | - | | **onChange** | change event | `(e: React.ChangeEvent) => void` | - | - | | **onClearClick** | clear icon event | `(e: React.MouseEvent) => void` | - | - | | **ref** | forwardRef | Ref<HTMLInputElement | null> | - | - | | ... | native props | `InputHTMLAttributes` | `'alt', 'type', 'className', ...` | - | Input.Password.Props | Attribute | Description | Type | Accepted values | Default | | -------------- | ---------------- | ------------- | --------------------------- | ------- | | **hideToggle** | hide toggle icon | `boolean` | - | `false` | | ... | input props | `Input.Props` | [Input.Props](#input.props) | - | InputTypes ```ts type InputTypes = 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` useInput ```ts type useInput = (initialValue: string) => { state: string setState: Dispatch> currentRef: MutableRefObject reset: () => void bindings: { value: string onChange: (event: React.ChangeEvent) => void } } ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Keyboard, Grid } from 'core' export const meta = { title: 'Keyboard', description: 'Display keyboard input that triggers an action.', sidebar: 'components', group: 'Components', index: 21 } ## Keyboard Display keyboard input that triggers an action. The `Keyboard` can only display layout styles, if you need to bind the keyboard events, please read subsection [useKeyboard](/docs/hooks/use-keyboard). C `} /> `} /> f e b `} /> Keyboard.Props | Attribute | Description | Type | Accepted values | Default | | ----------- | ---------------- | ---------------------- | ----------------------------- | ------- | | **command** | show command key | `boolean` | - | `false` | | **shift** | show shift key | `boolean` | - | `false` | | **option** | show option key | `boolean` | - | `false` | | **ctrl** | show ctrl key | `boolean` | - | `false` | | ... | native props | `KeygenHTMLAttributes` | `'keyType', 'className', ...` | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Link, Text, Code, Grid } from 'core' import { useRouter } from 'next/navigation' export const meta = { title: 'Link', description: 'Hyperlinks between pages.', sidebar: 'components', group: 'Components', index: 22 } ## Link Hyperlinks between pages. Is a reference to the data you can follow directly by tapping. `} /> Is a reference to the data you can follow directly by tapping. `} /> Is a reference to the data you can follow directly by tapping. Is a reference to the data you can follow directly by tapping. `} /> Is a reference to the data you can follow directly by tapping. Is a reference to the data you can follow directly by tapping. Is a reference to the data you can follow directly by tapping. Is a reference to the data you can follow directly by tapping. `} /> Is a reference to the data you can follow directly by tapping. `} /> { const router = useRouter() return ( { event.preventDefault() router.push('/docs/components/button') }} > Docs of Button ) } `} /> Link.Props | Attribute | Description | Type | Accepted values | Default | | ------------- | --------------------------- | ----------------------------------------------- | ---------------------- | ------- | | **href** | link url | `string` | - | - | | **color** | display color for link | `boolean` | - | `false` | | **icon** | show icon | `boolean` | - | `false` | | **underline** | display underline | `boolean` | - | `false` | | **block** | display as a separate block | `boolean` | - | `false` | | **ref** | forwardRef | Ref<HTMLAnchorElement | null> | - | - | | ... | native props | `AnchorHTMLAttributes` | `'rel', 'target', ...` | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Loading, Grid } from 'core' export const meta = { title: 'Loading', description: 'Indicate an action running in the background.', sidebar: 'components', group: 'Components', index: 23 } ## Loading Indicate an action running in the background. `} /> Loading `} /> `} /> `} /> Loading.Props | Attribute | Description | Type | Accepted values | Default | | -------------- | ---------------------------------- | ---------------- | --------------------------------- | --------- | | **type** | bg-color type | `LoadingTypes` | [LoadingTypes](#loadingtypes) | `default` | | **color** | custom bg color | `string` | - | - | | **spaceRatio** | percentage of space between points | `number` | - | 1 | | ... | native props | `HTMLAttributes` | `'id', 'title', 'className', ...` | - | LoadingTypes ```ts type LoadingTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Marquee, Tag, Card, Text } from 'core' export const meta = { title: 'Marquee', description: 'Loop content horizontally without end.', sidebar: 'components', group: 'Components', index: 56 } ## Marquee Loop content horizontally without end. React Next.js Gatsby RedwoodJS Vite Remix `} /> “Easy to theme and clear docs.” “We shipped our dashboard in a week.” “The best defaults I have used.” `} /> Acme Globex Initech Umbrella Hooli Stark Wayne Wonka Cyberdyne Soylent
`} /> Marquee.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | -------------------------- | ---------------- | --------------- | ------- | | **duration** | seconds for one full loop | `number` | - | `30` | | **pauseOnHover** | pause while hovering | `boolean` | - | `true` | | **reverse** | run in the other direction | `boolean` | - | `false` | | **gap** | space between items | `string` | - | `2rem` | | ... | native props | `HTMLAttributes` | - | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Mention, Card, Text, Button } from 'core' export const meta = { title: 'Mention', description: 'Type a trigger character in a text field to pick a person, a tag or a command from a list.', sidebar: 'components', group: 'Components', index: 57 } ## Mention Type a trigger character in a text field to pick a person, a tag or a command from a list. `} /> `} /> { const people = [ { value: 'ana', label: 'Ana Souza' }, { value: 'bruno', label: 'Bruno Lima' }, { value: 'carla', label: 'Carla Dias' } ] const [text, setText] = React.useState('') const [posted, setPosted] = React.useState(null) const mentioned = people.filter((p) => text.includes('@' + p.value + ' ') || text.endsWith('@' + p.value)) return (
{mentioned.length ? 'Notifies ' + mentioned.map((p) => p.label).join(', ') : 'Nobody is mentioned yet.'}
{posted !== null && Posted, {posted} {posted === 1 ? 'person' : 'people'} notified.}
) } `} /> Mention.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | ---------------------------------------------------------------- | ----------------------------------------------------- | --------------- | ------------ | | **options** | what can be mentioned. `value` is inserted, `label` is shown | `{ value: string; label?: string; disabled?: boolean }[]` | - | - | | **trigger** | character that opens the list | `string` | - | `@` | | **value** | text of the field, to control it | `string` | - | - | | **initialValue** | text at the start | `string` | - | `''` | | **onChange** | called with the new text | `(text: string) => void` | - | - | | **onSelect** | called with the option that was inserted | `(option: MentionOption) => void` | - | - | | **rows** | height of the field | `number` | - | `3` | | **placeholder** | hint while the field is empty | `string` | - | - | | **emptyText** | shown when nothing matches | `string` | - | `No results` | | **disabled** | block the field | `boolean` | - | `false` | | ... | native props of the textarea | `TextareaHTMLAttributes` | - | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Menu, Button, Grid } from 'core' export const meta = { title: 'Menu', description: 'A list of actions that opens from a button, with submenus, checkbox and radio items and keyboard support.', sidebar: 'components', group: 'Components', index: 49 } ## Menu A list of actions that opens from a button. Use it for commands, like editing or sharing something. To pick a value for a form, use `Select` or `Combobox`. Options}> Edit Duplicate Archive Delete
`} /> Account}> Profile Settings Billing Team Invite people Log out `} /> File}> New Open Email Copy link Embed Export Close `} /> { const [grid, setGrid] = React.useState(true) const [ruler, setRuler] = React.useState(false) const [sort, setSort] = React.useState('name') return ( View}> Show grid Show ruler Sort by Name Date Size ) } `} /> { const [visible, setVisible] = React.useState(false) return ( {visible ? 'Open' : 'Closed'}} > Edit Duplicate ) } `} /> Menu.Props | Attribute | Description | Type | Accepted values | Default | | --------------------- | ---------------------------------------------------- | ------------------------------ | --------------------------------- | ------- | | **trigger** | the element that opens the menu, usually a `Button` | `ReactElement` | - | - | | **visible** | open state, to control the menu | `boolean` | - | - | | **initialVisible** | open state at the start | `boolean` | - | `false` | | **onVisibleChange** | called when the menu wants to open or close | `(visible: boolean) => void` | - | - | | **getPopupContainer** | element that receives the menu, `document.body` when missing | `() => HTMLElement` | - | - | | ... | native props, passed to the element around the trigger | `HTMLAttributes` | `'id', 'className', ...` | - | Menu.Item.Props | Attribute | Description | Type | Accepted values | Default | | -------------------- | ----------------------------------------------- | -------------------------- | ------------------------ | --------- | | **onClick** | called when the item is chosen, by click or key | `(event) => void` | - | - | | **icon** | shown before the label | `ReactNode` | - | - | | **shortcut** | shown after the label, only for the eye | `string` | - | - | | **type** | color of the item | `string` | `'default', 'error'` | `default` | | **disabled** | the item cannot be chosen or focused | `boolean` | - | `false` | | **disableAutoClose** | keep the menu open after the item is chosen | `boolean` | - | `false` | | ... | native props | `HTMLAttributes` | `'aria-keyshortcuts', ...` | - | Menu.CheckboxItem.Props Accepts the props of `Menu.Item`, except `onClick`, plus: | Attribute | Description | Type | Accepted values | Default | | -------------------- | ------------------------------------------- | ----------------------------- | --------------- | ------- | | **checked** | whether the option is on | `boolean` | - | `false` | | **onChange** | called with the new state | `(checked: boolean) => void` | - | - | | **disableAutoClose** | keep the menu open after the item is chosen | `boolean` | - | `true` | Menu.RadioGroup.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | ---------------------------------------------- | ------------------------- | ------------------------ | ------- | | **value** | the value of the checked item | `string` | - | - | | **onChange** | called with the value of the chosen item | `(value: string) => void` | - | - | | ... | native props, name the group with `aria-label` | `HTMLAttributes` | `'aria-label', ...` | - | Menu.RadioItem.Props Accepts the props of `Menu.Item`, except `onClick`, plus: | Attribute | Description | Type | Accepted values | Default | | -------------------- | ------------------------------------------- | --------- | --------------- | ------- | | **value** | the value this item checks in its group | `string` | - | - | | **disableAutoClose** | keep the menu open after the item is chosen | `boolean` | - | `true` | Menu.Sub.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | ----------------------------------- | ---------------- | --------------- | ------- | | **label** | text of the item that opens it | `ReactNode` | - | - | | **icon** | shown before the label | `ReactNode` | - | - | | **disabled** | the submenu cannot be opened | `boolean` | - | `false` | | ... | native props, passed to the item | `HTMLAttributes` | - | - | Menu.Label and Menu.Divider Both accept native props. `Menu.Label` is a title for the items below it, and `Menu.Divider` is a line between groups. Ref The `ref` of `Menu` points at the element around the trigger. The `ref` of each item, of `Menu.Label` and of `Menu.Divider` points at its own element, and the `ref` of `Menu.Sub` at the item that opens it. Accessibility The trigger gets `aria-haspopup="menu"` and `aria-expanded`. The list is a `menu`, named by the trigger, with `menuitem`, `menuitemcheckbox` and `menuitemradio` items. A radio group is a `group`; name it with `aria-label`. The `shortcut` is only visual: to announce it, pass `aria-keyshortcuts`, like `aria-keyshortcuts="Meta+E"`. | Key | Action | | --------------------- | ---------------------------------------------------------- | | Arrow Down and Up | On the trigger, open on the first or the last item. In the menu, move between the items | | Enter and Space | Choose the focused item, or open its submenu | | Home and End | Go to the first or the last item | | Arrow Right | Open the submenu of the focused item | | Arrow Left | Close the submenu and go back to its item | | Escape | Close the submenu, or the menu and focus the trigger | | Tab | Close the menu and focus the trigger | | Letters | Go to the next item that starts with what was typed | Disabled items are skipped by the keyboard. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Modal, Button, Code, useModal, Grid, Text } from 'core' import { useState } from 'react' export const meta = { title: 'Modal', description: 'Display popup content that requires attention or provides additional information.', sidebar: 'components', group: 'Components', index: 24 } ## Modal Display popup content that requires attention or provides additional information. If you just need to prompt for a text message, try component [Toast](/docs/hooks/use-toast). The Modal contain an additional Hooks, see subsection [useModal](/docs/hooks/use-modal) for details. { const [state, setState] = useState(false) const handler = () => setState(true) const closeHandler = (event) => { setState(false) console.log('closed') } return ( setState(false)}> Modal Example of a modal

Demo content for the modal.

setState(false)}> Cancel Accepted
) } `} /> { const { visible, setVisible, bindings } = useModal() return ( Modal Example of a modal

Demo content for the modal.

setVisible(false)}> Cancel Accepted
) } `} /> { const [state, setState] = useState(false) const handler = () => setState(true) const closeHandler = (event) => { setState(false) console.log('closed') } return ( setState(false)}> Modal Example of a modal

Demo content for the modal.

) } `} /> { const [state, setState] = useState(false) const handler = () => setState(true) const closeHandler = (event) => { setState(false) console.log('closed') } return ( <> Modal Example of a modal

Demo content for the modal.

setState(false)}>Cancel Submit
) } `} /> { const { setVisible, bindings } = useModal() return ( My Favorites

This is the width I want.

) } `} /> { const { visible, setVisible, bindings } = useModal() return ( Modal Example of a modal

Demo content for the modal.

setVisible(false)}> Cancel Accepted
) } `} /> { const { visible, setVisible, bindings } = useModal() return ( Modal Modal with a very large content

React has been designed from the start for gradual adoption, and you can use as little or as much React as you need. Whether you want to get a taste of React, add some interactivity to a simple HTML page, or start a complex React-powered app, the links in this section will help you get started.

React has been designed from the start for gradual adoption, and you can use as little or as much React as you need. Whether you want to get a taste of React, add some interactivity to a simple HTML page, or start a complex React-powered app, the links in this section will help you get started.

React has been designed from the start for gradual adoption, and you can use as little or as much React as you need. Whether you want to get a taste of React, add some interactivity to a simple HTML page, or start a complex React-powered app, the links in this section will help you get started.

React has been designed from the start for gradual adoption, and you can use as little or as much React as you need. Whether you want to get a taste of React, add some interactivity to a simple HTML page, or start a complex React-powered app, the links in this section will help you get started.

React has been designed from the start for gradual adoption, and you can use as little or as much React as you need. Whether you want to get a taste of React, add some interactivity to a simple HTML page, or start a complex React-powered app, the links in this section will help you get started.

React has been designed from the start for gradual adoption, and you can use as little or as much React as you need. Whether you want to get a taste of React, add some interactivity to a simple HTML page, or start a complex React-powered app, the links in this section will help you get started.

React has been designed from the start for gradual adoption, and you can use as little or as much React as you need. Whether you want to get a taste of React, add some interactivity to a simple HTML page, or start a complex React-powered app, the links in this section will help you get started.

setVisible(false)}> Cancel Accepted
) } `} /> { const { setVisible, bindings } = useModal() const [deleting, setDeleting] = React.useState(false) const [done, setDone] = React.useState(false) const remove = () => { setDeleting(true) setTimeout(() => { setDeleting(false) setDone(true) setVisible(false) }, 1200) } return ( {done && Project deleted.} Delete this project?

All 14 files and 3 members lose access. This cannot be undone.

setVisible(false)}>Keep project Delete project
) } `} /> Modal.Props | Attribute | Description | Type | Accepted values | Default | | ------------------------ | -------------------------------- | ------------------------- | --------------------------------------- | ------- | | **visible** | open or close | `boolean` | - | `false` | | **onClose** | open event | `() => void` | - | - | | **onContentClick** | event from modal content | `(e: MouseEvent) => void` | - | - | | **wrapClassName** | className of the modal dialog | `string` | - | - | | **keyboard** | press Esc to close modal | `boolean` | - | `true` | | **disableBackdropClick** | click background and don't close | `boolean` | - | `false` | | **role** | use `alertdialog` for a message that needs an answer | `'dialog'` / `'alertdialog'` | - | `dialog` | | **aria-label** | name of the dialog when there is no `Modal.Title` | `string` | - | - | | ... | native props | `HTMLAttributes` | `'autoFocus', 'name', 'className', ...` | - | The dialog is named by `Modal.Title` and described by `Modal.Subtitle` on its own. Without a title, pass `aria-label` or `aria-labelledby`. Modal.Title.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | ------------------------ | ------- | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Modal.Subtitle.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | ------------------------ | ------- | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Modal.Content.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | ------------------------ | ------- | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Modal.Action.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | ---------------------- | -------------------------------------------------- | ------------------------ | ------- | | **passive** | display passive mode | `boolean` | - | `false` | | **disabled** | disable current action | `boolean` | - | `false` | | **onClick** | click handler | [(e: ModalActionEvent) => void](#modalactionevent) | - | - | | **loading** | show loading | `boolean` | - | `false` | | ... | native props | `ButtonHTMLAttributes` | `'id', 'className', ...` | - | useModal ```ts type useModal = (initialVisible: boolean) => { visible: boolean setVisible: Dispatch> currentRef: MutableRefObject bindings: { visible: boolean onClose: () => void } } ``` ModalActionEvent ```ts type ModalActionEvent = MouseEvent & { close: () => void } ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Note, Grid } from 'core' export const meta = { title: 'Note', description: 'Display text that requires attention or provides additional information.', sidebar: 'components', group: 'Components', index: 25 } ## Note Display text that requires attention or provides additional information. Check payment pending. `} /> Check payment pending. Check payment pending. Check payment pending. Check payment pending. Check payment pending. Check payment pending. Check payment pending. `} /> Demo note! `} /> Customize a note. `} /> Customize a note. Check payment pending. Check payment pending. Check payment pending. Check payment pending. Check payment pending. Check payment pending. `} /> Your changes are live. You used 9 of 10 projects. Upgrade to add more. We could not charge your card. Update it to keep your plan. `} /> Note.Props | Attribute | Description | Type | Accepted values | Default | | ---------- | ------------------------- | -------------------- | ------------------------ | --------- | | **type** | note type | `NoteTypes` | [NoteTypes](#nodetypes) | `default` | | **label** | show label or custom text | `boolean` / `string` | - | - | | **filled** | filled variant: fill color | `boolean` | - | `false` | | **light** | light variant: tinted background | `boolean` | - | `false` | | **subtle** | subtle variant: no border | `boolean` | - | `false` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | NoteTypes ```ts type NoteTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { NumberInput, Grid, Text, Code } from 'core' export const meta = { title: 'Number Input', description: 'A field for numbers, with buttons and arrow keys to step the value and limits it stays within.', sidebar: 'components', group: 'Components', index: 52 } ## Number Input A field for numbers. The buttons and the arrow keys step the value, and it stays within `min` and `max`. `} /> `} /> `} /> { const [guests, setGuests] = React.useState(12) const tooMany = guests !== null && guests > 10 return ( Guests ) } `} /> { const [value, setValue] = React.useState(3) return ( Value: {value === null ? 'empty' : value} ) } `} /> `} /> `} /> NumberInput.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | --------------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------- | ------------------ | | **value** | the number, to control the field | `number` / `null` | - | - | | **initialValue** | the number at the start | `number` / `null` | - | `null` | | **onChange** | called with the number, or `null` when the field is empty | (value: number | null) => void | - | - | | **min** | lowest value | `number` | - | - | | **max** | highest value | `number` | - | - | | **step** | how much a button or an arrow key adds | `number` | - | `1` | | **precision** | decimal places kept | `number` | - | the ones of `step` | | **type** | color of the field | `NormalTypes` | `'default', 'primary', 'secondary', 'success', 'warning', 'error', 'info'` | `default` | | **hideControls** | hide the buttons | `boolean` | - | `false` | | **error** | mark the value as invalid | `boolean` | - | `false` | | **errorMessage** | text shown below the field with `error` | `string` | - | - | | **disabled** | disable the field | `boolean` | - | `false` | | **rounded** | round the corners | `boolean` | - | `false` | | **filled** | filled variant | `boolean` | - | `false` | | **light** | light variant | `boolean` | - | `false` | | **ghost** | outline variant | `boolean` | - | `false` | | **subtle** | subtle variant | `boolean` | - | `false` | | **readOnly** | show the value without letting it change | `boolean` | - | `false` | | **children** | label shown above the field | `ReactNode` | - | - | | ... | native props, passed to the input | `InputHTMLAttributes` | `'aria-label', 'name', 'placeholder', ...` | - | Typing and limits The field accepts digits, a minus sign and one decimal separator, a dot or a comma. While the user types, `onChange` receives the number as it is. When the field loses the focus, the value is kept within `min` and `max` and rounded to `precision`. The buttons and the keys never go past the limits. Ref The `ref` points at the `input`. Accessibility The input has `role="spinbutton"` with `aria-valuenow`, `aria-valuemin` and `aria-valuemax`. The buttons are named Increase and Decrease and stay out of the tab order, since the keys do the same from the input. With `error`, the input has `aria-invalid` and is described by the message. | Key | Action | | ----------------- | ------------------------------ | | Arrow Up and Down | Add or subtract `step` | | Page Up and Down | Add or subtract ten steps | | Home and End | Go to `min` or `max`, when set | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { ComponentTag } from 'src/components' import { Grid, Spacer } from 'core' export const meta = { title: 'Overview', description: 'Browse every Bolio UI component, grouped by what it does.', sidebar: 'components', group: 'Components', index: 0 } ## Overview Browse every component, grouped by what it does. ### Layout Alert Chip Col Container Divider Grid Mention Page Row Splitter Section Spacer ### Typography Code Description Keyboard Link Text ### Buttons Button Button Dropdown Button Group Menu ### Forms Checkbox Color Input Color Picker Combobox DatePicker DateRangePicker Dropzone Fieldset Input Number Input Tags Input Pin Input Radio Rating Segmented Control Select Slider Textarea Toast Toggle ### Data Display Avatar Badge Calendar Card Carousel Collapse Display Dot Icons Image Image Zoom Marquee Snippet Stat Table Tag Timeline ### Feedback Capacity Empty State Loading Note Progress Skeleton Spinner ### Overlays Drawer Context Menu Modal Popover Toolbar Tooltip ### Navigation Breadcrumbs Command Pagination Stepper Tour Tabs Tree export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Page, Button, Grid } from 'core' import { Layout, Playground, Attributes } from 'src/components' import MockPage from 'core/MdxWidgets/MockPage' export const meta = { title: 'Page', description: 'Container of general for display page content.', sidebar: 'components', group: 'Components', index: 26 } ## Page Container of general for display page content. { const Child = () => ( <>

Hi my dear!

This is an example to show the body of a page.

) const [visible, setVisible] = React.useState(false) return ( setVisible(false)}> ) } `} /> { const [visible, setVisible] = React.useState(false) return ( setVisible(false)}>

Header

Hi my dear!

This is an example to show the body of a page.

Footer

) } `} /> Page.Props | Attribute | Description | Type | Accepted values | Default | | --------------- | ---------------------------------- | --------------------------------- | ------------------------ | --------- | | **render** | render mode | [PageRenderMode](#pagerendermode) | - | `default` | | **dotBackdrop** | show decorations in the background | `boolean` | - | `false` | | **dotSize** | dot size in the background | `CSSProperties` | - | `1px` | | **dotSpace** | space multiple between each dot | `number` | - | `1` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Page.Header.Props | Attribute | Description | Type | Accepted values | Default | | ---------- | ------------ | ---------------- | ------------------------ | ------- | | **center** | align center | `boolean` | - | `false` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Page.Content.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | ------------------------ | ------- | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Page.Footer.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | ------------------------ | ------- | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | PageRenderMode ```ts type PageRenderMode = | 'default' // Normal rendering | 'effect' // Render after the first effect trigger | 'effect-seo' // like "effect", but prerender strings for SEO ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Pagination, Grid, Text } from 'core' import { ChevronRight, ChevronLeft, ArrowRight, ArrowLeft, ArrowRightCircle, ArrowLeftCircle } from '@bolio-ui/icons' export const meta = { title: 'Pagination', description: 'Navigation and identification between multiple pages.', sidebar: 'components', group: 'Components', index: 27 } ## Pagination Navigation and identification between multiple pages. `} /> `} /> `} /> { const customers = Array.from({ length: 23 }, (_, index) => 'Customer ' + (index + 1)) const size = 5 const [page, setPage] = React.useState(1) const shown = customers.slice((page - 1) * size, page * size) return ( {shown.map((name) => ( {name} ))} {(page - 1) * size + 1} to {Math.min(page * size, customers.length)} of {customers.length} ) } `} /> Pagination.Props | Attribute | Description | Type | Accepted values | Default | | --------------- | ---------------------------- | ------------------------ | ------------------------ | ------- | | **initialPage** | the page selected by default | `number` | - | 1 | | **page** | current page | `number` | - | 1 | | **count** | the total number of pages | `number` | - | 1 | | **limit** | limit of display page | `number` | - | 7 | | **onChange** | change event | `(page: number) => void` | - | - | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Pagination.Previous.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------------- | ------------------------ | ------- | | ... | native props | `ButtonHTMLAttributes` | `'id', 'className', ...` | - | Pagination.Next.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------------- | ------------------------ | ------- | | ... | native props | `ButtonHTMLAttributes` | `'id', 'className', ...` | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { PinInput, Grid, Text } from 'core' export const meta = { title: 'Pin Input', description: 'A row of boxes to type a short code, like a verification code or a PIN.', sidebar: 'components', group: 'Components', index: 61 } ## Pin Input A row of boxes to type a short code, like a verification code or a PIN. Each character goes to its own box and the focus moves ahead by itself. `} /> { const [code, setCode] = React.useState('') const [done, setDone] = React.useState(false) return ( { setCode(next); setDone(false) }} onComplete={() => setDone(true)} /> {done ? 'Code ' + code + ' is complete.' : 'Typed so far: ' + (code || 'nothing')} ) } `} /> `} /> `} /> `} /> PinInput.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | ------------------------------------------------------------ | --------------------------------------------- | -------------------------------------------------------------------------- | -------------------------- | | **length** | number of boxes | `number` | - | `6` | | **value** | the code, to control the component | `string` | - | - | | **initialValue** | the code at the start | `string` | - | `''` | | **onChange** | called with the code each time it changes | `(value: string) => void` | - | - | | **onComplete** | called with the code when every box is filled | `(value: string) => void` | - | - | | **numeric** | accepts only digits and opens the numeric keyboard | `boolean` | - | `false` | | **mask** | hides the characters | `boolean` | - | `false` | | **boxLabel** | name of each box for screen readers | `(index: number, length: number) => string` | - | `Character 1 of 6` | | **disabled** | disable the component | `boolean` | - | `false` | | **error** | red boxes, marked as invalid | `boolean` | - | `false` | | **type** | color of the boxes | `NormalTypes` | `'default', 'primary', 'secondary', 'success', 'warning', 'error', 'info'` | `default` | | **rounded** | round the corners | `boolean` | - | `false` | | **filled** | filled variant | `boolean` | - | `false` | | **light** | light variant | `boolean` | - | `false` | | **ghost** | outline variant | `boolean` | - | `false` | | **subtle** | subtle variant | `boolean` | - | `false` | | ... | native props, passed to the group `div` | `HTMLAttributes` | `'aria-label', 'id', ...` | - | Typing and pasting - • **A character** fills its box and moves the focus to the next one. Typing over a filled box replaces its character. - • **Backspace** clears the box. On an empty box, it goes back to the previous one and clears it. - • **Paste** fills the boxes from the one that received it, and what does not fit is dropped. The first box accepts the one time code that a phone offers from a text message in the same way. - • **Left and Right arrows** move between the boxes. - • The code has no gaps, so a click on a box past the end goes to the first empty one. Ref The `ref` points at the group `div`. Accessibility The boxes are native text inputs in a group named by `aria-label`, and each one has its own name, like "Character 3 of 6", which you can translate with `boxLabel`. The first box has `autocomplete="one-time-code"`, so phones can offer the code from a message. `error` sets `aria-invalid` on every box. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Popover, Grid, Spacer, Link, Text, Button } from 'core' import { Bell } from '@bolio-ui/icons' import { useState } from 'react' export const meta = { title: 'Popover', description: 'The floating box popped by clicking or hovering.', sidebar: 'components', group: 'Components', index: 28 } ## Popover The floating box popped by clicking or hovering. { const content = () => (
A hyperlink External link
) return ( Menu ) } `} /> { const content = () => ( <> User Settings A hyperlink A hyperlink for edit profile Command-Line ) return ( Menu ) } `} /> { const [visible, setVisible] = useState(false) const changeHandler = (next) => { setVisible(next) } const content = () => (
setVisible(false)}>Click to close Nothing
) return ( Menu ) } `} /> { const [unread, setUnread] = React.useState(3) const content = () => (
{unread ? unread + ' unread' : 'You are all caught up'} Ana commented on Pricing.md Rui invited you to Billing Your export is ready
) return ( ) } `} /> Popover.Props | Attribute | Description | Type | Accepted values | Default | | ------------------------- | ---------------------------------------------- | ----------------------------- | ------------------- | -------- | | **content** | content of pop-up | `ReactNode` `() => ReactNode` | - | - | | **visible** | visible or not | `boolean` | - | `false` | | **initialVisible** | visible on initial | `boolean` | - | `false` | | **hideArrow** | hide arrow icon | `boolean` | - | `false` | | **placement** | position of the popover relative to the target | [Placement](#placement) | - | `bottom` | | **trigger** | tooltip trigger mode | `'click' / 'hover'` | - | `click` | | **enterDelay**(ms) | delay before popover is shown | `number` | - | `100` | | **leaveDelay**(ms) | delay before popover is hidden | `number` | - | `0` | | **offset**(px) | distance between pop-up and target | `number` | - | `12` | | **portalClassName** | className of pop-up box | `string` | - | - | | **onVisibleChange** | call when visibility of the popover is changed | `(visible: boolean) => void` | - | - | | **disableItemsAutoClose** | prevent close Popover when Items clicked | `boolean` | - | - | | ... | native props | `HTMLAttributes` | `'id', 'name', ...` | - | Popover.Item | Attribute | Description | Type | Accepted values | Default | | -------------------- | ---------------------------------- | --------- | --------------- | ------- | | **line** | show a line | `boolean` | - | `false` | | **title** | show text with title style | `boolean` | - | `false` | | **disableAutoClose** | prevent close Popover when clicked | `boolean` | - | `false` | Placement ```ts type Placement = 'top' | 'topStart', | 'topEnd', | 'left', | 'leftStart', | 'leftEnd', | 'bottom', | 'bottomStart', | 'bottomEnd', | 'right', | 'rightStart', | 'rightEnd', ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Progress, Grid, useTheme, Button, Text } from 'core' import { useState } from 'react' export const meta = { title: 'Progress', description: 'Display progress relative to a limit or related to a task.', sidebar: 'components', group: 'Components', index: 28 } ## Progress Display progress relative to a limit or related to a task. `} /> `} /> { const theme = useTheme() const [value, setValue] = useState(20) const colors = { 20: theme.palette.error, 40: theme.palette.warning, 60: theme.palette.success, 80: '#000' } return ( ) }`} /> `} /> `} /> `} /> { const [value, setValue] = React.useState(0) const upload = () => { setValue(10) const timer = setInterval(() => { setValue((last) => { if (last >= 100) { clearInterval(timer) return 100 } return last + 10 }) }, 300) } const label = value === 100 ? 'Upload complete' : value ? 'Uploading report.pdf, ' + value + '%' : 'report.pdf is ready to upload' return ( {label} ) } `} /> Progress.Props | Attribute | Description | Type | Accepted values | Default | | --------------- | ---------------------- | --------------------------- | ------------------------------- | --------- | | **value** | current value | `number` | - | 0 | | **max** | max value | `number` | - | 100 | | **fixedTop** | fix progress to top | `boolean` | - | `false` | | **fixedBottom** | fix progress to bottom | `boolean` | - | `false` | | **segments** | split the bar in blocks | `number` | - | - | | **circular** | show a ring instead of a bar | `boolean` | - | `false` | | **colors** | custom colors | `{ [key: number]: string }` | - | - | | **type** | predefined state types | `ProgressTypes` | [ProgressTypes](#progresstypes) | `default` | | ... | native props | `ProgressHTMLAttributes` | `'aria-busy', ...` | - | ProgressTypes ```ts type ProgressTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Radio, Grid, Code, Button } from 'core' import { useState } from 'react' export const meta = { title: 'Radio', description: 'Provides single user input from a selection of options.', sidebar: 'components', group: 'Components', index: 29 } ## Radio Provides single user input from a selection of options. Option 1 `} /> { const [state, setState] = useState('1') const handler = (val) => { setState(val) console.log(val) } return ( Option 1 Option 2 ) } `} /> Default Primary Secondary Success Warning Error Info `} /> console.log(val)}> Option 1 Example description for Option 1 `} /> Option 1 Option 2 `} /> Option 1Description for Option1 Option 2Description for Option2 `} /> { const plans = { free: ['Free', '$0 a month', '1 project'], pro: ['Pro', '$12 a month', 'Unlimited projects'], team: ['Team', '$36 a month', 'Up to 10 members'] } const [plan, setPlan] = React.useState('pro') return ( {Object.entries(plans).map(([key, [name, price, hint]]) => ( {name} {price}. {hint}. ))} ) } `} /> Radio.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | ----------------------------- | ---------------------------------------------- | ------------------------- | --------- | | **checked** | selected or not (in single) | `boolean` | - | `false` | | **value** | unique ident value (in group) | `string` | - | - | | **id** | native attr | `string` | - | - | | **disabled** | disable current radio | `boolean` | - | `false` | | **type** | current type | `RadioTypes` | [RadioTypes](#radiotypes) | `default` | | **onChange** | change event | `(e: RadioEvent) => void` | - | - | | **ref** | forwardRef | Ref<HTMLInputElement | null> | - | - | | ... | native props | `InputHTMLAttributes` | `'id', 'className', ...` | - | Radio.Group.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | -------------------- | ------------------------- | ------------------------ | ------- | | **initialValue** | initial value | `string` | - | - | | **value** | selected child radio | `string` | - | - | | **useRow** | horizontal layout | `boolean` | - | `false` | | **disabled** | disable all radios | `boolean` | - | `false` | | **onChange** | change event | `(value: string) => void` | - | - | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Radio.Description.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | ------------------------ | ------- | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | RadioTypes ```ts type RadioTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Rating, Grid } from 'core' import { useState } from 'react' import { Umbrella, Zap } from '@bolio-ui/icons' export const meta = { title: 'Rating', description: 'Pick or show a score with stars or any other icon.', sidebar: 'components', group: 'Components', index: 30 } ## Rating Pick or show a score with stars or any other icon. The value only changes when the user clicks or uses the arrow keys, and hovering shows a preview. { const [value, setValue] = useState(3) return ( Selection: {value} ) } `} /> `} /> `} /> `} /> `} /> `} /> } /> } highlightSelectedOnly /> `} /> Rating.Props | Attribute | Description | Type | Accepted values | Default | | ------------------------- | --------------------------------------------------- | ------------------------------------------ | --------------------------- | --------- | | **value** | current score, to control the component | `number` | `0` to `count` | - | | **initialValue** | score at the start | `number` | `0` to `count` | `0` | | **onChange** | called with the score the user picked | `(value: number) => void` | - | - | | **onHoverChange** | called with the previewed score, or `null` on leave | `(value: number \| null) => void` | - | - | | **count** | amount of icons | `number` | - | `5` | | **precision** | step of the score | `RatingPrecision` | `1`, `0.5` | `1` | | **type** | color of the icons | `RatingTypes` | [RatingTypes](#ratingtypes) | `default` | | **variant** | look of the empty icons | `RatingVariants` | `'outline', 'filled'` | `outline` | | **icon** | icon of the filled state | `React.ReactNode` | - | star | | **emptyIcon** | icon of the empty state | `React.ReactNode` | - | `icon` | | **readOnly** | show the score without picking | `boolean` | - | `false` | | **disabled** | block the component | `boolean` | - | `false` | | **clearable** | a click on the current score clears it | `boolean` | - | `false` | | **highlightSelectedOnly** | light only the icon of the score | `boolean` | - | `false` | | **getLabel** | accessible name of each score | `(value: number, count: number) => string` | - | `3 of 5` | | ... | native props | `HTMLAttributes` | - | - | RatingTypes ```ts type RatingTypes = 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` Accessibility The component is a group of native radio buttons, so the arrow keys move the score and Tab leaves the group. Give it an `aria-label`. With `readOnly` or `disabled` it becomes an image named by `getLabel`. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Row, Col, Card, Text } from 'core' export const meta = { title: 'Row', description: 'A flex row that holds columns.', sidebar: 'components', group: 'Components', index: 46 } ## Row A flex row that holds columns. Each `Col` takes a number of twelfths of the row, so the spans in a row should add up to 12 or less. span 4 span 4 span 4 `} /> span 3 span 3 `} /> short a taller
cell
`} /> gap 2 gap 2 `} /> Row.Props | Attribute | Description | Type | Accepted values | Default | | ------------- | -------------------------------------------------------- | ----------------------------- | ---------------------------------------------------------- | ------- | | **justify** | horizontal alignment of the columns | `string` | `start`, `end`, `center`, `space-around`, `space-between` | `start` | | **align** | vertical alignment of the columns | `string` | `top`, `middle`, `bottom` | `top` | | **gap** | space around the content of the columns, in theme gaps | `number` | - | `0` | | **component** | the element to render | `keyof JSX.IntrinsicElements` | `'div', 'ul', 'section', ...` | `div` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | The row does not wrap. If the spans add up to more than 12, the columns get narrower instead of going to the next line. Use a new `Row` for the next line, or use `Grid`, which wraps. Ref The `ref` points at the root element. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Section, Container, Text, Button, useTheme } from 'core' export const meta = { title: 'Section', description: 'A band of the page, with an optional background.', sidebar: 'components', group: 'Components', index: 48 } ## Section A band of the page that groups related content, with an optional background. It renders a `section` element. Put a `Container` inside it to limit the width of the content. A section of the page. `} /> { const theme = useTheme() return (
A band with a background.
) } `} /> { const theme = useTheme() return ( <>
Everything you need to ship Forms, tables and dialogs that work with your theme from the first line.
Start with the free plan No card needed. Upgrade when your team grows.
) } `} /> Section.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------------------------ | ---------------- | ------------------------ | ------------- | | **bg** | background color | `string` | any CSS color | `transparent` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | Ref The `ref` points at the `section` element. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { SegmentedControl, Grid, Text } from 'core' export const meta = { title: 'Segmented Control', description: 'A row of options where exactly one is selected, for switching a view or a setting in place.', sidebar: 'components', group: 'Components', index: 58 } ## Segmented Control A row of options where exactly one is selected. Use it to switch a view or a setting in place, like a period or a layout. Day Week Month `} /> { const [view, setView] = React.useState('list') return ( List Grid Board Showing the {view} view. ) } `} /> Monthly Yearly `} /> List Grid Board List Grid `} /> SegmentedControl.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | -------------------------------------------- | ----------------------------------- | ------------------------- | ------- | | **value** | selected item, to control it | `string` | `number` | - | - | | **initialValue** | item selected on the first render | `string` | `number` | - | - | | **onChange** | called with the `value` of the chosen item | `(value: string \| number) => void` | - | - | | **disabled** | disables every item | `boolean` | - | `false` | | **fullWidth** | fills the width of the container | `boolean` | - | `false` | | ... | native props, passed to the `div` | `HTMLAttributes` | `'aria-label', 'id', ...` | - | SegmentedControl.Item.Props | Attribute | Description | Type | Accepted values | Default | | ------------ | -------------------------------------------- | ------------------------ | --------------- | ------- | | **value** | identifies the item in `value` and `onChange` | `string` | `number` | - | - | | **disabled** | the item cannot be chosen | `boolean` | - | `false` | | ... | native props, passed to the radio `input` | `InputHTMLAttributes` | `'id', ...` | - | Ref The `ref` of `SegmentedControl` points at the `div`, and the `ref` of each item at its radio `input`. Accessibility The group is a `radiogroup` and each item is a native radio, so a screen reader announces the name of the group, the option and its position. Name the group with `aria-label`. Tab moves focus into the group on the selected item, and the arrow keys move between the items and select the one in focus. The selected item is not shown by color alone: it also gets a raised background. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Select, Grid, Code, Modal, useModal, Button, Text } from 'core' export const meta = { title: 'Select', description: 'Display a dropdown list of items.', sidebar: 'components', group: 'Components', index: 31 } ## Select Display a dropdown list of items. The Select contain an additional Hooks, see subsection [useModal](/docs/hooks/use-modal) for details. { const handler = (val) => console.log(val) return ( ) } `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> { const { visible, setVisible, bindings } = useModal() return ( Modal

Scroll through the content to see the changes.

Scroll through the content to see the changes.

setVisible(false)}>Cancel
) }`} /> { const [status, setStatus] = React.useState('open') const [sort, setSort] = React.useState('recent') return ( Showing {status} issues, {sort}. ) } `} /> Select.Props | Attribute | Description | Type | Accepted values | Default | | --------------------------- | -------------------------------------------------------- | --------------------------------------------------- | --------------------------- | --------------- | | **value** | selected value | `string`, `string[]` | - | - | | **initialValue** | initial value | `string`, `string[]` | - | - | | **placeholder** | placeholder string | `string` | - | - | | **width** | css width value of select | `string` | - | `initial` | | **type** | current type | `SelectTypes` | [SelectTypes](#selecttypes) | `default` | | **icon** | icon component | `ComponentType` | - | `SVG Component` | | **pure** | remove icon component | `boolean` | - | `false` | | **multiple** | support multiple selection | `boolean` | - | `false` | | **clearable** | add clear icon on multiple selection (ignored otherwise) | `boolean` | - | `true` | | **disabled** | disable current radio | `boolean` | - | `false` | | **rounded** | round the corners | `boolean` | - | `false` | | **filled** | filled variant | `boolean` | - | `false` | | **light** | light variant | `boolean` | - | `false` | | **ghost** | outline variant | `boolean` | - | `false` | | **subtle** | subtle variant | `boolean` | - | `false` | | **rounded** | round the corners | `boolean` | - | `false` | | **filled** | filled variant | `boolean` | - | `false` | | **light** | light variant | `boolean` | - | `false` | | **ghost** | outline variant | `boolean` | - | `false` | | **subtle** | subtle variant | `boolean` | - | `false` | | **onChange** | selected value | (val: string | string[]) => void | - | - | | **dropdownClassName** | className of dropdown menu | `string` | - | - | | **dropdownStyle** | style of dropdown menu | `object` | - | - | | **disableMatchWidth** | disable Option from follow Select width | `boolean` | - | `false` | | **getPopupContainer** | dropdown render parent element, the default is `body` | `() => HTMLElement` | - | - | | **onDropdownVisibleChange** | dropdown change events | `(visible: boolean) => void` | - | - | | **ref** | forwardRef | `SelectRef` | [SelectRef](#selectref) | - | | ... | native props | `HTMLAttributes` | `'name', 'alt', ...` | - | Select.Option.Props | Attribute | Description | Type | Accepted values | Default | | ------------------- | ---------------------- | ---------------- | ------------------- | ------- | | **value**(required) | unique ident value | `string` | - | - | | **disabled** | disable current option | `boolean` | - | `false` | | **divider** | display a line | `boolean` | - | `false` | | **label** | display a group title | `boolean` | - | `false` | | ... | native props | `HTMLAttributes` | `'name', 'id', ...` | - | SelectRef ```ts type SelectRef = { focus: () => void blur: () => void scrollTo?: (options?: ScrollToOptions) => void } ``` SelectTypes ```ts type SelectTypes = 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Skeleton, Grid, Text, Button } from 'core' export const meta = { title: 'Skeleton', description: 'A placeholder in the shape of the content while it loads, so the layout does not jump.', sidebar: 'components', group: 'Components', index: 50 } ## Skeleton A placeholder in the shape of the content while it loads, so the layout does not jump when the content arrives. `} /> `} /> `} /> { const [loading, setLoading] = React.useState(true) return ( The content shows up here once it has loaded. ) } `} /> Skeleton.Props | Attribute | Description | Type | Accepted values | Default | | ----------- | ------------------------------------------------------------- | ------------------ | -------------------------- | ------- | | **width** | width of the placeholder; a number is a multiple of the theme unit | `string` / `number` | `'60%'`, `'48px'`, ... | `100%`, `2.5em` for a circle | | **height** | height of each line; a number is a multiple of the theme unit | `string` / `number` | `'120px'`, ... | `1em`, the width for a circle | | **lines** | number of lines; the last one is shorter | `number` | - | `1` | | **circle** | round shape, for avatars | `boolean` | - | `false` | | **loading** | with children, shows the placeholder while `true` | `boolean` | - | `true` | | ... | native props, passed to the root element | `HTMLAttributes` | `'id', 'className', ...` | - | Ref The `ref` points at the root element of the placeholder. With children and `loading={false}`, the children render alone and the `ref` is not used. Accessibility The placeholder has `aria-hidden`, so screen readers skip it. When it wraps content, the wrapper has `aria-busy="true"` while loading. With `prefers-reduced-motion`, the shimmer stops and the shapes stay still. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Slider, Grid, Text } from 'core' import { useState } from 'react' export const meta = { title: 'Slider', description: 'Display the current value and an inputable range.', sidebar: 'components', group: 'Components', index: 32 } ## Slider Display the current value and an inputable range. `} /> `} /> `} /> `} /> `} /> { const [value, setValue] = useState() const handler = (val) => { console.log(val) setValue(val) } return ( ) } `} /> { const [budget, setBudget] = React.useState(500) return ( Monthly budget: {'$' + budget} ) } `} /> Slider.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | -------------------------------------------------- | ----------------------- | -------------------------------- | --------- | | **initialValue** | initial value | `number` | - | 0 | | **value** | slider value | `number` | - | 0 | | **type** | current type | `SliderTypes` | [SliderTypes](#slidertypes) | `default` | | **step** | the granularity the slider can step through values | `number` | - | 1 | | **max** | the maximum value of slider | `number` | - | 100 | | **min** | the minimum value of slider | `number` | - | 0 | | **disabled** | disable slider interaction | `boolean` | `false` | | **showMarkers** | show each marker | `boolean` | - | `false` | | **hideValue** | hide slider value | `boolean` | - | `false` | | **onChange** | called when the value of silder changes | `(val: number) => void` | - | - | | ... | native props | `HTMLAttributes` | `'id', 'name', 'className', ...` | - | SliderTypes ```ts type SliderTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Snippet, Grid, Code } from 'core' export const meta = { title: 'Snippet', description: 'Display a snippet of copyable code for the command line.', sidebar: 'components', group: 'Components', index: 33 } ## Snippet Display a snippet of copyable code for the command line. `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> `} /> Snippet.Props | Attribute | Description | Type | Accepted values | Default | | ------------- | ----------------------- | ------------------- | -------------------------------- | ---------------------- | | **text** | code snippet | `string` `string[]` | - | - | | **type** | snippet types | `SnippetTypes` | [SnippetTypes](#snippettypes) | `default` | | **filled** | filled variant | `boolean` | - | `false` | | **light** | light variant | `boolean` | - | `false` | | **ghost** | outline variant | `boolean` | - | `false` | | **subtle** | subtle variant | `boolean` | - | `false` | | **width** | set CSS string | `string` | - | `initial` | | **copy** | function of copy button | `CopyTypes` | [CopyTypes](#copytypes) | `default` | | **symbol** | symbol snippet | `string` | - | `$` | | **toastText** | toast text | `string` | - | `Copied to clipboard!` | | **toastType** | toast type | `ToastTypes` | [ToastTypes](#toasttypes) | `success` | | ... | native props | `HTMLAttributes` | `'id', 'name', 'className', ...` | - | SnippetTypes ```ts type SnippetTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` CopyTypes ```ts type CopyTypes = 'default' | 'silent' | 'prevent' ``` ToastTypes ```ts type ToastTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Spacer, Grid, Input, Button, useTheme } from 'core' export const meta = { title: 'Spacer', description: 'Provide empty space.', sidebar: 'components', group: 'Components', index: 34 } ## Spacer Provide empty space. { const theme = useTheme() const block = (color) => ({ background: color, borderRadius: theme.layout.radius }) return ( ) } `} /> { const theme = useTheme() const block = { background: theme.palette.accents_3, borderRadius: theme.layout.radius } return ( ) } `} /> Email Password
`} /> Spacer.Props | Attribute | Description | Type | Accepted values | Default | | ---------- | -------------- | ------------------ | ------------------------ | ------- | | **w** | x-axis spacing | `number` / `float` | - | 1 | | **h** | y-axis spacing | `number` / `float` | - | 1 | | **inline** | inline space | `boolean` | - | `false` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Spinner, Grid, Card, Button, Text } from 'core' export const meta = { title: 'Spinner', description: 'Indicate an action running in the background.', sidebar: 'components', group: 'Components', index: 35 } ## Spinner Indicate an action running in the background. As an indicator of load waiting, see also component [Loading](/docs/components/loading).
`} /> { const [loading, setLoading] = React.useState(false) const refresh = () => { setLoading(true) setTimeout(() => setLoading(false), 1500) } return ( Recent invoices
{loading ? : 3 invoices are waiting for payment.}
) } `} /> Saving your changes `} /> Spinner.Props | Attribute | Description | Type | Accepted values | Default | | --------- | ------------ | ---------------- | ------------------------ | ------- | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Splitter, Text, useTheme } from 'core' export const meta = { title: 'Splitter', description: 'Panels that share a space, with a line between them that the user drags to resize them.', sidebar: 'components', group: 'Components', index: 68 } ## Splitter Panels that share a space, with a line between them that the user drags, or moves with the arrow keys, to give more room to one of them. The Splitter fills its container, so the container needs a height. { const theme = useTheme() return (
Sidebar Content
) } `} /> { const theme = useTheme() return (
Editor Console
) } `} /> { const theme = useTheme() const [sizes, setSizes] = React.useState([20, 55, 25]) return (
Files Editor Outline
{sizes.map((size) => Math.round(size) + '%').join(' / ')}
) } `} /> Splitter.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | ----------------------------------------------------------------------- | ------------------------------ | ------------------------- | ------------ | | **direction** | `horizontal` puts the panels side by side, `vertical` stacks them | `string` | `'horizontal', 'vertical'` | `horizontal` | | **onResize** | called with the size of every panel, in percent, when one of them changes | `(sizes: number[]) => void` | - | - | | **handleLabel** | name of the lines, for screen readers | `string` | - | `Resize` | | ... | native props, passed to the root `div` | `HTMLAttributes` | `'id', 'style', ...` | - | Splitter.Panel.Props | Attribute | Description | Type | Accepted values | Default | | --------------- | ------------------------------------------------------------------------------------ | -------- | --------------- | ------- | | **defaultSize** | percent of the space the panels share; the panels without one split what is left | `number` | `0` to `100` | - | | **minSize** | smallest size the panel can have, in percent | `number` | `0` to `100` | `0` | | **maxSize** | largest size the panel can have, in percent | `number` | `0` to `100` | `100` | | ... | native props, passed to the panel `div` | `HTMLAttributes` | `'className', 'style', ...` | - | Behavior - • **Sizes** are percents of the space the panels share, without the lines, so the panels stay in proportion when the container is resized. - • **A line** moves the panel before it and the one after it, by the same amount, as far as the limits of both allow. - • **Overflow**: each panel scrolls its own content. - • **Panels that come or go** start the sizes again from the `defaultSize` values. Ref The `ref` of `Splitter` points at the root `div`, and the `ref` of a panel at its `div`. Accessibility Each line is a `separator` that can be focused, with `aria-valuenow`, `aria-valuemin` and `aria-valuemax` for the size of the panel before it, and `aria-controls` pointing at that panel. The arrow keys that go along the splitter move it by 1%, or by 10% with Shift: Left and Right when the panels are side by side, Up and Down when they are stacked. Home and End go to the smallest and the largest size the limits allow. Name the lines with `handleLabel`. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Stat, Grid, Card, Progress, SegmentedControl } from 'core' export const meta = { title: 'Stat', description: 'Show a number with its label and trend.', sidebar: 'components', group: 'Components', index: 53 } ## Stat Show a number with its label and trend. `} /> } /> `} /> { const periods = { week: [ ['Revenue', '$11,300', '+3.2% vs last week'], ['Active users', '2,914', '+1.1% vs last week'], ['Churn', '0.4%', '-0.1% vs last week'] ], month: [ ['Revenue', '$48,200', '+12.4% vs last month'], ['Active users', '3,842', '+4.1% vs last month'], ['Churn', '1.8%', '-0.3% vs last month'] ], year: [ ['Revenue', '$512,900', '+31.0% vs last year'], ['Active users', '3,842', '+58.2% vs last year'], ['Churn', '6.2%', '-1.4% vs last year'] ] } const [period, setPeriod] = React.useState('month') return ( Week Month Year {periods[period].map(([label, value, change]) => ( ))} ) } `} /> Stat.Props | Attribute | Description | Type | Accepted values | Default | | ---------- | ------------------------------------------ | ---------------- | --------------- | ------- | | **label** | what the number measures | `ReactNode` | - | - | | **value** | the number | `ReactNode` | - | - | | **change** | trend text, a leading `-` is shown as drop | `string` | - | - | | **extra** | chart or icon on the right | `ReactNode` | - | - | | ... | native props | `HTMLAttributes` | - | - | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Stepper, Button, Grid } from 'core' export const meta = { title: 'Stepper', description: 'Shows the steps of a flow and which one the user is on, like a checkout or a signup.', sidebar: 'components', group: 'Components', index: 51 } ## Stepper Shows the steps of a flow and which one the user is on, like a checkout or a signup. The steps before `active` are completed. `} /> { const [active, setActive] = React.useState(0) return ( {' '} ) } `} /> `} /> `} /> Stepper.Props | Attribute | Description | Type | Accepted values | Default | | --------------- | --------------------------------------------------- | ------------------------- | ---------------------------- | ------------ | | **active** | index of the current step, from `0` | `number` | - | - | | **onStepClick** | called with the index of the clicked step; turns the steps into buttons | `(index: number) => void` | - | - | | **orientation** | direction of the steps | `string` | `'horizontal', 'vertical'` | `horizontal` | | ... | native props, passed to the `ol` | `OlHTMLAttributes` | `'aria-label', 'id', ...` | - | Stepper.Step.Props | Attribute | Description | Type | Accepted values | Default | | --------------- | ------------------------------------------------------ | ---------------- | --------------- | ------- | | **label** | name of the step | `ReactNode` | - | - | | **description** | text below the label | `ReactNode` | - | - | | **icon** | replaces the number, the check and the error mark | `ReactNode` | - | - | | **error** | the step failed | `boolean` | - | `false` | | **disabled** | the step cannot be clicked, with `onStepClick` | `boolean` | - | `false` | | ... | native props, passed to the `li` | `LiHTMLAttributes` | - | - | Ref The `ref` of `Stepper` points at the `ol`, and the `ref` of each step at its `li`. Accessibility The steps are an ordered list, so a screen reader hears how many there are and the position of each. Name the list with `aria-label`. The current step has `aria-current="step"`, and completed and failed steps say so in text, not only in color. With `onStepClick`, each step is a real button, reached with Tab. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, PlaygroundTitle, Attributes } from 'src/components' import { Table, Spacer, Code, Text, Button, Dot, Grid } from 'core' import { useState } from 'react' export const meta = { title: 'Table', description: 'Display tabular data in format.', sidebar: 'components', group: 'Components', index: 42 } ## Table Display tabular data in format. { const data = [ { property: 'type', description: 'Content type', type: 'secondary | warning', default: '-' }, { property: 'Component', description: 'DOM element to use', type: 'string', default: '-' }, { property: 'bold', description: 'Bold style', type: 'boolean', default: 'true' }, ] return (
) } `} /> { const data = [ { property: 'type', description: 'Content type', type: 'secondary | warning', default: '-' }, { property: 'Component', description: 'DOM element to use', type: string, default: '-' }, { property: bold, description: 'Bold style', type: boolean, default: true }, ] return (
) } `} /> { const data = [ { property: 'type', description: 'Content type', type: 'secondary | warning', default: '-' }, { property: 'Component', description: 'DOM element to use', type: string, default: '-' }, { property: bold, description: 'Bold style', type: boolean, default: true }, ] return (
) } `} /> { const dataSource = [ { property: 'type', description: 'Content type', operation: '' }, { property: 'Component', description: 'DOM element to use', operation: '' }, { property: bold, description: 'Bold style', operation: '' }, ] const [data, setData] = React.useState(dataSource) const renderAction = (value, rowData, index) => { const removeHandler = () => { setData(last => last.filter((_, dataIndex) => dataIndex !== index)) } return ( ) } return ( setData(value)}>
) } `} /> { const dataSource = [ { property: 'type', description: 'Content type', operation: '' }, { property: 'Component', description: 'DOM element to use', operation: '' }, { property: bold, description: 'Bold style', operation: '' }, ] const [data, setData] = React.useState(dataSource) const renderAction = (value, rowData, rowIndex) => { const updateHandler = () => { setData(last => { return last.map((item, dataIndex) => { if (dataIndex !== rowIndex) return item return { ...item, property: Math.random().toString(16).slice(-5) } }) }) } return ( ) } return ( setData(value)}>
) } `} /> { const data = [ { property: 'type', description: 'Content type', type: 'secondary | warning', default: '-' }, { property: 'Component', description: 'DOM element to use', type: string, default: '-' }, { property: bold, description: 'Bold style', type: boolean, default: true }, ] return ( type default
) } `} /> { const data = Array.from({ length: 23 }, (_, index) => ({ id: index + 1, name: 'Item ' + (index + 1), })) return (
) } `} /> { const [page, setPage] = useState(1) const rows = Array.from({ length: 5 }, (_, index) => { const id = (page - 1) * 5 + index + 1 return { id, name: 'Item ' + id } }) return (
) } `} /> ```tsx type User = { name: string role: string records: Array<{ date: string }> } const renderHandler: TableColumnRender = (value, rowData, index) => { return
{rowData.date}
} const data: Array = [ { name: 'witt', role: 'admin', records: [{ date: '2021-05-01' }] } ] const MyComponent = () => ( data={data}> prop="name" label="username" /> prop="role" label="role" /> prop="records" label="records" render={renderHandler} /> ) ``` { const data = [ { id: '#1042', customer: 'Ana Souza', status: 'paid', total: '$129.00' }, { id: '#1043', customer: 'Rui Pires', status: 'pending', total: '$54.50' }, { id: '#1044', customer: 'Marta Lima', status: 'refunded', total: '$89.90' } ] const types = { paid: 'success', pending: 'warning', refunded: 'error' } const renderStatus = (value) => {value} return (
) } `} /> { const invoices = [ { id: 'INV-014', customer: 'Ana Souza', amount: 129, due: '2026-11-03' }, { id: 'INV-009', customer: 'Rui Pires', amount: 1450, due: '2026-10-21' }, { id: 'INV-021', customer: 'Marta Lima', amount: 89.9, due: '2026-12-01' }, { id: 'INV-003', customer: 'Joao Reis', amount: 300, due: '2026-10-30' } ] const money = (value) => {'$' + value.toFixed(2)} return (
) } `} /> { const [rows, setRows] = React.useState([ { id: 1, name: 'Ana Souza', role: 'Owner' }, { id: 2, name: 'Rui Pires', role: 'Editor' }, { id: 3, name: 'Marta Lima', role: 'Editor' }, { id: 4, name: 'Joao Reis', role: 'Viewer' } ]) const [selected, setSelected] = React.useState([]) const remove = () => { setRows((last) => last.filter((row) => !selected.includes(row.id))) setSelected([]) } return ( {selected.length} of {rows.length} selected
) } `} /> { const rows = Array.from({ length: 14 }, (_, index) => ({ id: index + 1, name: 'Customer ' + (index + 1), orders: ((index * 7) % 11) + 1 })) const [selected, setSelected] = React.useState([]) return ( {selected.length} selected
) } `} /> Table.Props | Attribute | Description | Type | Accepted values | Default | | ---------------- | -------------------------------------------- | ----------------------------------------------------- | ------------------ | ------- | | **data** | data source | `Array` | - | - | | **initialData** | inital datas | `Array` | - | `[]` | | **emptyText** | displayed text when table's content is empty | `string` | - | - | | **hover** | table's hover effect | `boolean` | - | `true` | | **onRow** | callback row's content by click | [TableOnRowClick](#tableonrowclick) | - | - | | **onCell** | callback cell's content by click | [TableOnCellClick](#tableoncellclick) | - | - | | **onChange** | data change event | `(data: T) => void` | - | - | | **pagination** | split the rows in pages | [TablePagination](#tablepagination) | - | - | | **rowClassName** | set className to each row | [TableRowClassNameHandler](#tablerowclassnamehandler) | - | - | | **sort** | the column the rows are sorted by, to control it | [TableSort](#tablesort) / `null` | - | - | | **initialSort** | sort on the first render | [TableSort](#tablesort) / `null` | - | `null` | | **onSortChange** | called with the new sort, or `null` when it is cleared | `(sort: TableSort \| null) => void` | - | - | | **selectable** | a checkbox on each row, and one in the header | `boolean` | - | `false` | | **rowKey** | what identifies a row: a prop, or a function. The position in `data` when missing | `keyof T` / `(row: T) => string \| number` | - | - | | **selectedKeys** | keys of the selected rows, to control them | `Array` | - | - | | **initialSelectedKeys** | keys of the rows selected on the first render | `Array` | - | `[]` | | **onSelectionChange** | called with the keys and the rows selected | `(keys, rows: T[]) => void` | - | - | | **selectRowLabel** | name of the checkbox of a row, for screen readers | `string` | - | `Select row` | | **selectAllLabel** | name of the checkbox in the header | `string` | - | `Select all rows` | | ... | native props | `TableHTMLAttributes` | `'id', 'name' ...` | - | Table.Column.Props | Attribute | Description | Type | Accepted values | Default | | ------------------ | -------------------------------------- | --------------------------------------- | --------------- | ------- | | **prop**(required) | table-column's prop | `string` | - | - | | **label** | table-column's label | `string` | - | - | | **width** | width number (px) | `number` | - | - | | **className** | set className to each column | `string` | - | - | | **sortable** | the header becomes a button that sorts the rows | `boolean` | - | `false` | | **sorter** | how two rows compare, when the default order does not fit | `(a: T, b: T) => number` | - | - | | **render** | render returns elements in all columns | [TableColumnRender](#tablecolumnrender) | - | - | TableSort ```ts type TableSort = { prop: string; direction: 'asc' | 'desc' } ``` Sorting and selection - • **Order**: numbers are compared by value, and any other value as text, where `item 2` comes before `item 10`. Use `sorter` on a column for anything else. The header has `aria-sort`, and the sorted column shows an arrow. - • **Server rows**: with `pagination.total`, the rows are the ones of the server, so the table does not sort them. It only calls `onSortChange`, and you send the new order with the data. - • **Selection keys**: the selection is kept by key, so it survives a sort and a change of page. `onSelectionChange` receives the rows that are in `data`, which are only the current page when the rows are on the server. - • **Select all**: the checkbox in the header selects the rows in view, the current page. It is checked when all of them are selected, and in between when only some are. TablePagination | Attribute | Description | Type | Accepted values | Default | | ---------------- | ---------------------------------------------- | ------------------------ | --------------- | ------- | | **pageSize** | rows in each page | `number` | - | - | | **page** | current page, to control it | `number` | - | `1` | | **onPageChange** | called with the page the user picked | `(page: number) => void` | - | - | | **total** | all the rows on the server, `data` is the page | `number` | - | - | TableOnRowClick ```ts type TableOnRowClick = (rowData: T, rowIndex: number) => void ``` TableOnCellClick ```ts type TableOnCellClick = ( value: T[keyof T], rowIndex: number, colunmIndex: number ) => void ``` TableRowClassNameHandler ```ts type TableRowClassNameHandler = (rowData: T, rowIndex: number) => string ``` TableColumnRender ```ts type TableColumnRender = ( value: T[keyof T], rowData: T, rowIndex: number ) => JSX.Element | void ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Tabs, Grid, Text, Button, Code, useTabs, Input, Spacer } from 'core' import { useState } from 'react' import { Instagram, Facebook } from '@bolio-ui/icons' export const meta = { title: 'Tabs', description: 'Display tab content.', sidebar: 'components', group: 'Components', index: 36 } ## Tabs Display tab content. The Tabs contain an additional Hooks, see subsection [useTabs](/docs/hooks/use-tabs) for details. React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Build encapsulated components that manage their own state, then compose them to make complex UIs. `} /> React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. `} /> A summary of the project. Everything that changed this week. Names, members and billing. `} /> React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Build encapsulated components that manage their own state, then compose them to make complex UIs. `} /> React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Build encapsulated components that manage their own state, then compose them to make complex UIs. `} /> Instagram } value="1" > Hello, this is my profile. Facebook } value="2" > Hi, this is my page. `} /> Hello! Cool stuff. Good people. Amazing. Very low. Clear. Extraordinary person. Easy to tweak. Charts. Privacy focused. `} /> { const [value, setValue] = useState('1') const switchHandler = () => setValue('2') const changeHandler = val => setValue(val) return ( React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Build encapsulated components that manage their own state, then compose them to make complex UIs. ) } `} /> Name You are on the Pro plan. The next charge of $12 is on Nov 3. 3 members have access to this workspace. `} /> Tabs.Props | Attribute | Description | Type | Accepted values | Default | | -------------------- | --------------------------------------- | ----------------------- | ------------------------------- | ------- | | **initialValue** | initial value | `string` | - | - | | **value** | current selected value | `string` | - | - | | **hideDivider** | hide default divider | `boolean` | - | `false` | | **hideBorder** | hide border on active | `boolean` | - | `false` | | **slide** | sliding indicator under the active tab | `boolean` | - | `false` | | **leftSpace** | space area on the left side | `CSSProperties` | - | `12px` | | **onChange** | change event | `(val: string) => void` | - | - | | **align** | horizontal alignment of each child item | `justifyContent` | - | `left` | | **activeClassName** | className of active child item | `string` | - | - | | **activeStyles** | style of active child item | `object` | - | - | | **hoverHeightRatio** | height percentage of highlight block | `number` | - | 0.7 | | **hoverWidthRatio** | width percentage of highlight block | `number` | - | 1.15 | | ... | native props | `HTMLAttributes` | `'alt', 'id', 'className', ...` | - | Tabs.Item.Props | Attribute | Description | Type | Accepted values | Default | | ------------------- | ------------------- | --------- | --------------- | ------- | | **label**(required) | display tab's label | `string` | - | - | | **value**(required) | unique ident value | `string` | - | - | | **disabled** | disable current tab | `boolean` | - | `false` | export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Tag, Grid, Text } from 'core' export const meta = { title: 'Tag', description: 'Display a unique keyword, optionally as a part of a set.', sidebar: 'components', group: 'Components', index: 37 } ## Tag Display a unique keyword, optionally as a part of a set. Status: Unstable `} /> Default Primary Secondary Success Warning Error Dark Lite `} /> Default Primary Secondary Success Warning Error Dark Lite `} /> Designing accessible forms
Published Accessibility Forms 5 min read
`} /> Tag.Props | Attribute | Description | Type | Accepted values | Default | | ---------- | --------------------------- | --------------------- | ------------------------ | --------- | | **type** | tag type | [TagTypes](#tagtypes) | - | `default` | | **invert** | filled variant: invert color and background | `boolean` | - | `false` | | **light** | light variant: tinted background | `boolean` | - | `false` | | **subtle** | subtle variant: no background | `boolean` | - | `false` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | TagTypes ```ts type TagTypes = | 'default' | 'secondary' | 'success' | 'warning' | 'error' | 'dark' | 'lite' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { TagsInput, Grid, Text } from 'core' export const meta = { title: 'Tags Input', description: 'A field where each entry becomes a tag, for lists like skills, topics or email addresses.', sidebar: 'components', group: 'Components', index: 59 } ## Tags Input A field where each entry becomes a tag. Enter or a comma ends a tag, and the remove button or Backspace takes it out. Topics `} /> { const [tags, setTags] = React.useState(['design']) return ( {tags.length} tags: {tags.join(', ')} ) } `} /> `} /> `} /> `} /> `} /> TagsInput.Props | Attribute | Description | Type | Accepted values | Default | | ------------------- | -------------------------------------------------------- | ---------------------------- | --------------------------------------------------------------------- | --------- | | **value** | tags, to control the field | `string[]` | - | - | | **initialValue** | tags on the first render | `string[]` | - | `[]` | | **onChange** | called with the whole list when a tag is added or removed | `(tags: string[]) => void` | - | - | | **max** | most tags the field holds; the next ones are ignored | `number` | - | - | | **allowDuplicates** | accepts a tag that is already in the list | `boolean` | - | `false` | | **type** | color of the field | `string` | `'default', 'primary', 'secondary', 'success', 'warning', 'error', 'info'` | `default` | | **rounded** | rounded corners | `boolean` | - | `false` | | **filled** | filled surface | `boolean` | - | `false` | | **light** | light surface | `boolean` | - | `false` | | **ghost** | ghost surface | `boolean` | - | `false` | | **subtle** | subtle surface | `boolean` | - | `false` | | **disabled** | locks the field | `boolean` | - | `false` | | **readOnly** | shows the tags without changing them | `boolean` | - | `false` | | **error** | marks the field as invalid | `boolean` | - | `false` | | **errorMessage** | text shown below the field with `error` | `string` | - | - | | ... | native props, passed to the `input` | `InputHTMLAttributes` | `'placeholder', 'aria-label', 'id', ...` | - | Adding and removing tags - • **Enter** turns the text into a tag. With an empty field, Enter works as usual, so a form can still submit. - • **A comma** ends a tag, typed or pasted, so `a, b, c` becomes three tags. - • **Leaving the field** adds the text that is still in it. - • **Backspace** on an empty field removes the last tag, and each tag also has a remove button. - • Spaces around a tag are trimmed, and empty tags are ignored. Ref The `ref` points at the `input`. Accessibility The field is a native text input, so a label passed as children, or `aria-label`, names it. Each remove button is named after its tag, like "Remove React", and sits in the tab order. `error` sets `aria-invalid` and links the message with `aria-describedby`. export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Text, Grid } from 'core' export const meta = { title: 'Text', description: 'Display text using well-defined typographic styles.', sidebar: 'components', group: 'Components', index: 38 } ## Text Display text using well-defined typographic styles. Hello my friend, have fun with Bolio UI 🥷🏼 `} /> Make your development more creative and with amazing tools for React. Make your development more creative and with amazing tools for React. `} /> React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. `} /> Build encapsulated components that manage their own state, then compose them to make complex UIs. `} /> Text colored Text colored Text colored Text colored Text colored Text colored Text colored `} /> Font Size: 12px; Font Size: 14px; Font Size: 1rem; Font Size Scale: 1.25; `} /> Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM. We don’t make assumptions about the rest of your technology stack, so you can develop new features in React without rewriting existing code. `} /> Text.Props | Attribute | Description | Type | Accepted values | Default | | -------------- | -------------- | ---------------- | ------------------------ | --------- | | **p** | component name | `boolean` | - | `true` | | **h1 - h6** | component name | `boolean` | - | `false` | | **small** | component name | `boolean` | - | `false` | | **span** | component name | `boolean` | - | `false` | | **del** | component name | `boolean` | - | `false` | | **i** | component name | `boolean` | - | `false` | | **em** | component name | `boolean` | - | `false` | | **b** | component name | `boolean` | - | `false` | | **blockquote** | component name | `boolean` | - | `false` | | **type** | text type | `TextTypes` | [TextTypes](#texttypes) | `default` | | ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - | TextTypes ```ts type TextTypes = | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' ``` export default Docs.withMeta(meta) --- import Docs from 'src/templates/Docs' import { Playground, Attributes } from 'src/components' import { Textarea, Grid, useInput, Button, Code } from 'core' import { useState } from 'react' export const meta = { title: 'Textarea', description: 'Retrieve multi-line user input.', sidebar: 'components', group: 'Components', index: 39 } ## Textarea Retrieve multi-line user input.