diff --git a/web/libs/ui/src/index.ts b/web/libs/ui/src/index.ts index 130c69c401e6..273600e953dd 100644 --- a/web/libs/ui/src/index.ts +++ b/web/libs/ui/src/index.ts @@ -12,6 +12,7 @@ export * from "./lib/code-block/code-block"; export * from "./lib/code-editor/code-editor"; export * from "./lib/empty-state/empty-state"; export * from "./lib/enterprise-badge/enterprise-badge"; +export * from "./lib/enterprise-upgrade-overlay/enterprise-upgrade-overlay"; export * from "./lib/label/label"; export * from "./lib/select/select"; export * from "./lib/skeleton/skeleton"; diff --git a/web/libs/ui/src/lib/enterprise-badge/enterprise-badge.module.scss b/web/libs/ui/src/lib/enterprise-badge/enterprise-badge.module.scss index 07b323b0b61c..4fe9e603aceb 100644 --- a/web/libs/ui/src/lib/enterprise-badge/enterprise-badge.module.scss +++ b/web/libs/ui/src/lib/enterprise-badge/enterprise-badge.module.scss @@ -9,12 +9,12 @@ .filled { .label { background: none; - color: var(--color-accent-persimmon-base); + color: var(--color-neutral-on-dark-content); } .icon { path { - fill: var(--color-accent-persimmon-base); + fill: var(--color-neutral-on-dark-content); } } } @@ -31,4 +31,5 @@ align-items: center; line-height: 100%; font-weight: 500; + cursor: default; } \ No newline at end of file diff --git a/web/libs/ui/src/lib/enterprise-upgrade-overlay/enterprise-upgrade-overlay.module.scss b/web/libs/ui/src/lib/enterprise-upgrade-overlay/enterprise-upgrade-overlay.module.scss new file mode 100644 index 000000000000..71674f600544 --- /dev/null +++ b/web/libs/ui/src/lib/enterprise-upgrade-overlay/enterprise-upgrade-overlay.module.scss @@ -0,0 +1,75 @@ +.overlay { + position: absolute; + display: flex; + align-items: center; + justify-content: center; + z-index: 3000; + backdrop-filter: blur(2px) grayscale(80%); + background: rgb(var(--color-neutral-background-raw) / 70%); + inset: -16px -24px; +} + +.container { + // Gradient border effect using padding + background + pseudo-element + padding: 2px; + background: linear-gradient(109.47deg, var(--color-accent-canteloupe-base) 0%, var(--color-accent-persimmon-base) 50%, var(--color-accent-plum-base) 100%); + border-radius: 12px; + width: 780px; + box-shadow: 0 8px 24px rgb(var(--color-neutral-shadow-raw) / 24%), 0 4px 16px rgb(var(--color-neutral-shadow-raw) / 32%); + position: relative; + transform: translateY(-3rem); + + // Inner content container with actual background + &::before { + content: ""; + position: absolute; + inset: 2px; + background: var(--color-neutral-background); + opacity: 0.95; + border-radius: 10px; + z-index: 0; + } + + // All children need to be above the pseudo-element + > * { + position: relative; + z-index: 1; + } +} + +.content { + padding: 3rem; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: var(--spacing-base); +} + +.badge { + transform: scale(1.4); +} + +.title { + // Typography component handles font styles + margin: 0; +} + +.description { + // Typography component handles font styles + max-width: 600px; + margin: 0; +} + +.actions { + display: flex; + gap: var(--spacing-base); + margin-top: var(--spacing-tight); + flex-wrap: wrap; + justify-content: center; + + button { + white-space: nowrap; + } +} + diff --git a/web/libs/ui/src/lib/enterprise-upgrade-overlay/enterprise-upgrade-overlay.stories.tsx b/web/libs/ui/src/lib/enterprise-upgrade-overlay/enterprise-upgrade-overlay.stories.tsx new file mode 100644 index 000000000000..6ffaf5bb8350 --- /dev/null +++ b/web/libs/ui/src/lib/enterprise-upgrade-overlay/enterprise-upgrade-overlay.stories.tsx @@ -0,0 +1,168 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { EnterpriseUpgradeOverlay } from "./enterprise-upgrade-overlay"; + +const meta: Meta = { + component: EnterpriseUpgradeOverlay, + title: "UI/EnterpriseUpgradeOverlay", + argTypes: { + title: { control: "text" }, + description: { control: "text" }, + feature: { control: "text" }, + learnMoreUrl: { control: "text" }, + primaryButtonLabel: { control: "text" }, + secondaryButtonLabel: { control: "text" }, + showLearnMore: { control: "boolean" }, + className: { control: "text" }, + "data-testid": { control: "text" }, + onContactSales: { action: "contact sales clicked" }, + onLearnMore: { action: "learn more clicked" }, + }, + decorators: [ + (Story) => ( +
+ +
+ ), + ], +}; + +export default meta; +type Story = StoryObj; + +/** + * Default overlay with standard messaging + */ +export const Default: Story = { + args: {}, +}; + +/** + * Overlay customized for Project Dashboards feature + */ +export const ProjectDashboards: Story = { + args: { + title: "Get access to Project Dashboards!", + description: + "Performance analytics are available within the Enterprise plan. Contact our sales team to get access to this and more!", + feature: "Project Dashboards", + learnMoreUrl: "https://docs.humansignal.com/guide/dashboards.html", + }, +}; + +/** + * Overlay for SSO & Security features + */ +export const SSOAndSecurity: Story = { + args: { + title: "SSO & Advanced Security", + description: "Enable Single Sign-On, advanced security features, and compliance tools with our Enterprise plan.", + feature: "SSO & Security Features", + learnMoreUrl: "https://docs.humansignal.com/guide/security.html", + secondaryButtonLabel: "Learn more", + }, +}; + +/** + * Overlay for Custom Workflows + */ +export const CustomWorkflows: Story = { + args: { + title: "Advanced Workflows", + description: "Create custom automation workflows and advanced labeling pipelines with our Enterprise plan.", + feature: "Advanced Workflows", + learnMoreUrl: "https://docs.humansignal.com/guide/workflows.html", + }, +}; + +/** + * Overlay without the "Learn More" button + */ +export const WithoutLearnMore: Story = { + args: { + title: "Premium Feature", + description: "This feature is available exclusively in our Enterprise plan. Contact sales to learn more.", + feature: "Premium Features", + showLearnMore: false, + }, +}; + +/** + * Overlay with custom button labels + */ +export const CustomButtonLabels: Story = { + args: { + title: "Upgrade to Enterprise", + description: "Access all premium features and dedicated support.", + feature: "Enterprise Plan", + primaryButtonLabel: "Talk to Sales", + secondaryButtonLabel: "View Pricing", + learnMoreUrl: "https://humansignal.com/pricing", + }, +}; + +/** + * Overlay shown in context over blurred content + */ +export const InContext: Story = { + render: () => ( +
+
+
+

+ Project Performance Dashboard +

+

+ Track your team's annotation progress and quality metrics +

+
+ +
+
+
+ Total Tasks +
+
1,247
+
+
+
+ Completed +
+
892
+
+
+
+ Agreement Score +
+
94%
+
+
+ +
+

+ Annotation Velocity +

+
+ Chart visualization would appear here +
+
+
+ +
+ ), +}; diff --git a/web/libs/ui/src/lib/enterprise-upgrade-overlay/enterprise-upgrade-overlay.tsx b/web/libs/ui/src/lib/enterprise-upgrade-overlay/enterprise-upgrade-overlay.tsx new file mode 100644 index 000000000000..f068af2c97aa --- /dev/null +++ b/web/libs/ui/src/lib/enterprise-upgrade-overlay/enterprise-upgrade-overlay.tsx @@ -0,0 +1,144 @@ +import { forwardRef, type ReactNode } from "react"; +import { cn } from "../../utils/utils"; +import { Button } from "../button/button"; +import { EnterpriseBadge } from "../enterprise-badge/enterprise-badge"; +import { Typography } from "../typography/typography"; +import styles from "./enterprise-upgrade-overlay.module.scss"; + +/** + * EnterpriseUpgradeOverlay Component + * + * A reusable overlay component that encourages users to upgrade to Enterprise plan. + * Displays a centered card with an Enterprise badge, customizable messaging, and action buttons. + * + * Features: + * - Gradient border effect with backdrop blur + * - Customizable title, description, and button labels + * - Optional "Learn more" button with configurable URL + * - Flexible callback handlers for user interactions + * - Consistent styling with design system + * + * @example + * Basic usage: + * ```tsx + * console.log('Contact sales clicked')} + * /> + * ``` + * + * @example + * Custom button labels and URL: + * ```tsx + * + * ``` + * + * @example + * Without "Learn more" button: + * ```tsx + * + * ``` + */ + +export interface EnterpriseUpgradeOverlayProps { + /** Main title displayed in the overlay */ + title?: ReactNode; + /** Description text or content explaining the feature */ + description?: ReactNode; + /** Name of the feature being promoted (used in default text) */ + feature?: string; + /** Optional URL for the "Learn more" button */ + learnMoreUrl?: string; + /** Optional custom label for the primary CTA button */ + primaryButtonLabel?: string; + /** Optional custom label for the secondary button */ + secondaryButtonLabel?: string; + /** Whether to show the "Learn more" button */ + showLearnMore?: boolean; + /** Callback when contact sales button is clicked */ + onContactSales?: () => void; + /** Callback when learn more button is clicked */ + onLearnMore?: () => void; + /** Custom wrapper class name */ + className?: string; + /** Test ID for testing */ + "data-testid"?: string; +} + +export const EnterpriseUpgradeOverlay = forwardRef( + ( + { + title = "Get access to Enterprise Features", + description = "This feature is available within the Enterprise plan. Contact our sales team to get access to this and more!", + learnMoreUrl = "https://docs.humansignal.com", + primaryButtonLabel = "Contact Sales", + secondaryButtonLabel = "Learn more", + showLearnMore = true, + onContactSales, + onLearnMore, + className, + "data-testid": testId, + }, + ref, + ) => { + const handleContactSales = () => { + onContactSales?.(); + }; + + const handleLearnMore = () => { + if (onLearnMore) { + onLearnMore(); + } else { + window.open(learnMoreUrl, "_blank"); + } + }; + + return ( +
+
+
+
+ +
+ + + {title} + + + + {description} + + +
+ + {showLearnMore && ( + + )} +
+
+
+
+ ); + }, +); + +EnterpriseUpgradeOverlay.displayName = "EnterpriseUpgradeOverlay"; + +export default EnterpriseUpgradeOverlay; diff --git a/web/libs/ui/src/lib/enterprise-upgrade-overlay/index.ts b/web/libs/ui/src/lib/enterprise-upgrade-overlay/index.ts new file mode 100644 index 000000000000..6c15c7df1ef6 --- /dev/null +++ b/web/libs/ui/src/lib/enterprise-upgrade-overlay/index.ts @@ -0,0 +1,2 @@ +export { EnterpriseUpgradeOverlay } from "./enterprise-upgrade-overlay"; +export type { EnterpriseUpgradeOverlayProps } from "./enterprise-upgrade-overlay";