Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitfcac4ab

Browse files
authored
fix(site): standardize headers for Admin Settings page (#16911)
## Changes made- Switched almost all headers to use the `SettingHeader` component- Redesigned component to be more composition-based, to stay in linewith the patterns we're starting to use more throughout the codebase- Refactored `SettingHeader` to be based on Radix and Tailwind, ratherthan Emotion/MUI- Added additional props to `SettingHeader` to help resolve issues withthe component creating invalid HTML- Beefed up `SettingHeader` to have better out-of-the-box accessibility- Addressed some typographic problems in `SettingHeader`- Addressed some responsive layout problems for `SettingsHeader`- Added first-ever stories for `SettingsHeader`## Notes- There are still a few headers that aren't using `SettingHeader` yet.There were some UI edge cases that meant I couldn't reliably bring it inwithout consulting the Design team first. I'm a little less worriedabout them, because they at least *look* like the other headers, butit'd be nice if we could centralize everything in a followup PR
1 parent1e11e82 commitfcac4ab

File tree

27 files changed

+556
-246
lines changed

27 files changed

+556
-246
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
importtype{Meta,StoryObj}from"@storybook/react";
2+
import{docs}from"utils/docs";
3+
import{
4+
SettingsHeader,
5+
SettingsHeaderDescription,
6+
SettingsHeaderDocsLink,
7+
SettingsHeaderTitle,
8+
}from"./SettingsHeader";
9+
10+
constmeta:Meta<typeofSettingsHeader>={
11+
title:"components/SettingsHeader",
12+
component:SettingsHeader,
13+
};
14+
15+
exportdefaultmeta;
16+
typeStory=StoryObj<typeofSettingsHeader>;
17+
18+
exportconstPrimaryHeaderOnly:Story={
19+
args:{
20+
children:<SettingsHeaderTitle>This is a header</SettingsHeaderTitle>,
21+
},
22+
};
23+
24+
exportconstPrimaryHeaderWithDescription:Story={
25+
args:{
26+
children:(
27+
<>
28+
<SettingsHeaderTitle>Another primary header</SettingsHeaderTitle>
29+
<SettingsHeaderDescription>
30+
This description can be any ReactNode. This provides more options for
31+
composition.
32+
</SettingsHeaderDescription>
33+
</>
34+
),
35+
},
36+
};
37+
38+
exportconstPrimaryHeaderWithDescriptionAndDocsLink:Story={
39+
args:{
40+
children:(
41+
<>
42+
<SettingsHeaderTitle>Another primary header</SettingsHeaderTitle>
43+
<SettingsHeaderDescription>
44+
This description can be any ReactNode. This provides more options for
45+
composition.
46+
</SettingsHeaderDescription>
47+
</>
48+
),
49+
actions:<SettingsHeaderDocsLinkhref={docs("/admin/external-auth")}/>,
50+
},
51+
};
52+
53+
exportconstSecondaryHeaderWithDescription:Story={
54+
args:{
55+
children:(
56+
<>
57+
<SettingsHeaderTitlelevel="h6"hierarchy="secondary">
58+
This is a secondary header.
59+
</SettingsHeaderTitle>
60+
<SettingsHeaderDescription>
61+
The header's styling is completely independent of its semantics. Both
62+
can be adjusted independently to help avoid invalid HTML.
63+
</SettingsHeaderDescription>
64+
</>
65+
),
66+
},
67+
};
68+
69+
exportconstSecondaryHeaderWithDescriptionAndDocsLink:Story={
70+
args:{
71+
children:(
72+
<>
73+
<SettingsHeaderTitlelevel="h3"hierarchy="secondary">
74+
Another secondary header
75+
</SettingsHeaderTitle>
76+
<SettingsHeaderDescription>
77+
Nothing to add, really.
78+
</SettingsHeaderDescription>
79+
</>
80+
),
81+
actions:<SettingsHeaderDocsLinkhref={docs("/admin/external-auth")}/>,
82+
},
83+
};
Lines changed: 97 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,107 @@
1-
import{useTheme}from"@emotion/react";
1+
import{typeVariantProps,cva}from"class-variance-authority";
22
import{Button}from"components/Button/Button";
3-
import{Stack}from"components/Stack/Stack";
43
import{SquareArrowOutUpRightIcon}from"lucide-react";
5-
importtype{FC,ReactNode}from"react";
4+
importtype{FC,PropsWithChildren,ReactNode}from"react";
5+
import{cn}from"utils/cn";
66

7-
interfaceHeaderProps{
8-
title:ReactNode;
9-
description?:ReactNode;
10-
secondary?:boolean;
11-
docsHref?:string;
12-
tooltip?:ReactNode;
13-
}
14-
15-
exportconstSettingsHeader:FC<HeaderProps>=({
16-
title,
17-
description,
18-
docsHref,
19-
secondary,
20-
tooltip,
7+
typeSettingsHeaderProps=Readonly<
8+
PropsWithChildren<{
9+
actions?:ReactNode;
10+
className?:string;
11+
}>
12+
>;
13+
exportconstSettingsHeader:FC<SettingsHeaderProps>=({
14+
children,
15+
actions,
16+
className,
2117
})=>{
22-
consttheme=useTheme();
18+
return(
19+
<hgroupclassName="flex flex-col justify-between items-start gap-2 pb-6 sm:flex-row">
20+
{/*
21+
* The text-sm class is only meant to adjust the font size of
22+
* SettingsDescription, but we need to apply it here. That way,
23+
* text-sm combines with the max-w-prose class and makes sure
24+
* we have a predictable max width for the header + description by
25+
* default.
26+
*/}
27+
<divclassName={cn("text-sm max-w-prose",className)}>{children}</div>
28+
{actions}
29+
</hgroup>
30+
);
31+
};
2332

33+
typeSettingsHeaderDocsLinkProps=Readonly<
34+
PropsWithChildren<{href:string}>
35+
>;
36+
exportconstSettingsHeaderDocsLink:FC<SettingsHeaderDocsLinkProps>=({
37+
href,
38+
children="Read the docs",
39+
})=>{
2440
return(
25-
<StackalignItems="baseline"direction="row"justifyContent="space-between">
26-
<divcss={{maxWidth:420,marginBottom:24}}>
27-
<Stackdirection="row"spacing={1}alignItems="center">
28-
<h1
29-
css={[
30-
{
31-
fontSize:32,
32-
fontWeight:700,
33-
display:"flex",
34-
alignItems:"baseline",
35-
lineHeight:"initial",
36-
margin:0,
37-
marginBottom:4,
38-
gap:8,
39-
},
40-
secondary&&{
41-
fontSize:24,
42-
fontWeight:500,
43-
},
44-
]}
45-
>
46-
{title}
47-
</h1>
48-
{tooltip}
49-
</Stack>
41+
<ButtonasChildvariant="outline">
42+
<ahref={href}target="_blank"rel="noreferrer">
43+
<SquareArrowOutUpRightIcon/>
44+
{children}
45+
<spanclassName="sr-only"> (link opens in new tab)</span>
46+
</a>
47+
</Button>
48+
);
49+
};
5050

51-
{description&&(
52-
<span
53-
css={{
54-
fontSize:14,
55-
color:theme.palette.text.secondary,
56-
lineHeight:"160%",
57-
}}
58-
>
59-
{description}
60-
</span>
61-
)}
62-
</div>
51+
consttitleVariants=cva("m-0 pb-1 flex items-center gap-2 leading-tight",{
52+
variants:{
53+
hierarchy:{
54+
primary:"text-3xl font-bold",
55+
secondary:"text-2xl font-medium",
56+
},
57+
},
58+
defaultVariants:{
59+
hierarchy:"primary",
60+
},
61+
});
62+
typeSettingsHeaderTitleProps=Readonly<
63+
PropsWithChildren<
64+
VariantProps<typeoftitleVariants>&{
65+
level?: `h${1|2|3|4|5|6}`;
66+
tooltip?:ReactNode;
67+
className?:string;
68+
}
69+
>
70+
>;
71+
exportconstSettingsHeaderTitle:FC<SettingsHeaderTitleProps>=({
72+
children,
73+
tooltip,
74+
className,
75+
level="h1",
76+
hierarchy="primary",
77+
})=>{
78+
// Explicitly not using Radix's Slot component, because we don't want to
79+
// allow any arbitrary element to be composed into this. We specifically
80+
// only want to allow the six HTML headers. Anything else will likely result
81+
// in invalid markup
82+
constTitle=level;
83+
return(
84+
<divclassName="flex flex-row gap-2 items-center">
85+
<TitleclassName={cn(titleVariants({ hierarchy}),className)}>
86+
{children}
87+
</Title>
88+
{tooltip}
89+
</div>
90+
);
91+
};
6392

64-
{docsHref&&(
65-
<ButtonasChildvariant="outline">
66-
<ahref={docsHref}target="_blank"rel="noreferrer">
67-
<SquareArrowOutUpRightIcon/>
68-
Read the docs
69-
</a>
70-
</Button>
71-
)}
72-
</Stack>
93+
typeSettingsHeaderDescriptionProps=Readonly<
94+
PropsWithChildren<{
95+
className?:string;
96+
}>
97+
>;
98+
exportconstSettingsHeaderDescription:FC<SettingsHeaderDescriptionProps>=({
99+
children,
100+
className,
101+
})=>{
102+
return(
103+
<pclassName={cn("m-0 text-content-secondary leading-relaxed",className)}>
104+
{children}
105+
</p>
73106
);
74107
};

‎site/src/pages/DeploymentSettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import {
88
}from"components/Badges/Badges";
99
import{Button}from"components/Button/Button";
1010
import{PopoverPaywall}from"components/Paywall/PopoverPaywall";
11-
import{SettingsHeader}from"components/SettingsHeader/SettingsHeader";
11+
import{
12+
SettingsHeader,
13+
SettingsHeaderDescription,
14+
SettingsHeaderTitle,
15+
}from"components/SettingsHeader/SettingsHeader";
1216
import{
1317
Popover,
1418
PopoverContent,
@@ -54,10 +58,12 @@ export const AppearanceSettingsPageView: FC<
5458

5559
return(
5660
<>
57-
<SettingsHeader
58-
title="Appearance"
59-
description="Customize the look and feel of your Coder deployment."
60-
/>
61+
<SettingsHeader>
62+
<SettingsHeaderTitle>Appearance</SettingsHeaderTitle>
63+
<SettingsHeaderDescription>
64+
Customize the look and feel of your Coder deployment.
65+
</SettingsHeaderDescription>
66+
</SettingsHeader>
6167

6268
<Badges>
6369
<Popovermode="hover">

‎site/src/pages/DeploymentSettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ import TableRow from "@mui/material/TableRow";
88
importtype{DeploymentValues,ExternalAuthConfig}from"api/typesGenerated";
99
import{Alert}from"components/Alert/Alert";
1010
import{PremiumBadge}from"components/Badges/Badges";
11-
import{SettingsHeader}from"components/SettingsHeader/SettingsHeader";
11+
import{
12+
SettingsHeader,
13+
SettingsHeaderDescription,
14+
SettingsHeaderDocsLink,
15+
SettingsHeaderTitle,
16+
}from"components/SettingsHeader/SettingsHeader";
1217
importtype{FC}from"react";
1318
import{docs}from"utils/docs";
1419

@@ -22,10 +27,14 @@ export const ExternalAuthSettingsPageView: FC<
2227
return(
2328
<>
2429
<SettingsHeader
25-
title="External Authentication"
26-
description="Coder integrates with GitHub, GitLab, BitBucket, Azure Repos, and OpenID Connect to authenticate developers with external services."
27-
docsHref={docs("/admin/external-auth")}
28-
/>
30+
actions={<SettingsHeaderDocsLinkhref={docs("/admin/external-auth")}/>}
31+
>
32+
<SettingsHeaderTitle>External Authentication</SettingsHeaderTitle>
33+
<SettingsHeaderDescription>
34+
Coder integrates with GitHub, GitLab, BitBucket, Azure Repos, and
35+
OpenID Connect to authenticate developers with external services.
36+
</SettingsHeaderDescription>
37+
</SettingsHeader>
2938

3039
<video
3140
autoPlay

‎site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/AddNewLicensePageView.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ import { ErrorAlert } from "components/Alert/ErrorAlert";
33
import{Button}from"components/Button/Button";
44
import{FileUpload}from"components/FileUpload/FileUpload";
55
import{displayError}from"components/GlobalSnackbar/utils";
6-
import{SettingsHeader}from"components/SettingsHeader/SettingsHeader";
6+
import{
7+
SettingsHeader,
8+
SettingsHeaderDescription,
9+
SettingsHeaderTitle,
10+
}from"components/SettingsHeader/SettingsHeader";
711
import{Stack}from"components/Stack/Stack";
812
import{ChevronLeftIcon}from"lucide-react";
913
importtype{FC}from"react";
@@ -50,10 +54,13 @@ export const AddNewLicensePageView: FC<AddNewLicenseProps> = ({
5054
direction="row"
5155
justifyContent="space-between"
5256
>
53-
<SettingsHeader
54-
title="Add a license"
55-
description="Get access to high availability, RBAC, quotas, and more."
56-
/>
57+
<SettingsHeader>
58+
<SettingsHeaderTitle>Add a license</SettingsHeaderTitle>
59+
<SettingsHeaderDescription>
60+
Get access to high availability, RBAC, quotas, and more.
61+
</SettingsHeaderDescription>
62+
</SettingsHeader>
63+
5764
<ButtonasChildvariant="outline">
5865
<RouterLinkto="/deployment/licenses">
5966
<ChevronLeftIcon/>

‎site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import Skeleton from "@mui/material/Skeleton";
88
importTooltipfrom"@mui/material/Tooltip";
99
importtype{GetLicensesResponse}from"api/api";
1010
importtype{UserStatusChangeCount}from"api/typesGenerated";
11-
import{SettingsHeader}from"components/SettingsHeader/SettingsHeader";
11+
import{
12+
SettingsHeader,
13+
SettingsHeaderDescription,
14+
SettingsHeaderTitle,
15+
}from"components/SettingsHeader/SettingsHeader";
1216
import{Stack}from"components/Stack/Stack";
1317
import{useWindowSize}from"hooks/useWindowSize";
1418
importtype{FC}from"react";
@@ -60,10 +64,12 @@ const LicensesSettingsPageView: FC<Props> = ({
6064
direction="row"
6165
justifyContent="space-between"
6266
>
63-
<SettingsHeader
64-
title="Licenses"
65-
description="Manage licenses to unlock Premium features."
66-
/>
67+
<SettingsHeader>
68+
<SettingsHeaderTitle>Licenses</SettingsHeaderTitle>
69+
<SettingsHeaderDescription>
70+
Manage licenses to unlock Premium features.
71+
</SettingsHeaderDescription>
72+
</SettingsHeader>
6773

6874
<Stackdirection="row"spacing={2}>
6975
<Button

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp