From 35cf2a2ad274c52d3f2314159339f85e464f06ba Mon Sep 17 00:00:00 2001 From: winkerVSbecks Date: Wed, 27 Nov 2024 12:49:09 -0500 Subject: [PATCH 1/9] wrap NavDesktopItemCard with NavigationMenu.Link to fix keyboard nav --- src/Header/NavDesktopContent.tsx | 27 +++++++++++++++------------ src/Header/data.tsx | 15 ++++++++++++++- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/Header/NavDesktopContent.tsx b/src/Header/NavDesktopContent.tsx index 36ca442c..43c97885 100644 --- a/src/Header/NavDesktopContent.tsx +++ b/src/Header/NavDesktopContent.tsx @@ -6,6 +6,7 @@ import { HeaderDesktopItem, HeaderDesktopItemContent } from './types'; import { Text } from '../Text'; import { VStack } from '../Stack/Stack'; import { LinkWithWrapper } from '../LinkWithWrapper'; +import * as NavigationMenu from '@radix-ui/react-navigation-menu'; interface Props { item: HeaderDesktopItem; @@ -73,19 +74,21 @@ const NavDesktopItemCard = ({ linkWrapper, href, }: HeaderDesktopItemContent) => ( - - - - - {title} - - - {description} - + + + + + + {title} + + + {description} + + + - - - + + ); export const NavDesktopContent: FC = ({ item }) => { diff --git a/src/Header/data.tsx b/src/Header/data.tsx index d05c1a50..b844873e 100644 --- a/src/Header/data.tsx +++ b/src/Header/data.tsx @@ -222,7 +222,7 @@ export const desktopData: HeaderProps['desktopData'] = [ { id: 'customers', name: 'Customers', - leftPosition: -120, + leftPosition: -420, menu: [ { content: [ @@ -291,6 +291,19 @@ export const desktopData: HeaderProps['desktopData'] = [ ], backgroundColor: 'white', }, + { + content: [ + { + type: 'card', + title: 'Frontend testing guide', + description: + 'We researched dozens of teams to figure out which testing strategies actually work. ', + image: '/frontend-testing-guide.jpg', + href: '#', + }, + ], + backgroundColor: 'blue50', + }, ], }, { From 35677e28717654d119234cf6ea30fc40e127ba29 Mon Sep 17 00:00:00 2001 From: winkerVSbecks Date: Wed, 27 Nov 2024 15:57:04 -0500 Subject: [PATCH 2/9] fix icon spacing for link --- src/Link/Link.stories.tsx | 39 +++++++++++++++++++++++++++++++++++++++ src/Link/Link.tsx | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/Link/Link.stories.tsx b/src/Link/Link.stories.tsx index 67e7385f..606d653f 100644 --- a/src/Link/Link.stories.tsx +++ b/src/Link/Link.stories.tsx @@ -94,3 +94,42 @@ export const InlineSize: Story = { ), }; + +export const RightIcon: Story = { + args: { + children: 'Hello World', + color: 'blue500', + rightIcon: 'arrowright', + }, + render: ({ children, ...args }) => ( + <> + + {children} + + + {children} + + + {children} + + + {children} + + + ), + decorators: [ + (Story) => ( +
+ +
+ ), + ], +}; + +export const LeftIcon: Story = { + ...RightIcon, + args: { + ...Base.args, + leftIcon: 'arrowleft', + }, +}; diff --git a/src/Link/Link.tsx b/src/Link/Link.tsx index a56bb4f8..abc47ac3 100644 --- a/src/Link/Link.tsx +++ b/src/Link/Link.tsx @@ -43,7 +43,7 @@ const Container = styled.a<{ }}; font-weight: ${(props) => fontWeight[props.weight]}; font-family: ${fontFamily.sans}; - gap: 0.75rem; + gap: 0.25em; transition: all 0.16s ease-in-out; text-decoration: none; From 5981c84995bbde57954c0b085d2b88b052cd65af Mon Sep 17 00:00:00 2001 From: winkerVSbecks Date: Wed, 27 Nov 2024 20:09:56 -0500 Subject: [PATCH 3/9] generate desktop and mobile menus from links record --- .../frontend-testing-guide-thumbnail.jpg} | Bin src/Header/Header.stories.tsx | 5 +- src/Header/Header.tsx | 37 +- src/Header/NavDesktop.tsx | 16 +- src/Header/NavDesktopContent.stories.tsx | 2 +- src/Header/NavMobile.tsx | 28 +- src/Header/context.tsx | 16 - src/Header/data.tsx | 327 ++++++++---------- src/Header/index.ts | 1 + src/Header/types.ts | 8 +- src/Link/Link.tsx | 1 + 11 files changed, 186 insertions(+), 255 deletions(-) rename public/{frontend-testing-guide.jpg => guides/frontend-testing-guide-thumbnail.jpg} (100%) diff --git a/public/frontend-testing-guide.jpg b/public/guides/frontend-testing-guide-thumbnail.jpg similarity index 100% rename from public/frontend-testing-guide.jpg rename to public/guides/frontend-testing-guide-thumbnail.jpg diff --git a/src/Header/Header.stories.tsx b/src/Header/Header.stories.tsx index 27dd612a..960b3ac0 100644 --- a/src/Header/Header.stories.tsx +++ b/src/Header/Header.stories.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { within, userEvent } from '@storybook/testing-library'; import { Header } from './Header'; import { Button } from '../Button'; -import { desktopData, mobileData } from './data'; +import { defaultLinks } from './data'; import { Link } from '../Link'; import { SubNav } from '../SubNav'; @@ -21,8 +21,7 @@ type Story = StoryObj; export const DesktopLight: Story = { args: { theme: 'light', - desktopData, - mobileData, + links: defaultLinks, desktopRight: ( <> diff --git a/src/Header/Header.tsx b/src/Header/Header.tsx index eea369eb..ca8f9dfc 100644 --- a/src/Header/Header.tsx +++ b/src/Header/Header.tsx @@ -68,67 +68,48 @@ const DesktopOnly = styled.div` } `; -export const Header: FC = ({ +export const Header = ({ theme = 'light', - logo, - logoHref, logoLinkWrapper, - desktopData, desktopRight, desktopActiveId, - mobileData, mobileBottom, mobileTop, fullWidth = false, -}) => { + links, +}: HeaderProps) => { + const HeaderContainer = fullWidth ? FullWidthContainer : Container; + return ( - - - ); -}; - -const HeaderWithProvider: FC<{ - fullWidth?: boolean; -}> = ({ fullWidth = false }) => { - const { theme, logoHref, logoLinkWrapper, desktopRight } = useHeaderContext(); - - const HeaderContainer = fullWidth ? FullWidthContainer : Container; - - return ( - <> - + {desktopRight} - + - + ); }; diff --git a/src/Header/NavDesktop.tsx b/src/Header/NavDesktop.tsx index bdfe76ca..6fe9dd9c 100644 --- a/src/Header/NavDesktop.tsx +++ b/src/Header/NavDesktop.tsx @@ -1,9 +1,9 @@ import styled from '@emotion/styled'; -import React, { FC } from 'react'; +import React, { FC, useMemo } from 'react'; import * as NavigationMenu from '@radix-ui/react-navigation-menu'; -import { useHeaderContext } from './context'; import { NavDesktopLink } from './NavDesktopLink'; import { NavDesktopTrigger } from './NavDesktopTrigger'; +import { HeaderLinks, createDesktopMenu } from './data'; const NavigationMenuRoot = styled(NavigationMenu.Root)` position: relative; @@ -25,14 +25,18 @@ const NavigationMenuItem = styled(NavigationMenu.Item)` position: relative; `; -export const NavDesktop: FC = (props) => { - const { desktopData } = useHeaderContext(); +interface NavDesktopProps { + links: HeaderLinks; +} + +export const NavDesktop = ({ links, ...props }: NavDesktopProps) => { + const desktopLinks = useMemo(() => createDesktopMenu(links), [links]); return ( - {desktopData && - desktopData.map((item) => ( + {desktopLinks && + desktopLinks.map((item) => ( {item.menu ? ( diff --git a/src/Header/NavDesktopContent.stories.tsx b/src/Header/NavDesktopContent.stories.tsx index d07b2af8..76409616 100644 --- a/src/Header/NavDesktopContent.stories.tsx +++ b/src/Header/NavDesktopContent.stories.tsx @@ -214,7 +214,7 @@ export const TwoColumnWithCard: Story = { title: 'Frontend testing guide', description: 'We researched dozens of teams to figure out which testing strategies actually work. ', - image: '/frontend-testing-guide.jpg', + image: '/guides/frontend-testing-guide-thumbnail.jpg', href: '#', }, ], diff --git a/src/Header/NavMobile.tsx b/src/Header/NavMobile.tsx index ffece40d..30d08692 100644 --- a/src/Header/NavMobile.tsx +++ b/src/Header/NavMobile.tsx @@ -1,5 +1,5 @@ import styled from '@emotion/styled'; -import React, { FC } from 'react'; +import React, { FC, useMemo } from 'react'; import { AnimatePresence, motion } from 'framer-motion'; import * as Popover from '@radix-ui/react-popover'; import { color, spacing } from '../_tokens'; @@ -8,6 +8,7 @@ import { minSm } from '../_helpers'; import { NavMobileTrigger } from './NavMobileTrigger'; import { NavMobileSection } from './NavMobileSection'; import { resetCSS } from '../_localHelpers/resetCSS'; +import { createMobileMenu, HeaderLinks } from './data'; const NavigationMenu = styled(motion.div)` ${resetCSS} @@ -43,14 +44,15 @@ const Bottom = styled.div` padding: ${spacing[3]} ${spacing[2]} ${spacing[3]} ${spacing[2]}; `; -export const NavMobile: FC = () => { - const { - mobileData, - mobileMenuOpen, - mobileTop, - mobileBottom, - setMobileMenuOpen, - } = useHeaderContext(); +interface NavMobileProps { + links: HeaderLinks; +} + +export const NavMobile = ({ links }: NavMobileProps) => { + const { mobileMenuOpen, mobileTop, mobileBottom, setMobileMenuOpen } = + useHeaderContext(); + + const mobileLinks = useMemo(() => createMobileMenu(links), [links]); return ( @@ -70,10 +72,10 @@ export const NavMobile: FC = () => { transition={{ ease: 'easeOut', duration: 0.14 }} > {mobileTop && {mobileTop}} - {mobileData && - mobileData.map((section, i) => { - const index = mobileData.indexOf(section); - const isLast = index === mobileData.length - 1; + {mobileLinks && + mobileLinks.map((section, i) => { + const index = mobileLinks.indexOf(section); + const isLast = index === mobileLinks.length - 1; return ( > = ({ children, theme, - logo, - logoHref, logoLinkWrapper, - desktopData, desktopRight, desktopActiveId, - mobileData, mobileTop, mobileBottom, }) => { @@ -69,13 +57,9 @@ export const HeaderProvider: FC> = ({ , href: '/features/figma-plugin', }, - madeForStorybook: { - title: 'Made for Storybook', - icon: 'contrast', - iconColor: 'cyan500', - href: '/solutions/storybook', - }, frontendTeams: { title: 'Frontend teams', icon: 'browser', @@ -125,12 +115,78 @@ const links: HeaderLinks = { iconColor: 'green500', href: '/security', }, + enterprise: { + title: 'Enterprise', + icon: 'admin', + iconColor: 'green500', + href: '/enterprise', + }, + netlify: { + title: 'Netlify', + customIcon: , + href: '/customers/netlify', + }, + monday: { + title: 'monday.com', + customIcon: , + href: '/customers/monday', + }, + collective: { + title: 'Collective.work', + customIcon: , + href: '/customers/collective', + }, + ezcater: { + title: 'ezCater', + customIcon: , + href: '/customers/ezcater', + }, + blog: { + title: 'Blog', + icon: 'starhollow', + iconColor: 'purple500', + href: '/blog', + }, + changelog: { + title: 'Changelog', + icon: 'book', + iconColor: 'green500', + href: '/blog/releases', + }, + frontendTestingGuide: { + title: 'Frontend testing guide', + href: '/frontend-testing-guide', + }, + docs: { + title: 'Docs', + icon: 'browser', + iconColor: 'orange500', + href: '/docs', + }, + pricing: { + title: 'Pricing', + href: '/pricing', + icon: 'starhollow', + iconColor: 'yellow500', + }, + sales: { + title: 'Contact sales', + icon: 'email', + iconColor: 'blue500', + href: '/sales', + }, }; -export const desktopData: HeaderProps['desktopData'] = [ +type HeaderLinkKeys = keyof typeof defaultLinks; + +export type HeaderLinks = Record; + +export const createDesktopMenu = ( + links: HeaderLinks = defaultLinks +): HeaderDesktopItem[] => [ { - id: 'features', - name: 'Features', + id: 'platform', + name: 'Platform', leftPosition: -220, menu: [ { @@ -140,12 +196,12 @@ export const desktopData: HeaderProps['desktopData'] = [ title: 'Test', }, { - ...links.UITest, + ...links.uiTest, type: 'link', description: 'Test how UIs look & function', }, { - ...links.VisualTest, + ...links.visualTest, type: 'link', description: 'Pinpoint bugs down to the browser, viewport, and pixel', @@ -171,12 +227,12 @@ export const desktopData: HeaderProps['desktopData'] = [ title: 'Review', }, { - ...links.UIReview, + ...links.uiReview, type: 'link', description: 'Speed up team sign-off and manage change requests', }, { - ...links.Publish, + ...links.publish, type: 'link', description: 'Index & version components to reuse existing work', }, @@ -202,12 +258,14 @@ export const desktopData: HeaderProps['desktopData'] = [ { ...links.playwright, type: 'link', - description: 'Test every page in your Playwright E2E suite', + description: + 'Visual tests for every page in your Playwright E2E suite', }, { ...links.cypress, type: 'link', - description: 'Test every page in your Cypress E2E suite', + description: + 'Visual tests for every page in your Cypress E2E suite', }, ], backgroundColor: 'white', @@ -215,14 +273,9 @@ export const desktopData: HeaderProps['desktopData'] = [ ], }, { - id: 'pricing', - name: 'Pricing', - href: '/pricing', - }, - { - id: 'customers', - name: 'Customers', - leftPosition: -420, + id: 'solutions', + name: 'Solutions', + leftPosition: -120, menu: [ { content: [ @@ -230,11 +283,6 @@ export const desktopData: HeaderProps['desktopData'] = [ type: 'separator', title: 'Use cases', }, - { - ...links.madeForStorybook, - type: 'link', - description: 'Ship UI components with less manual work', - }, { ...links.frontendTeams, type: 'link', @@ -250,6 +298,12 @@ export const desktopData: HeaderProps['desktopData'] = [ type: 'link', description: 'Increase margins by speeding up client sign-off', }, + { + ...links.enterprise, + type: 'link', + title: 'Enterprise', + description: 'Scale frontend development & testing', + }, ], }, { @@ -259,211 +313,116 @@ export const desktopData: HeaderProps['desktopData'] = [ title: 'Customer Stories', }, { + ...links.netlify, type: 'link', - title: 'Netlify', description: 'How Netlify rebranded in six weeks without bugs', - customIcon: , - href: '/customers/netlify', }, { + ...links.monday, type: 'link', - title: 'monday.com', description: 'How 200 developers speed up their frontend velocity', - customIcon: , - href: '/customers/monday', }, { + ...links.collective, type: 'link', - title: 'Collective.work', description: 'How to deliver personalized UX across borders & devices', - customIcon: , - href: '/customers/collective', }, { + ...links.ezcater, type: 'link', - title: 'ezCater', description: - 'How to test UI appearance & functionality simultaneously', - customIcon: , - href: '/customers/ezcater', + 'How to simultaneously test UI appearance & functionality', }, ], backgroundColor: 'white', }, - { - content: [ - { - type: 'card', - title: 'Frontend testing guide', - description: - 'We researched dozens of teams to figure out which testing strategies actually work. ', - image: '/frontend-testing-guide.jpg', - href: '#', - }, - ], - backgroundColor: 'blue50', - }, ], }, { id: 'docs', name: 'Docs', - href: '/docs', + ...links.docs, }, { - id: 'blog', - name: 'Blog', - href: '/blog', - }, - { - id: 'company', - name: 'Company', - leftPosition: -20, + id: 'resources', + name: 'Resources', + leftPosition: -220, menu: [ { content: [ { - ...links.aboutChromatic, + ...links.blog, type: 'link', - description: 'Our mission is to improve the UX of the internet', - }, - { - ...links.careers, - type: 'link', - title: 'Careers', - description: 'Opportunities and culture. Join our team.', - icon: 'user', - iconColor: 'purple500', - href: '/company/careers', + description: 'News and feature updates from our team.', }, + ], + backgroundColor: 'white', + }, + { + content: [ { - ...links.security, - type: 'link', - title: 'Security', - description: 'Security report and overview of compliance', + ...links.frontendTestingGuide, + type: 'card', + title: 'Frontend testing guide', + description: + 'We researched dozens of teams to figure out which testing strategies actually work.', + image: '/guides/frontend-testing-guide-thumbnail.jpg', }, ], - backgroundColor: 'white', + backgroundColor: 'blue50', }, ], }, + { + id: 'pricing', + name: 'Pricing', + ...links.pricing, + }, ]; -export const mobileData: HeaderProps['mobileData'] = [ +export const createMobileMenu = ( + links: HeaderLinks = defaultLinks +): HeaderMobileSection[] => [ { name: 'Features', maxItems: 3, content: [ - links.UITest, - links.UIReview, - links.Publish, - links.VisualTest, + links.uiTest, + links.uiReview, + links.publish, + links.visualTest, links.interactionTest, links.turboSnap, links.figmaPlugin, ], }, { - content: [ - { - title: 'Pricing', - icon: 'starhollow', - iconColor: 'yellow500', - href: '/pricing', - }, - { - title: 'Docs', - icon: 'browser', - iconColor: 'orange500', - href: '/docs', - }, - { - title: 'Blog', - icon: 'grow', - iconColor: 'purple500', - href: '/blog', - }, - { - title: 'Contact sales', - icon: 'email', - iconColor: 'blue500', - href: '/sales', - }, - ], + content: [links.pricing, links.docs, links.blog, links.sales], }, { name: 'Integrations', collapsible: true, - content: [ - { - ...links.storybook, - }, - { - ...links.playwright, - }, - { - ...links.cypress, - }, - ], + content: [links.storybook, links.playwright, links.cypress], }, { name: 'Use cases', collapsible: true, content: [ - { - ...links.madeForStorybook, - }, - { - ...links.frontendTeams, - }, - { - ...links.designSystems, - }, - { - ...links.digitalAgencies, - }, + links.frontendTeams, + links.designSystems, + links.digitalAgencies, + links.enterprise, ], }, { name: 'Customer Stories', collapsible: true, - content: [ - { - title: 'Netlify', - customIcon: , - href: '/customers/netlify', - }, - { - title: 'monday.com', - customIcon: , - href: '/customers/monday', - }, - { - title: 'Collective.work', - customIcon: , - href: '/customers/collective', - }, - { - title: 'ezCater', - customIcon: , - href: '/customers/ezcater', - }, - ], + content: [links.netlify, links.monday, links.collective, links.ezcater], }, { name: 'Company', collapsible: true, - content: [ - { - ...links.aboutChromatic, - }, - { - ...links.careers, - }, - { - ...links.security, - }, - ], + content: [links.aboutChromatic, links.careers, links.security], }, ]; diff --git a/src/Header/index.ts b/src/Header/index.ts index 1906e6f4..d9deb494 100644 --- a/src/Header/index.ts +++ b/src/Header/index.ts @@ -8,3 +8,4 @@ export { PlaywrightIcon } from './icons/playwright'; export { CypressIcon } from './icons/cypress'; export { BBCIcon } from './icons/bbc'; export { EzCaterIcon } from './icons/ezcater'; +export type { HeaderLinks } from './data'; diff --git a/src/Header/types.ts b/src/Header/types.ts index 8116a2a5..9c503f98 100644 --- a/src/Header/types.ts +++ b/src/Header/types.ts @@ -1,6 +1,7 @@ import { ReactNode } from 'react'; import type { Icons } from '../Icon/Icon'; import { color } from '../_tokens'; +import { HeaderLinks } from './data'; export interface HeaderMobileSection { name?: string; @@ -42,14 +43,13 @@ export interface HeaderDesktopItem { export interface HeaderProps { theme?: 'light' | 'dark'; - logo?: 'chromatic' | 'storybook'; - logoHref?: string; logoLinkWrapper?: any; - desktopData: HeaderDesktopItem[]; desktopRight?: ReactNode; desktopActiveId?: string; - mobileData: HeaderMobileSection[]; mobileTop?: ReactNode; mobileBottom?: ReactNode; fullWidth?: boolean; + loggedIn?: boolean; + maintenanceMode?: boolean; + links: HeaderLinks; } diff --git a/src/Link/Link.tsx b/src/Link/Link.tsx index abc47ac3..e1b965c7 100644 --- a/src/Link/Link.tsx +++ b/src/Link/Link.tsx @@ -80,6 +80,7 @@ export const Link = forwardRef< ) => { let iconSize: 12 | 14 | 16 = 14; if (size === 'sm') iconSize = 12; + if (size === 'md') iconSize = 14; if (size === 'lg') iconSize = 16; let asContainer: LinkProps['as'] = 'button'; From 0f50c5eae5e079a2bcd4936d16ecd477e86fea53 Mon Sep 17 00:00:00 2001 From: winkerVSbecks Date: Thu, 28 Nov 2024 16:45:35 -0500 Subject: [PATCH 4/9] refactor header to hardcode all CTAs --- src/Button/Button.tsx | 2 +- src/Header/Header.tsx | 110 ++++++++++++++++++++---- src/Header/NavMobile.tsx | 75 ++++++++++++++-- src/Header/context.tsx | 21 ----- src/Header/data.tsx | 10 ++- src/Header/types.ts | 6 +- src/LinkWithWrapper/LinkWithWrapper.tsx | 7 +- 7 files changed, 180 insertions(+), 51 deletions(-) diff --git a/src/Button/Button.tsx b/src/Button/Button.tsx index 7c8cdb0f..c79ecb1b 100644 --- a/src/Button/Button.tsx +++ b/src/Button/Button.tsx @@ -14,7 +14,7 @@ export interface ButtonProps { href?: string; target?: '_blank' | '_self' | '_parent' | '_top'; onClick?: () => void; - as?: 'button' | 'a'; + as?: 'button' | 'a' | 'span'; } const Container = styled.a<{ diff --git a/src/Header/Header.tsx b/src/Header/Header.tsx index ca8f9dfc..2fdde542 100644 --- a/src/Header/Header.tsx +++ b/src/Header/Header.tsx @@ -1,17 +1,19 @@ import React, { FC } from 'react'; import styled from '@emotion/styled'; -import { HeaderProvider, useHeaderContext } from './context'; +import { HeaderProvider } from './context'; import { HeaderLogo } from './HeaderLogo'; -import { spacing } from '../_tokens'; +import { fontWeight, spacing } from '../_tokens'; import { Container, FullWidthContainer } from '../Container'; import { NavDesktop } from './NavDesktop'; import { NavMobile } from './NavMobile'; import { HeaderProps } from './types'; -import { minSm } from '../_helpers'; +import { minSm, typography } from '../_helpers'; import { LinkWithWrapper } from '../LinkWithWrapper'; import { resetCSS } from '../_localHelpers/resetCSS'; import { Divider } from '../Divider'; import { desktopBreakpoint } from './styles'; +import { Link } from '../Link'; +import { Button } from '../Button'; const Wrapper = styled.div` ${resetCSS} @@ -68,27 +70,30 @@ const DesktopOnly = styled.div` } `; +const HeaderCTAButton = styled(Button)` + height: ${spacing[8]}; + ${typography.body14}; + font-weight: ${fontWeight.bold}; +`; + +const DefaultTrackSignUp: FC<{ children: React.ReactNode }> = ({ + children, +}) => <>{children}; + export const Header = ({ theme = 'light', + links, logoLinkWrapper, - desktopRight, desktopActiveId, - mobileBottom, - mobileTop, fullWidth = false, - links, + loggedIn, + maintenanceMode, + TrackSignUp = DefaultTrackSignUp, }: HeaderProps) => { const HeaderContainer = fullWidth ? FullWidthContainer : Container; return ( - + @@ -103,9 +108,80 @@ export const Header = ({ - {desktopRight} + + <> + + + Contact + + + {!loggedIn && ( + <> + {!maintenanceMode && ( + + + {links.signin.title} + + + )} + + + + {links.signup.title} + + + + + )} + {loggedIn && !maintenanceMode && ( + + + Go to app + + + )} + + - + diff --git a/src/Header/NavMobile.tsx b/src/Header/NavMobile.tsx index 30d08692..d9e518f8 100644 --- a/src/Header/NavMobile.tsx +++ b/src/Header/NavMobile.tsx @@ -9,6 +9,9 @@ import { NavMobileTrigger } from './NavMobileTrigger'; import { NavMobileSection } from './NavMobileSection'; import { resetCSS } from '../_localHelpers/resetCSS'; import { createMobileMenu, HeaderLinks } from './data'; +import { HeaderProps } from './types'; +import { Button } from '../Button'; +import { LinkWithWrapper } from '../LinkWithWrapper'; const NavigationMenu = styled(motion.div)` ${resetCSS} @@ -44,13 +47,26 @@ const Bottom = styled.div` padding: ${spacing[3]} ${spacing[2]} ${spacing[3]} ${spacing[2]}; `; +const MobileButtons = styled.div` + display: flex; + flex-direction: column; + gap: ${spacing[3]}; +`; + interface NavMobileProps { links: HeaderLinks; + loggedIn?: boolean; + maintenanceMode?: boolean; + TrackSignUp: HeaderProps['TrackSignUp']; } -export const NavMobile = ({ links }: NavMobileProps) => { - const { mobileMenuOpen, mobileTop, mobileBottom, setMobileMenuOpen } = - useHeaderContext(); +export const NavMobile = ({ + links, + loggedIn, + maintenanceMode, + TrackSignUp, +}: NavMobileProps) => { + const { mobileMenuOpen, setMobileMenuOpen } = useHeaderContext(); const mobileLinks = useMemo(() => createMobileMenu(links), [links]); @@ -71,7 +87,6 @@ export const NavMobile = ({ links }: NavMobileProps) => { exit={{ opacity: 0, y: -8 }} transition={{ ease: 'easeOut', duration: 0.14 }} > - {mobileTop && {mobileTop}} {mobileLinks && mobileLinks.map((section, i) => { const index = mobileLinks.indexOf(section); @@ -85,7 +100,57 @@ export const NavMobile = ({ links }: NavMobileProps) => { /> ); })} - {mobileBottom && {mobileBottom}} + + + {!loggedIn && ( + <> + {!maintenanceMode && ( + + + + )} + + + + + + + )} + {loggedIn && !maintenanceMode && ( + + + + )} + + diff --git a/src/Header/context.tsx b/src/Header/context.tsx index d8d56d35..c06170bb 100644 --- a/src/Header/context.tsx +++ b/src/Header/context.tsx @@ -8,18 +8,9 @@ import React, { import { HeaderProps } from './types'; interface HeaderContextType { - // Both Desktop and Mobile theme?: HeaderProps['theme']; // To switch between light and dark theme - logoLinkWrapper?: HeaderProps['logoLinkWrapper']; // The wrapper to use for the logo link - - // Desktop - desktopRight?: HeaderProps['desktopRight']; // The content to display on the right desktopActiveId?: HeaderProps['desktopActiveId']; // The content to display when the menu is open - - // Mobile mobileMenuOpen: boolean; // Is the menu on mobile open or not - mobileTop?: HeaderProps['mobileTop']; // The content to display at the top of the mobile menu - mobileBottom?: HeaderProps['mobileBottom']; // The content to display at the bottom of the mobile menu setMobileMenuOpen: (value: boolean) => void; // To open or close the mobile menu } @@ -35,21 +26,13 @@ export function useHeaderContext() { interface HeaderProviderProps { theme: HeaderProps['theme']; - logoLinkWrapper?: HeaderProps['logoLinkWrapper']; - desktopRight?: HeaderProps['desktopRight']; desktopActiveId?: HeaderProps['desktopActiveId']; - mobileTop?: HeaderProps['mobileTop']; - mobileBottom?: HeaderProps['mobileBottom']; } export const HeaderProvider: FC> = ({ children, theme, - logoLinkWrapper, - desktopRight, desktopActiveId, - mobileTop, - mobileBottom, }) => { const [mobileMenuOpen, setMobileMenuOpen] = useState(false); @@ -57,12 +40,8 @@ export const HeaderProvider: FC> = ({ diff --git a/src/Header/data.tsx b/src/Header/data.tsx index 49aa5232..fde383ab 100644 --- a/src/Header/data.tsx +++ b/src/Header/data.tsx @@ -3,7 +3,7 @@ import { CollectiveIcon } from './icons/collective'; import { FigmaIcon } from './icons/figma'; import { NetlifyIcon } from './icons/netlify'; import { MondayIcon } from './icons/monday'; -import { HeaderDesktopItem, HeaderMobileSection, HeaderProps } from './types'; +import { HeaderDesktopItem, HeaderMobileSection } from './types'; import { color } from '../_tokens'; import { Icons } from '../Icon/Icon'; import { PlaywrightIcon } from './icons/playwright'; @@ -20,6 +20,14 @@ interface HeaderLink { } export const defaultLinks: { [key: string]: HeaderLink } = { + signin: { + title: 'Sign in', + href: '/start', + }, + signup: { + title: 'Sign up', + href: '/start?startWithSignup=true', + }, uiTest: { title: 'UI Tests', icon: 'contrast', diff --git a/src/Header/types.ts b/src/Header/types.ts index 9c503f98..77053996 100644 --- a/src/Header/types.ts +++ b/src/Header/types.ts @@ -1,4 +1,4 @@ -import { ReactNode } from 'react'; +import { ComponentType, ReactNode } from 'react'; import type { Icons } from '../Icon/Icon'; import { color } from '../_tokens'; import { HeaderLinks } from './data'; @@ -44,12 +44,10 @@ export interface HeaderDesktopItem { export interface HeaderProps { theme?: 'light' | 'dark'; logoLinkWrapper?: any; - desktopRight?: ReactNode; desktopActiveId?: string; - mobileTop?: ReactNode; - mobileBottom?: ReactNode; fullWidth?: boolean; loggedIn?: boolean; maintenanceMode?: boolean; links: HeaderLinks; + TrackSignUp: ComponentType<{ children: ReactNode }>; } diff --git a/src/LinkWithWrapper/LinkWithWrapper.tsx b/src/LinkWithWrapper/LinkWithWrapper.tsx index 92e08b4c..cf563d46 100644 --- a/src/LinkWithWrapper/LinkWithWrapper.tsx +++ b/src/LinkWithWrapper/LinkWithWrapper.tsx @@ -5,6 +5,7 @@ export interface LinkWithWrapperProps LinkWrapper?: ElementType; children: ReactNode; href: string; + noAnchor?: boolean; } /** @@ -14,7 +15,7 @@ export interface LinkWithWrapperProps export const LinkWithWrapper = forwardRef< HTMLAnchorElement, LinkWithWrapperProps ->(({ children, href, LinkWrapper, ...props }, ref) => { +>(({ children, href, LinkWrapper, noAnchor, ...props }, ref) => { if (LinkWrapper) { return ( @@ -23,7 +24,9 @@ export const LinkWithWrapper = forwardRef< ); } - return ( + return noAnchor ? ( + <>{children} + ) : ( {children} From a91910299a055e4fc29cd0a98c11e471105bb08e Mon Sep 17 00:00:00 2001 From: winkerVSbecks Date: Thu, 28 Nov 2024 20:53:06 -0500 Subject: [PATCH 5/9] Add login and maintenanceMode stories for header --- src/Header/Header.stories.tsx | 51 ++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/Header/Header.stories.tsx b/src/Header/Header.stories.tsx index 960b3ac0..a239cf22 100644 --- a/src/Header/Header.stories.tsx +++ b/src/Header/Header.stories.tsx @@ -2,9 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import React from 'react'; import { within, userEvent } from '@storybook/testing-library'; import { Header } from './Header'; -import { Button } from '../Button'; import { defaultLinks } from './data'; -import { Link } from '../Link'; import { SubNav } from '../SubNav'; const meta: Meta = { @@ -22,26 +20,6 @@ export const DesktopLight: Story = { args: { theme: 'light', links: defaultLinks, - desktopRight: ( - <> - - Sign in - - - - ), - mobileBottom: ( -
- - -
- ), }, parameters: { layout: 'fullscreen', @@ -63,6 +41,35 @@ export const DesktopDark: Story = { }, }; +export const DesktopLoggedOut: Story = { + args: { + ...DesktopLight.args, + loggedIn: false, + }, +}; + +export const DesktopLoggedIn: Story = { + args: { + ...DesktopLight.args, + loggedIn: true, + }, +}; + +export const DesktopLoggedOutMaintenance: Story = { + args: { + ...DesktopLight.args, + maintenanceMode: true, + }, +}; + +export const DesktopLoggedInMaintenance: Story = { + args: { + ...DesktopLight.args, + loggedIn: true, + maintenanceMode: true, + }, +}; + export const WithSubNav: Story = { render: (args) => ( <> From 86ab9cf92de0e05ede1be4dede1c2a509f3934bc Mon Sep 17 00:00:00 2001 From: winkerVSbecks Date: Thu, 28 Nov 2024 21:04:28 -0500 Subject: [PATCH 6/9] display contact and signin for mobile header --- src/Header/NavMobile.tsx | 48 +++++++++++++++++++++++++++++++-- src/Header/NavMobileTrigger.tsx | 1 + 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/Header/NavMobile.tsx b/src/Header/NavMobile.tsx index d9e518f8..f93f4b96 100644 --- a/src/Header/NavMobile.tsx +++ b/src/Header/NavMobile.tsx @@ -12,6 +12,8 @@ import { createMobileMenu, HeaderLinks } from './data'; import { HeaderProps } from './types'; import { Button } from '../Button'; import { LinkWithWrapper } from '../LinkWithWrapper'; +import { Link } from '../Link'; +import { HStack } from '../Stack'; const NavigationMenu = styled(motion.div)` ${resetCSS} @@ -53,6 +55,14 @@ const MobileButtons = styled.div` gap: ${spacing[3]}; `; +const SignInWrapper = styled.div` + display: none; + + @media (min-width: 400px) { + display: contents; + } +`; + interface NavMobileProps { links: HeaderLinks; loggedIn?: boolean; @@ -66,13 +76,47 @@ export const NavMobile = ({ maintenanceMode, TrackSignUp, }: NavMobileProps) => { - const { mobileMenuOpen, setMobileMenuOpen } = useHeaderContext(); + const { theme, mobileMenuOpen, setMobileMenuOpen } = useHeaderContext(); const mobileLinks = useMemo(() => createMobileMenu(links), [links]); return ( - + + + + Contact + + + + {!maintenanceMode && ( + + + {links.signin.title} + + + )} + + + {mobileMenuOpen && ( diff --git a/src/Header/NavMobileTrigger.tsx b/src/Header/NavMobileTrigger.tsx index c708f2f6..fa0f52a4 100644 --- a/src/Header/NavMobileTrigger.tsx +++ b/src/Header/NavMobileTrigger.tsx @@ -14,6 +14,7 @@ const MobileTrigger = styled(Popover.Trigger)` width: 40px; height: 40px; border-radius: 6px; + margin-left: -10px; &:focus { box-shadow: 0 0 0 2px rgba(30, 167, 253, 0.3); From f26f05beff2a8d776beddde1d5d48092de1147bf Mon Sep 17 00:00:00 2001 From: winkerVSbecks Date: Thu, 28 Nov 2024 21:10:27 -0500 Subject: [PATCH 7/9] fix tests --- src/Header/Header.stories.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Header/Header.stories.tsx b/src/Header/Header.stories.tsx index a239cf22..ad0d517b 100644 --- a/src/Header/Header.stories.tsx +++ b/src/Header/Header.stories.tsx @@ -138,7 +138,7 @@ export const DesktopLightOpen: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); const MenuButton = await canvas.findByRole('button', { - name: 'Features', + name: 'Platform', }); MenuButton.focus(); await userEvent.keyboard('{enter}'); @@ -162,7 +162,7 @@ export const DesktopDarkOpen: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); const MenuButton = await canvas.findByRole('button', { - name: 'Features', + name: 'Platform', }); MenuButton.focus(); await userEvent.keyboard('{enter}'); From fe3505285e022ccdc8b854eb303e871a1b64b8db Mon Sep 17 00:00:00 2001 From: winkerVSbecks Date: Fri, 29 Nov 2024 12:43:57 -0500 Subject: [PATCH 8/9] refactor footer to hardcode columns --- src/Footer/Footer.stories.tsx | 10 +--- src/Footer/Footer.tsx | 26 ++++------ src/Footer/data.tsx | 96 +++++++++++++++++++++-------------- src/Header/data.tsx | 9 ++-- src/Icon/iconPaths.tsx | 5 ++ src/shared-types.ts | 30 +++++++++++ 6 files changed, 109 insertions(+), 67 deletions(-) create mode 100644 src/shared-types.ts diff --git a/src/Footer/Footer.stories.tsx b/src/Footer/Footer.stories.tsx index 16d288e3..87411db7 100644 --- a/src/Footer/Footer.stories.tsx +++ b/src/Footer/Footer.stories.tsx @@ -2,7 +2,6 @@ import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { Footer } from './Footer'; -import { footerColumns, footerSocialLinks, homeLink } from './data'; const meta: Meta = { title: 'Components/Footer', @@ -18,17 +17,10 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Base: Story = { - args: { - columns: footerColumns, - socialLinks: footerSocialLinks, - homeLink, - }, -}; +export const Base: Story = {}; export const Inverse: Story = { args: { - ...Base.args, theme: 'dark', }, }; diff --git a/src/Footer/Footer.tsx b/src/Footer/Footer.tsx index dbe8dcf5..5ebf9856 100644 --- a/src/Footer/Footer.tsx +++ b/src/Footer/Footer.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { ElementType, useMemo } from 'react'; import styled from '@emotion/styled'; import { minSm, typography } from '../_helpers'; import { color, spacing } from '../_tokens'; @@ -7,7 +7,7 @@ import { Container } from '../Container'; import { Logo } from '../Logo'; import { Icon } from '../Icon'; import { HStack } from '../Stack'; -import { FooterColumn, FooterSocialItem, HomeItem } from './types'; +import { createFooterColumns, footerSocialLinks } from './data'; const Columns = styled.div` display: grid; @@ -67,7 +67,7 @@ const SocialLink = styled(LinkWithWrapper, { border-color: ${({ inverse }) => inverse ? color.whiteTr10 : color.blackTr10}; - transition: border-color: 150ms ease-out; + transition: border-color 150ms ease-out; svg { display: block; @@ -142,19 +142,15 @@ const HomeLink = styled(LinkWithWrapper)` export interface FooterProps { theme: 'light' | 'dark'; - columns: FooterColumn[]; - socialLinks: FooterSocialItem[]; - homeLink: HomeItem; + LinkWrapper: ElementType; } -export const Footer = ({ - theme, - columns, - socialLinks, - homeLink, - ...props -}: FooterProps) => { +export const Footer = ({ theme, LinkWrapper, ...props }: FooterProps) => { const inverse = theme === 'dark'; + const columns = useMemo( + () => createFooterColumns(LinkWrapper), + [LinkWrapper] + ); return ( @@ -173,7 +169,7 @@ export const Footer = ({ - + - {socialLinks.map(({ title, icon, ...linkProps }) => ( + {footerSocialLinks.map(({ title, icon, ...linkProps }) => ( [ { - title: 'Product', + title: 'Company', links: [ - { title: 'Pricing', href: '/pricing' }, - { title: 'About', href: '/company/about' }, - { title: 'Jobs', href: '/company/careers' }, + { title: 'About', href: '/company/about', LinkWrapper }, + { title: 'Careers', href: '/company/careers', LinkWrapper }, { title: 'Terms of Service', href: '/docs/terms-of-service' }, { title: 'Privacy', href: '/docs/privacy-policy' }, - { title: 'Status', href: 'https://status.chromatic.com/' }, { title: 'Security • SOC 2', href: '/security' }, - { title: 'Contact Sales', href: '/sales' }, + { title: 'Status', href: 'https://status.chromatic.com/' }, + { title: 'Contact Sales', href: '/sales', LinkWrapper }, ], }, { - title: 'Features', + title: 'Platform', links: [ - { title: 'UI Tests', href: '/features/test' }, + { title: 'UI Tests', href: '/features/test', LinkWrapper }, { title: 'Visual test', href: '/features/visual-test', + LinkWrapper, }, { title: 'Interaction test', href: '/features/interaction-test', - }, - { title: 'TurboSnap', href: '/features/turbosnap' }, - { title: 'UI Review', href: '/features/review' }, - { title: 'Publish', href: '/features/publish' }, + LinkWrapper, + }, + { title: 'TurboSnap', href: '/features/turbosnap', LinkWrapper }, + { title: 'UI Review', href: '/features/review', LinkWrapper }, + { title: 'Publish', href: '/features/publish', LinkWrapper }, + { title: 'Storybook', href: '/storybook', LinkWrapper }, + { title: 'Playwright', href: '/playwright', LinkWrapper }, + { title: 'Cypress', href: '/cypress', LinkWrapper }, { title: 'Figma plugin', href: '/features/figma-plugin' }, - { - title: 'Storybook', - href: '/storybook', - }, - { - title: 'Playwright', - href: '/playwright', - }, - { - title: 'Cypress', - href: '/cypress', - }, + { title: 'Pricing', href: '/pricing', LinkWrapper }, ], }, { title: 'Customers', links: [ - { title: 'Made for Storybook', href: '/solutions/storybook' }, + { title: 'Enterprise', href: '/enterprise', LinkWrapper }, { title: 'Frontend teams', href: '/solutions/frontend', + LinkWrapper, }, { title: 'Design systems', href: '/solutions/design-systems', + LinkWrapper, }, { title: 'Digital agencies', href: '/solutions/agencies', + LinkWrapper, }, { title: 'Netlify', href: '/customers/netlify', + LinkWrapper, }, { title: 'Monday.com', href: '/customers/monday', + LinkWrapper, }, { title: 'Collective.work', href: '/customers/collective', + LinkWrapper, }, + { title: 'ezCater', href: '/customers/ezcater', LinkWrapper }, ], }, { @@ -91,42 +94,59 @@ export const footerColumns: FooterProps['columns'] = [ title: 'Component Driven UIs', href: 'https://www.componentdriven.org/', }, + { + title: 'Frontend testing guide', + href: '/frontend-testing-guide', + LinkWrapper, + }, ], }, { title: 'Compare', links: [ + { + title: 'Overview of tools', + href: '/choose/visual-testing', + LinkWrapper, + }, { title: 'Applitools', href: '/compare/applitools', - }, - { title: 'Percy', href: '/compare/percy' }, + LinkWrapper, + }, + { title: 'Percy', href: '/compare/percy', LinkWrapper }, + { title: 'Sauce Labs', href: '/compare/sauce-labs', LinkWrapper }, + { title: 'Katalon', href: '/compare/katalon', LinkWrapper }, + { title: 'LambdaTest', href: '/compare/lambdatest', LinkWrapper }, + { title: 'SmartBear', href: '/compare/smartbear', LinkWrapper }, + { title: 'TestingBot', href: '/compare/testingbot', LinkWrapper }, + { title: 'Lost Pixel', href: '/compare/lost-pixel', LinkWrapper }, + { title: 'Backstop', href: '/compare/backstop', LinkWrapper }, + { title: 'Playwright', href: '/compare/playwright', LinkWrapper }, { title: 'Deploy Storybook', href: '/choose/storybook-deploy', - }, - { - title: 'Visual testing services', - href: '/choose/visual-testing', + LinkWrapper, }, ], }, ]; -export const footerSocialLinks: FooterProps['socialLinks'] = [ +export const footerSocialLinks: FooterSocialItem[] = [ { title: 'github', icon: 'github', href: 'https://github.com/chromaui/' }, { title: 'twitter', icon: 'twitter', href: 'https://twitter.com/chromaticcom', }, + { + title: 'BlueSky', + icon: 'bluesky', + href: 'https://bsky.app/profile/chromaticui.bsky.social', + }, { title: 'youtube', icon: 'youtube', href: 'https://youtube.com/@chromaticui', }, ]; - -export const homeLink: FooterProps['homeLink'] = { - href: '/', -}; diff --git a/src/Header/data.tsx b/src/Header/data.tsx index fde383ab..b6b7843e 100644 --- a/src/Header/data.tsx +++ b/src/Header/data.tsx @@ -9,6 +9,7 @@ import { Icons } from '../Icon/Icon'; import { PlaywrightIcon } from './icons/playwright'; import { CypressIcon } from './icons/cypress'; import { EzCaterIcon } from './icons/ezcater'; +import { LinkKeys } from '../shared-types'; interface HeaderLink { title: string; @@ -19,7 +20,9 @@ interface HeaderLink { linkWrapper?: any; } -export const defaultLinks: { [key: string]: HeaderLink } = { +export type HeaderLinks = Record; + +export const defaultLinks: HeaderLinks = { signin: { title: 'Sign in', href: '/start', @@ -185,10 +188,6 @@ export const defaultLinks: { [key: string]: HeaderLink } = { }, }; -type HeaderLinkKeys = keyof typeof defaultLinks; - -export type HeaderLinks = Record; - export const createDesktopMenu = ( links: HeaderLinks = defaultLinks ): HeaderDesktopItem[] => [ diff --git a/src/Icon/iconPaths.tsx b/src/Icon/iconPaths.tsx index c2d03939..e86bdd79 100644 --- a/src/Icon/iconPaths.tsx +++ b/src/Icon/iconPaths.tsx @@ -1466,4 +1466,9 @@ export const icons = { ), + bluesky: ( + <> + + + ), } as const; diff --git a/src/shared-types.ts b/src/shared-types.ts new file mode 100644 index 00000000..18a6e724 --- /dev/null +++ b/src/shared-types.ts @@ -0,0 +1,30 @@ +export type LinkKeys = + | 'signin' + | 'signup' + | 'uiTest' + | 'visualTest' + | 'interactionTest' + | 'storybook' + | 'playwright' + | 'cypress' + | 'turboSnap' + | 'uiReview' + | 'publish' + | 'figmaPlugin' + | 'frontendTeams' + | 'designSystems' + | 'digitalAgencies' + | 'aboutChromatic' + | 'careers' + | 'security' + | 'enterprise' + | 'netlify' + | 'monday' + | 'collective' + | 'ezcater' + | 'blog' + | 'changelog' + | 'frontendTestingGuide' + | 'docs' + | 'pricing' + | 'sales'; From 4e7efd38f9d19af70e0d6c618376391f61bc2446 Mon Sep 17 00:00:00 2001 From: winkerVSbecks Date: Fri, 29 Nov 2024 14:19:01 -0500 Subject: [PATCH 9/9] clean up --- src/Header/data.tsx | 3 +-- src/Header/types.ts | 31 +++++++++++++++++++++++++++++++ src/shared-types.ts | 30 ------------------------------ 3 files changed, 32 insertions(+), 32 deletions(-) delete mode 100644 src/shared-types.ts diff --git a/src/Header/data.tsx b/src/Header/data.tsx index b6b7843e..b39b6d09 100644 --- a/src/Header/data.tsx +++ b/src/Header/data.tsx @@ -3,13 +3,12 @@ import { CollectiveIcon } from './icons/collective'; import { FigmaIcon } from './icons/figma'; import { NetlifyIcon } from './icons/netlify'; import { MondayIcon } from './icons/monday'; -import { HeaderDesktopItem, HeaderMobileSection } from './types'; +import { HeaderDesktopItem, HeaderMobileSection, LinkKeys } from './types'; import { color } from '../_tokens'; import { Icons } from '../Icon/Icon'; import { PlaywrightIcon } from './icons/playwright'; import { CypressIcon } from './icons/cypress'; import { EzCaterIcon } from './icons/ezcater'; -import { LinkKeys } from '../shared-types'; interface HeaderLink { title: string; diff --git a/src/Header/types.ts b/src/Header/types.ts index 77053996..e53081b2 100644 --- a/src/Header/types.ts +++ b/src/Header/types.ts @@ -51,3 +51,34 @@ export interface HeaderProps { links: HeaderLinks; TrackSignUp: ComponentType<{ children: ReactNode }>; } + +export type LinkKeys = + | 'signin' + | 'signup' + | 'uiTest' + | 'visualTest' + | 'interactionTest' + | 'storybook' + | 'playwright' + | 'cypress' + | 'turboSnap' + | 'uiReview' + | 'publish' + | 'figmaPlugin' + | 'frontendTeams' + | 'designSystems' + | 'digitalAgencies' + | 'aboutChromatic' + | 'careers' + | 'security' + | 'enterprise' + | 'netlify' + | 'monday' + | 'collective' + | 'ezcater' + | 'blog' + | 'changelog' + | 'frontendTestingGuide' + | 'docs' + | 'pricing' + | 'sales'; diff --git a/src/shared-types.ts b/src/shared-types.ts deleted file mode 100644 index 18a6e724..00000000 --- a/src/shared-types.ts +++ /dev/null @@ -1,30 +0,0 @@ -export type LinkKeys = - | 'signin' - | 'signup' - | 'uiTest' - | 'visualTest' - | 'interactionTest' - | 'storybook' - | 'playwright' - | 'cypress' - | 'turboSnap' - | 'uiReview' - | 'publish' - | 'figmaPlugin' - | 'frontendTeams' - | 'designSystems' - | 'digitalAgencies' - | 'aboutChromatic' - | 'careers' - | 'security' - | 'enterprise' - | 'netlify' - | 'monday' - | 'collective' - | 'ezcater' - | 'blog' - | 'changelog' - | 'frontendTestingGuide' - | 'docs' - | 'pricing' - | 'sales';