Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 18da110

Browse files
committed
feat: implement Premium page with Tailwind and shadcn button
1 parent 7af2abe commit 18da110

File tree

9 files changed

+368
-127
lines changed

9 files changed

+368
-127
lines changed

.vscode/settings.json

+5-4
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,11 @@
249249
"playwright.reuseBrowser": true,
250250

251251
"[javascript][javascriptreact][json][jsonc][typescript][typescriptreact]": {
252-
"editor.defaultFormatter": "biomejs.biome"
253-
// "editor.codeActionsOnSave": {
254-
// "source.organizeImports.biome": "explicit"
255-
// }
252+
"editor.defaultFormatter": "biomejs.biome",
253+
"editor.codeActionsOnSave": {
254+
"quickfix.biome": "explicit"
255+
// "source.organizeImports.biome": "explicit"
256+
}
256257
},
257258

258259
"[css][html][markdown][yaml]": {

site/components.json

+19-19
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
{
2-
"$schema": "https://ui.shadcn.com/schema.json",
3-
"style": "new-york",
4-
"rsc": false,
5-
"tsx": true,
6-
"tailwind": {
7-
"config": "tailwind.config.js",
8-
"css": "src/index.css",
9-
"baseColor": "zinc",
10-
"cssVariables": false,
11-
"prefix": ""
12-
},
13-
"aliases": {
14-
"components": "@/components",
15-
"utils": "@/lib/utils",
16-
"ui": "@/components/ui",
17-
"lib": "@/lib",
18-
"hooks": "@/hooks"
19-
}
20-
}
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "new-york",
4+
"rsc": false,
5+
"tsx": true,
6+
"tailwind": {
7+
"config": "tailwind.config.js",
8+
"css": "src/index.css",
9+
"baseColor": "zinc",
10+
"cssVariables": true,
11+
"prefix": ""
12+
},
13+
"aliases": {
14+
"components": "@/components",
15+
"utils": "@/lib/utils",
16+
"ui": "@/components/ui",
17+
"lib": "@/lib",
18+
"hooks": "@/hooks"
19+
}
20+
}

site/src/components/ui/button.tsx

+44-48
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,53 @@
1-
import * as React from "react"
2-
import { Slot } from "@radix-ui/react-slot"
3-
import { cva, type VariantProps } from "class-variance-authority"
1+
import { Slot } from "@radix-ui/react-slot";
2+
import { type VariantProps, cva } from "class-variance-authority";
3+
import * as React from "react";
44

5-
import { cn } from "@/lib/utils"
5+
import { cn } from "@/lib/utils";
66

77
const buttonVariants = cva(
8-
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
9-
{
10-
variants: {
11-
variant: {
12-
default:
13-
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
14-
destructive:
15-
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
16-
outline:
17-
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
18-
secondary:
19-
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
20-
ghost: "hover:bg-accent hover:text-accent-foreground",
21-
link: "text-primary underline-offset-4 hover:underline",
22-
},
23-
size: {
24-
default: "h-9 px-4 py-2",
25-
sm: "h-8 rounded-md px-3 text-xs",
26-
lg: "h-10 rounded-md px-8",
27-
icon: "h-9 w-9",
28-
},
29-
},
30-
defaultVariants: {
31-
variant: "default",
32-
size: "default",
33-
},
34-
}
35-
)
8+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-0 font-semibold",
9+
{
10+
variants: {
11+
variant: {
12+
default:
13+
"bg-surface-invert-primary text-content-invert hover:bg-surface-invert-secondary",
14+
outline:
15+
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
16+
subtle:
17+
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
18+
warning:
19+
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
20+
},
21+
size: {
22+
default: "h-10 px-3 py-2",
23+
sm: "h-8 px-2 text-xs",
24+
},
25+
},
26+
defaultVariants: {
27+
variant: "default",
28+
size: "default",
29+
},
30+
},
31+
);
3632

3733
export interface ButtonProps
38-
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
39-
VariantProps<typeof buttonVariants> {
40-
asChild?: boolean
34+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
35+
VariantProps<typeof buttonVariants> {
36+
asChild?: boolean;
4137
}
4238

4339
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
44-
({ className, variant, size, asChild = false, ...props }, ref) => {
45-
const Comp = asChild ? Slot : "button"
46-
return (
47-
<Comp
48-
className={cn(buttonVariants({ variant, size, className }))}
49-
ref={ref}
50-
{...props}
51-
/>
52-
)
53-
}
54-
)
55-
Button.displayName = "Button"
40+
({ className, variant, size, asChild = false, ...props }, ref) => {
41+
const Comp = asChild ? Slot : "button";
42+
return (
43+
<Comp
44+
className={cn(buttonVariants({ variant, size, className }))}
45+
ref={ref}
46+
{...props}
47+
/>
48+
);
49+
},
50+
);
51+
Button.displayName = "Button";
5652

57-
export { Button, buttonVariants }
53+
export { Button, buttonVariants };

site/src/contexts/ThemeProvider.tsx

+11
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ export const ThemeProvider: FC<PropsWithChildren> = ({ children }) => {
5555
// The janky casting here is find because of the much more type safe fallback
5656
// We need to support `themePreference` being wrong anyway because the database
5757
// value could be anything, like an empty string.
58+
59+
useEffect(() => {
60+
const root = window.document.documentElement;
61+
root.classList.remove("light", "dark");
62+
if (themePreference === "auto") {
63+
root.classList.add(preferredColorScheme);
64+
} else {
65+
root.classList.add(themePreference);
66+
}
67+
}, [themePreference, preferredColorScheme]);
68+
5869
const theme =
5970
themes[themePreference as keyof typeof themes] ??
6071
themes[preferredColorScheme];

site/src/index.css

+24-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,29 @@
11
@tailwind base;
22
@tailwind components;
33
@tailwind utilities;
4+
45
@layer base {
5-
:root {
6-
--radius: 0.5rem
7-
}
6+
:root {
7+
--content-primary: #27272a;
8+
--content-secondary: #52525b;
9+
--content-link: #2563eb;
10+
--content-invert: #fafafa;
11+
--surface-primary: #fafafa;
12+
--surface-secondary: #f4f4f5;
13+
--surface-tertiary: #e4e4e7;
14+
--surface-invert-primary: #27272a;
15+
--surface-invert-secondary: #3f3f46;
16+
--radius: 0.5rem;
17+
}
18+
.dark {
19+
--content-primary: #fafafa;
20+
--content-secondary: #a1a1aa;
21+
--content-link: #60a5fa;
22+
--content-invert: #09090b;
23+
--surface-primary: #09090b;
24+
--surface-secondary: #18181b;
25+
--surface-tertiary: #27272a;
26+
--surface-invert-primary: #e4e4e7;
27+
--surface-invert-secondary: #a1a1aa;
28+
}
829
}

site/src/lib/utils.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { clsx, type ClassValue } from "clsx"
2-
import { twMerge } from "tailwind-merge"
1+
import { type ClassValue, clsx } from "clsx";
2+
import { twMerge } from "tailwind-merge";
33

44
export function cn(...inputs: ClassValue[]) {
5-
return twMerge(clsx(inputs))
5+
return twMerge(clsx(inputs));
66
}

site/src/pages/DeploymentSettingsPage/PremiumPage/PremiumPage.tsx

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
import { Loader } from "components/Loader/Loader";
2-
import { useDeploymentSettings } from "modules/management/DeploymentSettingsProvider";
1+
import { useDashboard } from "modules/dashboard/useDashboard";
32
import type { FC } from "react";
43
import { Helmet } from "react-helmet-async";
54
import { pageTitle } from "utils/page";
65
import { PremiumPageView } from "./PremiumPageView";
7-
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
86

97
const PremiumPage: FC = () => {
10-
const { multiple_organizations: hasPremiumLicense } = useFeatureVisibility();
8+
const { entitlements } = useDashboard();
119

1210
return (
1311
<>
1412
<Helmet>
1513
<title>{pageTitle("Premium Features")}</title>
1614
</Helmet>
17-
<PremiumPageView isPremium={hasPremiumLicense} />
15+
<PremiumPageView isEnterprise={entitlements.has_license} />
1816
</>
1917
);
2018
};

0 commit comments

Comments
 (0)