Skip to content

Commit 09a92cb

Browse files
authored
feat: update licensing pills to reflect new premium tier (#14670)
* feat: update licensing pills to reflect new premium tier * fix: format
1 parent 01ae143 commit 09a92cb

File tree

14 files changed

+182
-66
lines changed

14 files changed

+182
-66
lines changed

site/src/components/Badges/Badges.tsx

+20-3
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,32 @@ export const DisabledBadge: FC = forwardRef<
106106
);
107107
});
108108

109+
export const EnterpriseBadge: FC = () => {
110+
return (
111+
<span
112+
css={[
113+
styles.badge,
114+
(theme) => ({
115+
backgroundColor: theme.branding.enterprise.background,
116+
border: `1px solid ${theme.branding.enterprise.border}`,
117+
color: theme.branding.enterprise.text,
118+
}),
119+
]}
120+
>
121+
Enterprise
122+
</span>
123+
);
124+
};
125+
109126
export const PremiumBadge: FC = () => {
110127
return (
111128
<span
112129
css={[
113130
styles.badge,
114131
(theme) => ({
115-
backgroundColor: theme.branding.background,
116-
border: `1px solid ${theme.branding.border}`,
117-
color: theme.roles.notice.text,
132+
backgroundColor: theme.branding.premium.background,
133+
border: `1px solid ${theme.branding.premium.border}`,
134+
color: theme.branding.premium.text,
118135
}),
119136
]}
120137
>

site/src/components/Paywall/Paywall.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ const FeatureIcon: FC = () => {
7878
<TaskAltIcon
7979
css={[
8080
(theme) => ({
81-
color: theme.branding.border,
81+
color: theme.branding.premium.border,
8282
}),
8383
]}
8484
/>
@@ -95,8 +95,8 @@ const styles = {
9595
padding: 24,
9696
borderRadius: 8,
9797
gap: 32,
98-
backgroundImage: `linear-gradient(160deg, transparent, ${theme.branding.background})`,
99-
border: `1px solid ${theme.branding.border}`,
98+
backgroundImage: `linear-gradient(160deg, transparent, ${theme.branding.premium.background})`,
99+
border: `1px solid ${theme.branding.premium.border}`,
100100
}),
101101
title: {
102102
fontWeight: 600,
@@ -112,7 +112,7 @@ const styles = {
112112
separator: (theme) => ({
113113
width: 1,
114114
height: 220,
115-
backgroundColor: theme.branding.divider,
115+
backgroundColor: theme.branding.premium.divider,
116116
marginLeft: 8,
117117
}),
118118
learnButton: {

site/src/components/Paywall/PopoverPaywall.tsx

+22-17
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ export const PopoverPaywall: FC<PopoverPaywallProps> = ({
2323
css={[
2424
styles.root,
2525
(theme) => ({
26-
backgroundImage: `linear-gradient(160deg, transparent, ${theme.branding.background})`,
27-
border: `1px solid ${theme.branding.border}`,
26+
backgroundImage: `linear-gradient(160deg, transparent, ${theme.branding.premium.background})`,
27+
border: `1px solid ${theme.branding.premium.border}`,
2828
}),
2929
]}
3030
>
@@ -45,7 +45,7 @@ export const PopoverPaywall: FC<PopoverPaywallProps> = ({
4545
</Link>
4646
</div>
4747
<div css={styles.separator} />
48-
<Stack direction="column" alignItems="center" spacing={2}>
48+
<Stack direction="column" alignItems="left" spacing={2}>
4949
<ul css={styles.featureList}>
5050
<li css={styles.feature}>
5151
<FeatureIcon /> High availability & workspace proxies
@@ -60,16 +60,18 @@ export const PopoverPaywall: FC<PopoverPaywallProps> = ({
6060
<FeatureIcon /> Unlimited Git & external auth integrations
6161
</li>
6262
</ul>
63-
<Button
64-
href={docs("/enterprise")}
65-
target="_blank"
66-
rel="noreferrer"
67-
startIcon={<span css={{ fontSize: 22 }}>&rarr;</span>}
68-
variant="outlined"
69-
color="neutral"
70-
>
71-
Learn about Premium
72-
</Button>
63+
<div css={styles.learnButton}>
64+
<Button
65+
href={docs("/enterprise")}
66+
target="_blank"
67+
rel="noreferrer"
68+
startIcon={<span css={{ fontSize: 22 }}>&rarr;</span>}
69+
variant="outlined"
70+
color="neutral"
71+
>
72+
Learn about Premium
73+
</Button>
74+
</div>
7375
</Stack>
7476
</div>
7577
);
@@ -80,7 +82,7 @@ const FeatureIcon: FC = () => {
8082
<TaskAltIcon
8183
css={[
8284
(theme) => ({
83-
color: theme.branding.border,
85+
color: theme.branding.premium.border,
8486
}),
8587
]}
8688
/>
@@ -92,7 +94,7 @@ const styles = {
9294
display: "flex",
9395
flexDirection: "row",
9496
alignItems: "center",
95-
maxWidth: 600,
97+
maxWidth: 770,
9698
padding: "24px 36px",
9799
borderRadius: 8,
98100
gap: 18,
@@ -106,7 +108,7 @@ const styles = {
106108
description: (theme) => ({
107109
marginTop: 8,
108110
fontFamily: "inherit",
109-
maxWidth: 420,
111+
maxWidth: 360,
110112
lineHeight: "160%",
111113
color: theme.palette.text.secondary,
112114
fontSize: 14,
@@ -121,10 +123,13 @@ const styles = {
121123
listStyle: "none",
122124
margin: 0,
123125
marginRight: 8,
124-
padding: "0 12px",
126+
padding: "0 0 0 24px",
125127
fontSize: 13,
126128
fontWeight: 500,
127129
},
130+
learnButton: {
131+
padding: "0 28px",
132+
},
128133
feature: {
129134
display: "flex",
130135
alignItems: "center",

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

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { appearanceConfigKey, updateAppearance } from "api/queries/appearance";
33
import type { UpdateAppearanceConfig } from "api/typesGenerated";
44
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
55
import { useDashboard } from "modules/dashboard/useDashboard";
6+
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
67
import type { FC } from "react";
78
import { Helmet } from "react-helmet-async";
89
import { useMutation, useQueryClient } from "react-query";
@@ -15,6 +16,7 @@ import { AppearanceSettingsPageView } from "./AppearanceSettingsPageView";
1516
// the command line would be a significantly worse user experience.
1617
const AppearanceSettingsPage: FC = () => {
1718
const { appearance, entitlements } = useDashboard();
19+
const { multiple_organizations: hasPremiumLicense } = useFeatureVisibility();
1820
const queryClient = useQueryClient();
1921
const updateAppearanceMutation = useMutation(updateAppearance(queryClient));
2022

@@ -46,6 +48,7 @@ const AppearanceSettingsPage: FC = () => {
4648
isEntitled={
4749
entitlements.features.appearance.entitlement !== "not_entitled"
4850
}
51+
isPremium={hasPremiumLicense}
4952
/>
5053
</>
5154
);

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

+13-9
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import TextField from "@mui/material/TextField";
44
import type { UpdateAppearanceConfig } from "api/typesGenerated";
55
import {
66
Badges,
7-
DisabledBadge,
8-
EntitledBadge,
7+
EnterpriseBadge,
98
PremiumBadge,
109
} from "components/Badges/Badges";
1110
import { PopoverPaywall } from "components/Paywall/PopoverPaywall";
@@ -24,14 +23,15 @@ import { AnnouncementBannerSettings } from "./AnnouncementBannerSettings";
2423
export type AppearanceSettingsPageViewProps = {
2524
appearance: UpdateAppearanceConfig;
2625
isEntitled: boolean;
26+
isPremium: boolean;
2727
onSaveAppearance: (
2828
newConfig: Partial<UpdateAppearanceConfig>,
2929
) => Promise<void>;
3030
};
3131

3232
export const AppearanceSettingsPageView: FC<
3333
AppearanceSettingsPageViewProps
34-
> = ({ appearance, isEntitled, onSaveAppearance }) => {
34+
> = ({ appearance, isEntitled, isPremium, onSaveAppearance }) => {
3535
const applicationNameForm = useFormik<{
3636
application_name: string;
3737
}>({
@@ -60,13 +60,17 @@ export const AppearanceSettingsPageView: FC<
6060
/>
6161

6262
<Badges>
63-
{isEntitled ? <EntitledBadge /> : <DisabledBadge />}
6463
<Popover mode="hover">
65-
<PopoverTrigger>
66-
<span>
67-
<PremiumBadge />
68-
</span>
69-
</PopoverTrigger>
64+
{isEntitled && !isPremium ? (
65+
<EnterpriseBadge />
66+
) : (
67+
<PopoverTrigger>
68+
<span>
69+
<PremiumBadge />
70+
</span>
71+
</PopoverTrigger>
72+
)}
73+
7074
<PopoverContent css={{ transform: "translateY(-28px)" }}>
7175
<PopoverPaywall
7276
message="Appearance"

site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPage.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Loader } from "components/Loader/Loader";
22
import { useDashboard } from "modules/dashboard/useDashboard";
3+
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
34
import type { FC } from "react";
45
import { Helmet } from "react-helmet-async";
56
import { pageTitle } from "utils/page";
@@ -9,6 +10,7 @@ import { ObservabilitySettingsPageView } from "./ObservabilitySettingsPageView";
910
const ObservabilitySettingsPage: FC = () => {
1011
const { deploymentValues } = useDeploySettings();
1112
const { entitlements } = useDashboard();
13+
const { multiple_organizations: hasPremiumLicense } = useFeatureVisibility();
1214

1315
return (
1416
<>
@@ -20,6 +22,7 @@ const ObservabilitySettingsPage: FC = () => {
2022
<ObservabilitySettingsPageView
2123
options={deploymentValues.options}
2224
featureAuditLogEnabled={entitlements.features.audit_log.enabled}
25+
isPremium={hasPremiumLicense}
2326
/>
2427
) : (
2528
<Loader />

site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPageView.tsx

+28-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
import type { SerpentOption } from "api/typesGenerated";
22
import {
33
Badges,
4-
DisabledBadge,
5-
EnabledBadge,
4+
EnterpriseBadge,
65
PremiumBadge,
76
} from "components/Badges/Badges";
7+
import { PopoverPaywall } from "components/Paywall/PopoverPaywall";
8+
import {
9+
Popover,
10+
PopoverContent,
11+
PopoverTrigger,
12+
} from "components/Popover/Popover";
813
import { SettingsHeader } from "components/SettingsHeader/SettingsHeader";
914
import { Stack } from "components/Stack/Stack";
1015
import type { FC } from "react";
@@ -15,11 +20,12 @@ import OptionsTable from "../OptionsTable";
1520
export type ObservabilitySettingsPageViewProps = {
1621
options: SerpentOption[];
1722
featureAuditLogEnabled: boolean;
23+
isPremium: boolean;
1824
};
1925

2026
export const ObservabilitySettingsPageView: FC<
2127
ObservabilitySettingsPageViewProps
22-
> = ({ options, featureAuditLogEnabled }) => {
28+
> = ({ options, featureAuditLogEnabled, isPremium }) => {
2329
return (
2430
<>
2531
<Stack direction="column" spacing={6}>
@@ -33,8 +39,25 @@ export const ObservabilitySettingsPageView: FC<
3339
/>
3440

3541
<Badges>
36-
{featureAuditLogEnabled ? <EnabledBadge /> : <DisabledBadge />}
37-
<PremiumBadge />
42+
<Popover mode="hover">
43+
{featureAuditLogEnabled && !isPremium ? (
44+
<EnterpriseBadge />
45+
) : (
46+
<PopoverTrigger>
47+
<span>
48+
<PremiumBadge />
49+
</span>
50+
</PopoverTrigger>
51+
)}
52+
53+
<PopoverContent css={{ transform: "translateY(-28px)" }}>
54+
<PopoverPaywall
55+
message="Observability"
56+
description="With a Premium license, you can monitor your application with logs and metrics."
57+
documentationLink="https://coder.com/docs/admin/appearance"
58+
/>
59+
</PopoverContent>
60+
</Popover>
3861
</Badges>
3962
</div>
4063

site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx

+39-10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import TextField from "@mui/material/TextField";
22
import { isApiValidationError } from "api/errors";
33
import type { CreateOrganizationRequest } from "api/typesGenerated";
44
import { ErrorAlert } from "components/Alert/ErrorAlert";
5+
import { Badges, PremiumBadge } from "components/Badges/Badges";
56
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne";
67
import {
78
FormFields,
@@ -11,6 +12,12 @@ import {
1112
} from "components/Form/Form";
1213
import { IconField } from "components/IconField/IconField";
1314
import { Paywall } from "components/Paywall/Paywall";
15+
import { PopoverPaywall } from "components/Paywall/PopoverPaywall";
16+
import {
17+
Popover,
18+
PopoverContent,
19+
PopoverTrigger,
20+
} from "components/Popover/Popover";
1421
import { SettingsHeader } from "components/SettingsHeader/SettingsHeader";
1522
import { Stack } from "components/Stack/Stack";
1623
import { useFormik } from "formik";
@@ -58,17 +65,39 @@ export const CreateOrganizationPageView: FC<
5865
const getFieldHelpers = getFormHelpers(form, error);
5966

6067
return (
61-
<Stack spacing={3}>
62-
<SettingsHeader
63-
title="New Organization"
64-
description="Organize your deployment into multiple platform teams."
65-
/>
68+
<Stack>
69+
<div>
70+
<SettingsHeader
71+
title="New Organization"
72+
description="Organize your deployment into multiple platform teams."
73+
/>
74+
75+
{Boolean(error) && !isApiValidationError(error) && (
76+
<div css={{ marginBottom: 32 }}>
77+
<ErrorAlert error={error} />
78+
</div>
79+
)}
80+
81+
<Badges>
82+
<Popover mode="hover">
83+
{isEntitled && (
84+
<PopoverTrigger>
85+
<span>
86+
<PremiumBadge />
87+
</span>
88+
</PopoverTrigger>
89+
)}
6690

67-
{Boolean(error) && !isApiValidationError(error) && (
68-
<div css={{ marginBottom: 32 }}>
69-
<ErrorAlert error={error} />
70-
</div>
71-
)}
91+
<PopoverContent css={{ transform: "translateY(-28px)" }}>
92+
<PopoverPaywall
93+
message="Organizations"
94+
description="Create multiple organizations within a single Coder deployment, allowing several platform teams to operate with isolated users, templates, and distinct underlying infrastructure."
95+
documentationLink={docs("/guides/using-organizations")}
96+
/>
97+
</PopoverContent>
98+
</Popover>
99+
</Badges>
100+
</div>
72101

73102
<ChooseOne>
74103
<Cond condition={!isEntitled}>

site/src/pages/ManagementSettingsPage/GroupsPage/GroupPage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ export const GroupPage: FC = () => {
165165
<TableRow>
166166
<TableCell width="59%">User</TableCell>
167167
<TableCell width="40">Status</TableCell>
168-
<TableCell width="1%"></TableCell>
168+
<TableCell width="1%" />
169169
</TableRow>
170170
</TableHead>
171171

0 commit comments

Comments
 (0)