diff --git a/site/src/hooks/useClickable.ts b/site/src/hooks/useClickable.ts
index a694a5f6821af..0c761d7106c1c 100644
--- a/site/src/hooks/useClickable.ts
+++ b/site/src/hooks/useClickable.ts
@@ -1,6 +1,6 @@
import { KeyboardEvent } from "react"
-interface UseClickableResult {
+export interface UseClickableResult {
tabIndex: 0
role: "button"
onClick: () => void
diff --git a/site/src/hooks/useClickableTableRow.ts b/site/src/hooks/useClickableTableRow.ts
new file mode 100644
index 0000000000000..26c62c46f3700
--- /dev/null
+++ b/site/src/hooks/useClickableTableRow.ts
@@ -0,0 +1,31 @@
+import { makeStyles } from "@material-ui/core/styles"
+import { useClickable, UseClickableResult } from "./useClickable"
+
+interface UseClickableTableRowResult extends UseClickableResult {
+ className: string
+ hover: true
+}
+
+export const useClickableTableRow = (
+ onClick: () => void,
+): UseClickableTableRowResult => {
+ const styles = useStyles()
+ const clickable = useClickable(onClick)
+
+ return {
+ ...clickable,
+ className: styles.row,
+ hover: true,
+ }
+}
+
+const useStyles = makeStyles((theme) => ({
+ row: {
+ cursor: "pointer",
+
+ "&:focus": {
+ outline: `1px solid ${theme.palette.secondary.dark}`,
+ outlineOffset: -1,
+ },
+ },
+}))
diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.tsx
index b97f5c777041f..7ca1d6b9485ca 100644
--- a/site/src/pages/TemplatesPage/TemplatesPageView.tsx
+++ b/site/src/pages/TemplatesPage/TemplatesPageView.tsx
@@ -1,15 +1,13 @@
import Button from "@material-ui/core/Button"
import Link from "@material-ui/core/Link"
-import { makeStyles, Theme } from "@material-ui/core/styles"
+import { makeStyles } from "@material-ui/core/styles"
import Table from "@material-ui/core/Table"
import TableBody from "@material-ui/core/TableBody"
import TableCell from "@material-ui/core/TableCell"
import TableContainer from "@material-ui/core/TableContainer"
import TableHead from "@material-ui/core/TableHead"
import TableRow from "@material-ui/core/TableRow"
-import KeyboardArrowRight from "@material-ui/icons/KeyboardArrowRight"
import AddIcon from "@material-ui/icons/AddOutlined"
-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"
@@ -28,7 +26,6 @@ import {
PageHeaderTitle,
} from "../../components/PageHeader/PageHeader"
import { Stack } from "../../components/Stack/Stack"
-import { TableCellLink } from "../../components/TableCellLink/TableCellLink"
import { TableLoader } from "../../components/TableLoader/TableLoader"
import {
HelpTooltip,
@@ -39,6 +36,11 @@ import {
} from "../../components/Tooltips/HelpTooltip/HelpTooltip"
import { EmptyTemplates } from "./EmptyTemplates"
import { TemplatesContext } from "xServices/templates/templatesXService"
+import { useClickableTableRow } from "hooks/useClickableTableRow"
+import { Template } from "api/typesGenerated"
+import { combineClasses } from "util/combineClasses"
+import { colors } from "theme/colors"
+import ArrowForwardOutlined from "@material-ui/icons/ArrowForwardOutlined"
export const Language = {
developerCount: (activeCount: number): string => {
@@ -54,7 +56,6 @@ export const Language = {
templateTooltipText:
"With templates you can create a common configuration for your workspaces using Terraform.",
templateTooltipLink: "Manage templates",
- createdByLabel: "Created by",
}
const TemplateHelpTooltip: React.FC = () => {
@@ -71,6 +72,73 @@ const TemplateHelpTooltip: React.FC = () => {
)
}
+const TemplateRow: FC<{ template: Template }> = ({ template }) => {
+ const templatePageLink = `/templates/${template.name}`
+ const hasIcon = template.icon && template.icon !== ""
+ const navigate = useNavigate()
+ const styles = useStyles()
+ const { className: clickableClassName, ...clickableRow } =
+ useClickableTableRow(() => {
+ navigate(templatePageLink)
+ })
+
+ return (
+
+
+ 0
+ ? template.display_name
+ : template.name
+ }
+ subtitle={template.description}
+ highlightTitle
+ avatar={
+ hasIcon && (
+
+

+
+ )
+ }
+ />
+
+
+
+ {Language.developerCount(template.active_user_count)}
+
+
+
+ {formatTemplateBuildTime(template.build_time_stats.start.P50)}
+
+
+
+ {createDayString(template.updated_at)}
+
+
+
+ }
+ title={`Create a workspace using the ${template.display_name} template`}
+ onClick={(e) => {
+ e.stopPropagation()
+ navigate(`/templates/${template.name}/workspace`)
+ }}
+ >
+ Use template
+
+
+
+ )
+}
+
export interface TemplatesPageViewProps {
context: TemplatesContext
}
@@ -78,9 +146,6 @@ export interface TemplatesPageViewProps {
export const TemplatesPageView: FC<
React.PropsWithChildren
> = ({ context }) => {
- const styles = useStyles()
- const navigate = useNavigate()
- const theme: Theme = useTheme()
const { templates, error, examples, permissions } = context
const isLoading = !templates
const isEmpty = Boolean(templates && templates.length === 0)
@@ -136,11 +201,10 @@ export const TemplatesPageView: FC<
- {Language.nameLabel}
- {Language.usedByLabel}
- {Language.buildTimeLabel}
- {Language.lastUpdatedLabel}
- {Language.createdByLabel}
+ {Language.nameLabel}
+ {Language.usedByLabel}
+ {Language.buildTimeLabel}
+ {Language.lastUpdatedLabel}
@@ -158,91 +222,9 @@ export const TemplatesPageView: FC<
- {templates?.map((template) => {
- const templatePageLink = `/templates/${template.name}`
- const hasIcon = template.icon && template.icon !== ""
-
- return (
- {
- if (event.key === "Enter") {
- navigate(templatePageLink)
- }
- }}
- className={styles.clickableTableRow}
- >
-
- 0
- ? template.display_name
- : template.name
- }
- subtitle={template.description}
- highlightTitle
- avatar={
- hasIcon && (
-
-

-
- )
- }
- />
-
-
-
-
- {Language.developerCount(
- template.active_user_count,
- )}
-
-
-
-
-
- {formatTemplateBuildTime(
- template.build_time_stats.start.P50,
- )}
-
-
-
-
-
- {createDayString(template.updated_at)}
-
-
-
-
-
- {template.created_by_name}
-
-
-
-
-
-
-
-
-
- )
- })}
+ {templates?.map((template) => (
+
+ ))}
@@ -255,27 +237,6 @@ export const TemplatesPageView: FC<
}
const useStyles = makeStyles((theme) => ({
- clickableTableRow: {
- "&:hover td": {
- backgroundColor: theme.palette.action.hover,
- },
-
- "&:focus": {
- outline: `1px solid ${theme.palette.secondary.dark}`,
- },
-
- "& .MuiTableCell-root:last-child": {
- paddingRight: theme.spacing(2),
- },
- },
- arrowRight: {
- color: theme.palette.text.secondary,
- width: 20,
- height: 20,
- },
- arrowCell: {
- display: "flex",
- },
templateIconWrapper: {
// Same size then the avatar component
width: 36,
@@ -286,4 +247,23 @@ const useStyles = makeStyles((theme) => ({
width: "100%",
},
},
+ actionCell: {
+ whiteSpace: "nowrap",
+ },
+ secondary: {
+ color: theme.palette.text.secondary,
+ },
+ tableRow: {
+ "&:hover $actionButton": {
+ color: theme.palette.text.primary,
+ borderColor: colors.gray[11],
+ "&:hover": {
+ borderColor: theme.palette.text.primary,
+ },
+ },
+ },
+ actionButton: {
+ color: theme.palette.text.secondary,
+ transition: "none",
+ },
}))