Files
EvoBGP/apps/web/src/components/segmented-tabs.tsx
T
DenozordecandClaude Sonnet 5.5 aba18e15b7
quality / changes (push) Successful in 9s
quality / go (push) Skipped
quality / bird2 (push) Skipped
quality / commitlint (push) Skipped
quality / docker-check (push) Skipped
quality / openapi (push) Successful in 23s
quality / web (push) Successful in 1m22s
CD / quality (push) Successful in 1m57s
CD / publish (push) Successful in 3m31s
feat(web): pages and tables as on shared mockup boards
ResourcePage и FrameDataGrid получили раскладку досок: заголовок Frame с поиском и фильтрами, линейные виды со счётчиками, подвал «Показано N из M». Страница модулей — KPI-полоса, кнопка создания в шапке, вкладка. Операции: действия применения и перезагрузки BIRD в шапке, баннер при ошибках задач. Сеть: баннер пиров на одобрение. Кнопки шапок — стандартной высоты.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-23 21:59:12 +07:00

66 lines
1.8 KiB
TypeScript

import type { ReactNode } from 'react'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@evobgp/ui/components/tabs'
import { cn } from '@evobgp/ui/lib/utils'
export type SegmentedTabItem = {
value: string
label: string
count?: number
/** @deprecated Счётчик теперь без плашки (линейные вкладки макета). */
badgeVariant?: string
icon?: ReactNode
}
interface SegmentedTabsProps {
items: SegmentedTabItem[]
value?: string
defaultValue?: string
onValueChange?: (value: string) => void
children: ReactNode
className?: string
listClassName?: string
contentClassName?: string
}
/**
* Page-level section switcher — line tabs as on the shared mockup boards.
* @see https://reui.io/preview/base/components/c-tabs-9
* @see https://reui.io/components/tabs
*/
export function SegmentedTabs({
items,
value,
defaultValue,
onValueChange,
children,
className,
listClassName,
contentClassName,
}: SegmentedTabsProps) {
return (
<Tabs
value={value}
defaultValue={defaultValue}
onValueChange={onValueChange}
orientation="horizontal"
className={cn('w-full min-w-0 gap-4', className)}
>
<TabsList variant="line" className={cn('h-10! w-full min-w-0 justify-start gap-0.5 overflow-x-auto [scrollbar-width:none]', listClassName)}>
{items.map((item) => (
<TabsTrigger key={item.value} value={item.value} className="flex-none shrink-0 gap-1.5 px-4 text-sm">
{item.icon}
{item.label}
{item.count !== undefined ? (
<span className="text-muted-foreground font-mono text-xs font-normal">{item.count}</span>
) : null}
</TabsTrigger>
))}
</TabsList>
<div className={cn('w-full min-w-0', contentClassName)}>{children}</div>
</Tabs>
)
}
export { TabsContent }