diff --git a/PROJECT.md b/PROJECT.md index 2527bdd..c882600 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -118,6 +118,23 @@ Tabs (из CategoryTabs), Breadcrumbs (новый), Sidebar (из SideNav), AppL Drawer(?). Сначала «расцепить» от роутинга портала → сделать controlled (items + activeId + onSelect), потом переносить. Даёт новым приложениям готовую оболочку. +### Миграция request-portal (в процессе) +- [СДЕЛАНО] Формы переведены на пакет через переключение barrel shared/ui/index.ts + (перенесённые компоненты реэкспортятся из @tnsu/ui-kit). FormMode объединён на пакетный. +- [СДЕЛАНО] Чистка: 12 прямых импортеров (SideNav, табы, Drawer, RequestGrid, пикеры, + unsavedChanges, RequestPortal→IconSprite, ItemsTable, SubmitActions) → @tnsu/ui-kit; + удалены 20 локальных папок-дублей. В shared/ui осталось: ItemsTable, PeopleField, + SubmitActions, ErrorOverlay, InitiatorLine (+useRequestSubmit, index). Heft собирается. +- [СДЕЛАНО] B: локальный components/SideNav заменён на пакетный Sidebar + SidebarToggle. + В RequestPortal: navItems (с counts), состояние mobileNavOpen, бургер в шапке main + (.mobileNav, виден < 768px). Shell CSS: убран старый перелом 900px; на < 768 .side + схлопывается (drawer position:fixed), main на всю ширину. SideNav удалён. Heft ок. + +### Badge (0.3.0) — паттерн «презентация в kit, смысл в проекте» +Generic Badge в kit (variant: neutral/muted/info/success/warning/danger/primary). Портальный +StatusBadge переписан в тонкий маппер REQUEST_STATUS→variant поверх Badge; StatusBadge.module.scss +удалён. Это шаблон для будущего разделения пикеров (group 3): вид в kit, привязка к данным в проекте. + ### Порядок работ 1. [СДЕЛАНО в 0.1.0] Быстрая пачка (20 компонентов): вся Группа 1 (кроме ErrorOverlay/ StatusBadge — оказались связаны с diagnostics/statuses, отложены) + ConfirmDialog/ diff --git a/package.json b/package.json index 16dd266..8d5af35 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tnsu/ui-kit", - "version": "0.2.0", + "version": "0.3.0", "description": "TNSU shared UI components for SPFx web parts", "author": "Timur Gorodetskiy", "license": "ISC", diff --git a/src/Badge/Badge.module.scss b/src/Badge/Badge.module.scss new file mode 100644 index 0000000..7e1a3d0 --- /dev/null +++ b/src/Badge/Badge.module.scss @@ -0,0 +1,29 @@ +@import '../tokens/tokens'; + +.badge { + display: inline-flex; + align-items: center; + padding: 5px 12px; + border-radius: $r-sm; + font-family: $font-sans; + font-size: 12.5px; + font-weight: 600; + letter-spacing: .2px; + white-space: nowrap; +} + +// Компактный вариант — для ячейки таблицы. +.sm { + padding: 3px 10px; + border-radius: $r-md; + font-size: $fs-caption; + letter-spacing: normal; +} + +.neutral { background: $gray-100; color: $gray-700; } +.muted { background: $gray-100; color: $gray-500; } +.info { background: $blue-50; color: $blue-600; } +.success { background: $green-50; color: $green-600; } +.warning { background: $gold-50; color: $amber-700; } +.danger { background: $red-50; color: $red-500; } +.primary { background: $navy-50; color: $navy-800; } diff --git a/src/Badge/Badge.stories.tsx b/src/Badge/Badge.stories.tsx new file mode 100644 index 0000000..c52549a --- /dev/null +++ b/src/Badge/Badge.stories.tsx @@ -0,0 +1,35 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { Badge } from './Badge'; + +const meta: Meta = { + title: 'Сообщения/Badge', + component: Badge, + tags: ['autodocs'], + argTypes: { + variant: { + control: 'select', + options: ['neutral', 'muted', 'info', 'success', 'warning', 'danger', 'primary'] + }, + size: { control: 'radio', options: ['sm', 'md'] } + }, + args: { variant: 'info', size: 'md', children: 'На согласовании' } +}; + +export default meta; +type Story = StoryObj; + +export const Info: Story = {}; + +export const AllVariants: Story = { + render: () => ( +
+ Черновик + В очереди + На согласовании + Согласовано + Возвращена + Отклонена + На исполнении +
+ ) +}; diff --git a/src/Badge/Badge.tsx b/src/Badge/Badge.tsx new file mode 100644 index 0000000..e8bb8e4 --- /dev/null +++ b/src/Badge/Badge.tsx @@ -0,0 +1,30 @@ +import * as React from 'react'; +import styles from './Badge.module.scss'; + +export type BadgeVariant = 'neutral' | 'muted' | 'info' | 'success' | 'warning' | 'danger' | 'primary'; + +export interface IBadgeProps { + /** Цвет плашки. Смысл (статус заявки и т.п.) назначает проект. */ + variant?: BadgeVariant; + /** 'md' (по умолчанию) — обычный; 'sm' — компактный (для ячейки таблицы). */ + size?: 'sm' | 'md'; + children: React.ReactNode; +} + +const variantClass: Record = { + neutral: styles.neutral, + muted: styles.muted, + info: styles.info, + success: styles.success, + warning: styles.warning, + danger: styles.danger, + primary: styles.primary +}; + +/** Цветная плашка-бейдж. Цвет — через variant; что он означает, решает проект. */ +export const Badge: React.FC = ({ variant = 'neutral', size = 'md', children }) => { + const classes = [styles.badge, size === 'sm' ? styles.sm : '', variantClass[variant]] + .filter(Boolean) + .join(' '); + return {children}; +}; diff --git a/src/index.ts b/src/index.ts index e93a5a5..6d4ca61 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,8 @@ export { PrintButton } from './PrintButton/PrintButton'; // --- Сообщения / плашки --- export { Alert } from './Alert/Alert'; export { RequestNumber } from './RequestNumber/RequestNumber'; +export { Badge } from './Badge/Badge'; +export type { IBadgeProps, BadgeVariant } from './Badge/Badge'; // --- Оболочка и раскладка формы --- export { FormCard } from './FormCard/FormCard';