Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(app-preview): add logic for mobile sidebar and update ui #190

Merged
merged 1 commit into from
Apr 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
117 changes: 78 additions & 39 deletions apps/preview/app/src/components/nav.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Cross2Icon, QuestionMarkCircledIcon } from '@radix-ui/react-icons';
import { Cross2Icon, QuestionMarkCircledIcon, HamburgerMenuIcon } from '@radix-ui/react-icons';
import * as Popover from '@radix-ui/react-popover';
import * as ToggleGroup from '@radix-ui/react-toggle-group';
import classnames from 'classnames';
Expand All @@ -12,50 +12,89 @@ import { NavButton } from './nav-button';
interface NavProps extends React.ComponentPropsWithoutRef<'header'> {
activeView?: Views;
markup?: string;
openNav: () => void;
setActiveView?: (view: Views) => void;
title: string;
}

export const Nav = React.forwardRef<React.ElementRef<'header'>, Readonly<NavProps>>(
({ className, title, markup, activeView, setActiveView, ...props }, forwardedRef) => (
<header
ref={forwardedRef}
className={classnames(
'bg-dark-bg flex relative items-center px-6 justify-between h-[70px] border-b border-dark-bg-border',
className
)}
{...props}
>
<div className={`items-center overflow-hidden hidden lg:flex`}>
<h2 className="text-base font-bold truncate text">{title}</h2>
</div>
({ className, title, markup, activeView, setActiveView, openNav, ...props }, forwardedRef) => (
<>
<header
ref={forwardedRef}
className={classnames(
'bg-dark-bg flex relative items-center px-6 justify-between h-[70px] border-b border-dark-bg-border',
className
)}
{...props}
>
<div className="flex items-center gap-4">
<button
onClick={openNav}
className="inlne-block lg:hidden w-5 h-5"
aria-label="Toggle nav menu"
>
<HamburgerMenuIcon className="h-5 w-5" />
</button>
{!!title && (
<div className={`items-center overflow-hidden hidden lg:flex`}>
<h2 className="text-base font-bold truncate text">{title}</h2>
</div>
)}
</div>

<div>
<Popover.Root>
<Popover.Trigger asChild>
<button
className="align-top h-[20px] w-[20px] pt-[9px] mr-4"
aria-label="Preview Information"
>
<QuestionMarkCircledIcon className="h-[20px] w-[20px]" />
</button>
</Popover.Trigger>
<Popover.Portal>
<Popover.Content className="note" sideOffset={5}>
<div className="pt-4 text-xs">
The Desktop and Mobile views are <em>an approximation</em> of what your email
template will looke like on various devices. It should not be considered a source of
truth, but rather a guide for styling and layout. Always send a test email to your
target email clients for Quality Control, before sending emails in production.
</div>
<Popover.Close className="note-close" aria-label="Close">
<Cross2Icon />
</Popover.Close>
<Popover.Arrow className="note-arrow" />
</Popover.Content>
</Popover.Portal>
</Popover.Root>
{!!title && (
<div className="flex flex-row items-center gap-4">
<Popover.Root>
<Popover.Trigger asChild>
<button className="h-5 w-5" aria-label="Preview Information">
<QuestionMarkCircledIcon className="h-5 w-5" />
</button>
</Popover.Trigger>
<Popover.Portal>
<Popover.Content className="note" sideOffset={5}>
<div className="pt-4 text-xs">
The Desktop and Mobile views are <em>an approximation</em> of what your email
template will looke like on various devices. It should not be considered a
source of truth, but rather a guide for styling and layout. Always send a test
email to your target email clients for Quality Control, before sending emails in
production.
</div>
<Popover.Close className="note-close" aria-label="Close">
<Cross2Icon />
</Popover.Close>
<Popover.Arrow className="note-arrow" />
</Popover.Content>
</Popover.Portal>
</Popover.Root>

<LayoutGroup id="topbar">
{setActiveView && (
<ToggleGroup.Root
className="hidden sm:inline-block items-center bg-darker-bg border border-dark-bg-border rounded overflow-hidden"
type="single"
value={activeView}
aria-label="View mode"
onValueChange={(value) => {
if (value) setActiveView(value as Views);
}}
>
<NavButton
activeView={activeView}
addClassNames="px-1 py-1 sm:px-3 sm:py-2"
label={Views.Desktop}
/>
<NavButton activeView={activeView} label={Views.Mobile} />
<NavButton activeView={activeView} label={Views.Jsx} />
<NavButton activeView={activeView} label={Views.Html} />
<NavButton activeView={activeView} label={Views.Plain} />
</ToggleGroup.Root>
)}
</LayoutGroup>
</div>
)}
</header>
<div className="bg-dark-bg h-[70px] flex sm:hidden items-center justify-center">
<LayoutGroup id="topbar">
{setActiveView && (
<ToggleGroup.Root
Expand All @@ -80,7 +119,7 @@ export const Nav = React.forwardRef<React.ElementRef<'header'>, Readonly<NavProp
)}
</LayoutGroup>
</div>
</header>
</>
)
);

Expand Down
2 changes: 1 addition & 1 deletion apps/preview/app/src/components/send.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const Send: React.FC<SendProps> = ({ markup }) => {
<div className="rounded bg-darker-bg absolute top-[20px] right-[20px] w-7 h-7 animate-[ping_1s_cubic-bezier(0,0,0.2,1)_2]" />
<Popover.Trigger asChild>
<IconButton
className="bg-darker-bg p-1 rounded focus:text-dark-bg-text ease-in-out transition duration-200 focus:outline-none focus:ring-2 focus:ring-gray-8 hover:text-dark-bg-text absolute top-[20px] right-[20px] hidden md:block"
className="bg-darker-bg p-1 rounded focus:text-dark-bg-text ease-in-out transition duration-200 focus:outline-none focus:ring-2 focus:ring-gray-8 hover:text-dark-bg-text absolute top-[20px] right-[20px]"
title="Send preview email"
>
<IconPaperAirplane />
Expand Down
20 changes: 10 additions & 10 deletions apps/preview/app/src/components/shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ interface ShellProps extends RootProps {

export const Shell = React.forwardRef<ShellElement, Readonly<ShellProps>>(
({ title, templateParts, children, html, activeView, setActiveView }, forwardedRef) => {
const [showNav] = React.useState(false);
const [showNav, setShowNav] = React.useState(false);
return (
<div className="flex flex-col h-screen overflow-x-hidden">
<div ref={forwardedRef} className="flex justify-between h-full">
<Sidebar
className={classNames('w-screen max-w-full md:max-w-[275px]', {
closeNav={() => setShowNav(false)}
className={classNames('w-screen max-w-full lg:max-w-[275px]', {
'translate-x-[-100%] lg:translate-x-0 absolute lg:relative': !showNav,
'translate-x-0': showNav
})}
Expand All @@ -36,14 +37,13 @@ export const Shell = React.forwardRef<ShellElement, Readonly<ShellProps>>(
'w-screen lg:w-[calc(100%_-_275px)]': !showNav
})}
>
{title && (
<Nav
title={title}
activeView={activeView}
setActiveView={setActiveView}
markup={html}
/>
)}
<Nav
title={title}
activeView={activeView}
setActiveView={setActiveView}
markup={html}
openNav={() => setShowNav(true)}
/>
<div className="relative h-[calc(100vh_-_70px)] overflow-auto">
<div className="mx-auto">{children}</div>
</div>
Expand Down
25 changes: 21 additions & 4 deletions apps/preview/app/src/components/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import classnames from 'classnames';
import * as React from 'react';
import { Link, useLocation } from 'react-router-dom';

import { Cross1Icon } from '@radix-ui/react-icons';

import type { TemplatePart } from '../types';

import { Logo } from './logo';
Expand All @@ -11,11 +13,13 @@ type SidebarElement = React.ElementRef<'aside'>;
type RootProps = React.ComponentPropsWithoutRef<'aside'>;

interface SidebarProps extends RootProps {
closeNav: () => void;
templateParts: TemplatePart[];
title?: string;
}

interface SidebarSectionProps {
closeNav: () => void;
currentPageTitle: string;
isSubSection?: boolean;
templateParts: TemplatePart[];
Expand Down Expand Up @@ -80,7 +84,8 @@ const FileName = () => (
</svg>
);

const SidebarSection = ({
export const SidebarSection = ({
closeNav,
templateParts,
currentPageTitle,
isSubSection,
Expand Down Expand Up @@ -140,6 +145,7 @@ const SidebarSection = ({
return isParent ? (
<div className="pl-4" key={item.name}>
<SidebarSection
closeNav={closeNav}
templateParts={item.children}
currentPageTitle={currentPageTitle}
title={item.name}
Expand All @@ -156,6 +162,7 @@ const SidebarSection = ({
}
key={item.name}
to={`/${item.path}`}
onClick={closeNav}
>
<span
className={classnames(
Expand Down Expand Up @@ -187,11 +194,21 @@ const SidebarSection = ({
};

export const Sidebar = React.forwardRef<SidebarElement, Readonly<SidebarProps>>(
({ className, templateParts, title, ...props }, forwardedRef) => (
({ className, templateParts, closeNav, title, ...props }, forwardedRef) => (
<aside ref={forwardedRef} className={className} {...props}>
<nav className="h-full p-6 w-screen md:w-full md:min-w-[275px] md:max-w-[275px] flex flex-col gap-4 border-r border-dark-bg-border">
<Logo />
<nav className="h-full p-6 w-screen lg:w-full lg:min-w-[275px] lg:max-w-[275px] flex flex-col gap-4 border-r border-dark-bg-border">
<div className="flex items-center justify-between">
<Logo />
<button
onClick={closeNav}
className="inlne-block lg:hidden w-5 h-5"
aria-label="Toggle nav menu"
>
<Cross1Icon className="w-5 h-5" />
</button>
</div>
<SidebarSection
closeNav={closeNav}
templateParts={templateParts}
currentPageTitle={title}
title="Email Templates"
Expand Down