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

33 - Create the navigation elements of the design system #54

Merged
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ describe('Layout', () => {
it('renders the Header', () => {
cy.mount(<Layout></Layout>)

cy.findByRole('img', { name: 'brandLogoImage' }).should('exist')
cy.findByRole('img', { name: 'Brand Logo Image' }).should('exist')
cy.findByText('brandTitle').should('exist')

cy.findByRole('button', { name: 'Toggle navigation' }).click()
Expand Down
55 changes: 55 additions & 0 deletions cypress/component/ui/navbar/Navbar.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Navbar } from '../../../../src/sections/ui/navbar/Navbar'

const brand = {
logoImgSrc: '/logo.svg',
title: 'Brand Title',
href: '/home'
}

describe('Navbar component', () => {
it('renders the brand logo and title', () => {
cy.mount(<Navbar brand={brand} />)

cy.findByRole('img', { name: 'Brand Logo Image' }).should('exist')
cy.findByText('Brand Title').should('exist')
})

it('renders the navbar links', () => {
cy.mount(
<Navbar brand={brand}>
<Navbar.Link href="/link-1">Link 1</Navbar.Link>
<Navbar.Link href="/link-2">Link 2</Navbar.Link>
<Navbar.Dropdown title="Dropdown" id="dropdown">
<Navbar.Dropdown.Item href="/sublink-1">Sublink 1</Navbar.Dropdown.Item>
<Navbar.Dropdown.Item href="/sublink-2">Sublink 2</Navbar.Dropdown.Item>
</Navbar.Dropdown>
</Navbar>
)

cy.findByRole('button', { name: 'Toggle navigation' }).click()
cy.findByRole('link', { name: 'Link 1' }).should('exist')
cy.findByRole('link', { name: 'Link 2' }).should('exist')

const dropdownElement = cy.findByRole('button', { name: 'Dropdown' })
dropdownElement.should('exist')
})

it('shows the sublinks when the dropdown is clicked', () => {
cy.mount(
<Navbar brand={brand}>
<Navbar.Link href="/link-1">Link 1</Navbar.Link>
<Navbar.Link href="/link-2">Link 2</Navbar.Link>
<Navbar.Dropdown title="Dropdown" id="dropdown">
<Navbar.Dropdown.Item href="/sublink-1">Sublink 1</Navbar.Dropdown.Item>
<Navbar.Dropdown.Item href="/sublink-2">Sublink 2</Navbar.Dropdown.Item>
</Navbar.Dropdown>
</Navbar>
)
cy.findByRole('button', { name: 'Toggle navigation' }).click()
const dropdownElement = cy.findByRole('button', { name: 'Dropdown' })
dropdownElement.click()

cy.findByRole('link', { name: 'Sublink 1' }).should('exist')
cy.findByRole('link', { name: 'Sublink 2' }).should('exist')
})
})
49 changes: 0 additions & 49 deletions cypress/component/ui/navbar/navbar.spec.tsx

This file was deleted.

35 changes: 17 additions & 18 deletions src/sections/layout/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import logo from '../../ui/logo.svg'
import { useTranslation } from 'react-i18next'
import { Navbar } from '../../ui/navbar/Navbar'
import { Route } from '../../route.enum'
import { Link } from '../../ui/navbar/NavbarProps'

type User = {
name: string
Expand All @@ -15,23 +14,23 @@ interface HeaderProps {
export function Header({ user }: HeaderProps) {
const { t } = useTranslation('header')

const links: Link[] = user
? [{ title: user.name, value: [{ title: t('logOut'), value: Route.LOG_OUT }] }]
: [
{ title: t('signUp'), value: Route.SIGN_UP },
{ title: t('logIn'), value: Route.LOG_IN }
]

return (
<>
<Navbar
brand={{
logo: { src: logo, altText: t('brandLogoImage') },
title: t('brandTitle'),
path: Route.HOME
}}
links={links}
/>
</>
<Navbar
brand={{
title: t('brandTitle'),
href: Route.HOME,
logoImgSrc: logo
}}>
{user ? (
<Navbar.Dropdown title={user.name} id="dropdown-user">
<Navbar.Dropdown.Item href={Route.LOG_OUT}>{t('logOut')}</Navbar.Dropdown.Item>
</Navbar.Dropdown>
) : (
<>
<Navbar.Link href={Route.LOG_IN}>{t('logIn')}</Navbar.Link>
<Navbar.Link href={Route.SIGN_UP}>{t('signUp')}</Navbar.Link>
</>
)}
</Navbar>
)
}
7 changes: 6 additions & 1 deletion src/sections/ui/assets/styles/bootstrap-customized.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ $danger: $dv-danger-color;
$body-color: $dv-text-color;
$headings-color: $dv-headings-color;

// Typography
// Typography
$font-family-base: $dv-font-family;

$font-size-base: $dv-font-size;
Expand Down Expand Up @@ -53,6 +53,11 @@ $link-hover-color: $dv-link-hover-color;
// Badge
@import "bootstrap/scss/badge";

// Breadcrumb
$breadcrumb-divider: ">";

@import "bootstrap/scss/breadcrumb";

// Tooltip
@import "bootstrap/scss/tooltip";

Expand Down
11 changes: 11 additions & 0 deletions src/sections/ui/breadcrumb/Breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Breadcrumb as BreadcrumbBS } from 'react-bootstrap'
import { PropsWithChildren } from 'react'
import { BreadcrumbItem } from './BreadcrumbItem'

function Breadcrumb({ children }: PropsWithChildren) {
return <BreadcrumbBS>{children}</BreadcrumbBS>
}

Breadcrumb.Item = BreadcrumbItem

export { Breadcrumb }
14 changes: 14 additions & 0 deletions src/sections/ui/breadcrumb/BreadcrumbItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { BreadcrumbItem as BreadcrumbItemBS } from 'react-bootstrap'
import { PropsWithChildren } from 'react'

interface BreadcrumbItemProps {
href?: string
active?: boolean
}
export function BreadcrumbItem({ href, active, children }: PropsWithChildren<BreadcrumbItemProps>) {
return (
<BreadcrumbItemBS href={href} active={active}>
{children}
</BreadcrumbItemBS>
)
}
39 changes: 22 additions & 17 deletions src/sections/ui/navbar/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import { Navbar as NavbarBS } from 'react-bootstrap'
import { Nav } from 'react-bootstrap'
import { Link, NavbarProps } from './NavbarProps'
import { NavDropdown } from './nav-dropdown/NavDropdown'
import { NavbarDropdown } from './navbar-dropdown/NavbarDropdown'
import { Container } from '../grid/Container'
import { PropsWithChildren } from 'react'
import { NavbarLink } from './NavbarLink'

export function Navbar({ brand, links }: NavbarProps) {
interface Brand {
title: string
href: string
logoImgSrc: string
}

export interface NavbarProps {
brand: Brand
}

function Navbar({ brand, children }: PropsWithChildren<NavbarProps>) {
return (
<NavbarBS collapseOnSelect bg="light" expand="lg" fixed="top">
<Container>
<NavbarBS.Brand href={brand.path}>
<img width="28" height="28" src={brand.logo.src} alt={brand.logo.altText} />
<NavbarBS.Brand href={brand.href}>
<img width="28" height="28" src={brand.logoImgSrc} alt="Brand Logo Image" />
{brand.title}
</NavbarBS.Brand>
<NavbarBS.Toggle aria-controls="responsive-navbar-nav" />
<NavbarBS.Collapse id="responsive-navbar-nav">
<Nav>
{links.length != 0 &&
links.map((link: Link, index) =>
typeof link.value == 'string' ? (
<Nav.Link eventKey={index} key={index} href={link.value}>
{link.title}
</Nav.Link>
) : (
<NavDropdown key={index} title={link.title} links={link.value} />
)
)}
</Nav>
<Nav>{children}</Nav>
</NavbarBS.Collapse>
</Container>
</NavbarBS>
)
}

Navbar.Link = NavbarLink
Navbar.Dropdown = NavbarDropdown

export { Navbar }
10 changes: 10 additions & 0 deletions src/sections/ui/navbar/NavbarLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Nav } from 'react-bootstrap'
import { PropsWithChildren } from 'react'

interface NavbarLinkProps {
href: string
}

export function NavbarLink({ href, children }: PropsWithChildren<NavbarLinkProps>) {
return <Nav.Link href={href}>{children}</Nav.Link>
}
20 changes: 0 additions & 20 deletions src/sections/ui/navbar/NavbarProps.ts

This file was deleted.

23 changes: 0 additions & 23 deletions src/sections/ui/navbar/nav-dropdown/NavDropdown.tsx

This file was deleted.

20 changes: 20 additions & 0 deletions src/sections/ui/navbar/navbar-dropdown/NavbarDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { NavDropdown as NavDropdownBS } from 'react-bootstrap'
import { PropsWithChildren } from 'react'
import { NavbarDropdownItem } from './NavbarDropdownItem'

interface DropdownProps {
title: string
id: string
}

function NavbarDropdown({ title, id, children }: PropsWithChildren<DropdownProps>) {
return (
<NavDropdownBS title={title} id={id}>
{children}
</NavDropdownBS>
)
}

NavbarDropdown.Item = NavbarDropdownItem

export { NavbarDropdown }
10 changes: 10 additions & 0 deletions src/sections/ui/navbar/navbar-dropdown/NavbarDropdownItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { NavDropdown } from 'react-bootstrap'
import { PropsWithChildren } from 'react'

interface NavbarDropdownItemProps {
href: string
}

export function NavbarDropdownItem({ href, children }: PropsWithChildren<NavbarDropdownItemProps>) {
return <NavDropdown.Item href={href}>{children}</NavDropdown.Item>
}
15 changes: 15 additions & 0 deletions src/sections/ui/tabs/Tab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { PropsWithChildren } from 'react'
import { Tab as TabBS } from 'react-bootstrap'

export interface TabProps {
title: string
eventKey: string
}

export function Tab({ title, eventKey, children }: PropsWithChildren<TabProps>) {
return (
<TabBS title={title} eventKey={eventKey}>
{children}
</TabBS>
)
}
15 changes: 15 additions & 0 deletions src/sections/ui/tabs/Tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { PropsWithChildren } from 'react'
import { Tab } from './Tab'
import { Tabs as TabsBS } from 'react-bootstrap'

interface TabsProps {
defaultActiveKey: string
}

function Tabs({ defaultActiveKey, children }: PropsWithChildren<TabsProps>) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this have a heading of "Props"? This is what I see:

Screen Shot 2023-04-18 at 10 17 42 AM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @pdurbin ! The Props heading is missing because this branch is older than the #40 mdx storybook docs template. Then the template with the Props heading is missing in this branch but once this is merged it should look good in dev

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MellyGray yes, you're right. I hope you don't mind but I did git rebase develop on this PR and then force pushed it. The Props heading is there now:

Screen Shot 2023-04-18 at 2 21 51 PM

return <TabsBS defaultActiveKey={defaultActiveKey}>{children}</TabsBS>
}

Tabs.Tab = Tab

export { Tabs }
Loading