mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: popover paywall in appearance settings (#13217)
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { PopoverPaywall } from "./PopoverPaywall";
|
||||
|
||||
const meta: Meta<typeof PopoverPaywall> = {
|
||||
title: "components/Paywall/PopoverPaywall",
|
||||
component: PopoverPaywall,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof PopoverPaywall>;
|
||||
|
||||
const Example: Story = {
|
||||
args: {
|
||||
message: "Black Lotus",
|
||||
description:
|
||||
"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.",
|
||||
},
|
||||
};
|
||||
|
||||
export { Example as PopoverPaywall };
|
||||
@@ -0,0 +1,125 @@
|
||||
import type { Interpolation, Theme } from "@emotion/react";
|
||||
import TaskAltIcon from "@mui/icons-material/TaskAlt";
|
||||
import Button from "@mui/material/Button";
|
||||
import Link from "@mui/material/Link";
|
||||
import type { FC, ReactNode } from "react";
|
||||
import { EnterpriseBadge } from "components/Badges/Badges";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { docs } from "utils/docs";
|
||||
|
||||
export interface PopoverPaywallProps {
|
||||
message: string;
|
||||
description?: ReactNode;
|
||||
documentationLink?: string;
|
||||
}
|
||||
|
||||
export const PopoverPaywall: FC<PopoverPaywallProps> = ({
|
||||
message,
|
||||
description,
|
||||
documentationLink,
|
||||
}) => {
|
||||
return (
|
||||
<div css={styles.root}>
|
||||
<div>
|
||||
<Stack direction="row" alignItems="center" css={{ marginBottom: 18 }}>
|
||||
<h5 css={styles.title}>{message}</h5>
|
||||
<EnterpriseBadge />
|
||||
</Stack>
|
||||
|
||||
{description && <p css={styles.description}>{description}</p>}
|
||||
<Link
|
||||
href={documentationLink}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
css={{ fontWeight: 600 }}
|
||||
>
|
||||
Read the documentation
|
||||
</Link>
|
||||
</div>
|
||||
<div css={styles.separator}></div>
|
||||
<Stack direction="column" alignItems="center" spacing={2}>
|
||||
<ul css={styles.featureList}>
|
||||
<li css={styles.feature}>
|
||||
<FeatureIcon /> Template access control
|
||||
</li>
|
||||
<li css={styles.feature}>
|
||||
<FeatureIcon /> User groups
|
||||
</li>
|
||||
<li css={styles.feature}>
|
||||
<FeatureIcon /> 24 hour support
|
||||
</li>
|
||||
<li css={styles.feature}>
|
||||
<FeatureIcon /> Audit logs
|
||||
</li>
|
||||
</ul>
|
||||
<Button
|
||||
href={docs("/enterprise")}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
startIcon={<span css={{ fontSize: 22 }}>→</span>}
|
||||
variant="outlined"
|
||||
color="neutral"
|
||||
>
|
||||
Learn about Enterprise
|
||||
</Button>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const FeatureIcon: FC = () => {
|
||||
return <TaskAltIcon css={styles.featureIcon} />;
|
||||
};
|
||||
|
||||
const styles = {
|
||||
root: (theme) => ({
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
maxWidth: 600,
|
||||
padding: "24px 36px",
|
||||
backgroundImage: `linear-gradient(160deg, transparent, ${theme.roles.active.background})`,
|
||||
border: `1px solid ${theme.roles.active.fill.outline}`,
|
||||
borderRadius: 8,
|
||||
gap: 18,
|
||||
}),
|
||||
title: {
|
||||
fontWeight: 600,
|
||||
fontFamily: "inherit",
|
||||
fontSize: 18,
|
||||
margin: 0,
|
||||
},
|
||||
description: (theme) => ({
|
||||
marginTop: 8,
|
||||
fontFamily: "inherit",
|
||||
maxWidth: 420,
|
||||
lineHeight: "160%",
|
||||
color: theme.palette.text.secondary,
|
||||
fontSize: 14,
|
||||
}),
|
||||
separator: (theme) => ({
|
||||
width: 1,
|
||||
height: 180,
|
||||
backgroundColor: theme.palette.divider,
|
||||
marginLeft: 8,
|
||||
}),
|
||||
featureList: {
|
||||
listStyle: "none",
|
||||
margin: 0,
|
||||
marginRight: 8,
|
||||
padding: "0 12px",
|
||||
fontSize: 13,
|
||||
fontWeight: 500,
|
||||
},
|
||||
featureIcon: (theme) => ({
|
||||
color: theme.roles.active.fill.outline,
|
||||
fontSize: "1.5em",
|
||||
}),
|
||||
feature: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
padding: 3,
|
||||
gap: 8,
|
||||
lineHeight: 1.2,
|
||||
},
|
||||
} satisfies Record<string, Interpolation<Theme>>;
|
||||
+20
-1
@@ -10,6 +10,12 @@ import {
|
||||
EnterpriseBadge,
|
||||
EntitledBadge,
|
||||
} from "components/Badges/Badges";
|
||||
import { PopoverPaywall } from "components/Paywall/PopoverPaywall";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "components/Popover/Popover";
|
||||
import { getFormHelpers } from "utils/formUtils";
|
||||
import { Fieldset } from "../Fieldset";
|
||||
import { Header } from "../Header";
|
||||
@@ -55,7 +61,20 @@ export const AppearanceSettingsPageView: FC<
|
||||
|
||||
<Badges>
|
||||
{isEntitled ? <EntitledBadge /> : <DisabledBadge />}
|
||||
<EnterpriseBadge />
|
||||
<Popover mode="hover">
|
||||
<PopoverTrigger>
|
||||
<span>
|
||||
<EnterpriseBadge />
|
||||
</span>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent css={{ transform: "translateY(-28px)" }}>
|
||||
<PopoverPaywall
|
||||
message="Appearance"
|
||||
description="With an Enterprise license, you can customize the appearance of your deployment."
|
||||
documentationLink="https://coder.com/docs/v2/latest/admin/appearance"
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</Badges>
|
||||
|
||||
<Fieldset
|
||||
|
||||
Reference in New Issue
Block a user