fix(design-preview): переключатели вида и периода на компоненте Tabs

Кнопки с aria-pressed выглядели криво в тёмной теме; заменены на общий Segmented.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
DenozordecandClaude Sonnet 5.5 committed 2026-10-17 22:10:01 +07:00
1 parent 157396613d
commit 0be272f917
4 files changed
+40 -54

No files matched your search

+26
View File
@@ -22,6 +22,7 @@ import {
import { Button } from '@authportal/ui/components/button'
import { Input } from '@authportal/ui/components/input'
import { Label } from '@authportal/ui/components/label'
import { Tabs, TabsList, TabsTrigger } from '@authportal/ui/components/tabs'
import {
Sheet,
SheetClose,
@@ -367,3 +368,28 @@ export function CodeBlock({ label, children }: { label: string; children: string
</div>
)
}
/** Сегментированный переключатель на Tabs (вид таблицы, период). */
export function Segmented({
label,
options,
value,
onChange,
}: {
label: string
options: string[]
value: number
onChange: (index: number) => void
}) {
return (
<Tabs value={String(value)} onValueChange={(v) => onChange(Number(v))} aria-label={label} className="max-w-full">
<TabsList className="max-w-full justify-start overflow-x-auto">
{options.map((o, i) => (
<TabsTrigger key={o} value={String(i)}>
{o}
</TabsTrigger>
))}
</TabsList>
</Tabs>
)
}
@@ -7,7 +7,7 @@ import { AuditRetentionPanel } from '@/components/reui-kit/audit-retention-panel
import { KpiStatGrid } from '@/components/reui-kit/kpi-stat-grid'
import { Button } from '@authportal/ui/components/button'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@authportal/ui/components/tabs'
import { CodeBlock, KvList, PageHead, PreviewSheet, StatesFrame, StatusBadge, TypedConfirm } from '../bits'
import { Segmented, CodeBlock, KvList, PageHead, PreviewSheet, StatesFrame, StatusBadge, TypedConfirm } from '../bits'
import { MOCK_AUDIT, APP_SHORT, type Tone } from '../mock'
import { PreviewSectionGrid, TwoLineCell, type GridColumn } from '../section-grid'
@@ -85,21 +85,7 @@ export function AuditPage() {
</>
}
/>
<div role="group" aria-label="Период" className="bg-muted/60 flex w-fit max-w-full flex-wrap gap-0.5 rounded-lg p-0.5">
{['24 ч', '7 д', '30 д', '90 д', 'Весь период'].map((p, i) => (
<Button
key={p}
type="button"
size="xs"
variant="ghost"
aria-pressed={i === period}
onClick={() => setPeriod(i)}
className={i === period ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'}
>
{p}
</Button>
))}
</div>
<Segmented label="Период" options={['24 ч', '7 д', '30 д', '90 д', 'Весь период']} value={period} onChange={setPeriod} />
<KpiStatGrid
aria-label="Показатели"
items={[
@@ -5,7 +5,7 @@ import { toast } from 'sonner'
import { KpiStatGrid } from '@/components/reui-kit/kpi-stat-grid'
import { Button } from '@authportal/ui/components/button'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@authportal/ui/components/tabs'
import { CodeBlock, KvList, PageHead, PreviewSheet, SignalAlert, StatesFrame, StatusBadge } from '../bits'
import { Segmented, CodeBlock, KvList, PageHead, PreviewSheet, SignalAlert, StatesFrame, StatusBadge } from '../bits'
import { MOCK_LOGINS, MOCK_SESSIONS, type LoginRow, type SessionRow } from '../mock'
import { PreviewSectionGrid, TwoLineCell, type GridColumn } from '../section-grid'
@@ -83,21 +83,7 @@ export function LoginsPage() {
>
6 неудачных входов с 203.0.113.58 за 10 минут. При необходимости отключите учётную запись в разделе «Пользователи».
</SignalAlert>
<div role="group" aria-label="Период" className="bg-muted/60 flex w-fit max-w-full flex-wrap gap-0.5 rounded-lg p-0.5">
{PERIODS.map((p, i) => (
<Button
key={p}
type="button"
size="xs"
variant="ghost"
aria-pressed={i === period}
onClick={() => setPeriod(i)}
className={i === period ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'}
>
{p}
</Button>
))}
</div>
<Segmented label="Период" options={PERIODS} value={period} onChange={setPeriod} />
<KpiStatGrid
aria-label="Показатели"
items={[
+10 -22
View File
@@ -30,6 +30,7 @@ import { Button } from '@authportal/ui/components/button'
import { Separator } from '@authportal/ui/components/separator'
import { InputGroup, InputGroupAddon, InputGroupInput } from '@authportal/ui/components/input-group'
import { cn } from '@authportal/ui/lib/utils'
import { Segmented } from './bits'
export type GridColumn<T> = {
id: string
@@ -167,28 +168,15 @@ export function PreviewSectionGrid<T extends object>({
<div className="flex flex-wrap items-center justify-between gap-2 px-(--frame-panel-header-px) py-(--frame-panel-header-py)">
<div className="flex min-w-0 flex-wrap items-center gap-2">
{views ? (
<div role="group" aria-label="Вид" className="bg-muted/60 inline-flex flex-wrap gap-0.5 rounded-lg p-0.5">
{views.map((v, i) => (
<Button
key={v.label}
type="button"
size="xs"
variant="ghost"
aria-pressed={i === view}
onClick={() => {
setView(i)
setPagination((p) => ({ ...p, pageIndex: 0 }))
}}
className={cn(
i === view
? 'bg-background text-foreground shadow-sm'
: 'text-muted-foreground hover:text-foreground',
)}
>
{v.label}
</Button>
))}
</div>
<Segmented
label="Вид"
options={views.map((v) => v.label)}
value={view}
onChange={(i) => {
setView(i)
setPagination((p) => ({ ...p, pageIndex: 0 }))
}}
/>
) : null}
{searchText ? (
<InputGroup className="w-56 max-w-full">