From 6bced710373b52e8682670b1c811f39b0d360ff5 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Wed, 19 Aug 2026 22:37:54 +0700 Subject: [PATCH] feat(ui): refactor ServiceIpList and ServiceUnitCard components for improved layout and functionality - Replaced div elements with Item components in ServiceIpList for better alignment and structure. - Introduced alignWithMenu prop to align IP Switch with the card menu. - Updated ServiceUnitCard to utilize Item components, enhancing the visual consistency and responsiveness of the service card layout. - Improved overall user experience by streamlining component structure and ensuring proper alignment of UI elements. --- .../components/services/service-fqdn-list.tsx | 105 +++++++++----- .../components/services/service-unit-card.tsx | 134 ++++++++++-------- 2 files changed, 143 insertions(+), 96 deletions(-) diff --git a/apps/web/src/components/services/service-fqdn-list.tsx b/apps/web/src/components/services/service-fqdn-list.tsx index dba74f2..bd8f536 100644 --- a/apps/web/src/components/services/service-fqdn-list.tsx +++ b/apps/web/src/components/services/service-fqdn-list.tsx @@ -8,6 +8,13 @@ import { useCopyToClipboard } from '@/hooks/use-copy-to-clipboard' import { serviceDisplayFqdns } from '@/lib/service-utils' import type { ServiceView } from '@/lib/schemas' import { Button } from '@cfdm/ui/components/button' +import { + Item, + ItemActions, + ItemContent, + ItemGroup, + ItemMedia, +} from '@cfdm/ui/components/item' import { Switch } from '@cfdm/ui/components/switch' import { Tooltip, @@ -17,6 +24,9 @@ import { } from '@cfdm/ui/components/tooltip' import { cn } from '@cfdm/ui/lib/utils' +/** Matches `Button size="icon-sm"` so Switch columns align with the card menu. */ +const MENU_SLOT_CLASS = 'size-7 shrink-0' + export function CopyFqdnButton({ value, className, @@ -126,6 +136,8 @@ interface ServiceIpListProps { togglingIp?: string | null ipToggleDisabled?: boolean onToggleIp?: (ip: string, enabled: boolean) => void + /** Invisible icon-sm slot so IP Switch lines up with the card overflow menu. */ + alignWithMenu?: boolean className?: string emptyLabel?: string copyable?: boolean @@ -139,6 +151,7 @@ export function ServiceIpList({ togglingIp = null, ipToggleDisabled = false, onToggleIp, + alignWithMenu = false, className, emptyLabel = 'Нет IP', copyable = false, @@ -155,49 +168,69 @@ export function ServiceIpList({ const healthByIp = new Map(ipHealth.map((row) => [row.ip, row])) const visible = onToggleIp ? ips : ips.slice(0, VISIBLE_IP_LIMIT) const extraCount = ips.length - visible.length + const showMenuSlot = Boolean(onToggleIp && alignWithMenu) return ( -
+ {visible.map((ip) => { const health = healthByIp.get(ip) const enabled = ipEnabled[ip] !== false return ( -
- - - {ip} - - {copyable ? : null} - {onToggleIp ? ( - { - event.stopPropagation() - }} - onCheckedChange={(checked) => onToggleIp(ip, Boolean(checked))} - aria-label={ - enabled ? `Выключить IP ${ip}` : `Включить IP ${ip}` - } + + + + + +
+ + {ip} + + {copyable ? : null} +
+
+ {onToggleIp ? ( + + { + event.stopPropagation() + }} + onCheckedChange={(checked) => + onToggleIp(ip, Boolean(checked)) + } + aria-label={ + enabled ? `Выключить IP ${ip}` : `Включить IP ${ip}` + } + /> + {showMenuSlot ? ( + ) : null} -
+ ) })} {extraCount > 0 ? ( @@ -224,6 +257,6 @@ export function ServiceIpList({ ) : null} -
+ ) } diff --git a/apps/web/src/components/services/service-unit-card.tsx b/apps/web/src/components/services/service-unit-card.tsx index 68f7481..74c7911 100644 --- a/apps/web/src/components/services/service-unit-card.tsx +++ b/apps/web/src/components/services/service-unit-card.tsx @@ -5,7 +5,6 @@ import { Badge } from '@/components/reui/badge' import { Frame, FrameDescription, - FrameHeader, FramePanel, FrameTitle, } from '@/components/reui/frame' @@ -23,6 +22,12 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '@cfdm/ui/components/dropdown-menu' +import { + Item, + ItemActions, + ItemContent, + ItemMedia, +} from '@cfdm/ui/components/item' import { Switch } from '@cfdm/ui/components/switch' import { Tooltip, @@ -31,6 +36,12 @@ import { TooltipTrigger, } from '@cfdm/ui/components/tooltip' +/** + * Compact service card — settings-8 DNA (Badge + copy + Switch + menu). + * Preview: https://reui.io/preview/base/settings-8 + * Frame: https://reui.io/docs/components/base/frame + * IconTile: https://reui.io/docs/components/base/icon-tile + */ interface ServiceUnitCardProps { service: ServiceView togglingId: number | null @@ -55,18 +66,20 @@ export function ServiceUnitCard({ const extraCount = Math.max(0, fqdns.length - 1) return ( - - -
- -
+ + + + + + + ) : null}
-
- -
- - onToggleService(service.id, Boolean(checked)) - } - aria-label={ - service.enabled ? 'Выключить сервис' : 'Включить сервис' - } - /> - - + + + + onToggleService(service.id, Boolean(checked)) } - > - - - - + + } > - Обзор - - onEditService(service)}> - Изменить - - onDeleteService(service)} - > - Удалить - - - -
-
+ + + + + } + > + Обзор + + onEditService(service)}> + Изменить + + onDeleteService(service)} + > + Удалить + + + + + + - +