mirror of
https://github.com/coder/coder.git
synced 2025-07-13 21:36:50 +00:00
refactor: Refactor create workspace page (#4862)
This commit is contained in:
@ -47,6 +47,11 @@ const useStyles = makeStyles((theme) => ({
|
||||
"&:hover": {
|
||||
opacity: 1,
|
||||
},
|
||||
|
||||
[theme.breakpoints.down("sm")]: {
|
||||
top: theme.spacing(1),
|
||||
right: theme.spacing(1),
|
||||
},
|
||||
},
|
||||
label: {
|
||||
position: "absolute",
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Button from "@material-ui/core/Button"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { ClassNameMap } from "@material-ui/core/styles/withStyles"
|
||||
import { FC } from "react"
|
||||
import { LoadingButton } from "../LoadingButton/LoadingButton"
|
||||
|
||||
@ -8,36 +9,22 @@ export const Language = {
|
||||
defaultSubmitLabel: "Submit",
|
||||
}
|
||||
|
||||
type FormFooterStyles = ClassNameMap<"footer" | "button">
|
||||
export interface FormFooterProps {
|
||||
onCancel: () => void
|
||||
isLoading: boolean
|
||||
styles?: FormFooterStyles
|
||||
submitLabel?: string
|
||||
submitDisabled?: boolean
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
footer: {
|
||||
display: "flex",
|
||||
flex: "0",
|
||||
// The first button is the submit so it is the first element to be focused
|
||||
// on tab so we use row-reverse to display it on the right
|
||||
flexDirection: "row-reverse",
|
||||
gap: theme.spacing(1.5),
|
||||
alignItems: "center",
|
||||
marginTop: theme.spacing(3),
|
||||
},
|
||||
button: {
|
||||
width: "100%",
|
||||
},
|
||||
}))
|
||||
|
||||
export const FormFooter: FC<React.PropsWithChildren<FormFooterProps>> = ({
|
||||
export const FormFooter: FC<FormFooterProps> = ({
|
||||
onCancel,
|
||||
isLoading,
|
||||
submitLabel = Language.defaultSubmitLabel,
|
||||
submitDisabled,
|
||||
submitLabel = Language.defaultSubmitLabel,
|
||||
styles = defaultStyles(),
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
return (
|
||||
<div className={styles.footer}>
|
||||
<LoadingButton
|
||||
@ -63,3 +50,19 @@ export const FormFooter: FC<React.PropsWithChildren<FormFooterProps>> = ({
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const defaultStyles = makeStyles((theme) => ({
|
||||
footer: {
|
||||
display: "flex",
|
||||
flex: "0",
|
||||
// The first button is the submit so it is the first element to be focused
|
||||
// on tab so we use row-reverse to display it on the right
|
||||
flexDirection: "row-reverse",
|
||||
gap: theme.spacing(1.5),
|
||||
alignItems: "center",
|
||||
marginTop: theme.spacing(3),
|
||||
},
|
||||
button: {
|
||||
width: "100%",
|
||||
},
|
||||
}))
|
||||
|
55
site/src/components/FullPageForm/FullPageHorizontalForm.tsx
Normal file
55
site/src/components/FullPageForm/FullPageHorizontalForm.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
import { FormCloseButton } from "../FormCloseButton/FormCloseButton"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import Typography from "@material-ui/core/Typography"
|
||||
import { Margins } from "components/Margins/Margins"
|
||||
import { FC, ReactNode } from "react"
|
||||
|
||||
export interface FormTitleProps {
|
||||
title: string
|
||||
detail?: ReactNode
|
||||
}
|
||||
|
||||
export interface FullPageHorizontalFormProps {
|
||||
title: string
|
||||
detail?: ReactNode
|
||||
onCancel: () => void
|
||||
}
|
||||
|
||||
export const FullPageHorizontalForm: FC<
|
||||
React.PropsWithChildren<FullPageHorizontalFormProps>
|
||||
> = ({ title, detail, onCancel, children }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
<>
|
||||
<header className={styles.title}>
|
||||
<Margins size="medium">
|
||||
<Typography variant="h3">{title}</Typography>
|
||||
{detail && <Typography variant="caption">{detail}</Typography>}
|
||||
</Margins>
|
||||
</header>
|
||||
|
||||
<FormCloseButton onClose={onCancel} />
|
||||
|
||||
<main className={styles.main}>
|
||||
<Margins size="medium">{children}</Margins>
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
title: {
|
||||
paddingTop: theme.spacing(6),
|
||||
paddingBottom: theme.spacing(8),
|
||||
|
||||
[theme.breakpoints.down("sm")]: {
|
||||
paddingTop: theme.spacing(4),
|
||||
paddingBottom: theme.spacing(4),
|
||||
},
|
||||
},
|
||||
|
||||
main: {
|
||||
paddingBottom: theme.spacing(10),
|
||||
},
|
||||
}))
|
@ -1,12 +1,16 @@
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { FC } from "react"
|
||||
import { containerWidth, sidePadding } from "../../theme/constants"
|
||||
import {
|
||||
containerWidth,
|
||||
containerWidthMedium,
|
||||
sidePadding,
|
||||
} from "../../theme/constants"
|
||||
|
||||
type Size = "regular" | "medium" | "small"
|
||||
|
||||
const widthBySize: Record<Size, number> = {
|
||||
regular: containerWidth,
|
||||
medium: containerWidth / 2,
|
||||
medium: containerWidthMedium,
|
||||
small: containerWidth / 3,
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@ import TextField from "@material-ui/core/TextField"
|
||||
import { Stack } from "components/Stack/Stack"
|
||||
import { FC } from "react"
|
||||
import { ParameterSchema } from "../../api/typesGenerated"
|
||||
import { MONOSPACE_FONT_FAMILY } from "../../theme/constants"
|
||||
|
||||
const isBoolean = (schema: ParameterSchema) => {
|
||||
return schema.validation_value_type === "bool"
|
||||
@ -16,12 +15,18 @@ const isBoolean = (schema: ParameterSchema) => {
|
||||
const ParameterLabel: React.FC<{ schema: ParameterSchema }> = ({ schema }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
if (schema.name && schema.description) {
|
||||
return (
|
||||
<label className={styles.label} htmlFor={schema.name}>
|
||||
<strong>var.{schema.name}</strong>
|
||||
{schema.description && (
|
||||
<label htmlFor={schema.name}>
|
||||
<span className={styles.labelName}>var.{schema.name}</span>
|
||||
<span className={styles.labelDescription}>{schema.description}</span>
|
||||
)}
|
||||
</label>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<label htmlFor={schema.name}>
|
||||
<span className={styles.labelDescription}>var.{schema.name}</span>
|
||||
</label>
|
||||
)
|
||||
}
|
||||
@ -38,7 +43,7 @@ export const ParameterInput: FC<
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
<Stack direction="column" className={styles.root}>
|
||||
<Stack direction="column" spacing={0.75}>
|
||||
<ParameterLabel schema={schema} />
|
||||
<div className={styles.input}>
|
||||
<ParameterField
|
||||
@ -119,19 +124,17 @@ const ParameterField: React.FC<
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
fontFamily: MONOSPACE_FONT_FAMILY,
|
||||
paddingTop: theme.spacing(2),
|
||||
paddingBottom: theme.spacing(2),
|
||||
},
|
||||
label: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
fontSize: 21,
|
||||
labelName: {
|
||||
fontSize: 14,
|
||||
color: theme.palette.text.secondary,
|
||||
display: "block",
|
||||
marginBottom: theme.spacing(0.5),
|
||||
},
|
||||
labelDescription: {
|
||||
fontSize: 14,
|
||||
marginTop: theme.spacing(1),
|
||||
fontSize: 16,
|
||||
color: theme.palette.text.primary,
|
||||
display: "block",
|
||||
fontWeight: 600,
|
||||
},
|
||||
input: {
|
||||
display: "flex",
|
||||
|
@ -6,7 +6,6 @@ import { AlertBanner } from "components/AlertBanner/AlertBanner"
|
||||
import { Stack } from "components/Stack/Stack"
|
||||
import { FC } from "react"
|
||||
import * as TypesGen from "../../api/typesGenerated"
|
||||
import { MONOSPACE_FONT_FAMILY } from "../../theme/constants"
|
||||
|
||||
export const Language = {
|
||||
of: "of",
|
||||
@ -27,7 +26,7 @@ export const WorkspaceQuota: FC<WorkspaceQuotaProps> = ({ quota, error }) => {
|
||||
return (
|
||||
<Box>
|
||||
<Stack spacing={1} className={styles.stack}>
|
||||
<span className={styles.title}>Workspace Quota</span>
|
||||
<span className={styles.title}>Usage Quota</span>
|
||||
<AlertBanner severity="error" error={error} />
|
||||
</Stack>
|
||||
</Box>
|
||||
@ -39,7 +38,7 @@ export const WorkspaceQuota: FC<WorkspaceQuotaProps> = ({ quota, error }) => {
|
||||
return (
|
||||
<Box>
|
||||
<Stack spacing={1} className={styles.stack}>
|
||||
<span className={styles.title}>Workspace Quota</span>
|
||||
<span className={styles.title}>Usage quota</span>
|
||||
<LinearProgress color="primary" />
|
||||
<div className={styles.label}>
|
||||
<Skeleton className={styles.skeleton} />
|
||||
@ -64,8 +63,23 @@ export const WorkspaceQuota: FC<WorkspaceQuotaProps> = ({ quota, error }) => {
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Stack spacing={1} className={styles.stack}>
|
||||
<span className={styles.title}>Workspace Quota</span>
|
||||
<Stack spacing={1.5} className={styles.stack}>
|
||||
<Stack direction="row" justifyContent="space-between">
|
||||
<span className={styles.title}>Usage Quota</span>
|
||||
<div className={styles.label}>
|
||||
<span className={styles.labelHighlight}>
|
||||
{quota.user_workspace_count}
|
||||
</span>{" "}
|
||||
{Language.of}{" "}
|
||||
<span className={styles.labelHighlight}>
|
||||
{quota.user_workspace_limit}
|
||||
</span>{" "}
|
||||
{quota.user_workspace_limit === 1
|
||||
? Language.workspace
|
||||
: Language.workspaces}
|
||||
{" used"}
|
||||
</div>
|
||||
</Stack>
|
||||
<LinearProgress
|
||||
className={
|
||||
quota.user_workspace_count >= quota.user_workspace_limit
|
||||
@ -75,14 +89,6 @@ export const WorkspaceQuota: FC<WorkspaceQuotaProps> = ({ quota, error }) => {
|
||||
value={value}
|
||||
variant="determinate"
|
||||
/>
|
||||
<div className={styles.label}>
|
||||
{quota.user_workspace_count} {Language.of}{" "}
|
||||
{quota.user_workspace_limit}{" "}
|
||||
{quota.user_workspace_limit === 1
|
||||
? Language.workspace
|
||||
: Language.workspaces}
|
||||
{" used"}
|
||||
</div>
|
||||
</Stack>
|
||||
</Box>
|
||||
)
|
||||
@ -101,18 +107,16 @@ const useStyles = makeStyles((theme) => ({
|
||||
},
|
||||
},
|
||||
title: {
|
||||
fontFamily: MONOSPACE_FONT_FAMILY,
|
||||
fontSize: 21,
|
||||
paddingBottom: "8px",
|
||||
fontSize: 16,
|
||||
},
|
||||
label: {
|
||||
fontFamily: MONOSPACE_FONT_FAMILY,
|
||||
fontSize: 12,
|
||||
textTransform: "uppercase",
|
||||
fontSize: 14,
|
||||
display: "block",
|
||||
fontWeight: 600,
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
labelHighlight: {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
skeleton: {
|
||||
minWidth: "150px",
|
||||
},
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"templateLabel": "Template",
|
||||
"nameLabel": "Name",
|
||||
"ownerLabel": "Workspace Owner"
|
||||
"nameLabel": "Workspace Name",
|
||||
"ownerLabel": "Owner",
|
||||
"createWorkspace": "Create workspace"
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
import { fireEvent, screen, waitFor } from "@testing-library/react"
|
||||
import userEvent from "@testing-library/user-event"
|
||||
import * as API from "api/api"
|
||||
import { Language as FooterLanguage } from "components/FormFooter/FormFooter"
|
||||
import i18next from "i18next"
|
||||
import {
|
||||
MockTemplate,
|
||||
@ -17,6 +16,7 @@ import CreateWorkspacePage from "./CreateWorkspacePage"
|
||||
const { t } = i18next
|
||||
|
||||
const nameLabelText = t("nameLabel", { ns: "createWorkspacePage" })
|
||||
const createWorkspaceText = t("createWorkspace", { ns: "createWorkspacePage" })
|
||||
|
||||
const renderCreateWorkspacePage = () => {
|
||||
return renderWithAuth(<CreateWorkspacePage />, {
|
||||
@ -48,7 +48,7 @@ describe("CreateWorkspacePage", () => {
|
||||
target: { value: "test" },
|
||||
})
|
||||
|
||||
const submitButton = screen.getByText(FooterLanguage.defaultSubmitLabel)
|
||||
const submitButton = screen.getByText(createWorkspaceText)
|
||||
userEvent.click(submitButton)
|
||||
|
||||
await waitFor(() =>
|
||||
|
@ -25,7 +25,6 @@ const CreateWorkspacePage: FC = () => {
|
||||
shallowEqual,
|
||||
)
|
||||
const workspaceQuotaEnabled = featureVisibility[FeatureNames.WorkspaceQuota]
|
||||
|
||||
const [authState] = useActor(xServices.authXService)
|
||||
const { me } = authState.context
|
||||
const [createWorkspaceState, send] = useMachine(createWorkspaceMachine, {
|
||||
@ -89,7 +88,8 @@ const CreateWorkspacePage: FC = () => {
|
||||
})
|
||||
}}
|
||||
onCancel={() => {
|
||||
navigate("/templates")
|
||||
// Go back
|
||||
navigate(-1)
|
||||
}}
|
||||
onSubmit={(request) => {
|
||||
send({
|
||||
|
@ -1,8 +1,6 @@
|
||||
import TextField from "@material-ui/core/TextField"
|
||||
import * as TypesGen from "api/typesGenerated"
|
||||
import { FormFooter } from "components/FormFooter/FormFooter"
|
||||
import { FullPageForm } from "components/FullPageForm/FullPageForm"
|
||||
import { Loader } from "components/Loader/Loader"
|
||||
import { ParameterInput } from "components/ParameterInput/ParameterInput"
|
||||
import { Stack } from "components/Stack/Stack"
|
||||
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"
|
||||
@ -14,6 +12,9 @@ import { useTranslation } from "react-i18next"
|
||||
import { getFormHelpers, nameValidator, onChangeTrimmed } from "util/formUtils"
|
||||
import * as Yup from "yup"
|
||||
import { AlertBanner } from "components/AlertBanner/AlertBanner"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { FullPageHorizontalForm } from "components/FullPageForm/FullPageHorizontalForm"
|
||||
import { FullScreenLoader } from "components/Loader/FullScreenLoader"
|
||||
|
||||
export enum CreateWorkspaceErrors {
|
||||
GET_TEMPLATES_ERROR = "getTemplatesError",
|
||||
@ -52,7 +53,8 @@ export const CreateWorkspacePageView: FC<
|
||||
React.PropsWithChildren<CreateWorkspacePageViewProps>
|
||||
> = (props) => {
|
||||
const { t } = useTranslation("createWorkspacePage")
|
||||
|
||||
const styles = useStyles()
|
||||
const formFooterStyles = useFormFooterStyles()
|
||||
const [parameterValues, setParameterValues] = useState<
|
||||
Record<string, string>
|
||||
>({})
|
||||
@ -92,11 +94,23 @@ export const CreateWorkspacePageView: FC<
|
||||
},
|
||||
})
|
||||
|
||||
const canSubmit =
|
||||
props.workspaceQuota && props.workspaceQuota.user_workspace_limit > 0
|
||||
? props.workspaceQuota.user_workspace_count <
|
||||
props.workspaceQuota.user_workspace_limit
|
||||
: true
|
||||
|
||||
const isLoading = props.loadingTemplateSchema || props.loadingTemplates
|
||||
|
||||
const getFieldHelpers = getFormHelpers<TypesGen.CreateWorkspaceRequest>(
|
||||
form,
|
||||
props.createWorkspaceErrors[CreateWorkspaceErrors.CREATE_WORKSPACE_ERROR],
|
||||
)
|
||||
|
||||
if (isLoading) {
|
||||
return <FullScreenLoader />
|
||||
}
|
||||
|
||||
if (props.hasTemplateErrors) {
|
||||
return (
|
||||
<Stack>
|
||||
@ -132,21 +146,10 @@ export const CreateWorkspacePageView: FC<
|
||||
)
|
||||
}
|
||||
|
||||
const canSubmit =
|
||||
props.workspaceQuota && props.workspaceQuota.user_workspace_limit > 0
|
||||
? props.workspaceQuota.user_workspace_count <
|
||||
props.workspaceQuota.user_workspace_limit
|
||||
: true
|
||||
|
||||
if (
|
||||
props.createWorkspaceErrors[CreateWorkspaceErrors.CREATE_WORKSPACE_ERROR]
|
||||
) {
|
||||
return (
|
||||
<FullPageForm title="Create workspace" onCancel={props.onCancel}>
|
||||
<form onSubmit={form.handleSubmit}>
|
||||
<Stack>
|
||||
{Boolean(
|
||||
props.createWorkspaceErrors[
|
||||
CreateWorkspaceErrors.CREATE_WORKSPACE_ERROR
|
||||
],
|
||||
) && (
|
||||
<AlertBanner
|
||||
severity="error"
|
||||
error={
|
||||
@ -155,18 +158,50 @@ export const CreateWorkspacePageView: FC<
|
||||
]
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<TextField
|
||||
disabled
|
||||
fullWidth
|
||||
label={t("templateLabel")}
|
||||
value={props.selectedTemplate?.name || props.templateName}
|
||||
variant="outlined"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<FullPageHorizontalForm title="New workspace" onCancel={props.onCancel}>
|
||||
<form onSubmit={form.handleSubmit}>
|
||||
<Stack direction="column" spacing={10} className={styles.formSections}>
|
||||
{/* General info */}
|
||||
<div className={styles.formSection}>
|
||||
<div className={styles.formSectionInfo}>
|
||||
<h2 className={styles.formSectionInfoTitle}>General info</h2>
|
||||
<p className={styles.formSectionInfoDescription}>
|
||||
The template and name of your new workspace.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Stack
|
||||
direction="column"
|
||||
spacing={1}
|
||||
className={styles.formSectionFields}
|
||||
>
|
||||
{props.selectedTemplate && (
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={2}
|
||||
className={styles.template}
|
||||
alignItems="center"
|
||||
>
|
||||
<div className={styles.templateIcon}>
|
||||
<img src={props.selectedTemplate.icon} alt="" />
|
||||
</div>
|
||||
<Stack direction="column" spacing={0.5}>
|
||||
<span className={styles.templateName}>
|
||||
{props.selectedTemplate.name}
|
||||
</span>
|
||||
{props.selectedTemplate.description && (
|
||||
<span className={styles.templateDescription}>
|
||||
{props.selectedTemplate.description}
|
||||
</span>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
{props.loadingTemplateSchema && <Loader />}
|
||||
{props.selectedTemplate && props.templateSchema && (
|
||||
<>
|
||||
<TextField
|
||||
{...getFieldHelpers("name")}
|
||||
disabled={form.isSubmitting}
|
||||
@ -176,8 +211,25 @@ export const CreateWorkspacePageView: FC<
|
||||
label={t("nameLabel")}
|
||||
variant="outlined"
|
||||
/>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
{/* Workspace owner */}
|
||||
{props.canCreateForUser && (
|
||||
<div className={styles.formSection}>
|
||||
<div className={styles.formSectionInfo}>
|
||||
<h2 className={styles.formSectionInfoTitle}>Workspace owner</h2>
|
||||
<p className={styles.formSectionInfoDescription}>
|
||||
The user that is going to own this workspace. If you are
|
||||
admin, you can create workspace for others.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Stack
|
||||
direction="column"
|
||||
spacing={1}
|
||||
className={styles.formSectionFields}
|
||||
>
|
||||
<UserAutocomplete
|
||||
value={props.owner}
|
||||
onChange={props.setOwner}
|
||||
@ -185,7 +237,6 @@ export const CreateWorkspacePageView: FC<
|
||||
inputMargin="dense"
|
||||
showAvatar
|
||||
/>
|
||||
)}
|
||||
|
||||
{props.workspaceQuota && (
|
||||
<WorkspaceQuota
|
||||
@ -197,9 +248,26 @@ export const CreateWorkspacePageView: FC<
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{props.templateSchema.length > 0 && (
|
||||
<Stack>
|
||||
{/* Template params */}
|
||||
{props.templateSchema && props.templateSchema.length > 0 && (
|
||||
<div className={styles.formSection}>
|
||||
<div className={styles.formSectionInfo}>
|
||||
<h2 className={styles.formSectionInfoTitle}>Template params</h2>
|
||||
<p className={styles.formSectionInfoDescription}>
|
||||
Those values are provided by your template‘s Terraform
|
||||
configuration.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Stack
|
||||
direction="column"
|
||||
spacing={4} // Spacing here is diff because the fields here don't have the MUI floating label spacing
|
||||
className={styles.formSectionFields}
|
||||
>
|
||||
{props.templateSchema.map((schema) => (
|
||||
<ParameterInput
|
||||
disabled={form.isSubmitting}
|
||||
@ -214,17 +282,115 @@ export const CreateWorkspacePageView: FC<
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<FormFooter
|
||||
styles={formFooterStyles}
|
||||
onCancel={props.onCancel}
|
||||
isLoading={props.creatingWorkspace}
|
||||
submitDisabled={!canSubmit}
|
||||
submitLabel={t("createWorkspace")}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</form>
|
||||
</FullPageForm>
|
||||
</FullPageHorizontalForm>
|
||||
)
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
formSections: {
|
||||
[theme.breakpoints.down("sm")]: {
|
||||
gap: theme.spacing(8),
|
||||
},
|
||||
},
|
||||
|
||||
formSection: {
|
||||
display: "flex",
|
||||
alignItems: "flex-start",
|
||||
gap: theme.spacing(15),
|
||||
|
||||
[theme.breakpoints.down("sm")]: {
|
||||
flexDirection: "column",
|
||||
gap: theme.spacing(2),
|
||||
},
|
||||
},
|
||||
|
||||
formSectionInfo: {
|
||||
width: 312,
|
||||
flexShrink: 0,
|
||||
position: "sticky",
|
||||
top: theme.spacing(3),
|
||||
|
||||
[theme.breakpoints.down("sm")]: {
|
||||
width: "100%",
|
||||
position: "initial",
|
||||
},
|
||||
},
|
||||
|
||||
formSectionInfoTitle: {
|
||||
fontSize: 20,
|
||||
color: theme.palette.text.primary,
|
||||
fontWeight: 400,
|
||||
margin: 0,
|
||||
marginBottom: theme.spacing(1),
|
||||
},
|
||||
|
||||
formSectionInfoDescription: {
|
||||
fontSize: 14,
|
||||
color: theme.palette.text.secondary,
|
||||
lineHeight: "160%",
|
||||
margin: 0,
|
||||
},
|
||||
|
||||
formSectionFields: {
|
||||
width: "100%",
|
||||
},
|
||||
|
||||
template: {
|
||||
padding: theme.spacing(2.5, 3),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
},
|
||||
|
||||
templateName: {
|
||||
fontSize: 16,
|
||||
},
|
||||
|
||||
templateDescription: {
|
||||
fontSize: 14,
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
|
||||
templateIcon: {
|
||||
width: theme.spacing(5),
|
||||
lineHeight: 1,
|
||||
|
||||
"& img": {
|
||||
width: "100%",
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
const useFormFooterStyles = makeStyles((theme) => ({
|
||||
button: {
|
||||
minWidth: theme.spacing(23),
|
||||
|
||||
[theme.breakpoints.down("sm")]: {
|
||||
width: "100%",
|
||||
},
|
||||
},
|
||||
footer: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-start",
|
||||
flexDirection: "row-reverse",
|
||||
gap: theme.spacing(2),
|
||||
|
||||
[theme.breakpoints.down("sm")]: {
|
||||
flexDirection: "column",
|
||||
gap: theme.spacing(1),
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
@ -9,6 +9,7 @@ export const lightButtonShadow = "0 2px 2px rgba(0, 23, 121, 0.08)"
|
||||
export const emptyBoxShadow = "none"
|
||||
export const navHeight = 62
|
||||
export const containerWidth = 1380
|
||||
export const containerWidthMedium = 1080
|
||||
export const sidePadding = 24
|
||||
export const TitleIconSize = 48
|
||||
export const CardRadius = 2
|
||||
|
@ -203,5 +203,10 @@ export const getOverrides = ({
|
||||
backgroundColor: palette.divider,
|
||||
},
|
||||
},
|
||||
MuiLinearProgress: {
|
||||
root: {
|
||||
borderRadius: 999,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user