@phpsoftbox/react-softbox
v1.11.0
Published
Набор UI‑компонентов для React.
Readme
ReactSoftBox
Набор UI‑компонентов для React.
Подключение
import '@phpsoftbox/react-softbox/foundations/index.css';import {
Alert,
Badge,
Breadcrumbs,
Button,
Card,
Checkbox,
Collapse,
CollapseButton,
Drawer,
Dropdown,
FileUploader,
FloatLabel,
FormField,
Grid,
Heading,
Image,
Input,
Menu,
Modal,
Notifier,
Pagination,
Progress,
Radio,
Row,
Select,
Stack,
Switch,
Table,
Tabs,
Text,
Textarea,
Tooltip,
Wizard,
} from '@phpsoftbox/react-softbox';Тема
import { initTheme, setThemeMode } from '@phpsoftbox/react-softbox';
initTheme({ defaultMode: 'system' });
setThemeMode('dark');Документация
docs/README.mddocs/layout.mddocs/navigation.mddocs/forms.mddocs/table.mddocs/tooltip.mddocs/overlays.mddocs/feedback.mddocs/card.mddocs/typography.mddocs/theme.mddocs/pagination.mddocs/tabs.mddocs/progress.mddocs/breadcrumbs.mddocs/wizard.md
Playground
Локальная площадка для проверки компонентов:
cd packages-js/ReactSoftBox/playground
yarn install
yarn dev --host 0.0.0.0 --port 5174Сборка пакета
yarn install
yarn buildКраткий обзор компонентов
Button
<Button variant="primary">Primary</Button>
<Button variant="info" appearance="outline">Info</Button>
<Button variant="danger" appearance="ghost">Danger</Button>
<Button variant="primary" size="sm">Small</Button>Input / FloatLabel
<Input>
<Input.Label>Email</Input.Label>
<Input.Field type="email" name="email" />
</Input>
<Input>
<Input.FloatLabel label="Password">
<Input.Field type="password" name="password" />
</Input.FloatLabel>
</Input>Textarea / Radio
<Textarea placeholder="Комментарий" />
<Radio name="mode" label="Основной" />
<Checkbox label="Согласен с условиями" />Switch
<Switch label="Автообновления" defaultChecked />Select
<Select label="Окружение" options={[{ value: 'dev', label: 'Development' }]} />
<Select label="Сервисы" options={options} multiple searchable />Table
const columns = [
{ id: 'name', header: 'Название', accessor: 'name' },
{ id: 'amount', header: 'Сумма', accessor: 'amount', align: 'right', sortable: true },
];
<Table columns={columns} data={rows} />;<Table
columns={columns}
data={rows}
selection={{
selectedIds,
onToggle: (id) => setSelected((prev) => prev.includes(id) ? prev.filter((key) => key !== id) : [...prev, id]),
onToggleAll: (ids) => setSelected((prev) => ids.length > 0 && ids.every((id) => prev.includes(id)) ? [] : ids),
}}
renderBulkAction={(ids) => <span>Выбрано: {ids.length}</span>}
/>;FileUploader
<FileUploader
allowedTypes={['.jpg', '.png', '.pdf']}
maxFileSizeKb={2048}
multiple
showPreview
onUpload={(files) => api.upload(files)}
/>;Tooltip
<Tooltip content="Подсказка">
<Button>Наведи</Button>
</Tooltip>Grid / Flex
<Grid columns={12} columnsLg={8} columnsMd={4} columnsSm={1} gap="16px">
<div>One</div>
<div>Two</div>
<div>Three</div>
</Grid>
<Row gap="12px">
<div>A</div>
<div>B</div>
</Row>
<Stack gap="12px">
<div>Item</div>
<div>Item</div>
</Stack>Menu / Dropdown
const items = [
{ label: 'Главная', href: '/', active: true },
{ label: 'Документы', href: '#' },
{ divider: true },
{ label: 'Настройки', href: '#' },
];
<Menu items={items} />
<Menu items={items} orientation="horizontal" />
<Dropdown trigger={<span>Открыть</span>} orientation="vertical">
<Dropdown.Header>Профиль</Dropdown.Header>
<Dropdown.Item>Настройки</Dropdown.Item>
<Dropdown.Separator />
<Dropdown.Item href="/logout">Выход</Dropdown.Item>
</Dropdown>
// Dropdown внутри горизонтального меню
const topMenu = [
{ label: 'Главная', href: '/' },
{ label: 'Команда', children: [{ label: 'Участники' }, { label: 'Роли' }] },
];
<Menu items={topMenu} orientation="horizontal" />Dropdown по умолчанию рендерится через портал (portal={true}), чтобы не клиппиться контейнерами со скроллом.
Если нужно встроенное поведение, передайте portal={false}.
Collapsible Menu
const collapsible = [
{
label: 'Сервисы',
open: true,
children: [
{ label: 'Database' },
{ label: 'Cache' },
],
},
];
<Menu items={collapsible} />Badge
<Badge>Default</Badge>
<Badge variant="primary">Primary</Badge>
<Badge variant="info">Info</Badge>
<Badge variant="success">Success</Badge>
<Badge variant="warning">Warning</Badge>
<Badge variant="danger">Danger</Badge>Typography
<Heading level={2}>Заголовок</Heading>
<Text muted>Подпись</Text>
<Text code>npm run dev</Text>Alert
<Alert title="Info">Синхронизация завершится через 3 минуты.</Alert>
<Alert variant="danger" title="Ошибка" onClose={() => {}}>
Ошибка доступа к сервису хранения.
</Alert>Notifier
<Notifier items={items} onDismiss={(id) => remove(id)} />Card
<Card>
<Card.Header title="Заголовок" right={<Button appearance="ghost">...</Button>} />
<Card.Body>
Контент карточки
</Card.Body>
<Card.Footer>
<Button appearance="ghost">Отмена</Button>
<Button>Сохранить</Button>
</Card.Footer>
</Card>CollapseButton
<CollapseButton targetId="filters-panel" open={open} onClick={() => setOpen((prev) => !prev)}>
Фильтры
</CollapseButton>Breadcrumbs
<Breadcrumbs
items={[
{ label: 'Главная', href: '/' },
{ label: 'Проекты', href: '#' },
{ label: 'Project', current: true },
]}
/>Tabs
const items = [
{ id: 'overview', label: 'Обзор', content: 'Основная информация' },
{ id: 'metrics', label: 'Метрики', content: 'Показатели' },
];
<Tabs items={items} />Progress
<Progress value={72} label="Сборка" variant="primary" />
<Progress label="Синхронизация" indeterminate />Pagination
<Pagination meta={pagination.meta} links={pagination.links} onNavigate={(page) => setPage(page)} />Modal / Drawer
<Modal open={open} title="Новый релиз" onClose={() => setOpen(false)}>
Контент модалки
</Modal>
<Drawer open={open} title="Меню" onClose={() => setOpen(false)}>
Контент шторки
</Drawer>Базовые состояния
Button: hover, focus-visible, active, disabledInput: focus, error, placeholder, disabledMenu: hover, active, disabled, divider, keyboard arrows
