Skip to content

Commit

Permalink
reduce prop drilling
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielmfern committed Nov 4, 2024
1 parent 03467ba commit be2bc44
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 49 deletions.
24 changes: 4 additions & 20 deletions packages/react-email/src/app/preview/[...slug]/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { Shell } from '../../../components/shell';
import { Tooltip } from '../../../components/tooltip';
import { useEmails } from '../../../contexts/emails';
import { useRenderingMetadata } from '../../../hooks/use-rendering-metadata';
import { RenderingError } from './rendering-error';
import { useIframeColorScheme } from '../../../hooks/use-iframe-color-scheme';
import { RenderingError } from './rendering-error';

interface PreviewProps {
slug: string;
Expand Down Expand Up @@ -66,36 +66,20 @@ const Preview = ({
});
}

const handleViewChange = (view: string) => {
const params = new URLSearchParams(searchParams);
params.set('view', view);
router.push(`${pathname}?${params.toString()}`);
};
const hasNoErrors = typeof renderedEmailMetadata !== 'undefined';

const handleLangChange = (lang: string) => {
const setActiveLang = (lang: string) => {
const params = new URLSearchParams(searchParams);
params.set('view', 'source');
params.set('lang', lang);
router.push(`${pathname}?${params.toString()}`);
};

const handleThemeChange = (theme: string) => {
const params = new URLSearchParams(searchParams);
params.set('theme', theme);
router.push(`${pathname}?${params.toString()}`);
};

const hasNoErrors = typeof renderedEmailMetadata !== 'undefined';

return (
<Shell
activeView={hasNoErrors ? activeView : undefined}
currentEmailOpenSlug={slug}
markup={renderedEmailMetadata?.markup}
pathSeparator={pathSeparator}
setActiveView={hasNoErrors ? handleViewChange : undefined}
setTheme={hasNoErrors ? handleThemeChange : undefined}
theme={hasNoErrors ? activeTheme : undefined}
>
{/* This relative is so that when there is any error the user can still switch between emails */}
<div className="relative h-full">
Expand Down Expand Up @@ -143,7 +127,7 @@ const Preview = ({
content: renderedEmailMetadata.plainText,
},
]}
setActiveLang={handleLangChange}
setActiveLang={setActiveLang}
/>
</Tooltip.Provider>
</div>
Expand Down
12 changes: 0 additions & 12 deletions packages/react-email/src/components/shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,13 @@ interface ShellProps extends RootProps {
markup?: string;
currentEmailOpenSlug?: string;
pathSeparator?: string;
activeView?: string;
setActiveView?: (view: string) => void;
theme?: string;
setTheme?: (theme: string) => void;
}

export const Shell = ({
currentEmailOpenSlug,
children,
pathSeparator,
markup,
activeView,
setActiveView,
theme,
setTheme,
}: ShellProps) => {
const [sidebarToggled, setSidebarToggled] = React.useState(false);
const [triggerTransition, setTriggerTransition] = React.useState(false);
Expand Down Expand Up @@ -93,7 +85,6 @@ export const Shell = ({
>
{currentEmailOpenSlug && pathSeparator ? (
<Topbar
activeView={activeView}
currentEmailOpenSlug={currentEmailOpenSlug}
markup={markup}
onToggleSidebar={() => {
Expand All @@ -108,9 +99,6 @@ export const Shell = ({
}, 300);
}}
pathSeparator={pathSeparator}
setActiveView={setActiveView}
setTheme={setTheme}
theme={theme}
/>
) : null}

Expand Down
45 changes: 28 additions & 17 deletions packages/react-email/src/components/topbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import * as ToggleGroup from '@radix-ui/react-toggle-group';
import { motion } from 'framer-motion';
import * as React from 'react';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { cn } from '../utils';
import { tabTransition } from '../utils/constants';
import { Heading } from './heading';
Expand All @@ -18,23 +19,33 @@ interface TopbarProps {
currentEmailOpenSlug: string;
pathSeparator: string;
markup?: string;
activeView?: string;
setActiveView?: (view: string) => void;
theme?: string;
setTheme?: (theme: string) => void;
onToggleSidebar?: () => void;
}

export const Topbar: React.FC<Readonly<TopbarProps>> = ({
currentEmailOpenSlug,
pathSeparator,
markup,
activeView,
setActiveView,
theme,
setTheme,
onToggleSidebar,
}) => {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();

const activeTheme = searchParams.get('theme') ?? 'light';
const activeView = searchParams.get('view') ?? 'desktop';

const setActiveView = (view: string) => {
const params = new URLSearchParams(searchParams);
params.set('view', view);
router.push(`${pathname}?${params.toString()}`);
};

const setTheme = (theme: string) => {
const params = new URLSearchParams(searchParams);
params.set('theme', theme);
router.push(`${pathname}?${params.toString()}`);
};
return (
<Tooltip.Provider>
<header className="flex relative items-center px-4 justify-between h-[70px] border-b border-slate-6">
Expand Down Expand Up @@ -67,10 +78,10 @@ export const Topbar: React.FC<Readonly<TopbarProps>> = ({
className="inline-block items-center bg-slate-2 border border-slate-6 rounded-md overflow-hidden h-[36px]"
id="theme-toggle"
onValueChange={(value) => {
if (value) setTheme?.(value);
if (value) setTheme(value);
}}
type="single"
value={theme}
value={activeTheme}
>
<ToggleGroup.Item value="light">
<Tooltip>
Expand All @@ -79,12 +90,12 @@ export const Topbar: React.FC<Readonly<TopbarProps>> = ({
className={cn(
'px-3 py-2 transition ease-in-out duration-200 relative hover:text-slate-12',
{
'text-slate-11': theme !== 'light',
'text-slate-12': theme === 'light',
'text-slate-11': activeTheme !== 'light',
'text-slate-12': activeTheme === 'light',
},
)}
>
{theme === 'light' && (
{activeTheme === 'light' && (
<motion.span
animate={{ opacity: 1 }}
className="absolute left-0 right-0 top-0 bottom-0 bg-slate-4"
Expand All @@ -107,12 +118,12 @@ export const Topbar: React.FC<Readonly<TopbarProps>> = ({
className={cn(
'px-3 py-2 transition ease-in-out duration-200 relative hover:text-slate-12',
{
'text-slate-11': theme !== 'dark',
'text-slate-12': theme === 'dark',
'text-slate-11': activeTheme !== 'dark',
'text-slate-12': activeTheme === 'dark',
},
)}
>
{theme === 'dark' && (
{activeTheme === 'dark' && (
<motion.span
animate={{ opacity: 1 }}
className="absolute left-0 right-0 top-0 bottom-0 bg-slate-4"
Expand All @@ -135,7 +146,7 @@ export const Topbar: React.FC<Readonly<TopbarProps>> = ({
className="inline-block items-center bg-slate-2 border border-slate-6 rounded-md overflow-hidden h-[36px]"
id="view-toggle"
onValueChange={(value) => {
if (value) setActiveView?.(value);
if (value) setActiveView(value);
}}
type="single"
value={activeView}
Expand Down

0 comments on commit be2bc44

Please sign in to comment.