refactor: Improve empty views (#5134)

This commit is contained in:
Bruno Quaresma
2022-11-19 01:46:11 +00:00
committed by GitHub
parent a477d901d6
commit 5fa3fdeca0
6 changed files with 122 additions and 55 deletions
+31 -34
View File
@@ -9,9 +9,9 @@ export interface EmptyStateProps {
message: string
/** Longer optional description to display below the message */
description?: string | React.ReactNode
descriptionClassName?: string
cta?: ReactNode
className?: string
image?: ReactNode
}
/**
@@ -25,14 +25,7 @@ export interface EmptyStateProps {
export const EmptyState: FC<React.PropsWithChildren<EmptyStateProps>> = (
props,
) => {
const {
message,
description,
cta,
descriptionClassName,
className,
...boxProps
} = props
const { message, description, cta, className, image, ...boxProps } = props
const styles = useStyles()
return (
@@ -44,38 +37,42 @@ export const EmptyState: FC<React.PropsWithChildren<EmptyStateProps>> = (
<Typography
variant="body2"
color="textSecondary"
className={combineClasses([styles.description, descriptionClassName])}
className={styles.description}
>
{description}
</Typography>
)}
{cta && <div className={styles.cta}>{cta}</div>}
{image}
</Box>
)
}
const useStyles = makeStyles(
(theme) => ({
root: {
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
textAlign: "center",
minHeight: 300,
padding: theme.spacing(3),
},
const useStyles = makeStyles((theme) => ({
root: {
overflow: "hidden",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
textAlign: "center",
minHeight: 360,
padding: theme.spacing(10, 5),
position: "relative",
},
title: {
fontSize: theme.spacing(3),
},
description: {
marginTop: theme.spacing(1.5),
fontSize: theme.spacing(2),
},
cta: {
marginTop: theme.spacing(4),
},
}),
{ name: "EmptyState" },
)
title: {
fontSize: theme.spacing(3),
},
description: {
marginTop: theme.spacing(1.5),
fontSize: theme.spacing(2),
lineHeight: "140%",
maxWidth: theme.spacing(60),
},
cta: {
marginTop: theme.spacing(4),
},
}))
@@ -0,0 +1,28 @@
import { makeStyles } from "@material-ui/core/styles"
import TableCell from "@material-ui/core/TableCell"
import TableRow from "@material-ui/core/TableRow"
import { FC } from "react"
import {
EmptyState,
EmptyStateProps,
} from "../../components/EmptyState/EmptyState"
export type TableEmptyProps = EmptyStateProps
export const TableEmpty: FC<TableEmptyProps> = (props) => {
const styles = useStyles()
return (
<TableRow>
<TableCell colSpan={999} className={styles.tableCell}>
<EmptyState {...props} />
</TableCell>
</TableRow>
)
}
const useStyles = makeStyles(() => ({
tableCell: {
padding: "0 !important",
},
}))
@@ -1,8 +1,9 @@
import Button from "@material-ui/core/Button"
import Link from "@material-ui/core/Link"
import { makeStyles } from "@material-ui/core/styles"
import TableCell from "@material-ui/core/TableCell"
import TableRow from "@material-ui/core/TableRow"
import AddCircleOutline from "@material-ui/icons/AddCircleOutline"
import AddOutlined from "@material-ui/icons/AddOutlined"
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"
import { FC } from "react"
import { useTranslation } from "react-i18next"
@@ -24,6 +25,7 @@ export const WorkspacesTableBody: FC<
React.PropsWithChildren<TableBodyProps>
> = ({ isLoading, workspaceRefs, filter, isNonInitialPage }) => {
const { t } = useTranslation("workspacesPage")
const styles = useStyles()
return (
<ChooseOne>
@@ -32,7 +34,7 @@ export const WorkspacesTableBody: FC<
</Cond>
<Cond condition={!workspaceRefs || workspaceRefs.length === 0}>
<TableRow>
<TableCell colSpan={999}>
<TableCell colSpan={999} className={styles.emptyTableCell}>
<ChooseOne>
<Cond condition={isNonInitialPage}>
<EmptyState message={t("emptyPageMessage")} />
@@ -44,6 +46,7 @@ export const WorkspacesTableBody: FC<
}
>
<EmptyState
className={styles.empty}
message={t("emptyCreateWorkspaceMessage")}
description={t("emptyCreateWorkspaceDescription")}
cta={
@@ -52,11 +55,16 @@ export const WorkspacesTableBody: FC<
component={RouterLink}
to="/templates"
>
<Button startIcon={<AddCircleOutline />}>
<Button startIcon={<AddOutlined />}>
{t("createFromTemplateButton")}
</Button>
</Link>
}
image={
<div className={styles.emptyImage}>
<img src="/empty/workspaces.webp" alt="" />
</div>
}
/>
</Cond>
<Cond>
@@ -75,3 +83,25 @@ export const WorkspacesTableBody: FC<
</ChooseOne>
)
}
const useStyles = makeStyles((theme) => ({
emptyTableCell: {
padding: "0 !important",
},
empty: {
paddingBottom: 0,
},
emptyImage: {
maxWidth: "50%",
height: theme.spacing(34),
overflow: "hidden",
marginTop: theme.spacing(6),
opacity: 0.85,
"& img": {
maxWidth: "100%",
},
},
}))
@@ -11,6 +11,7 @@ import useTheme from "@material-ui/styles/useTheme"
import { AlertBanner } from "components/AlertBanner/AlertBanner"
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"
import { Maybe } from "components/Conditionals/Maybe"
import { TableEmpty } from "components/TableEmpty/TableEmpty"
import { FC } from "react"
import { useTranslation } from "react-i18next"
import { useNavigate } from "react-router-dom"
@@ -22,7 +23,6 @@ import {
import * as TypesGen from "../../api/typesGenerated"
import { AvatarData } from "../../components/AvatarData/AvatarData"
import { CodeExample } from "../../components/CodeExample/CodeExample"
import { EmptyState } from "../../components/EmptyState/EmptyState"
import { Margins } from "../../components/Margins/Margins"
import {
PageHeader,
@@ -174,20 +174,21 @@ export const TemplatesPageView: FC<
<ChooseOne>
<Cond condition={empty}>
<TableRow>
<TableCell colSpan={999}>
<EmptyState
message={Language.emptyMessage}
description={
props.canCreateTemplate
? Language.emptyDescription
: Language.emptyViewNoPerms
}
descriptionClassName={styles.emptyDescription}
cta={<CodeExample code="coder templates init" />}
/>
</TableCell>
</TableRow>
<TableEmpty
className={styles.empty}
message={Language.emptyMessage}
description={
props.canCreateTemplate
? Language.emptyDescription
: Language.emptyViewNoPerms
}
cta={<CodeExample code="coder templates init" />}
image={
<div className={styles.emptyImage}>
<img src="/empty/templates.webp" alt="" />
</div>
}
/>
</Cond>
<Cond>
{props.templates?.map((template) => {
@@ -287,9 +288,6 @@ export const TemplatesPageView: FC<
}
const useStyles = makeStyles((theme) => ({
emptyDescription: {
maxWidth: theme.spacing(62),
},
clickableTableRow: {
"&:hover td": {
backgroundColor: theme.palette.action.hover,
@@ -321,4 +319,18 @@ const useStyles = makeStyles((theme) => ({
width: "100%",
},
},
empty: {
paddingBottom: 0,
},
emptyImage: {
maxWidth: "50%",
height: theme.spacing(40),
overflow: "hidden",
opacity: 0.85,
"& img": {
maxWidth: "100%",
},
},
}))
Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB