diff --git a/packages/squared/src/components/PrimaryNavigation/PrimaryNavigation.stories.tsx b/packages/squared/src/components/PrimaryNavigation/PrimaryNavigation.stories.tsx new file mode 100644 index 0000000..1523f6c --- /dev/null +++ b/packages/squared/src/components/PrimaryNavigation/PrimaryNavigation.stories.tsx @@ -0,0 +1,61 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { within, userEvent, screen } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +import { ChevronDown } from 'react-feather'; + +import { PrimaryNavigation } from './PrimaryNavigation'; + +const meta: Meta = { + title: 'Components/PrimaryNavigation', + component: PrimaryNavigation, + parameters: { + layout: 'centered', + backgrounds: { + default: 'dark', + values: [{ name: 'dark', value: '#1f2121' }], + }, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: {}, + render: (args) => ( + + + + Portal + + + + + + Notebooks + + + + + + Documentation + + + + + + Account + + + + Settings + + + Logout + + + + + ), +}; diff --git a/packages/squared/src/components/PrimaryNavigation/PrimaryNavigation.tsx b/packages/squared/src/components/PrimaryNavigation/PrimaryNavigation.tsx new file mode 100644 index 0000000..c66beba --- /dev/null +++ b/packages/squared/src/components/PrimaryNavigation/PrimaryNavigation.tsx @@ -0,0 +1,180 @@ +import React from 'react'; +import styled from 'styled-components'; + +import * as RadixNavigationMenu from '@radix-ui/react-navigation-menu'; + +export interface PrimaryNavigationProps { + children: React.ReactNode; +} + +export const PrimaryNavigation = ({ children }: PrimaryNavigationProps) => { + return ( + + {children} + + event.preventDefault()} + onPointerLeave={(event) => event.preventDefault()} + /> + + + ); +}; + +const MenuRoot = styled(RadixNavigationMenu.Root)` + position: relative; +`; + +const MenuList = styled(RadixNavigationMenu.List)` + list-style: none; + margin-bottom: 0; + padding: 0; + display: flex; + justify-self: end; + width: 100%; + font-size: 1.2rem; +`; + +const MenuItem = styled(RadixNavigationMenu.Item)` + margin: 0 1em; +`; + +const TriggerLink = styled(RadixNavigationMenu.Link)` + color: var(--rsd-component-header-nav-text-color); + border: none; + border-radius: 0.5rem; + padding: 2px 4px; + display: inline-block; // For consistency with MenuTrigger button + /* padding: 0; */ + + &:hover { + color: var(--rsd-component-header-nav-text-hover-color); + } + + &:focus { + outline: 1px solid var(--rsd-color-primary-500); + } +`; + +const MenuTrigger = styled(RadixNavigationMenu.Trigger)` + color: var(--rsd-component-header-nav-text-color); + padding: 2px 4px; + /* padding: 0; */ + + // Reset button styles + background-color: transparent; + border: none; + border-radius: 0.5rem; + + &:focus { + outline: 1px solid var(--rsd-color-primary-500); + } + + &:hover { + color: var(--rsd-component-header-nav-text-hover-color); + } + + svg { + display: inline-block; + width: 1rem; + height: 1rem; + vertical-align: middle; + } + + &[data-state='open'] { + svg { + transform: rotate(180deg); + } + } +`; + +const SubMenuContent = styled(RadixNavigationMenu.Content)` + /* This unit for the padding is also the basis for the spacing and + * sizing of the menu items. + */ + --gafaelfawr-user-menu-padding: 0.5rem; + + display: flex; + flex-direction: column; + gap: 0.25rem; + + list-style: none; + + font-size: 1rem; + background-color: var(--rsd-component-header-nav-menulist-background-color); + min-width: 12rem; + border-radius: 0.5rem; + padding: var(--gafaelfawr-user-menu-padding); + padding-right: 0; // to avoid double padding on the right side with MenuLink + box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), + 0px 10px 20px -15px rgba(22, 23, 24, 0.2); + animation-duration: 400ms; + animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); + will-change: transform, opacity; +`; + +const MenuContentItem = styled(RadixNavigationMenu.Item)` + display: flex; +`; + +export const MenuLink = styled(RadixNavigationMenu.Link)` + /* The styling on the menu triggers is overriding this colour. Need to re-address. */ + border-radius: 0.5rem; + padding: calc(var(--gafaelfawr-user-menu-padding) / 2) + var(--gafaelfawr-user-menu-padding); + margin: calc(var(--gafaelfawr-user-menu-padding) / -2); + margin-bottom: calc(var(--gafaelfawr-user-menu-padding) / 2); + width: 100%; + + color: var(--rsd-component-header-nav-menulist-text-color); + + &:last-of-type { + margin-bottom: 0; + } + + outline: 1px solid transparent; + + &:focus { + outline: 1px solid + var(--rsd-component-header-nav-menulist-selected-background-color); + } + + &:hover { + background-color: var( + --rsd-component-header-nav-menulist-selected-background-color + ); + color: white !important; + } +`; + +const ViewportContainer = styled.div` + position: absolute; + display: flex; + justify-content: center; + width: 100%; + top: 100%; + left: 0; + perspective: 2000px; +`; + +const ContentViewport = styled(RadixNavigationMenu.Viewport)` + position: relative; + transform-origin: top center; + margin-top: 10px; + width: 100%; + background-color: white; + border-radius: 6px; + overflow: hidden; + height: var(--radix-navigation-menu-viewport-height); + width: var(--radix-navigation-menu-viewport-width); +`; + +// Associate child components with the parent for easier imports. +PrimaryNavigation.TriggerLink = TriggerLink; +PrimaryNavigation.Link = MenuLink; +PrimaryNavigation.Item = MenuItem; +PrimaryNavigation.MenuItem = MenuContentItem; +PrimaryNavigation.Trigger = MenuTrigger; +PrimaryNavigation.SubMenuContent = SubMenuContent; + +export default PrimaryNavigation; diff --git a/packages/squared/src/components/PrimaryNavigation/index.ts b/packages/squared/src/components/PrimaryNavigation/index.ts new file mode 100644 index 0000000..c49d4ea --- /dev/null +++ b/packages/squared/src/components/PrimaryNavigation/index.ts @@ -0,0 +1,2 @@ +export * from './PrimaryNavigation'; +export { default } from './PrimaryNavigation'; diff --git a/packages/squared/src/index.ts b/packages/squared/src/index.ts index 708b843..a2b6cd0 100644 --- a/packages/squared/src/index.ts +++ b/packages/squared/src/index.ts @@ -9,6 +9,10 @@ export { type GafaelfawrUserMenuProps, } from './components/GafaelfawrUserMenu'; export { default as IconPill, type IconPillProps } from './components/IconPill'; +export { + default as PrimaryNavigation, + type PrimaryNavigationProps, +} from './components/PrimaryNavigation'; /* Hooks */ export { default as useCurrentUrl } from './hooks/useCurrentUrl';