Skip to content

Commit

Permalink
feat: Flyout for Meganav
Browse files Browse the repository at this point in the history
  • Loading branch information
aralovelace committed Jan 31, 2025
1 parent 3445311 commit 1546bfc
Show file tree
Hide file tree
Showing 6 changed files with 350 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
},
"dependencies": {
"@radix-ui/react-accordion": "^1.2.1",
"@radix-ui/react-navigation-menu": "^1.2.4",
"@radix-ui/react-switch": "^1.1.1",
"@radix-ui/react-tabs": "^1.1.1",
"addsearch-js-client": "^0.8.11",
Expand Down
84 changes: 84 additions & 0 deletions src/core/Flyout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import * as React from "react";
import {
NavigationMenu,
NavigationMenuItem,
NavigationMenuList,
NavigationMenuTrigger,
NavigationMenuContent,
NavigationMenuViewport,
NavigationMenuLink,
} from "@radix-ui/react-navigation-menu";
import cn from "./utils/cn";

const NavigationMenuDemo = ({
menuItems,
navMenuStyling,
flyOutStyling,
}: {
menuItems: {
label: string;
content?: React.ReactNode;
link?: string;
panelStyling?: string;
}[];
navMenuStyling?: string;
flyOutStyling?: string;
}) => {
const menuLinkStyles =
"ui-text-menu3 text-neutral-1000 font-bold px-12 py-8 hover:bg-neutral-100 hover:text-neutral-1300 cursor-pointer flex items-center";
const viewPortStyling =
"relative overflow-hidden w-full h-[var(--radix-navigation-menu-viewport-height)] origin-[top_center] transition-[width,_height] duration-300 data-[state=closed]:animate-scaleOut data-[state=open]:animate-scaleIn sm:w-[var(--radix-navigation-menu-viewport-width)]";
const boxShadowViewport =
"shadow-[0_201px_56px_0_rgba(20,25,36,0),0_129px_51px_0_rgba(20,25,36,0.02),0_72px_43px_0_rgba(20,25,36,0.06),0_32px_32px_0_rgba(20,25,36,0.10),0_8px_18px_0_rgba(20,25,36,0.12)]";

return (
<NavigationMenu className={cn(navMenuStyling, "flex w-full relative")}>
<NavigationMenuList className="flex list-none center">
{menuItems.map((menuItem) => (
<NavigationMenuItem key={menuItem.label}>
{menuItem.content ? (
<>
<NavigationMenuTrigger
className={cn(
menuLinkStyles,
"group outline-none focus:outline-none select-none flex items-center justify-between",
)}
>
{menuItem.label}
</NavigationMenuTrigger>
<NavigationMenuContent
className={cn(
menuItem.panelStyling,
"absolute left-0 top-0 p-24 z-10",
)}
>
{menuItem.content}
</NavigationMenuContent>
</>
) : (
<NavigationMenuLink>
<a href={menuItem.link} className={menuLinkStyles}>
{menuItem.label}
</a>
</NavigationMenuLink>
)}
</NavigationMenuItem>
))}
</NavigationMenuList>

<div
className={cn("absolute left-0 top-full flex w-full", flyOutStyling)}
>
<NavigationMenuViewport
className={cn(
viewPortStyling,
boxShadowViewport,
"border border-neutral-000 rounded-2xl mt-8",
)}
/>
</div>
</NavigationMenu>
);
};

export default NavigationMenuDemo;
131 changes: 131 additions & 0 deletions src/core/Flyout/Flyout.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import React from "react";
import { StoryFn } from "@storybook/react";
import Flyout from "../Flyout";
import ProductTile from "../ProductTile";
import { ProductName } from "../ProductTile/data";
import FeaturedLink from "../FeaturedLink";

export default {
title: "Components/Flyout",
component: Flyout,
tags: ["autodocs"],
};

const Template: StoryFn = (args) => <Flyout {...args} />;

const products: ProductName[] = [
"pubsub",
"chat",
"spaces",
"liveSync",
"assetTracking",
"liveObjects",
];

const platforms = [
"Infrastructure",
"Integrations",
"SDKs",
"Security & Compliance",
];

// Note: All the components and data used in this story are just temporary placeholders and will be added as separate component for the Meganav component that can be used here.
const ProductsGrid = ({ products }: { products: ProductName[] }) => (
<div className="grid grid-cols-2">
{products.map((product) => (
<ProductTile className="bg-neutral-000" name={product} key={product} />
))}
</div>
);

const Panels = ({
panelLeft,
platforms,
}: {
panelLeft: React.ReactNode;
platforms: string[];
}) => (
<div className="flex flex-row gap-x-24">
<div className="flex-6">{panelLeft}</div>
<div className="flex-4 pt-12">
<p className="ui-text-overline2 text-neutral-700 pb-6">platform</p>
{platforms.map((item) => (
<li className="list-none py-6" key={item}>
<a
className="ui-text-menu3 text-neutral-1000"
href={`/platform/${item.toLowerCase()}`}
>
{item}
</a>
</li>
))}
</div>
</div>
);

const DefaultPanelLeft = ({ title, desc }: { title: string; desc: string }) => (
<div className="bg-neutral-100 w-full p-24">
<h4 className="ui-text-h4">{title}</h4>
<p className="ui-text-p3 text-neutral-800 mt-8">{desc}</p>
<FeaturedLink
url=""
additionalCSS="text-neutral-1300"
iconColor="text-orange-600"
>
Learn more
</FeaturedLink>
</div>
);

const panelStyling = "w-full sm:w-[816px] bg-neutral-000";

export const Default = Template.bind({});
Default.args = {
menuItems: [
{ label: "Home", content: null, link: "" },
{
label: "Products",
content: (
<Panels
panelLeft={<ProductsGrid products={products as ProductName[]} />}
platforms={platforms}
/>
),
panelStyling: panelStyling,
},
{
label: "Solutions",
content: (
<Panels
panelLeft={
<DefaultPanelLeft
title="Fan engagement"
desc=" Capture the attention of millions of fans during live events."
/>
}
platforms={platforms}
/>
),
panelStyling: panelStyling,
},
{
label: "Company",
content: (
<Panels
panelLeft={
<DefaultPanelLeft
title="Leading the realtime revolution"
desc="Hear from our founders about Ably’s ambitious plans to become the world’s definitive realtime platform."
/>
}
platforms={platforms}
/>
),
panelStyling: panelStyling,
},
{ label: "Pricing", content: null, link: "/pricing" },
{ label: "Docs", content: null, link: "/docs" },
],
navMenuStyling: "justify-center",
flyOutStyling: "justify-center",
};
79 changes: 79 additions & 0 deletions src/core/Flyout/__snapshots__/Flyout.stories.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Components/Flyout Default smoke-test 1`] = `
<nav aria-label="Main"
data-orientation="horizontal"
dir="ltr"
class="justify-center flex w-full relative"
>
<div style="position: relative;">
<ul data-orientation="horizontal"
class="flex list-none center"
dir="ltr"
>
<li>
<a data-radix-collection-item>
<a href
class="ui-text-menu3 text-neutral-1000 font-bold px-12 py-8 hover:bg-neutral-100 hover:text-neutral-1300 cursor-pointer flex items-center"
>
Home
</a>
</a>
</li>
<li>
<button id="radix-:r0:-trigger-radix-:r2:"
data-state="closed"
aria-expanded="false"
aria-controls="radix-:r0:-content-radix-:r2:"
class="ui-text-menu3 text-neutral-1000 font-bold px-12 py-8 hover:bg-neutral-100 hover:text-neutral-1300 cursor-pointer group outline-none focus:outline-none select-none flex items-center justify-between"
data-radix-collection-item
>
Products
</button>
</li>
<li>
<button id="radix-:r0:-trigger-radix-:r3:"
data-state="closed"
aria-expanded="false"
aria-controls="radix-:r0:-content-radix-:r3:"
class="ui-text-menu3 text-neutral-1000 font-bold px-12 py-8 hover:bg-neutral-100 hover:text-neutral-1300 cursor-pointer group outline-none focus:outline-none select-none flex items-center justify-between"
data-radix-collection-item
>
Solutions
</button>
</li>
<li>
<button id="radix-:r0:-trigger-radix-:r4:"
data-state="closed"
aria-expanded="false"
aria-controls="radix-:r0:-content-radix-:r4:"
class="ui-text-menu3 text-neutral-1000 font-bold px-12 py-8 hover:bg-neutral-100 hover:text-neutral-1300 cursor-pointer group outline-none focus:outline-none select-none flex items-center justify-between"
data-radix-collection-item
>
Company
</button>
</li>
<li>
<a data-radix-collection-item>
<a href="/pricing"
class="ui-text-menu3 text-neutral-1000 font-bold px-12 py-8 hover:bg-neutral-100 hover:text-neutral-1300 cursor-pointer flex items-center"
>
Pricing
</a>
</a>
</li>
<li>
<a data-radix-collection-item>
<a href="/docs"
class="ui-text-menu3 text-neutral-1000 font-bold px-12 py-8 hover:bg-neutral-100 hover:text-neutral-1300 cursor-pointer flex items-center"
>
Docs
</a>
</a>
</li>
</ul>
</div>
<div class="absolute left-0 top-full flex w-full justify-center">
</div>
</nav>
`;
10 changes: 10 additions & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,20 @@ module.exports = {
from: { opacity: 0 },
to: { opacity: 0.1 },
},
scaleIn: {
from: { opacity: "0", transform: "rotateX(-10deg) scale(0.9)" },
to: { opacity: "1", transform: "rotateX(0deg) scale(1)" },
},
scaleOut: {
from: { opacity: "1", transform: "rotateX(0deg) scale(1)" },
to: { opacity: "0", transform: "rotateX(-10deg) scale(0.95)" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
scaleIn: "scaleIn 200ms ease",
scaleOut: "scaleOut 200ms ease",
},
},
listStyleType: {
Expand Down
45 changes: 45 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1168,13 +1168,44 @@
resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc"
integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==

"@radix-ui/react-dismissable-layer@1.1.4":
version "1.1.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.4.tgz#6e31ad92e7d9e77548001fd8c04f8561300c02a9"
integrity sha512-XDUI0IVYVSwjMXxM6P4Dfti7AH+Y4oS/TB+sglZ/EXc7cqLwGAmp1NlMrcUjj7ks6R5WTZuWKv44FBbLpwU3sA==
dependencies:
"@radix-ui/primitive" "1.1.1"
"@radix-ui/react-compose-refs" "1.1.1"
"@radix-ui/react-primitive" "2.0.1"
"@radix-ui/react-use-callback-ref" "1.1.0"
"@radix-ui/react-use-escape-keydown" "1.1.0"

"@radix-ui/react-id@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed"
integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==
dependencies:
"@radix-ui/react-use-layout-effect" "1.1.0"

"@radix-ui/react-navigation-menu@^1.2.4":
version "1.2.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.4.tgz#aba3ac0d343b1842924fdaf403d8922240fcfef6"
integrity sha512-wUi01RrTDTOoGtjEPHsxlzPtVzVc3R/AZ5wfh0dyqMAqolhHAHvG5iQjBCTi2AjQqa77FWWbA3kE3RkD+bDMgQ==
dependencies:
"@radix-ui/primitive" "1.1.1"
"@radix-ui/react-collection" "1.1.1"
"@radix-ui/react-compose-refs" "1.1.1"
"@radix-ui/react-context" "1.1.1"
"@radix-ui/react-direction" "1.1.0"
"@radix-ui/react-dismissable-layer" "1.1.4"
"@radix-ui/react-id" "1.1.0"
"@radix-ui/react-presence" "1.1.2"
"@radix-ui/react-primitive" "2.0.1"
"@radix-ui/react-use-callback-ref" "1.1.0"
"@radix-ui/react-use-controllable-state" "1.1.0"
"@radix-ui/react-use-layout-effect" "1.1.0"
"@radix-ui/react-use-previous" "1.1.0"
"@radix-ui/react-visually-hidden" "1.1.1"

"@radix-ui/react-presence@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.2.tgz#bb764ed8a9118b7ec4512da5ece306ded8703cdc"
Expand Down Expand Up @@ -1251,6 +1282,13 @@
dependencies:
"@radix-ui/react-use-callback-ref" "1.1.0"

"@radix-ui/react-use-escape-keydown@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754"
integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==
dependencies:
"@radix-ui/react-use-callback-ref" "1.1.0"

"@radix-ui/react-use-layout-effect@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27"
Expand All @@ -1268,6 +1306,13 @@
dependencies:
"@radix-ui/react-use-layout-effect" "1.1.0"

"@radix-ui/react-visually-hidden@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz#f7b48c1af50dfdc366e92726aee6d591996c5752"
integrity sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==
dependencies:
"@radix-ui/react-primitive" "2.0.1"

"@resvg/resvg-js-android-arm-eabi@2.6.2":
version "2.6.2"
resolved "https://registry.yarnpkg.com/@resvg/resvg-js-android-arm-eabi/-/resvg-js-android-arm-eabi-2.6.2.tgz#e761e0b688127db64879f455178c92468a9aeabe"
Expand Down

0 comments on commit 1546bfc

Please sign in to comment.