Skip to content

Commit

Permalink
feat: shadcn preview
Browse files Browse the repository at this point in the history
  • Loading branch information
mehdibha committed Dec 30, 2023
1 parent a8712e5 commit 292e471
Show file tree
Hide file tree
Showing 21 changed files with 485 additions and 219 deletions.
68 changes: 68 additions & 0 deletions apps/web/src/app/(app)/playground/form-provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"use client";

import React from "react";
import { useForm } from "react-hook-form";
import { Form } from "@palettify/ui";

const lightTheme = {
background: "0 0% 100%",
foreground: "222.2 47.4% 11.2%",
muted: "210 40% 96.1%",
mutedForeground: "215.4 16.3% 46.9%",
popover: "0 0% 100%",
popoverForeground: "222.2 47.4% 11.2%",
border: "214.3 31.8% 91.4%",
input: "214.3 31.8% 91.4%",
card: "0 0% 100%",
cardForeground: "222.2 47.4% 11.2%",
primary: "222.2 47.4% 11.2%",
primaryForeground: "210 40% 98%",
secondary: "210 40% 96.1%",
secondaryForeground: "222.2 47.4% 11.2%",
accent: "210 40% 96.1%",
accentForeground: "222.2 47.4% 11.2%",
destructive: "0 100% 50%",
destructiveForeground: "210 40% 98%",
ring: "215 20.2% 65.1%",
radius: "0.5rem",
};

const darkTheme = {
background: "224 71% 4%",
foreground: "213 31% 91%",
muted: "223 47% 11%",
mutedForeground: "215.4 16.3% 56.9%",
accent: "216 34% 17%",
accentForeground: "210 40% 98%",
popover: "224 71% 4%",
popoverForeground: "215 20.2% 65.1%",
border: "216 34% 17%",
input: "216 34% 17%",
card: "224 71% 4%",
cardForeground: "213 31% 91%",
primary: "210 40% 98%",
primaryForeground: "222.2 47.4% 1.2%",
secondary: "222.2 47.4% 11.2%",
secondaryForeground: "210 40% 98%",
destructive: "0 63% 31%",
destructiveForeground: "210 40% 98%",
ring: "216 34% 17%",
radius: "0.5rem",
};

interface FormProviderProps {
children: React.ReactNode;
}

export const FormProvider = (props: FormProviderProps) => {
const { children } = props;

const form = useForm({
values: {
library: "shadcn",
lightTheme,
darkTheme,
},
});
return <Form {...form}>{children}</Form>;
};
9 changes: 5 additions & 4 deletions apps/web/src/app/(app)/playground/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import { ReactNode } from "react";
import { FormProvider } from "./form-provider";
import { Preview } from "./preview";

interface DashboardLayoutProps {
children: ReactNode;
}

export default async function DashboardLayout(props: DashboardLayoutProps) {
export default function DashboardLayout(props: DashboardLayoutProps) {
const { children } = props;

return (
<div className="min-h-screen">
<div>
<FormProvider>
<div className="min-h-screen">
<div className="lg:w-[500px]">
<div className="container px-8">
<div className="bg-card rounded-xl border p-4 shadow-xl">{children}</div>
</div>
</div>
<Preview />
</div>
</div>
</FormProvider>
);
}
6 changes: 5 additions & 1 deletion apps/web/src/app/(app)/playground/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { useSearchParams } from "next/navigation";
import { UpdateSiteAppearance } from "@/modules/theme-previewer/components/theme-form";

export default function PalettesPage() {
function PalettesPage() {
useSearchParams();
return <UpdateSiteAppearance />;
}

export default PalettesPage;
9 changes: 6 additions & 3 deletions apps/web/src/app/(app)/playground/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"use client";

import React from "react";
import { useFormContext } from "react-hook-form";
import {
Button,
Maximize2Icon,
Minimize2Icon,
MonitorIcon,
ScrollArea,
SmartphoneIcon,
} from "@palettify/ui";
import { cn } from "@palettify/utils";
Expand All @@ -15,6 +17,7 @@ import { Preview as LibraryPreview } from "@/modules/theme-previewer/components/
export const Preview = () => {
const [mobileView, setMobileView] = React.useState(false);
const [fullScreen, setFullScreen] = React.useState(false);
const form = useFormContext();
useScrollLock(fullScreen);

const handleChangeMobileView = () => {
Expand All @@ -39,15 +42,15 @@ export const Preview = () => {
</Button>
</div>
</div>
<div className="overflow-y-scroll">
<ScrollArea className="h-full w-full">
<div
className={cn("bg-background/50 h-full w-full", {
"flex items-center justify-center p-2": mobileView,
})}
>
<LibraryPreview library="shadcn" />
<LibraryPreview library={form.watch("library")} />
</div>
</div>
</ScrollArea>
</div>
</PreviewWrapper>
);
Expand Down
22 changes: 9 additions & 13 deletions apps/web/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,15 @@ export default function RootLayout({ children }: { children: React.ReactNode })
<html lang="en" suppressHydrationWarning>
<body className={cn(inter.variable, display.variable)} suppressHydrationWarning>
<Providers>
<Analytics />
<div
className="grad relative bg-gradient-to-br from-[#e4e9ea] from-10% to-[#FFDEC1] to-80% dark:from-[#3f3541] dark:to-[#1d1917]"
// style={{
// background: "linear-gradient(to bottom right, #FBD7FF 10%, #FFDEC1 80%)",
// }}
>
{/* <Banner /> */}
<Suspense fallback={<div className="h-[64px]" />}>
<Header />
</Suspense>
<div className="min-h-[calc(100vh-64px)] pb-36">{children}</div>
<Footer />
<div className="theme-nature">
<Analytics />
<div className="grad relative bg-gradient-to-br from-[#e4e9ea] from-10% to-[#FFDEC1] to-80% dark:from-[#3f3541] dark:to-[#1d1917]">
<Suspense fallback={<div className="h-[64px]" />}>
<Header />
</Suspense>
<div className="min-h-[calc(100vh-64px)] pb-36">{children}</div>
<Footer />
</div>
</div>
</Providers>
</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const metadata: Metadata = {

export function DashboardPage() {
return (
<div className="flex flex-col">
<div className="light-mode flex flex-col">
<div className="border-b">
<div className="flex h-16 items-center px-4">
<TeamSwitcher />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,74 +1,74 @@
// "use client";
"use client";

// import React from "react";
import React from "react";
import { useTheme } from "next-themes";
import { useFormContext } from "react-hook-form";

// interface ThemeWrapperProps extends React.ComponentProps<"div"> {
// // defaultThemes: Theme[];
// // themes?: Theme[];
// }
interface ThemeWrapperProps extends React.ComponentProps<"div"> {
children: React.ReactNode;
}

// export function DynamicThemeWrapper({
// defaultThemes,
// themes = [],
// children,
// }: ThemeWrapperProps) {
// const darkTheme = (themes.find((t) => t.mode === "dark") ??
// defaultThemes.find((t) => t.mode === "dark")) as Theme;
// const lightTheme = (themes.find((t) => t.mode === "light") ??
// defaultThemes.find((t) => t.mode === "light")) as Theme;
export function DynamicThemeWrapper(props: ThemeWrapperProps) {
const { children } = props;

// return (
// <div>
// <style jsx global>{`
// :root {
// --background: ${lightTheme.background};
// --foreground: ${lightTheme.foreground};
// --card: ${lightTheme.card};
// --card-foreground: ${lightTheme.cardForeground};
// --popover: ${lightTheme.popover};
// --popover-foreground: ${lightTheme.popoverForeground};
// --primary: ${lightTheme.primary};
// --primary-foreground: ${lightTheme.primaryForeground};
// --secondary: ${lightTheme.secondary};
// --secondary-foreground: ${lightTheme.secondaryForeground};
// --muted: ${lightTheme.muted};
// --muted-foreground: ${lightTheme.mutedForeground};
// --accent: ${lightTheme.accent};
// --accent-foreground: ${lightTheme.accentForeground};
// --destructive: ${lightTheme.destructive};
// --destructive-foreground: ${lightTheme.destructiveForeground};
// --success: ${lightTheme.success};
// --success-foreground: ${lightTheme.successForeground};
// --border: ${lightTheme.border};
// --input: ${lightTheme.input};
// --ring: ${lightTheme.ring};
// }
const form = useFormContext();

// .dark {
// --background: ${darkTheme.background};
// --foreground: ${darkTheme.foreground};
// --card: ${darkTheme.card};
// --card-foreground: ${darkTheme.cardForeground};
// --popover: ${darkTheme.popover};
// --popover-foreground: ${darkTheme.popoverForeground};
// --primary: ${darkTheme.primary};
// --primary-foreground: ${darkTheme.primaryForeground};
// --secondary: ${darkTheme.secondary};
// --secondary-foreground: ${darkTheme.secondaryForeground};
// --muted: ${darkTheme.muted};
// --muted-foreground: ${darkTheme.mutedForeground};
// --accent: ${darkTheme.accent};
// --accent-foreground: ${darkTheme.accentForeground};
// --destructive: ${darkTheme.destructive};
// --destructive-foreground: ${darkTheme.destructiveForeground};
// --success: ${darkTheme.success};
// --success-foreground: ${darkTheme.successForeground};
// --border: ${darkTheme.border};
// --input: ${darkTheme.input};
// --ring: ${darkTheme.ring};
// }
// `}</style>
// {children}
// </div>
// );
// }
const mode = useTheme().resolvedTheme;
const darkTheme = form.watch("darkTheme");
const lightTheme = form.watch("lightTheme");
const resolvedTheme = mode === "dark" ? darkTheme : lightTheme;

return (
<div className="preview-mode">
<style jsx global>{`
.preview-mode {
--background: ${resolvedTheme.background};
--foreground: ${resolvedTheme.foreground};
--card: ${resolvedTheme.card};
--card-foreground: ${resolvedTheme.cardForeground};
--popover: ${resolvedTheme.popover};
--popover-foreground: ${resolvedTheme.popoverForeground};
--primary: ${resolvedTheme.primary};
--primary-foreground: ${resolvedTheme.primaryForeground};
--secondary: ${resolvedTheme.secondary};
--secondary-foreground: ${resolvedTheme.secondaryForeground};
--muted: ${resolvedTheme.muted};
--muted-foreground: ${resolvedTheme.mutedForeground};
--accent: ${resolvedTheme.accent};
--accent-foreground: ${resolvedTheme.accentForeground};
--destructive: ${resolvedTheme.destructive};
--destructive-foreground: ${resolvedTheme.destructiveForeground};
--success: ${resolvedTheme.success};
--success-foreground: ${resolvedTheme.successForeground};
--border: ${resolvedTheme.border};
--input: ${resolvedTheme.input};
--ring: ${resolvedTheme.ring};
}
.preview-mode.dark {
--background: ${resolvedTheme.background};
--foreground: ${resolvedTheme.foreground};
--card: ${resolvedTheme.card};
--card-foreground: ${resolvedTheme.cardForeground};
--popover: ${resolvedTheme.popover};
--popover-foreground: ${resolvedTheme.popoverForeground};
--primary: ${resolvedTheme.primary};
--primary-foreground: ${resolvedTheme.primaryForeground};
--secondary: ${resolvedTheme.secondary};
--secondary-foreground: ${resolvedTheme.secondaryForeground};
--muted: ${resolvedTheme.muted};
--muted-foreground: ${resolvedTheme.mutedForeground};
--accent: ${resolvedTheme.accent};
--accent-foreground: ${resolvedTheme.accentForeground};
--destructive: ${resolvedTheme.destructive};
--destructive-foreground: ${resolvedTheme.destructiveForeground};
--success: ${resolvedTheme.success};
--success-foreground: ${resolvedTheme.successForeground};
--border: ${resolvedTheme.border};
--input: ${resolvedTheme.input};
--ring: ${resolvedTheme.ring};
}
`}</style>
<div className="text-foreground bg-background">{children}</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from "react";
import React, { Suspense } from "react";
import { DashboardPage } from "./dashboard";
import { DynamicThemeWrapper } from "./dynamic-theme-wrapper";
import { StyledJsxRegistry } from "./registry";

// import { DynamicThemeWrapper } from "./dynamic-theme-wrapper";

export const ShadcnPreview = () => {
return (
<StyledJsxRegistry>
<DashboardPage />
<DynamicThemeWrapper>
<DashboardPage />
</DynamicThemeWrapper>
</StyledJsxRegistry>
);
};
Loading

0 comments on commit 292e471

Please sign in to comment.