Skip to content

Commit

Permalink
Merge pull request #54 from IQSS/feature/create-the-navigation-elemen…
Browse files Browse the repository at this point in the history
…ts-of-the-design-system

33 - Create the navigation elements of the design system
  • Loading branch information
kcondon authored Apr 26, 2023
2 parents 5ae8b02 + e886f0a commit a702cc5
Show file tree
Hide file tree
Showing 30 changed files with 476 additions and 240 deletions.
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>) {
return <TabsBS defaultActiveKey={defaultActiveKey}>{children}</TabsBS>
}

Tabs.Tab = Tab

export { Tabs }
Loading

0 comments on commit a702cc5

Please sign in to comment.