Skip to content

Commit 7eb228e

Browse files
authored
feat: popover paywall in appearance settings (#13217)
1 parent 6182ee9 commit 7eb228e

File tree

3 files changed

+165
-1
lines changed

3 files changed

+165
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import { PopoverPaywall } from "./PopoverPaywall";
3+
4+
const meta: Meta<typeof PopoverPaywall> = {
5+
title: "components/Paywall/PopoverPaywall",
6+
component: PopoverPaywall,
7+
};
8+
9+
export default meta;
10+
type Story = StoryObj<typeof PopoverPaywall>;
11+
12+
const Example: Story = {
13+
args: {
14+
message: "Black Lotus",
15+
description:
16+
"Adds 3 mana of any single color of your choice to your mana pool, then is discarded. Tapping this artifact can be played as an interrupt.",
17+
},
18+
};
19+
20+
export { Example as PopoverPaywall };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import type { Interpolation, Theme } from "@emotion/react";
2+
import TaskAltIcon from "@mui/icons-material/TaskAlt";
3+
import Button from "@mui/material/Button";
4+
import Link from "@mui/material/Link";
5+
import type { FC, ReactNode } from "react";
6+
import { EnterpriseBadge } from "components/Badges/Badges";
7+
import { Stack } from "components/Stack/Stack";
8+
import { docs } from "utils/docs";
9+
10+
export interface PopoverPaywallProps {
11+
message: string;
12+
description?: ReactNode;
13+
documentationLink?: string;
14+
}
15+
16+
export const PopoverPaywall: FC<PopoverPaywallProps> = ({
17+
message,
18+
description,
19+
documentationLink,
20+
}) => {
21+
return (
22+
<div css={styles.root}>
23+
<div>
24+
<Stack direction="row" alignItems="center" css={{ marginBottom: 18 }}>
25+
<h5 css={styles.title}>{message}</h5>
26+
<EnterpriseBadge />
27+
</Stack>
28+
29+
{description && <p css={styles.description}>{description}</p>}
30+
<Link
31+
href={documentationLink}
32+
target="_blank"
33+
rel="noreferrer"
34+
css={{ fontWeight: 600 }}
35+
>
36+
Read the documentation
37+
</Link>
38+
</div>
39+
<div css={styles.separator}></div>
40+
<Stack direction="column" alignItems="center" spacing={2}>
41+
<ul css={styles.featureList}>
42+
<li css={styles.feature}>
43+
<FeatureIcon /> Template access control
44+
</li>
45+
<li css={styles.feature}>
46+
<FeatureIcon /> User groups
47+
</li>
48+
<li css={styles.feature}>
49+
<FeatureIcon /> 24 hour support
50+
</li>
51+
<li css={styles.feature}>
52+
<FeatureIcon /> Audit logs
53+
</li>
54+
</ul>
55+
<Button
56+
href={docs("/enterprise")}
57+
target="_blank"
58+
rel="noreferrer"
59+
startIcon={<span css={{ fontSize: 22 }}>&rarr;</span>}
60+
variant="outlined"
61+
color="neutral"
62+
>
63+
Learn about Enterprise
64+
</Button>
65+
</Stack>
66+
</div>
67+
);
68+
};
69+
70+
const FeatureIcon: FC = () => {
71+
return <TaskAltIcon css={styles.featureIcon} />;
72+
};
73+
74+
const styles = {
75+
root: (theme) => ({
76+
display: "flex",
77+
flexDirection: "row",
78+
alignItems: "center",
79+
maxWidth: 600,
80+
padding: "24px 36px",
81+
backgroundImage: `linear-gradient(160deg, transparent, ${theme.roles.active.background})`,
82+
border: `1px solid ${theme.roles.active.fill.outline}`,
83+
borderRadius: 8,
84+
gap: 18,
85+
}),
86+
title: {
87+
fontWeight: 600,
88+
fontFamily: "inherit",
89+
fontSize: 18,
90+
margin: 0,
91+
},
92+
description: (theme) => ({
93+
marginTop: 8,
94+
fontFamily: "inherit",
95+
maxWidth: 420,
96+
lineHeight: "160%",
97+
color: theme.palette.text.secondary,
98+
fontSize: 14,
99+
}),
100+
separator: (theme) => ({
101+
width: 1,
102+
height: 180,
103+
backgroundColor: theme.palette.divider,
104+
marginLeft: 8,
105+
}),
106+
featureList: {
107+
listStyle: "none",
108+
margin: 0,
109+
marginRight: 8,
110+
padding: "0 12px",
111+
fontSize: 13,
112+
fontWeight: 500,
113+
},
114+
featureIcon: (theme) => ({
115+
color: theme.roles.active.fill.outline,
116+
fontSize: "1.5em",
117+
}),
118+
feature: {
119+
display: "flex",
120+
alignItems: "center",
121+
padding: 3,
122+
gap: 8,
123+
lineHeight: 1.2,
124+
},
125+
} satisfies Record<string, Interpolation<Theme>>;

site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx

+20-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ import {
1010
EnterpriseBadge,
1111
EntitledBadge,
1212
} from "components/Badges/Badges";
13+
import { PopoverPaywall } from "components/Paywall/PopoverPaywall";
14+
import {
15+
Popover,
16+
PopoverContent,
17+
PopoverTrigger,
18+
} from "components/Popover/Popover";
1319
import { getFormHelpers } from "utils/formUtils";
1420
import { Fieldset } from "../Fieldset";
1521
import { Header } from "../Header";
@@ -55,7 +61,20 @@ export const AppearanceSettingsPageView: FC<
5561

5662
<Badges>
5763
{isEntitled ? <EntitledBadge /> : <DisabledBadge />}
58-
<EnterpriseBadge />
64+
<Popover mode="hover">
65+
<PopoverTrigger>
66+
<span>
67+
<EnterpriseBadge />
68+
</span>
69+
</PopoverTrigger>
70+
<PopoverContent css={{ transform: "translateY(-28px)" }}>
71+
<PopoverPaywall
72+
message="Appearance"
73+
description="With an Enterprise license, you can customize the appearance of your deployment."
74+
documentationLink="https://coder.com/docs/v2/latest/admin/appearance"
75+
/>
76+
</PopoverContent>
77+
</Popover>
5978
</Badges>
6079

6180
<Fieldset

0 commit comments

Comments
 (0)