-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* [ui] TopNavigation: initial commit * [ui] TopNavigation: stub stories with output * [ui] TopNavigation, Item: render as anchors, buttons, or plain * [ui] TopNavigation: begin adding styles * [ui] TopNavigation: add item styles, parent tests * [ui] TopNavigation, Item: export components * [ui] TopNavigationItem: add tests, add aria-label prop, remove obsolete * [ui] bump version to 0.7.2
- Loading branch information
1 parent
5deac97
commit 6b13f3d
Showing
12 changed files
with
342 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
libs/juno-ui-components/src/components/TopNavigation/TopNavigation.component.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import React, { useEffect, useState } from "react"; | ||
import PropTypes from "prop-types"; | ||
import { Stack } from "../Stack/index" | ||
import { Icon } from "../Icon/index.js"; | ||
|
||
const topNavigationStyles = ` | ||
jn-gap-[3.9375rem] | ||
` | ||
|
||
/** | ||
A generic horizontal top level navigation component. To be placed below the application header but above application content. | ||
Place TopNavigationItem components as children. | ||
*/ | ||
export const TopNavigation = ({ | ||
children, | ||
className, | ||
...props | ||
}) => { | ||
return ( | ||
<Stack className={`juno-topnavigation ${topNavigationStyles} ${className}`} role="navigation" {...props} > | ||
{ children } | ||
</Stack> | ||
) | ||
} | ||
|
||
TopNavigation.propTypes = { | ||
/** The children of the Navigation. Typically these should be TopNavigationItem(s) */ | ||
children: PropTypes.node, | ||
/** Passa custom classname. */ | ||
className: PropTypes.string, | ||
} | ||
|
||
TopNavigation.defaultProps = { | ||
children: null, | ||
className: "", | ||
} |
28 changes: 28 additions & 0 deletions
28
libs/juno-ui-components/src/components/TopNavigation/TopNavigation.stories.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import React from "react" | ||
import { TopNavigation } from "./index.js" | ||
import { TopNavigationItem } from "../TopNavigationItem/TopNavigationItem.component" | ||
import { Default as TopNavigationItemStory } from "../TopNavigationItem/TopNavigationItem.stories" | ||
|
||
export default { | ||
title: "WiP/TopNavigation/TopNavigation", | ||
component: TopNavigation, | ||
argTypes: {}, | ||
} | ||
|
||
const Template = ({items, ...args}) => ( | ||
<TopNavigation {...args}> | ||
{items.map((item, i) => ( | ||
<TopNavigationItem key={i} {...item} /> | ||
))} | ||
</TopNavigation> | ||
) | ||
|
||
export const Default = Template.bind({}) | ||
Default.args = { | ||
items: [ | ||
{...TopNavigationItemStory.args}, | ||
{...TopNavigationItemStory.args}, | ||
{...TopNavigationItemStory.args, icon: "warning"}, | ||
{...TopNavigationItemStory.args, active: true}, | ||
] | ||
} |
27 changes: 27 additions & 0 deletions
27
libs/juno-ui-components/src/components/TopNavigation/TopNavigation.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import * as React from 'react'; | ||
import { render, screen, waitFor } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import { TopNavigation } from './index'; | ||
|
||
describe('TopNavigation', () => { | ||
test('render a ToppNavigation', async () => { | ||
render(<TopNavigation />); | ||
expect(screen.getByRole('navigation')).toBeInTheDocument(); | ||
expect(screen.getByRole('navigation')).toHaveClass("juno-topnavigation"); | ||
}); | ||
|
||
test("renders children as passed", async () => { | ||
render(<TopNavigation><button>Test</button></TopNavigation>) | ||
expect(screen.getByRole('button', {name: "Test"})).toBeInTheDocument(); | ||
}) | ||
|
||
test('renders custom classNames as passed', async () => { | ||
render(<TopNavigation className='my-custom-class' />); | ||
expect(screen.getByRole("navigation")).toHaveClass('my-custom-class'); | ||
}); | ||
|
||
test('renders all props as passed', async () => { | ||
render(<TopNavigation data-lol='Prop goes here' />); | ||
expect(screen.getByRole('navigation')).toHaveAttribute('data-lol', 'Prop goes here'); | ||
}); | ||
}); |
2 changes: 2 additions & 0 deletions
2
libs/juno-ui-components/src/components/TopNavigation/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { TopNavigation } from "./TopNavigation.component"; | ||
|
95 changes: 95 additions & 0 deletions
95
libs/juno-ui-components/src/components/TopNavigationItem/TopNavigationItem.component.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import React, { useEffect, useState } from "react"; | ||
import PropTypes from "prop-types"; | ||
import { Icon } from "../Icon/index.js"; | ||
import { knownIcons } from "../Icon/Icon.component.js" | ||
import "./topNavigationItem.scss" | ||
|
||
/** | ||
A top level navigation item. Top be placed inside TopNavigation. | ||
*/ | ||
|
||
export const TopNavigationItem = ({ | ||
icon, | ||
label, | ||
ariaLabel, | ||
href, | ||
active, | ||
onClick, | ||
children, | ||
className, | ||
...props | ||
}) => { | ||
|
||
const icn = icon ? <Icon icon={icon} size="18" color="jn-text-theme-default" className={ label && label.length ? "jn-mr-1" : "" } /> : null | ||
|
||
const content = label || children | ||
|
||
const handleButtonClick = (event) => { | ||
onClick && onClick(event) | ||
} | ||
|
||
const anchor = ( | ||
<a className={`juno-topnavigation-item ${ active ? "juno-topnavigation-item-active" : ""} ${className}`} | ||
href={href} | ||
aria-label={ariaLabel} | ||
{...props} | ||
> | ||
{ icn } | ||
{ content } | ||
</a> | ||
) | ||
|
||
const button = ( | ||
<button | ||
className={`juno-topnavigation-item ${ active ? "juno-topnavigation-item-active" : ""} ${className}`} | ||
onClick={handleButtonClick} | ||
aria-label={ariaLabel} | ||
{...props} | ||
> | ||
{ icn } | ||
{ content } | ||
</button> | ||
) | ||
|
||
const plain = ( | ||
<div className={`juno-topnavigation-item ${ active ? "juno-topnavigation-item-active" : ""} ${className}`} | ||
aria-label={ariaLabel} | ||
{...props} | ||
> | ||
{ icn } | ||
{ label || children } | ||
</div> | ||
) | ||
|
||
return href ? anchor : onClick ? button : plain | ||
} | ||
|
||
TopNavigationItem.propTypes = { | ||
/** pass an icon name */ | ||
icon: PropTypes.oneOf(knownIcons), | ||
/** The label of the item */ | ||
label: PropTypes.string, | ||
/** Children of the item. Will overwrite label when passed */ | ||
children: PropTypes.node, | ||
/** Pass a custom className */ | ||
className: PropTypes.string, | ||
/** The aria label of the item */ | ||
ariaLabel: PropTypes.string, | ||
/** The link the item should point to. Will render the item as an anchor if passed */ | ||
href: PropTypes.string, | ||
/** Whether the item is the currently active item */ | ||
active: PropTypes.bool, | ||
/** A handler to execute once the item is clicked. Will render the item as a button element if passed */ | ||
onClick: PropTypes.func, | ||
} | ||
|
||
TopNavigationItem.defaultProps = { | ||
icon: null, | ||
label: "", | ||
children: null, | ||
className: "", | ||
ariaLabel: "", | ||
href: "", | ||
active: false, | ||
onClick: undefined, | ||
} |
40 changes: 40 additions & 0 deletions
40
libs/juno-ui-components/src/components/TopNavigationItem/TopNavigationItem.stories.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import React from "react" | ||
import { TopNavigationItem } from "./index.js" | ||
|
||
export default { | ||
title: "WiP/TopNavigation/TopNavigationItem", | ||
component: TopNavigationItem, | ||
argTypes: {}, | ||
parameters: { actions: { argTypesRegex: null } } | ||
} | ||
|
||
const Template = (args) => <TopNavigationItem {...args} /> | ||
|
||
export const Default = Template.bind({}) | ||
Default.args = { | ||
label: "Navigation Item" | ||
} | ||
|
||
export const WithIcon = Template.bind({}) | ||
WithIcon.args = { | ||
label: "Navigation Item", | ||
icon: "warning" | ||
} | ||
|
||
export const AsAnchor = Template.bind({}) | ||
AsAnchor.args = { | ||
label: "Navigation Item", | ||
href: "#" | ||
} | ||
|
||
export const AsButton = Template.bind({}) | ||
AsButton.args = { | ||
label: "Navigation Item", | ||
onClick: () => {console.log("clicked")} | ||
} | ||
|
||
export const Active = Template.bind({}) | ||
Active.args = { | ||
label: "Navigation Item", | ||
active: true | ||
} |
73 changes: 73 additions & 0 deletions
73
libs/juno-ui-components/src/components/TopNavigationItem/TopNavigationItem.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import * as React from 'react'; | ||
import { render, screen, waitFor } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import { TopNavigationItem } from './index'; | ||
|
||
describe('TopNavigation', () => { | ||
|
||
test('renders a ToppNavigationItem', async () => { | ||
render(<TopNavigationItem data-testid="top-nav-item" />); | ||
expect(screen.getByTestId('top-nav-item')).toBeInTheDocument(); | ||
expect(screen.getByTestId('top-nav-item')).toHaveClass("juno-topnavigation-item"); | ||
}); | ||
|
||
test("renders an icon as passed", async () => { | ||
render(<TopNavigationItem icon="warning" />) | ||
expect(screen.getByRole("img")).toBeInTheDocument(); | ||
expect(screen.getByRole("img")).toHaveAttribute("alt", "warning"); | ||
}) | ||
|
||
test("renders a plain, non-interactive item when no href or onClick are passed", async () => { | ||
render(<TopNavigationItem data-testid="top-nav-item" />); | ||
expect(screen.queryByRole('link')).not.toBeInTheDocument(); | ||
expect(screen.queryByRole('button')).not.toBeInTheDocument(); | ||
}) | ||
|
||
test("renders as a link when a href prop is passed", async () => { | ||
render(<TopNavigationItem href="#"/>); | ||
expect(screen.getByRole("link")).toBeInTheDocument(); | ||
expect(screen.getByRole("link")).toHaveClass("juno-topnavigation-item"); | ||
}) | ||
|
||
test("renders as a button when an onClick prop is passed", async () => { | ||
render(<TopNavigationItem onClick={()=>{console.log("click")}} />); | ||
expect(screen.getByRole("button")).toBeInTheDocument(); | ||
expect(screen.getByRole("button")).toHaveClass("juno-topnavigation-item"); | ||
}) | ||
|
||
test('renders an active ToppNavigationItem as passed', async () => { | ||
render(<TopNavigationItem data-testid="top-nav-item" active />); | ||
expect(screen.getByTestId('top-nav-item')).toBeInTheDocument(); | ||
expect(screen.getByTestId('top-nav-item')).toHaveClass("juno-topnavigation-item"); | ||
expect(screen.getByTestId('top-nav-item')).toHaveClass("juno-topnavigation-item-active"); | ||
}); | ||
|
||
test('renders an aria-label as passed', async () => { | ||
render(<TopNavigationItem href="#" ariaLabel="hey nav item!" />); | ||
expect(screen.getByRole('link')).toHaveAttribute('aria-label', 'hey nav item!'); | ||
}); | ||
|
||
test("renders children as passed", async () => { | ||
render(<TopNavigationItem data-testid="top-nav-item" >Test</TopNavigationItem>) | ||
expect(screen.getByTestId('top-nav-item')).toBeInTheDocument(); | ||
expect(screen.getByTestId('top-nav-item')).toHaveTextContent("Test"); | ||
}) | ||
|
||
test("onClick handler is called as passed", () => { | ||
const onClickSpy = jest.fn() | ||
render(<TopNavigationItem onClick={onClickSpy} />) | ||
screen.getByRole("button").click() | ||
expect(onClickSpy).toHaveBeenCalled() | ||
}) | ||
|
||
test('renders custom classNames as passed', async () => { | ||
render(<TopNavigationItem data-testid="top-nav-item" className='my-custom-class' />); | ||
expect(screen.getByTestId('top-nav-item')).toHaveClass('my-custom-class'); | ||
}); | ||
|
||
test('renders all props as passed', async () => { | ||
render(<TopNavigationItem data-testid="top-nav-item" data-lol='Prop goes here' />); | ||
expect(screen.getByTestId('top-nav-item')).toHaveAttribute('data-lol', 'Prop goes here'); | ||
}); | ||
|
||
}); |
2 changes: 2 additions & 0 deletions
2
libs/juno-ui-components/src/components/TopNavigationItem/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { TopNavigationItem } from "./TopNavigationItem.component"; | ||
|
32 changes: 32 additions & 0 deletions
32
libs/juno-ui-components/src/components/TopNavigationItem/topNavigationItem.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
.juno-topnavigation-item { | ||
color: var(--color-text-default); | ||
font-weight: bold; | ||
display: inline-flex; | ||
align-items: center; | ||
gap: .5rem; | ||
border-bottom: 3px solid transparent; | ||
padding-top: .125rem; | ||
padding-bottom: 0.3125rem; | ||
|
||
&:hover { | ||
color: var(--color-text-high); | ||
border-bottom: 3px solid var(--color-accent); | ||
|
||
.juno-icon { | ||
color: var(--color-text-high); | ||
} | ||
|
||
} | ||
|
||
&:active, | ||
&.juno-topnavigation-item-active { | ||
color: var(--color-navigation-active); | ||
border-bottom: 3px solid var(--color-navigation-active); | ||
|
||
.juno-icon { | ||
color: var(--color-navigation-active); | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters