Refactor data table components for improved layout and functionality
Publish telemt-api gateway Docker image / test (push) Successful in 27s
Publish telemt-api gateway Docker image / build-and-push (push) Successful in 2m22s

- Made the `title` prop optional in `DataTableCard`, allowing for more flexible usage without a title.
- Updated the rendering logic in `DataTableCard` to conditionally display the title and description.
- Enhanced the styling of table headers across various pages for a more consistent appearance, removing unnecessary backdrop blur effects.
- Replaced button elements with native button tags in `SortableTh` for better accessibility and semantic HTML.
This commit is contained in:
Denozordec
2026-03-31 19:07:04 +07:00
parent 8e616cd1c4
commit 9533241624
7 changed files with 46 additions and 37 deletions
@@ -10,7 +10,8 @@
toolbar,
children
}: {
title: string;
/** Без title — как в shadcn dashboard-01: сразу toolbar и таблица */
title?: string;
description?: string;
toolbar?: Snippet;
children: Snippet;
@@ -19,12 +20,14 @@
</script>
<Card.Root class={cn('overflow-hidden rounded-lg border border-border shadow-sm', className)}>
<div class="border-b border-border bg-muted/40 px-4 py-3">
<Card.Title class="text-base font-semibold">{title}</Card.Title>
{#if description}
<Card.Description class="text-xs sm:text-sm">{description}</Card.Description>
{/if}
</div>
{#if title}
<div class="border-b border-border bg-muted/40 px-4 py-3">
<Card.Title class="text-base font-semibold">{title}</Card.Title>
{#if description}
<Card.Description class="text-xs sm:text-sm">{description}</Card.Description>
{/if}
</div>
{/if}
{#if toolbar}
{@render toolbar()}
{/if}
@@ -1,6 +1,5 @@
<script lang="ts">
import * as Table from '$lib/components/ui/table/index.js';
import { Button } from '$lib/components/ui/button/index.js';
import { cn } from '$lib/utils.js';
import ArrowUpDownIcon from '@lucide/svelte/icons/arrow-up-down';
import ArrowUpIcon from '@lucide/svelte/icons/arrow-up';
@@ -25,23 +24,31 @@
} = $props();
</script>
<Table.Head class={cn(numeric && 'text-right', className)}>
<Button
variant="ghost"
size="sm"
<Table.Head
class={cn(
'px-3 py-2 text-left align-middle text-sm font-medium text-foreground',
numeric && 'text-right',
className
)}
>
<button
type="button"
class={cn(
'-ml-2 h-8 gap-1 px-2 font-medium text-muted-foreground hover:text-foreground',
'inline-flex max-w-full items-center gap-1.5 rounded-md',
'text-foreground/90 transition-colors',
'hover:bg-accent/60 hover:text-foreground',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/45',
numeric && 'ms-auto'
)}
onclick={onToggle}
>
{@render children()}
{#if active && dir === 'asc'}
<ArrowUpIcon class="size-3.5 opacity-70" aria-hidden="true" />
<ArrowUpIcon class="size-3 shrink-0 opacity-70" aria-hidden="true" />
{:else if active && dir === 'desc'}
<ArrowDownIcon class="size-3.5 opacity-70" aria-hidden="true" />
<ArrowDownIcon class="size-3 shrink-0 opacity-70" aria-hidden="true" />
{:else}
<ArrowUpDownIcon class="size-3.5 opacity-50" aria-hidden="true" />
<ArrowUpDownIcon class="size-3 shrink-0 opacity-40" aria-hidden="true" />
{/if}
</Button>
</button>
</Table.Head>
+6 -6
View File
@@ -666,8 +666,8 @@
{/snippet}
<ScrollArea class="max-h-[min(70vh,520px)] w-full" orientation="both">
<Table.Root>
<Table.Header class="sticky top-0 z-10 bg-muted/95 backdrop-blur-sm">
<Table.Row>
<Table.Header class="sticky top-0 z-10 bg-muted">
<Table.Row class="border-b border-border/80 hover:bg-transparent">
<SortableTh
active={ipSortKey === 'ip'}
dir={ipSortDir}
@@ -819,8 +819,8 @@
{/snippet}
<ScrollArea class="max-h-[min(70vh,480px)] w-full" orientation="both">
<Table.Root>
<Table.Header class="sticky top-0 z-10 bg-muted/95 backdrop-blur-sm">
<Table.Row>
<Table.Header class="sticky top-0 z-10 bg-muted">
<Table.Row class="border-b border-border/80 hover:bg-transparent">
<SortableTh
active={nodeSortKey === 'alias'}
dir={nodeSortDir}
@@ -953,8 +953,8 @@
{/snippet}
<ScrollArea class="max-h-[min(60vh,400px)] w-full" orientation="vertical">
<Table.Root>
<Table.Header class="sticky top-0 z-10 bg-muted/95 backdrop-blur-sm">
<Table.Row>
<Table.Header class="sticky top-0 z-10 bg-muted">
<Table.Row class="border-b border-border/80 hover:bg-transparent">
<SortableTh
active={topSortKey === 'user'}
dir={topSortDir}
+2 -2
View File
@@ -378,8 +378,8 @@
{/snippet}
<ScrollArea class="max-h-[min(75vh,640px)] w-full" orientation="both">
<Table.Root>
<Table.Header class="sticky top-0 z-10 bg-muted/95 backdrop-blur-sm">
<Table.Row>
<Table.Header class="sticky top-0 z-10 bg-muted">
<Table.Row class="border-b border-border/80 hover:bg-transparent">
<SortableTh
active={incSortKey === 'sev'}
dir={incSortDir}
+2 -2
View File
@@ -610,8 +610,8 @@
{/snippet}
<ScrollArea class="max-h-[min(75vh,560px)] w-full" orientation="both">
<Table.Root>
<Table.Header class="sticky top-0 z-10 bg-muted/95 backdrop-blur-sm">
<Table.Row>
<Table.Header class="sticky top-0 z-10 bg-muted">
<Table.Row class="border-b border-border/80 hover:bg-transparent">
<SortableTh
active={ipSortKey === 'user'}
dir={ipSortDir}
+2 -2
View File
@@ -404,8 +404,8 @@
{/snippet}
<ScrollArea class="max-h-[min(70vh,520px)] w-full" orientation="both">
<Table.Root>
<Table.Header class="sticky top-0 z-10 bg-muted/95 backdrop-blur-sm">
<Table.Row>
<Table.Header class="sticky top-0 z-10 bg-muted">
<Table.Row class="border-b border-border/80 hover:bg-transparent">
<SortableTh
active={liveSortKey === 'sev'}
dir={liveSortDir}
+7 -8
View File
@@ -389,10 +389,7 @@
</Card.Root>
{/snippet}
{#snippet children()}
<DataTableCard
title="Список пользователей"
description="Слияние по имени между серверами; клик по строке — карточка пользователя"
>
<DataTableCard>
{#snippet toolbar()}
<div class="border-b border-border">
<div
@@ -467,8 +464,8 @@
{/snippet}
<ScrollArea class="max-h-[min(70vh,560px)] w-full" orientation="both">
<Table.Root>
<Table.Header class="sticky top-0 z-10 border-b border-border bg-muted/95 backdrop-blur-sm">
<Table.Row class="border-0 hover:bg-transparent">
<Table.Header class="sticky top-0 z-10 bg-muted">
<Table.Row class="border-b border-border/80 hover:bg-transparent">
<Table.Head class="w-10 px-2">
{#if pageUsernames.length > 0}
<Checkbox
@@ -487,7 +484,7 @@
>Имя</SortableTh>
<Table.Head
class={cn(
'text-muted-foreground text-xs font-medium uppercase tracking-wide',
'px-3 py-2 text-left align-middle text-sm font-medium text-foreground',
!showColLinks && 'hidden',
showColLinks && 'hidden sm:table-cell'
)}
@@ -515,7 +512,9 @@
showColExpires && 'hidden sm:table-cell'
)}
>Истекает</SortableTh>
<Table.Head class="w-12 px-2 text-right" aria-hidden="true"></Table.Head>
<Table.Head class="w-12 px-2 text-right">
<span class="sr-only">Действия</span>
</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>