diff --git a/site/src/components/Badges/Badges.tsx b/site/src/components/Badges/Badges.tsx index 9492184a273c7..278eb890cd2ee 100644 --- a/site/src/components/Badges/Badges.tsx +++ b/site/src/components/Badges/Badges.tsx @@ -106,15 +106,32 @@ export const DisabledBadge: FC = forwardRef< ); }); +export const EnterpriseBadge: FC = () => { + return ( + ({ + backgroundColor: theme.branding.enterprise.background, + border: `1px solid ${theme.branding.enterprise.border}`, + color: theme.branding.enterprise.text, + }), + ]} + > + Enterprise + + ); +}; + export const PremiumBadge: FC = () => { return ( ({ - backgroundColor: theme.branding.background, - border: `1px solid ${theme.branding.border}`, - color: theme.roles.notice.text, + backgroundColor: theme.branding.premium.background, + border: `1px solid ${theme.branding.premium.border}`, + color: theme.branding.premium.text, }), ]} > diff --git a/site/src/components/Paywall/Paywall.tsx b/site/src/components/Paywall/Paywall.tsx index d68244f5d0640..fd83900199ec4 100644 --- a/site/src/components/Paywall/Paywall.tsx +++ b/site/src/components/Paywall/Paywall.tsx @@ -78,7 +78,7 @@ const FeatureIcon: FC = () => { ({ - color: theme.branding.border, + color: theme.branding.premium.border, }), ]} /> @@ -95,8 +95,8 @@ const styles = { padding: 24, borderRadius: 8, gap: 32, - backgroundImage: `linear-gradient(160deg, transparent, ${theme.branding.background})`, - border: `1px solid ${theme.branding.border}`, + backgroundImage: `linear-gradient(160deg, transparent, ${theme.branding.premium.background})`, + border: `1px solid ${theme.branding.premium.border}`, }), title: { fontWeight: 600, @@ -112,7 +112,7 @@ const styles = { separator: (theme) => ({ width: 1, height: 220, - backgroundColor: theme.branding.divider, + backgroundColor: theme.branding.premium.divider, marginLeft: 8, }), learnButton: { diff --git a/site/src/components/Paywall/PopoverPaywall.tsx b/site/src/components/Paywall/PopoverPaywall.tsx index eac7fafcae010..96a431495bcd3 100644 --- a/site/src/components/Paywall/PopoverPaywall.tsx +++ b/site/src/components/Paywall/PopoverPaywall.tsx @@ -23,8 +23,8 @@ export const PopoverPaywall: FC = ({ css={[ styles.root, (theme) => ({ - backgroundImage: `linear-gradient(160deg, transparent, ${theme.branding.background})`, - border: `1px solid ${theme.branding.border}`, + backgroundImage: `linear-gradient(160deg, transparent, ${theme.branding.premium.background})`, + border: `1px solid ${theme.branding.premium.border}`, }), ]} > @@ -45,7 +45,7 @@ export const PopoverPaywall: FC = ({
- +
  • High availability & workspace proxies @@ -60,16 +60,18 @@ export const PopoverPaywall: FC = ({ Unlimited Git & external auth integrations
- +
+ +
); @@ -80,7 +82,7 @@ const FeatureIcon: FC = () => { ({ - color: theme.branding.border, + color: theme.branding.premium.border, }), ]} /> @@ -92,7 +94,7 @@ const styles = { display: "flex", flexDirection: "row", alignItems: "center", - maxWidth: 600, + maxWidth: 770, padding: "24px 36px", borderRadius: 8, gap: 18, @@ -106,7 +108,7 @@ const styles = { description: (theme) => ({ marginTop: 8, fontFamily: "inherit", - maxWidth: 420, + maxWidth: 360, lineHeight: "160%", color: theme.palette.text.secondary, fontSize: 14, @@ -121,10 +123,13 @@ const styles = { listStyle: "none", margin: 0, marginRight: 8, - padding: "0 12px", + padding: "0 0 0 24px", fontSize: 13, fontWeight: 500, }, + learnButton: { + padding: "0 28px", + }, feature: { display: "flex", alignItems: "center", diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx index b9153c6d1279b..9132e83876dfd 100644 --- a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx @@ -3,6 +3,7 @@ import { appearanceConfigKey, updateAppearance } from "api/queries/appearance"; import type { UpdateAppearanceConfig } from "api/typesGenerated"; import { displayError, displaySuccess } from "components/GlobalSnackbar/utils"; import { useDashboard } from "modules/dashboard/useDashboard"; +import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; import type { FC } from "react"; import { Helmet } from "react-helmet-async"; import { useMutation, useQueryClient } from "react-query"; @@ -15,6 +16,7 @@ import { AppearanceSettingsPageView } from "./AppearanceSettingsPageView"; // the command line would be a significantly worse user experience. const AppearanceSettingsPage: FC = () => { const { appearance, entitlements } = useDashboard(); + const { multiple_organizations: hasPremiumLicense } = useFeatureVisibility(); const queryClient = useQueryClient(); const updateAppearanceMutation = useMutation(updateAppearance(queryClient)); @@ -46,6 +48,7 @@ const AppearanceSettingsPage: FC = () => { isEntitled={ entitlements.features.appearance.entitlement !== "not_entitled" } + isPremium={hasPremiumLicense} /> ); diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx index 8c4e2f3285ee2..0c5d470c027fe 100644 --- a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx @@ -4,8 +4,7 @@ import TextField from "@mui/material/TextField"; import type { UpdateAppearanceConfig } from "api/typesGenerated"; import { Badges, - DisabledBadge, - EntitledBadge, + EnterpriseBadge, PremiumBadge, } from "components/Badges/Badges"; import { PopoverPaywall } from "components/Paywall/PopoverPaywall"; @@ -24,6 +23,7 @@ import { AnnouncementBannerSettings } from "./AnnouncementBannerSettings"; export type AppearanceSettingsPageViewProps = { appearance: UpdateAppearanceConfig; isEntitled: boolean; + isPremium: boolean; onSaveAppearance: ( newConfig: Partial, ) => Promise; @@ -31,7 +31,7 @@ export type AppearanceSettingsPageViewProps = { export const AppearanceSettingsPageView: FC< AppearanceSettingsPageViewProps -> = ({ appearance, isEntitled, onSaveAppearance }) => { +> = ({ appearance, isEntitled, isPremium, onSaveAppearance }) => { const applicationNameForm = useFormik<{ application_name: string; }>({ @@ -60,13 +60,17 @@ export const AppearanceSettingsPageView: FC< /> - {isEntitled ? : } - - - - - + {isEntitled && !isPremium ? ( + + ) : ( + + + + + + )} + { const { deploymentValues } = useDeploySettings(); const { entitlements } = useDashboard(); + const { multiple_organizations: hasPremiumLicense } = useFeatureVisibility(); return ( <> @@ -20,6 +22,7 @@ const ObservabilitySettingsPage: FC = () => { ) : ( diff --git a/site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPageView.tsx b/site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPageView.tsx index bdf7b47722603..ece25f476a721 100644 --- a/site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPageView.tsx +++ b/site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPageView.tsx @@ -1,10 +1,15 @@ import type { SerpentOption } from "api/typesGenerated"; import { Badges, - DisabledBadge, - EnabledBadge, + EnterpriseBadge, PremiumBadge, } from "components/Badges/Badges"; +import { PopoverPaywall } from "components/Paywall/PopoverPaywall"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "components/Popover/Popover"; import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { Stack } from "components/Stack/Stack"; import type { FC } from "react"; @@ -15,11 +20,12 @@ import OptionsTable from "../OptionsTable"; export type ObservabilitySettingsPageViewProps = { options: SerpentOption[]; featureAuditLogEnabled: boolean; + isPremium: boolean; }; export const ObservabilitySettingsPageView: FC< ObservabilitySettingsPageViewProps -> = ({ options, featureAuditLogEnabled }) => { +> = ({ options, featureAuditLogEnabled, isPremium }) => { return ( <> @@ -33,8 +39,25 @@ export const ObservabilitySettingsPageView: FC< /> - {featureAuditLogEnabled ? : } - + + {featureAuditLogEnabled && !isPremium ? ( + + ) : ( + + + + + + )} + + + + + diff --git a/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx b/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx index 035c1be28c287..abb8242aba6c1 100644 --- a/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx @@ -2,6 +2,7 @@ import TextField from "@mui/material/TextField"; import { isApiValidationError } from "api/errors"; import type { CreateOrganizationRequest } from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; +import { Badges, PremiumBadge } from "components/Badges/Badges"; import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; import { FormFields, @@ -11,6 +12,12 @@ import { } from "components/Form/Form"; import { IconField } from "components/IconField/IconField"; import { Paywall } from "components/Paywall/Paywall"; +import { PopoverPaywall } from "components/Paywall/PopoverPaywall"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "components/Popover/Popover"; import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { Stack } from "components/Stack/Stack"; import { useFormik } from "formik"; @@ -58,17 +65,39 @@ export const CreateOrganizationPageView: FC< const getFieldHelpers = getFormHelpers(form, error); return ( - - + +
+ + + {Boolean(error) && !isApiValidationError(error) && ( +
+ +
+ )} + + + + {isEntitled && ( + + + + + + )} - {Boolean(error) && !isApiValidationError(error) && ( -
- -
- )} + + + +
+
+
diff --git a/site/src/pages/ManagementSettingsPage/GroupsPage/GroupPage.tsx b/site/src/pages/ManagementSettingsPage/GroupsPage/GroupPage.tsx index 8a90404644b19..22841f5d2fbc0 100644 --- a/site/src/pages/ManagementSettingsPage/GroupsPage/GroupPage.tsx +++ b/site/src/pages/ManagementSettingsPage/GroupsPage/GroupPage.tsx @@ -165,7 +165,7 @@ export const GroupPage: FC = () => { User Status - + diff --git a/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx b/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx index 18200b1e5e3d4..a714d480cc702 100644 --- a/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx @@ -89,7 +89,7 @@ export const OrganizationMembersPageView: FC<
- + diff --git a/site/src/theme/branding.ts b/site/src/theme/branding.ts index d3b29ab7fd54c..c1e42e5111abd 100644 --- a/site/src/theme/branding.ts +++ b/site/src/theme/branding.ts @@ -1,6 +1,14 @@ export interface Branding { - background: string; - divider: string; - border: string; - text: string; + enterprise: { + background: string; + divider: string; + border: string; + text: string; + }; + premium: { + background: string; + divider: string; + border: string; + text: string; + }; } diff --git a/site/src/theme/dark/branding.ts b/site/src/theme/dark/branding.ts index c44a7326c86de..cc0b603b62f0c 100644 --- a/site/src/theme/dark/branding.ts +++ b/site/src/theme/dark/branding.ts @@ -2,8 +2,16 @@ import type { Branding } from "../branding"; import colors from "../tailwindColors"; export default { - background: colors.violet[950], - divider: colors.violet[900], - border: colors.violet[400], - text: colors.violet[50], + enterprise: { + background: colors.blue[950], + divider: colors.blue[900], + border: colors.blue[400], + text: colors.blue[50], + }, + premium: { + background: colors.violet[950], + divider: colors.violet[900], + border: colors.violet[400], + text: colors.violet[50], + }, } satisfies Branding; diff --git a/site/src/theme/darkBlue/branding.ts b/site/src/theme/darkBlue/branding.ts index c44a7326c86de..cc0b603b62f0c 100644 --- a/site/src/theme/darkBlue/branding.ts +++ b/site/src/theme/darkBlue/branding.ts @@ -2,8 +2,16 @@ import type { Branding } from "../branding"; import colors from "../tailwindColors"; export default { - background: colors.violet[950], - divider: colors.violet[900], - border: colors.violet[400], - text: colors.violet[50], + enterprise: { + background: colors.blue[950], + divider: colors.blue[900], + border: colors.blue[400], + text: colors.blue[50], + }, + premium: { + background: colors.violet[950], + divider: colors.violet[900], + border: colors.violet[400], + text: colors.violet[50], + }, } satisfies Branding; diff --git a/site/src/theme/light/branding.ts b/site/src/theme/light/branding.ts index 4b9ff1f3c8af3..97b6df71def0e 100644 --- a/site/src/theme/light/branding.ts +++ b/site/src/theme/light/branding.ts @@ -2,8 +2,16 @@ import type { Branding } from "../branding"; import colors from "../tailwindColors"; export default { - background: colors.violet[100], - divider: colors.violet[300], - border: colors.violet[600], - text: colors.violet[950], + enterprise: { + background: colors.blue[100], + divider: colors.blue[300], + border: colors.blue[600], + text: colors.blue[950], + }, + premium: { + background: colors.violet[100], + divider: colors.violet[300], + border: colors.violet[600], + text: colors.violet[950], + }, } satisfies Branding;