Skip to content

Commit b0cdf3f

Browse files
committed
emotion: Form & FormFooter
1 parent 95e9688 commit b0cdf3f

File tree

2 files changed

+90
-110
lines changed

2 files changed

+90
-110
lines changed

site/src/components/Form/Form.tsx

Lines changed: 75 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import { makeStyles } from "@mui/styles";
2-
import { AlphaBadge } from "components/DeploySettingsLayout/Badges";
3-
import {
4-
FormFooterProps as BaseFormFooterProps,
5-
FormFooter as BaseFormFooter,
6-
} from "components/FormFooter/FormFooter";
7-
import { Stack } from "components/Stack/Stack";
1+
import { type Interpolation, type Theme, useTheme } from "@emotion/react";
82
import {
93
createContext,
10-
FC,
11-
HTMLProps,
12-
PropsWithChildren,
4+
type FC,
5+
type HTMLProps,
6+
type PropsWithChildren,
137
useContext,
148
} from "react";
15-
import { combineClasses } from "utils/combineClasses";
9+
import { AlphaBadge } from "components/DeploySettingsLayout/Badges";
10+
import { Stack } from "components/Stack/Stack";
11+
import {
12+
FormFooter as BaseFormFooter,
13+
FormFooterProps,
14+
type FormFooterStyles,
15+
} from "../FormFooter/FormFooter";
1616

1717
type FormContextValue = { direction?: "horizontal" | "vertical" };
1818

@@ -24,14 +24,22 @@ type FormProps = HTMLProps<HTMLFormElement> & {
2424
direction?: FormContextValue["direction"];
2525
};
2626

27-
export const Form: FC<FormProps> = ({ direction, className, ...formProps }) => {
28-
const styles = useStyles({ direction });
27+
export const Form: FC<FormProps> = ({ direction, ...formProps }) => {
28+
const theme = useTheme();
2929

3030
return (
3131
<FormContext.Provider value={{ direction }}>
3232
<form
3333
{...formProps}
34-
className={combineClasses([styles.form, className])}
34+
css={{
35+
display: "flex",
36+
flexDirection: "column",
37+
gap: theme.spacing(direction === "horizontal" ? 10 : 5),
38+
39+
[theme.breakpoints.down("md")]: {
40+
gap: theme.spacing(8),
41+
},
42+
}}
3543
/>
3644
</FormContext.Provider>
3745
);
@@ -71,28 +79,50 @@ export const FormSection: FC<
7179
alpha?: boolean;
7280
}
7381
> = ({ children, title, description, classes = {}, alpha = false }) => {
74-
const formContext = useContext(FormContext);
75-
const styles = useStyles(formContext);
82+
const { direction } = useContext(FormContext);
83+
const theme = useTheme();
7684

7785
return (
78-
<div className={combineClasses([styles.formSection, classes.root])}>
86+
<div
87+
css={{
88+
display: "flex",
89+
alignItems: "flex-start",
90+
flexDirection: direction === "horizontal" ? "row" : "column",
91+
gap: theme.spacing(direction === "horizontal" ? 15 : 3),
92+
93+
[theme.breakpoints.down("md")]: {
94+
flexDirection: "column",
95+
gap: theme.spacing(2),
96+
},
97+
}}
98+
className={classes.root}
99+
>
79100
<div
80-
className={combineClasses([
81-
classes.sectionInfo,
82-
styles.formSectionInfo,
83-
])}
101+
css={{
102+
width: "100%",
103+
maxWidth: direction === "horizontal" ? 312 : undefined,
104+
flexShrink: 0,
105+
position: direction === "horizontal" ? "sticky" : undefined,
106+
top: theme.spacing(3),
107+
108+
[theme.breakpoints.down("md")]: {
109+
width: "100%",
110+
position: "initial" as const,
111+
},
112+
}}
113+
className={classes.sectionInfo}
84114
>
85115
<h2
86-
className={combineClasses([
116+
css={[
87117
styles.formSectionInfoTitle,
88118
alpha && styles.formSectionInfoTitleAlpha,
89-
classes.infoTitle,
90-
])}
119+
]}
120+
className={classes.infoTitle}
91121
>
92122
{title}
93123
{alpha && <AlphaBadge />}
94124
</h2>
95-
<div className={styles.formSectionInfoDescription}>{description}</div>
125+
<div css={styles.formSectionInfoDescription}>{description}</div>
96126
</div>
97127

98128
{children}
@@ -101,108 +131,55 @@ export const FormSection: FC<
101131
};
102132

103133
export const FormFields: FC<PropsWithChildren> = ({ children }) => {
104-
const styles = useStyles();
105134
return (
106-
<Stack
107-
direction="column"
108-
spacing={2.5}
109-
className={styles.formSectionFields}
110-
>
135+
<Stack direction="column" spacing={2.5} css={styles.formSectionFields}>
111136
{children}
112137
</Stack>
113138
);
114139
};
115140

116-
export const FormFooter: FC<BaseFormFooterProps> = (props) => {
117-
const formFooterStyles = useFormFooterStyles();
118-
return (
119-
<BaseFormFooter
120-
{...props}
121-
styles={{ ...formFooterStyles, ...props.styles }}
122-
/>
123-
);
124-
};
125-
const getFlexDirection = ({ direction }: FormContextValue = {}):
126-
| "row"
127-
| "column" =>
128-
direction === "horizontal" ? ("row" as const) : ("column" as const);
129-
130-
const useStyles = makeStyles((theme) => ({
131-
form: {
132-
display: "flex",
133-
flexDirection: "column",
134-
gap: ({ direction }: FormContextValue = {}) =>
135-
direction === "horizontal" ? theme.spacing(10) : theme.spacing(5),
136-
137-
[theme.breakpoints.down("md")]: {
138-
gap: theme.spacing(8),
139-
},
140-
},
141-
142-
formSection: {
143-
display: "flex",
144-
alignItems: "flex-start",
145-
gap: ({ direction }: FormContextValue = {}) =>
146-
direction === "horizontal" ? theme.spacing(15) : theme.spacing(3),
147-
flexDirection: getFlexDirection,
148-
149-
[theme.breakpoints.down("md")]: {
150-
flexDirection: "column",
151-
gap: theme.spacing(2),
152-
},
153-
},
154-
155-
formSectionInfo: {
156-
width: "100%",
157-
maxWidth: ({ direction }: FormContextValue = {}) =>
158-
direction === "horizontal" ? 312 : undefined,
159-
flexShrink: 0,
160-
position: ({ direction }: FormContextValue = {}) =>
161-
direction === "horizontal" ? "sticky" : undefined,
162-
top: theme.spacing(3),
163-
164-
[theme.breakpoints.down("md")]: {
165-
width: "100%",
166-
position: "initial" as const,
167-
},
168-
},
169-
170-
formSectionInfoTitle: {
141+
const styles = {
142+
formSectionInfoTitle: (theme) => ({
171143
fontSize: 20,
172144
color: theme.palette.text.primary,
173145
fontWeight: 400,
174146
margin: 0,
175147
marginBottom: theme.spacing(1),
176-
},
148+
}),
177149

178-
formSectionInfoTitleAlpha: {
150+
formSectionInfoTitleAlpha: (theme) => ({
179151
display: "flex",
180152
flexDirection: "row",
181153
alignItems: "center",
182154
gap: theme.spacing(1.5),
183-
},
155+
}),
184156

185-
formSectionInfoDescription: {
157+
formSectionInfoDescription: (theme) => ({
186158
fontSize: 14,
187159
color: theme.palette.text.secondary,
188160
lineHeight: "160%",
189161
margin: 0,
190-
},
162+
}),
191163

192164
formSectionFields: {
193165
width: "100%",
194166
},
195-
}));
167+
} satisfies Record<string, Interpolation<Theme>>;
168+
169+
export const FormFooter = (props: Exclude<FormFooterProps, "styles">) => (
170+
<BaseFormFooter {...props} styles={footerStyles} />
171+
);
196172

197-
const useFormFooterStyles = makeStyles((theme) => ({
198-
button: {
173+
const footerStyles = {
174+
button: (theme) => ({
199175
minWidth: theme.spacing(23),
200176

201177
[theme.breakpoints.down("md")]: {
202178
width: "100%",
203179
},
204-
},
205-
footer: {
180+
}),
181+
182+
footer: (theme) => ({
206183
display: "flex",
207184
alignItems: "center",
208185
justifyContent: "flex-start",
@@ -213,5 +190,5 @@ const useFormFooterStyles = makeStyles((theme) => ({
213190
flexDirection: "column",
214191
gap: theme.spacing(1),
215192
},
216-
},
217-
}));
193+
}),
194+
} satisfies FormFooterStyles;

site/src/components/FormFooter/FormFooter.tsx

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import Button from "@mui/material/Button";
2-
import { makeStyles } from "@mui/styles";
3-
import { ClassNameMap } from "@mui/styles/withStyles";
4-
import { FC } from "react";
2+
import { type FC } from "react";
53
import { LoadingButton } from "../LoadingButton/LoadingButton";
4+
import { Interpolation, Theme } from "@emotion/react";
65

76
export const Language = {
87
cancelLabel: "Cancel",
98
defaultSubmitLabel: "Submit",
109
};
1110

12-
type FormFooterStyles = ClassNameMap<"footer" | "button">;
11+
export interface FormFooterStyles {
12+
footer: Interpolation<Theme>;
13+
button: Interpolation<Theme>;
14+
}
15+
1316
export interface FormFooterProps {
1417
onCancel: () => void;
1518
isLoading: boolean;
@@ -23,15 +26,15 @@ export const FormFooter: FC<FormFooterProps> = ({
2326
isLoading,
2427
submitDisabled,
2528
submitLabel = Language.defaultSubmitLabel,
26-
styles = defaultStyles(),
29+
styles = defaultStyles,
2730
}) => {
2831
return (
29-
<div className={styles.footer}>
32+
<div css={styles.footer}>
3033
<LoadingButton
3134
size="large"
3235
tabIndex={0}
3336
loading={isLoading}
34-
className={styles.button}
37+
css={styles.button}
3538
variant="contained"
3639
color="primary"
3740
type="submit"
@@ -43,7 +46,7 @@ export const FormFooter: FC<FormFooterProps> = ({
4346
<Button
4447
size="large"
4548
type="button"
46-
className={styles.button}
49+
css={styles.button}
4750
onClick={onCancel}
4851
tabIndex={0}
4952
>
@@ -53,8 +56,8 @@ export const FormFooter: FC<FormFooterProps> = ({
5356
);
5457
};
5558

56-
const defaultStyles = makeStyles((theme) => ({
57-
footer: {
59+
const defaultStyles = {
60+
footer: (theme) => ({
5861
display: "flex",
5962
flex: "0",
6063
// The first button is the submit so it is the first element to be focused
@@ -63,8 +66,8 @@ const defaultStyles = makeStyles((theme) => ({
6366
gap: theme.spacing(1.5),
6467
alignItems: "center",
6568
marginTop: theme.spacing(3),
66-
},
69+
}),
6770
button: {
6871
width: "100%",
6972
},
70-
}));
73+
} satisfies FormFooterStyles;

0 commit comments

Comments
 (0)