diff --git a/site/src/components/Tabs/Tabs.tsx b/site/src/components/Tabs/Tabs.tsx
new file mode 100644
index 0000000000000..b7e6c6de61eb7
--- /dev/null
+++ b/site/src/components/Tabs/Tabs.tsx
@@ -0,0 +1,71 @@
+import { ReactNode } from "react";
+import { NavLink, NavLinkProps } from "react-router-dom";
+import { combineClasses } from "utils/combineClasses";
+import { Margins } from "components/Margins/Margins";
+import { css } from "@emotion/css";
+import { useTheme } from "@mui/material/styles";
+
+export const Tabs = ({ children }: { children: ReactNode }) => {
+ return (
+
({
+ borderBottom: `1px solid ${theme.palette.divider}`,
+ marginBottom: theme.spacing(5),
+ })}
+ >
+ ({
+ display: "flex",
+ alignItems: "center",
+ gap: theme.spacing(0.25),
+ })}
+ >
+ {children}
+
+
+ );
+};
+
+export const TabLink = (props: NavLinkProps) => {
+ const theme = useTheme();
+
+ const baseTabLink = css`
+ text-decoration: none;
+ color: ${theme.palette.text.secondary};
+ font-size: 14px;
+ display: block;
+ padding: ${theme.spacing(0, 2, 2)};
+
+ &:hover {
+ color: ${theme.palette.text.primary};
+ }
+ `;
+
+ const activeTabLink = css`
+ color: ${theme.palette.text.primary};
+ position: relative;
+
+ &:before {
+ content: "";
+ left: 0;
+ bottom: 0;
+ height: 2px;
+ width: 100%;
+ background: ${theme.palette.secondary.dark};
+ position: absolute;
+ }
+ `;
+
+ return (
+
+ combineClasses([
+ baseTabLink,
+ isActive ? activeTabLink : undefined,
+ props.className as string,
+ ])
+ }
+ {...props}
+ />
+ );
+};
diff --git a/site/src/components/UsersLayout/UsersLayout.tsx b/site/src/components/UsersLayout/UsersLayout.tsx
index 7a4d380b3e8cd..397cadc25bb60 100644
--- a/site/src/components/UsersLayout/UsersLayout.tsx
+++ b/site/src/components/UsersLayout/UsersLayout.tsx
@@ -1,6 +1,5 @@
import Button from "@mui/material/Button";
import Link from "@mui/material/Link";
-import { makeStyles } from "@mui/styles";
import GroupAdd from "@mui/icons-material/GroupAddOutlined";
import PersonAdd from "@mui/icons-material/PersonAddOutlined";
import { USERS_LINK } from "components/Dashboard/Navbar/NavbarView";
@@ -8,18 +7,11 @@ import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader";
import { useFeatureVisibility } from "hooks/useFeatureVisibility";
import { usePermissions } from "hooks/usePermissions";
import { FC } from "react";
-import {
- Link as RouterLink,
- NavLink,
- Outlet,
- useNavigate,
-} from "react-router-dom";
-import { combineClasses } from "utils/combineClasses";
+import { Link as RouterLink, Outlet, useNavigate } from "react-router-dom";
import { Margins } from "components/Margins/Margins";
-import { Stack } from "components/Stack/Stack";
+import { TabLink, Tabs } from "components/Tabs/Tabs";
export const UsersLayout: FC = () => {
- const styles = useStyles();
const { createUser: canCreateUser, createGroup: canCreateGroup } =
usePermissions();
const navigate = useNavigate();
@@ -53,35 +45,10 @@ export const UsersLayout: FC = () => {
-
-
-
-
- combineClasses([
- styles.tabItem,
- isActive ? styles.tabItemActive : undefined,
- ])
- }
- >
- Users
-
-
- combineClasses([
- styles.tabItem,
- isActive ? styles.tabItemActive : undefined,
- ])
- }
- >
- Groups
-
-
-
-
+
+ Users
+ Groups
+
@@ -89,39 +56,3 @@ export const UsersLayout: FC = () => {
>
);
};
-
-export const useStyles = makeStyles((theme) => {
- return {
- tabs: {
- borderBottom: `1px solid ${theme.palette.divider}`,
- marginBottom: theme.spacing(5),
- },
-
- tabItem: {
- textDecoration: "none",
- color: theme.palette.text.secondary,
- fontSize: 14,
- display: "block",
- padding: theme.spacing(0, 2, 2),
-
- "&:hover": {
- color: theme.palette.text.primary,
- },
- },
-
- tabItemActive: {
- color: theme.palette.text.primary,
- position: "relative",
-
- "&:before": {
- content: `""`,
- left: 0,
- bottom: 0,
- height: 2,
- width: "100%",
- background: theme.palette.secondary.dark,
- position: "absolute",
- },
- },
- };
-});
diff --git a/site/src/pages/TemplatePage/TemplateLayout.tsx b/site/src/pages/TemplatePage/TemplateLayout.tsx
index 24f4487048320..41a15264c9a7b 100644
--- a/site/src/pages/TemplatePage/TemplateLayout.tsx
+++ b/site/src/pages/TemplatePage/TemplateLayout.tsx
@@ -1,8 +1,7 @@
-import { css } from "@emotion/css";
import { useTheme } from "@emotion/react";
import { createContext, type FC, Suspense, useContext } from "react";
import { useQuery } from "react-query";
-import { NavLink, Outlet, useNavigate, useParams } from "react-router-dom";
+import { Outlet, useNavigate, useParams } from "react-router-dom";
import type { AuthorizationRequest } from "api/typesGenerated";
import {
checkAuthorization,
@@ -11,10 +10,10 @@ import {
} from "api/api";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { Margins } from "components/Margins/Margins";
-import { Stack } from "components/Stack/Stack";
import { Loader } from "components/Loader/Loader";
import { useOrganizationId } from "hooks/useOrganizationId";
import { TemplatePageHeader } from "./TemplatePageHeader";
+import { TabLink, Tabs } from "components/Tabs/Tabs";
const templatePermissions = (
templateId: string,
@@ -85,34 +84,6 @@ export const TemplateLayout: FC<{ children?: JSX.Element }> = ({
return ;
}
- const itemStyles = css`
- text-decoration: none;
- color: ${theme.palette.text.secondary};
- font-size: 14;
- display: block;
- padding: ${theme.spacing(0, 2, 2)};
-
- &:hover {
- color: ${theme.palette.text.primary};
- }
- `;
-
- const activeItemStyles = css`
- ${itemStyles}
- color: ${theme.palette.text.primary};
- position: relative;
-
- &:before {
- content: "";
- left: 0;
- bottom: 0;
- height: 2;
- width: 100%;
- background: ${theme.palette.secondary.dark};
- position: absolute;
- }
- `;
-
return (
<>
= ({
}}
/>
-
-
-
-
- isActive ? activeItemStyles : itemStyles
- }
- >
- Summary
-
-
- isActive ? activeItemStyles : itemStyles
- }
- >
- Docs
-
- {data.permissions.canUpdateTemplate && (
-
- isActive ? activeItemStyles : itemStyles
- }
- >
- Source Code
-
- )}
-
- isActive ? activeItemStyles : itemStyles
- }
- >
- Versions
-
-
- isActive ? activeItemStyles : itemStyles
- }
- >
- Embed
-
- {shouldShowInsights && (
-
- isActive ? activeItemStyles : itemStyles
- }
- >
- Insights
-
- )}
-
-
-
+
+
+ Summary
+
+ Docs
+ {data.permissions.canUpdateTemplate && (
+ Source Code
+ )}
+ Versions
+ Embed
+ {shouldShowInsights && (
+ Insights
+ )}
+