1
0
forked from baron/baron-sso

feat: implement sticky header and inner scrolling for user list page

This commit is contained in:
2026-03-19 12:57:00 +09:00
parent 4d11d3e554
commit 83991b13ca

View File

@@ -254,8 +254,8 @@ function UserListPage() {
}; };
return ( return (
<div className="space-y-8"> <div className="space-y-6 flex flex-col h-[calc(100vh-theme(spacing.32))]">
<header className="flex flex-wrap items-start justify-between gap-4"> <header className="flex flex-wrap items-start justify-between gap-4 flex-shrink-0">
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center gap-2 text-sm text-[var(--color-muted)]"> <div className="flex items-center gap-2 text-sm text-[var(--color-muted)]">
<span>{t("ui.admin.users.list.breadcrumb.section", "Users")}</span> <span>{t("ui.admin.users.list.breadcrumb.section", "Users")}</span>
@@ -353,8 +353,8 @@ function UserListPage() {
</div> </div>
</header> </header>
<Card className="bg-[var(--color-panel)]"> <Card className="flex-1 flex flex-col min-h-0 bg-[var(--color-panel)] overflow-hidden">
<CardHeader className="flex flex-row items-center justify-between"> <CardHeader className="flex flex-row items-center justify-between flex-shrink-0">
<div> <div>
<CardTitle> <CardTitle>
{t("ui.admin.users.list.registry.title", "User Registry")} {t("ui.admin.users.list.registry.title", "User Registry")}
@@ -368,8 +368,8 @@ function UserListPage() {
</CardDescription> </CardDescription>
</div> </div>
</CardHeader> </CardHeader>
<CardContent> <CardContent className="flex-1 flex flex-col min-h-0 pt-0">
<div className="mb-6 flex flex-wrap items-center gap-4"> <div className="mb-6 flex flex-wrap items-center gap-4 flex-shrink-0">
<div className="relative flex-1 min-w-[240px] max-w-sm"> <div className="relative flex-1 min-w-[240px] max-w-sm">
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" /> <Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
<Input <Input
@@ -412,14 +412,15 @@ function UserListPage() {
</div> </div>
{(errorMsg || fallbackError) && ( {(errorMsg || fallbackError) && (
<div className="mb-4 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive"> <div className="mb-4 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive flex-shrink-0">
{errorMsg ?? fallbackError} {errorMsg ?? fallbackError}
</div> </div>
)} )}
<div className="rounded-md border overflow-x-auto"> <div className="flex-1 rounded-md border overflow-hidden flex flex-col">
<div className="flex-1 overflow-auto relative custom-scrollbar">
<Table> <Table>
<TableHeader> <TableHeader className="sticky top-0 bg-muted/90 backdrop-blur z-10 shadow-sm">
<TableRow> <TableRow>
<TableHead className="w-12"> <TableHead className="w-12">
<input <input
@@ -433,7 +434,10 @@ function UserListPage() {
/> />
</TableHead> </TableHead>
<TableHead className="min-w-[200px]"> <TableHead className="min-w-[200px]">
{t("ui.admin.users.list.table.name_email", "NAME / EMAIL")} {t(
"ui.admin.users.list.table.name_email",
"NAME / EMAIL",
)}
</TableHead> </TableHead>
<TableHead> <TableHead>
{t("ui.admin.users.list.table.role", "ROLE")} {t("ui.admin.users.list.table.role", "ROLE")}
@@ -468,7 +472,7 @@ function UserListPage() {
{query.isLoading && ( {query.isLoading && (
<TableRow> <TableRow>
<TableCell <TableCell
colSpan={6 + userSchema.length} colSpan={7 + userSchema.length}
className="h-24 text-center" className="h-24 text-center"
> >
{t("msg.common.loading", "로딩 중...")} {t("msg.common.loading", "로딩 중...")}
@@ -478,10 +482,13 @@ function UserListPage() {
{!query.isLoading && items.length === 0 && ( {!query.isLoading && items.length === 0 && (
<TableRow> <TableRow>
<TableCell <TableCell
colSpan={6 + userSchema.length} colSpan={7 + userSchema.length}
className="h-24 text-center" className="h-24 text-center"
> >
{t("msg.admin.users.list.empty", "검색 결과가 없습니다.")} {t(
"msg.admin.users.list.empty",
"검색 결과가 없습니다.",
)}
</TableCell> </TableCell>
</TableRow> </TableRow>
)} )}
@@ -574,6 +581,7 @@ function UserListPage() {
</TableBody> </TableBody>
</Table> </Table>
</div> </div>
</div>
{/* Bulk Action Bar */} {/* Bulk Action Bar */}
{selectedUserIds.length > 0 && ( {selectedUserIds.length > 0 && (
@@ -639,7 +647,7 @@ function UserListPage() {
{/* Pagination */} {/* Pagination */}
{totalPages > 1 && ( {totalPages > 1 && (
<div className="mt-4 flex items-center justify-end gap-2"> <div className="mt-4 flex flex-shrink-0 items-center justify-end gap-2">
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"