Skip to content

Commit bb0e407

Browse files
authored
chore: remove some usage of useClassName (#19346)
1 parent accdcb8 commit bb0e407

File tree

6 files changed

+132
-226
lines changed

6 files changed

+132
-226
lines changed

site/src/@types/storybook.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type {
88
} from "api/typesGenerated";
99
import type { Permissions } from "modules/permissions";
1010
import type { QueryKey } from "react-query";
11+
import type { ReactRouterAddonStoryParameters } from "storybook-addon-remix-react-router";
1112

1213
declare module "@storybook/react-vite" {
1314
type WebSocketEvent =
@@ -24,5 +25,6 @@ declare module "@storybook/react-vite" {
2425
permissions?: Partial<Permissions>;
2526
deploymentValues?: DeploymentValues;
2627
deploymentOptions?: SerpentOption[];
28+
reactRouter?: ReactRouterAddonStoryParameters;
2729
}
2830
}
Lines changed: 13 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import type { Interpolation, Theme } from "@emotion/react";
21
import IconButton from "@mui/material/IconButton";
32
import Snackbar, {
43
type SnackbarProps as MuiSnackbarProps,
54
} from "@mui/material/Snackbar";
6-
import { type ClassName, useClassName } from "hooks/useClassName";
75
import { X as XIcon } from "lucide-react";
86
import type { FC } from "react";
7+
import { cn } from "utils/cn";
98

109
type EnterpriseSnackbarVariant = "error" | "info" | "success";
1110

@@ -35,29 +34,30 @@ export const EnterpriseSnackbar: FC<EnterpriseSnackbarProps> = ({
3534
action,
3635
...snackbarProps
3736
}) => {
38-
const content = useClassName(classNames.content(variant), [variant]);
39-
4037
return (
4138
<Snackbar
4239
anchorOrigin={{
4340
vertical: "bottom",
4441
horizontal: "right",
4542
}}
4643
action={
47-
<div css={styles.actionWrapper}>
44+
<div className="flex items-center">
4845
{action}
49-
<IconButton onClick={onClose} css={{ padding: 0 }}>
46+
<IconButton onClick={onClose} className="p-0">
5047
<XIcon
51-
css={styles.closeIcon}
5248
aria-label="close"
53-
className="size-icon-sm"
49+
className="size-icon-sm text-content-primary"
5450
/>
5551
</IconButton>
5652
</div>
5753
}
5854
ContentProps={{
5955
...ContentProps,
60-
className: content,
56+
className: cn(
57+
"rounded-lg bg-surface-secondary text-content-primary shadow",
58+
"py-2 pl-6 pr-4 items-[inherit] border-0 border-l-[4px]",
59+
variantColor(variant),
60+
),
6161
}}
6262
onClose={onClose}
6363
{...snackbarProps}
@@ -67,39 +67,13 @@ export const EnterpriseSnackbar: FC<EnterpriseSnackbarProps> = ({
6767
);
6868
};
6969

70-
const variantColor = (variant: EnterpriseSnackbarVariant, theme: Theme) => {
70+
const variantColor = (variant: EnterpriseSnackbarVariant) => {
7171
switch (variant) {
7272
case "error":
73-
return theme.palette.error.main;
73+
return "border-border-destructive";
7474
case "info":
75-
return theme.palette.info.main;
75+
return "border-highlight-sky";
7676
case "success":
77-
return theme.palette.success.main;
77+
return "border-border-success";
7878
}
7979
};
80-
81-
const classNames = {
82-
content:
83-
(variant: EnterpriseSnackbarVariant): ClassName =>
84-
(css, theme) =>
85-
css`
86-
border: 1px solid ${theme.palette.divider};
87-
border-left: 4px solid ${variantColor(variant, theme)};
88-
border-radius: 8px;
89-
padding: 8px 24px 8px 16px;
90-
box-shadow: ${theme.shadows[6]};
91-
align-items: inherit;
92-
background-color: ${theme.palette.background.paper};
93-
color: ${theme.palette.text.secondary};
94-
`,
95-
};
96-
97-
const styles = {
98-
actionWrapper: {
99-
display: "flex",
100-
alignItems: "center",
101-
},
102-
closeIcon: (theme) => ({
103-
color: theme.palette.primary.contrastText,
104-
}),
105-
} satisfies Record<string, Interpolation<Theme>>;

site/src/components/Sidebar/Sidebar.stories.tsx

Lines changed: 69 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
LockIcon,
88
UserIcon,
99
} from "lucide-react";
10+
import { Outlet } from "react-router";
1011
import { Sidebar, SidebarHeader, SidebarNavItem } from "./Sidebar";
1112

1213
const meta: Meta<typeof Sidebar> = {
@@ -18,30 +19,73 @@ export default meta;
1819
type Story = StoryObj<typeof Sidebar>;
1920

2021
export const Default: Story = {
21-
args: {
22-
children: (
23-
<Sidebar>
24-
<SidebarHeader
25-
avatar={<Avatar fallback="Jon" />}
26-
title="Jon"
27-
subtitle="jon@coder.com"
28-
/>
29-
<SidebarNavItem href="account" icon={UserIcon}>
30-
Account
31-
</SidebarNavItem>
32-
<SidebarNavItem href="schedule" icon={CalendarCogIcon}>
33-
Schedule
34-
</SidebarNavItem>
35-
<SidebarNavItem href="security" icon={LockIcon}>
36-
Security
37-
</SidebarNavItem>
38-
<SidebarNavItem href="ssh-keys" icon={FingerprintIcon}>
39-
SSH Keys
40-
</SidebarNavItem>
41-
<SidebarNavItem href="tokens" icon={KeyIcon}>
42-
Tokens
43-
</SidebarNavItem>
44-
</Sidebar>
45-
),
22+
decorators: [
23+
(Story) => {
24+
return (
25+
<div className="flex gap-2">
26+
<Story />
27+
<Outlet />
28+
</div>
29+
);
30+
},
31+
],
32+
render: () => (
33+
<Sidebar>
34+
<SidebarHeader
35+
avatar={<Avatar fallback="Jon" />}
36+
title="Jon"
37+
subtitle="jon@coder.com"
38+
/>
39+
<SidebarNavItem href="account" icon={UserIcon}>
40+
Account
41+
</SidebarNavItem>
42+
<SidebarNavItem href="schedule" icon={CalendarCogIcon}>
43+
Schedule
44+
</SidebarNavItem>
45+
<SidebarNavItem href="security" icon={LockIcon}>
46+
Security
47+
</SidebarNavItem>
48+
<SidebarNavItem href="ssh-keys" icon={FingerprintIcon}>
49+
SSH Keys
50+
</SidebarNavItem>
51+
<SidebarNavItem href="tokens" icon={KeyIcon}>
52+
Tokens
53+
</SidebarNavItem>
54+
</Sidebar>
55+
),
56+
parameters: {
57+
reactRouter: {
58+
location: {
59+
path: "/account",
60+
},
61+
routing: [
62+
{
63+
path: "/",
64+
useStoryElement: true,
65+
children: [
66+
{
67+
path: "account",
68+
element: <>Account page</>,
69+
},
70+
{
71+
path: "schedule",
72+
element: <>Schedule page</>,
73+
},
74+
{
75+
path: "security",
76+
element: <>Security page</>,
77+
},
78+
{
79+
path: "ssh-keys",
80+
element: <>SSH Keys</>,
81+
},
82+
{
83+
path: "tokens",
84+
element: <>Tokens page</>,
85+
},
86+
],
87+
},
88+
],
89+
},
4690
},
4791
};
Lines changed: 19 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import { cx } from "@emotion/css";
2-
import type { CSSObject, Interpolation, Theme } from "@emotion/react";
31
import { Stack } from "components/Stack/Stack";
4-
import { type ClassName, useClassName } from "hooks/useClassName";
52
import type { ElementType, FC, ReactNode } from "react";
63
import { Link, NavLink } from "react-router";
74
import { cn } from "utils/cn";
@@ -21,14 +18,19 @@ interface SidebarHeaderProps {
2118
linkTo?: string;
2219
}
2320

21+
const titleStyles = {
22+
normal:
23+
"text-semibold overflow-hidden whitespace-nowrap text-content-primary",
24+
};
25+
2426
export const SidebarHeader: FC<SidebarHeaderProps> = ({
2527
avatar,
2628
title,
2729
subtitle,
2830
linkTo,
2931
}) => {
3032
return (
31-
<Stack direction="row" spacing={1} css={styles.info}>
33+
<Stack direction="row" spacing={1} className="mb-4">
3234
{avatar}
3335
<div
3436
css={{
@@ -38,13 +40,15 @@ export const SidebarHeader: FC<SidebarHeaderProps> = ({
3840
}}
3941
>
4042
{linkTo ? (
41-
<Link css={styles.title} to={linkTo}>
43+
<Link className={cn(titleStyles.normal, "no-underline")} to={linkTo}>
4244
{title}
4345
</Link>
4446
) : (
45-
<span css={styles.title}>{title}</span>
47+
<span className={titleStyles.normal}>{title}</span>
4648
)}
47-
<span css={styles.subtitle}>{subtitle}</span>
49+
<span className="text-content-secondary text-sm overflow-hidden overflow-ellipsis">
50+
{subtitle}
51+
</span>
4852
</div>
4953
</Stack>
5054
);
@@ -88,14 +92,18 @@ export const SidebarNavItem: FC<SidebarNavItemProps> = ({
8892
href,
8993
icon: Icon,
9094
}) => {
91-
const link = useClassName(classNames.link, []);
92-
const activeLink = useClassName(classNames.activeLink, []);
93-
9495
return (
9596
<NavLink
9697
end
9798
to={href}
98-
className={({ isActive }) => cx([link, isActive && activeLink])}
99+
className={({ isActive }) =>
100+
cn(
101+
"block relative text-sm text-inherit mb-px p-3 pl-4 rounded-sm",
102+
"transition-colors no-underline hover:bg-surface-secondary",
103+
isActive &&
104+
"bg-surface-secondary border-0 border-solid border-l-[3px] border-highlight-sky",
105+
)
106+
}
99107
>
100108
<Stack alignItems="center" spacing={1.5} direction="row">
101109
<Icon css={{ width: 16, height: 16 }} />
@@ -104,60 +112,3 @@ export const SidebarNavItem: FC<SidebarNavItemProps> = ({
104112
</NavLink>
105113
);
106114
};
107-
108-
const styles = {
109-
info: (theme) => ({
110-
...(theme.typography.body2 as CSSObject),
111-
marginBottom: 16,
112-
}),
113-
114-
title: (theme) => ({
115-
fontWeight: 600,
116-
overflow: "hidden",
117-
textOverflow: "ellipsis",
118-
whiteSpace: "nowrap",
119-
color: theme.palette.text.primary,
120-
textDecoration: "none",
121-
}),
122-
subtitle: (theme) => ({
123-
color: theme.palette.text.secondary,
124-
fontSize: 12,
125-
overflow: "hidden",
126-
textOverflow: "ellipsis",
127-
}),
128-
} satisfies Record<string, Interpolation<Theme>>;
129-
130-
const classNames = {
131-
link: (css, theme) => css`
132-
color: inherit;
133-
display: block;
134-
font-size: 14px;
135-
text-decoration: none;
136-
padding: 12px 12px 12px 16px;
137-
border-radius: 4px;
138-
transition: background-color 0.15s ease-in-out;
139-
margin-bottom: 1px;
140-
position: relative;
141-
142-
&:hover {
143-
background-color: ${theme.palette.action.hover};
144-
}
145-
`,
146-
147-
activeLink: (css, theme) => css`
148-
background-color: ${theme.palette.action.hover};
149-
150-
&:before {
151-
content: "";
152-
display: block;
153-
width: 3px;
154-
height: 100%;
155-
position: absolute;
156-
left: 0;
157-
top: 0;
158-
background-color: ${theme.palette.primary.main};
159-
border-top-left-radius: 8px;
160-
border-bottom-left-radius: 8px;
161-
}
162-
`,
163-
} satisfies Record<string, ClassName>;

site/src/hooks/useClassName.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import { type DependencyList, useMemo } from "react";
55
export type ClassName = (cssFn: typeof css, theme: Theme) => string;
66

77
/**
8-
* An escape hatch for when you really need to manually pass around a
9-
* `className`. Prefer using the `css` prop whenever possible. If you
10-
* can't use that, then this might be helpful for you.
8+
* @deprecated This hook was used as an escape hatch to generate class names
9+
* using emotion when no other styling method would work. There is no valid new
10+
* usage of this hook. Use Tailwind classes instead.
1111
*/
1212
export function useClassName(styles: ClassName, deps: DependencyList): string {
1313
const theme = useTheme();

0 commit comments

Comments
 (0)