1
0
forked from baron/baron-sso

feat: apply sticky header and inner scroll pattern to all table pages

This commit is contained in:
2026-03-19 13:13:27 +09:00
parent 83991b13ca
commit f072d37362
9 changed files with 1007 additions and 944 deletions

View File

@@ -42,8 +42,8 @@ function TenantUsersPage() {
const users = usersQuery.data?.items ?? [];
return (
<Card className="mt-6 bg-[var(--color-panel)]">
<CardHeader>
<Card className="mt-6 bg-[var(--color-panel)] flex-1 flex flex-col min-h-0 overflow-hidden">
<CardHeader className="flex-shrink-0">
<CardTitle className="flex items-center gap-2">
<User size={18} className="text-primary" />
{t("ui.admin.tenants.members.title", "Tenant Members ({{count}})", {
@@ -51,66 +51,70 @@ function TenantUsersPage() {
})}
</CardTitle>
</CardHeader>
<CardContent>
<Table>
<TableHeader>
<TableRow>
<TableHead>
{t("ui.admin.tenants.members.table.name", "NAME")}
</TableHead>
<TableHead>
{t("ui.admin.tenants.members.table.email", "EMAIL")}
</TableHead>
<TableHead>
{t("ui.admin.tenants.members.table.role", "ROLE")}
</TableHead>
<TableHead>
{t("ui.admin.tenants.members.table.status", "STATUS")}
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{users.length === 0 && (
<TableRow>
<TableCell
colSpan={4}
className="text-center py-8 text-muted-foreground"
>
{t(
"msg.admin.tenants.members.empty",
"소속된 사용자가 없습니다.",
)}
</TableCell>
</TableRow>
)}
{users.map((user) => (
<TableRow key={user.id}>
<TableCell className="font-semibold">{user.name}</TableCell>
<TableCell>
<div className="flex items-center gap-1 text-xs">
<Mail size={12} className="text-muted-foreground" />
{user.email}
</div>
</TableCell>
<TableCell>
<Badge variant="outline" className="capitalize">
{t(
`ui.common.role.${user.role}`,
user.role.replace("_", " "),
)}
</Badge>
</TableCell>
<TableCell>
<Badge
variant={user.status === "active" ? "default" : "muted"}
>
{t(`ui.common.status.${user.status}`, user.status)}
</Badge>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
<CardContent className="flex-1 flex flex-col min-h-0 pt-0">
<div className="flex-1 rounded-md border overflow-hidden flex flex-col">
<div className="flex-1 overflow-auto relative custom-scrollbar">
<Table>
<TableHeader className="sticky top-0 bg-muted/90 backdrop-blur z-10 shadow-sm">
<TableRow>
<TableHead>
{t("ui.admin.tenants.members.table.name", "NAME")}
</TableHead>
<TableHead>
{t("ui.admin.tenants.members.table.email", "EMAIL")}
</TableHead>
<TableHead>
{t("ui.admin.tenants.members.table.role", "ROLE")}
</TableHead>
<TableHead>
{t("ui.admin.tenants.members.table.status", "STATUS")}
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{users.length === 0 && (
<TableRow>
<TableCell
colSpan={4}
className="text-center py-8 text-muted-foreground"
>
{t(
"msg.admin.tenants.members.empty",
"소속된 사용자가 없습니다.",
)}
</TableCell>
</TableRow>
)}
{users.map((user) => (
<TableRow key={user.id}>
<TableCell className="font-semibold">{user.name}</TableCell>
<TableCell>
<div className="flex items-center gap-1 text-xs">
<Mail size={12} className="text-muted-foreground" />
{user.email}
</div>
</TableCell>
<TableCell>
<Badge variant="outline" className="capitalize">
{t(
`ui.common.role.${user.role}`,
user.role.replace("_", " "),
)}
</Badge>
</TableCell>
<TableCell>
<Badge
variant={user.status === "active" ? "default" : "muted"}
>
{t(`ui.common.status.${user.status}`, user.status)}
</Badge>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</div>
</CardContent>
</Card>
);