diff --git a/ui/components/invitations/table/skeleton-table-invitations.tsx b/ui/components/invitations/table/skeleton-table-invitations.tsx index 1117358e32..2533655a1d 100644 --- a/ui/components/invitations/table/skeleton-table-invitations.tsx +++ b/ui/components/invitations/table/skeleton-table-invitations.tsx @@ -1,37 +1,102 @@ -import React from "react"; - -import { Card } from "@/components/shadcn/card/card"; import { Skeleton } from "@/components/shadcn/skeleton/skeleton"; -export const SkeletonTableInvitation = () => { +const SkeletonTableRow = () => { return ( - - {/* Table headers */} -
- - - - - - -
- - {/* Table body */} -
- {[...Array(10)].map((_, index) => ( -
- - - - - - -
- ))} -
-
+ + {/* Email */} + + + + {/* State - text */} + + + + {/* Role - text */} + + + + {/* Inserted At - date */} + + + + {/* Expires At - date */} + + + + {/* Actions */} + + + + + ); +}; + +export const SkeletonTableInvitation = () => { + const rows = 10; + + return ( +
+ {/* Toolbar: Search + Total entries */} +
+ {/* Search icon button */} + + {/* Total entries */} + +
+ + {/* Table */} + + + + {/* Email */} + + {/* State */} + + {/* Role */} + + {/* Inserted At */} + + {/* Expires At */} + + {/* Actions - empty header */} + + + + {Array.from({ length: rows }).map((_, i) => ( + + ))} + +
+ + + + + + + + + + +
+ + {/* Pagination */} +
+ {/* Rows per page */} +
+ + +
+ {/* Page info + navigation */} +
+ +
+ + + + +
+
+
+
); }; diff --git a/ui/components/manage-groups/table/skeleton-table-groups.tsx b/ui/components/manage-groups/table/skeleton-table-groups.tsx index 03c817b9d1..1da8eba819 100644 --- a/ui/components/manage-groups/table/skeleton-table-groups.tsx +++ b/ui/components/manage-groups/table/skeleton-table-groups.tsx @@ -1,39 +1,94 @@ -import React from "react"; - -import { Card } from "@/components/shadcn/card/card"; import { Skeleton } from "@/components/shadcn/skeleton/skeleton"; -export const SkeletonTableGroups = () => { +const SkeletonTableRow = () => { return ( - - {/* Table headers */} -
- - - - - - - -
- - {/* Table body */} -
- {[...Array(3)].map((_, index) => ( -
- - - - - - - -
- ))} -
-
+ + {/* Name - text */} + + + + {/* Providers - count in circle */} + + + + {/* Roles - count in circle */} + + + + {/* Added - date */} + + + + {/* Actions */} + + + + + ); +}; + +export const SkeletonTableGroups = () => { + const rows = 10; + + return ( +
+ {/* Toolbar: Search + Total entries */} +
+ {/* Search icon button */} + + {/* Total entries */} + +
+ + {/* Table */} + + + + {/* Name */} + + {/* Providers */} + + {/* Roles */} + + {/* Added */} + + {/* Actions - empty header */} + + + + {Array.from({ length: rows }).map((_, i) => ( + + ))} + +
+ + + + + + + + +
+ + {/* Pagination */} +
+ {/* Rows per page */} +
+ + +
+ {/* Page info + navigation */} +
+ +
+ + + + +
+
+
+
); }; diff --git a/ui/components/roles/table/skeleton-table-roles.tsx b/ui/components/roles/table/skeleton-table-roles.tsx index 15372fdc91..1bc62af5fb 100644 --- a/ui/components/roles/table/skeleton-table-roles.tsx +++ b/ui/components/roles/table/skeleton-table-roles.tsx @@ -1,37 +1,102 @@ -import React from "react"; - -import { Card } from "@/components/shadcn/card/card"; import { Skeleton } from "@/components/shadcn/skeleton/skeleton"; -export const SkeletonTableRoles = () => { +const SkeletonTableRow = () => { return ( - - {/* Table headers */} -
- - - - - - -
- - {/* Table body */} -
- {[...Array(10)].map((_, index) => ( -
- - - - - - -
- ))} -
-
+ + {/* Role - bold name text */} + + + + {/* Users - count text */} + + + + {/* Invitations - count text */} + + + + {/* Permissions - state text */} + + + + {/* Added - date */} + + + + {/* Actions */} + + + + + ); +}; + +export const SkeletonTableRoles = () => { + const rows = 10; + + return ( +
+ {/* Toolbar: Search + Total entries */} +
+ {/* Search icon button */} + {/* */} + {/* Total entries */} + +
+ + {/* Table */} + + + + {/* Role */} + + {/* Users */} + + {/* Invitations */} + + {/* Permissions */} + + {/* Added */} + + {/* Actions - empty header */} + + + + {Array.from({ length: rows }).map((_, i) => ( + + ))} + +
+ + + + + + + + + + +
+ + {/* Pagination */} +
+ {/* Rows per page */} +
+ + +
+ {/* Page info + navigation */} +
+ +
+ + + + +
+
+
+
); }; diff --git a/ui/components/users/profile/skeleton-user-info.tsx b/ui/components/users/profile/skeleton-user-info.tsx index 7e580593fd..ecbe6b498e 100644 --- a/ui/components/users/profile/skeleton-user-info.tsx +++ b/ui/components/users/profile/skeleton-user-info.tsx @@ -1,74 +1,156 @@ -import { Card, CardContent, Skeleton } from "@/components/shadcn"; +import { + Card, + CardAction, + CardContent, + CardHeader, + Separator, + Skeleton, +} from "@/components/shadcn"; +// Mirrors the real profile layout (UserBasicInfoCard full-width + a two-column +// grid with RolesCard and Organizations) so the page does not shift when the +// data resolves. Conditional cards (SAML / API keys) depend on permissions not +// known while loading, so we mirror only the always-present structure. export const SkeletonUserInfo = () => { return ( -
- {/* User Information */} - - -
- {/* Name */} -
-

- Name: -

- -
- {/* Email */} -
-

- Email: -

- -
- {/* Company */} -
-

- Company: -

- -
- {/* Date Joined */} -
-

- Date Joined: -

- -
- {/* Tenant ID */} -
-

- Tenant ID: -

- -
-
-
-
- - {/* Roles */} - - -

Roles

-
- {[1, 2, 3].map((i) => ( - - ))} -
-
-
- - {/* Memberships */} - - -

Memberships

-
- {[1, 2].map((i) => ( - - ))} -
-
-
+
+ +
+
+ +
+
+ +
+
+
+ ); +}; + +const UserBasicInfoSkeleton = () => { + return ( + + + {/* Avatar + name / email */} +
+ +
+ + +
+
+ + {/* Date Joined + Organization ID */} +
+ +
+ + +
+
+
+
+ ); +}; + +const RolesCardSkeleton = () => { + return ( + + + {/* Header: "Active roles" + subtitle */} +
+ + +
+
+ + +
+
+
+ ); +}; + +// Mirrors : inner card with a role badge + state on the left, a +// details toggle on the right, and a grid of permission rows below. +const RoleItemSkeleton = () => { + return ( + +
+
+ + +
+ +
+
+ {[0, 1, 2, 3].map((i) => ( +
+ + +
+ ))} +
+
+ ); +}; + +const OrganizationsCardSkeleton = () => { + return ( + + +
+ + +
+ + + +
+ +
+ + +
+
+
+ ); +}; + +// Mirrors : role badge (left), Name / Joined fields, and the +// "Active" badge (right). +const MembershipItemSkeleton = () => { + return ( + +
+ +
+ + +
+
+ +
+
+
+ ); +}; + +// Label + value pair. `inline` lays them side by side (info fields inside a +// row); otherwise stacked (a standalone field). +const FieldSkeleton = ({ + labelWidth, + valueWidth, + inline = false, +}: { + labelWidth: string; + valueWidth: string; + inline?: boolean; +}) => { + return ( +
+ +
); }; diff --git a/ui/components/users/table/skeleton-table-user.tsx b/ui/components/users/table/skeleton-table-user.tsx index c16074f976..c6d990a864 100644 --- a/ui/components/users/table/skeleton-table-user.tsx +++ b/ui/components/users/table/skeleton-table-user.tsx @@ -1,37 +1,102 @@ -import React from "react"; - -import { Card } from "@/components/shadcn/card/card"; import { Skeleton } from "@/components/shadcn/skeleton/skeleton"; -export const SkeletonTableUser = () => { +const SkeletonTableRow = () => { return ( - - {/* Table headers */} -
- - - - - - -
- - {/* Table body */} -
- {[...Array(10)].map((_, index) => ( -
- - - - - - -
- ))} -
-
+ + {/* Name */} + + + + {/* Email */} + + + + {/* Role */} + + + + {/* Company name */} + + + + {/* Joined - date */} + + + + {/* Actions */} + + + + + ); +}; + +export const SkeletonTableUser = () => { + const rows = 10; + + return ( +
+ {/* Toolbar: Search + Total entries */} +
+ {/* Search icon button */} + + {/* Total entries */} + +
+ + {/* Table */} + + + + {/* Name */} + + {/* Email */} + + {/* Role */} + + {/* Company name */} + + {/* Joined */} + + {/* Actions - empty header */} + + + + {Array.from({ length: rows }).map((_, i) => ( + + ))} + +
+ + + + + + + + + + +
+ + {/* Pagination */} +
+ {/* Rows per page */} +
+ + +
+ {/* Page info + navigation */} +
+ +
+ + + + +
+
+
+
); };