diff --git a/site/src/components/AvatarData/AvatarData.tsx b/site/src/components/AvatarData/AvatarData.tsx index 93aae3e876570..c88ddc07af779 100644 --- a/site/src/components/AvatarData/AvatarData.tsx +++ b/site/src/components/AvatarData/AvatarData.tsx @@ -23,7 +23,12 @@ export const AvatarData: FC> = ({ } return ( - + {avatar} @@ -35,6 +40,10 @@ export const AvatarData: FC> = ({ } const useStyles = makeStyles((theme) => ({ + root: { + minHeight: theme.spacing(5), // Make it predictable for the skeleton + }, + title: { color: theme.palette.text.primary, fontWeight: 600, diff --git a/site/src/components/AvatarData/AvatarDataSkeleton.tsx b/site/src/components/AvatarData/AvatarDataSkeleton.tsx new file mode 100644 index 0000000000000..d9994aa68e983 --- /dev/null +++ b/site/src/components/AvatarData/AvatarDataSkeleton.tsx @@ -0,0 +1,16 @@ +import { FC } from "react" +import { Stack } from "components/Stack/Stack" +import { Skeleton } from "@material-ui/lab" + +export const AvatarDataSkeleton: FC = () => { + return ( + + + + + + + + + ) +} diff --git a/site/src/components/TableLoader/TableLoader.tsx b/site/src/components/TableLoader/TableLoader.tsx index 413d86208c77d..6cb054ec9c46d 100644 --- a/site/src/components/TableLoader/TableLoader.tsx +++ b/site/src/components/TableLoader/TableLoader.tsx @@ -1,6 +1,8 @@ import { makeStyles } from "@material-ui/core/styles" import TableCell from "@material-ui/core/TableCell" import TableRow from "@material-ui/core/TableRow" +import Skeleton from "@material-ui/lab/Skeleton" +import { AvatarDataSkeleton } from "components/AvatarData/AvatarDataSkeleton" import { FC } from "react" import { Loader } from "../Loader/Loader" @@ -22,3 +24,36 @@ const useStyles = makeStyles((theme) => ({ height: theme.spacing(20), }, })) + +export const TableLoaderSkeleton: FC<{ + columns: number + rows?: number + useAvatarData?: boolean +}> = ({ columns, rows = 4, useAvatarData = false }) => { + const placeholderColumns = Array(columns).fill(undefined) + const placeholderRows = Array(rows).fill(undefined) + + return ( + <> + {placeholderRows.map((_, rowIndex) => ( + + {placeholderColumns.map((_, columnIndex) => { + if (useAvatarData && columnIndex === 0) { + return ( + + + + ) + } + + return ( + + + + ) + })} + + ))} + + ) +} diff --git a/site/src/components/UsersTable/UsersTableBody.tsx b/site/src/components/UsersTable/UsersTableBody.tsx index 88b1182cd88bf..c4f3ec9ea672e 100644 --- a/site/src/components/UsersTable/UsersTableBody.tsx +++ b/site/src/components/UsersTable/UsersTableBody.tsx @@ -11,7 +11,7 @@ import * as TypesGen from "../../api/typesGenerated" import { combineClasses } from "../../util/combineClasses" import { AvatarData } from "../AvatarData/AvatarData" import { EmptyState } from "../EmptyState/EmptyState" -import { TableLoader } from "../TableLoader/TableLoader" +import { TableLoaderSkeleton } from "../TableLoader/TableLoader" import { TableRowMenu } from "../TableRowMenu/TableRowMenu" import { EditRolesButton } from "components/EditRolesButton/EditRolesButton" import { Stack } from "components/Stack/Stack" @@ -70,7 +70,7 @@ export const UsersTableBody: FC< return ( - + diff --git a/site/src/components/WorkspacesTable/WorkspacesTableBody.tsx b/site/src/components/WorkspacesTable/WorkspacesTableBody.tsx index 3d58ff8395720..c42d4c4323a46 100644 --- a/site/src/components/WorkspacesTable/WorkspacesTableBody.tsx +++ b/site/src/components/WorkspacesTable/WorkspacesTableBody.tsx @@ -8,7 +8,7 @@ import { TableEmpty } from "components/TableEmpty/TableEmpty" import { FC } from "react" import { useTranslation } from "react-i18next" import { Link as RouterLink } from "react-router-dom" -import { TableLoader } from "../TableLoader/TableLoader" +import { TableLoaderSkeleton } from "../TableLoader/TableLoader" import { WorkspacesRow } from "./WorkspacesRow" interface TableBodyProps { @@ -29,7 +29,7 @@ export const WorkspacesTableBody: FC< } if (!workspaces) { - return + return } if (workspaces.length === 0) { diff --git a/site/src/pages/GroupsPage/GroupsPageView.tsx b/site/src/pages/GroupsPage/GroupsPageView.tsx index fb6b44d2bc6ba..57ac0a7764362 100644 --- a/site/src/pages/GroupsPage/GroupsPageView.tsx +++ b/site/src/pages/GroupsPage/GroupsPageView.tsx @@ -15,7 +15,7 @@ import { AvatarData } from "components/AvatarData/AvatarData" import { ChooseOne, Cond } from "components/Conditionals/ChooseOne" import { EmptyState } from "components/EmptyState/EmptyState" import { Stack } from "components/Stack/Stack" -import { TableLoader } from "components/TableLoader/TableLoader" +import { TableLoaderSkeleton } from "components/TableLoader/TableLoader" import { UserAvatar } from "components/UserAvatar/UserAvatar" import { FC } from "react" import { Link as RouterLink, useNavigate } from "react-router-dom" @@ -83,7 +83,7 @@ export const GroupsPageView: FC = ({ - + diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.tsx index d953dbe6119e0..4df1beaa408c0 100644 --- a/site/src/pages/TemplatesPage/TemplatesPageView.tsx +++ b/site/src/pages/TemplatesPage/TemplatesPageView.tsx @@ -26,7 +26,7 @@ import { PageHeaderTitle, } from "../../components/PageHeader/PageHeader" import { Stack } from "../../components/Stack/Stack" -import { TableLoader } from "../../components/TableLoader/TableLoader" +import { TableLoaderSkeleton } from "../../components/TableLoader/TableLoader" import { HelpTooltip, HelpTooltipLink, @@ -210,7 +210,7 @@ export const TemplatesPageView: FC< - + diff --git a/site/src/theme/props.ts b/site/src/theme/props.ts index eddeb36427c7d..930e8cb6c8ff6 100644 --- a/site/src/theme/props.ts +++ b/site/src/theme/props.ts @@ -41,4 +41,7 @@ export const props = { MuiPaper: { elevation: 0, }, + MuiSkeleton: { + animation: "wave", + }, } as ComponentsProps