Skip to content

Commit

Permalink
feat(ts/components/navMenu): upgrade mobile nav to use bootstrap comp…
Browse files Browse the repository at this point in the history
…onents (#2391)

* feat(ts/components/navMenu): upgrade mobile nav to use bootstrap components

* feat(sb/components/navMenu): add stories for mobile `navMenu`

* cleanup(ts/components/navMenu): convert `className` to use `joinClasses`

* fix:feat(ts/components/navMenu): update icons to use bootstrap icons

---------

Co-authored-by: Eddie Maldonado <[email protected]>
  • Loading branch information
firestack and lemald authored Feb 14, 2024
1 parent 481e56a commit 8677c6c
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 73 deletions.
2 changes: 1 addition & 1 deletion assets/css/bootstrap.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
// @import "../node_modules/bootstrap/scss/images";
@import "../node_modules/bootstrap/scss/list-group";
// @import "../node_modules/bootstrap/scss/modal";
// @import "../node_modules/bootstrap/scss/nav";
@import "../node_modules/bootstrap/scss/nav";
// @import "../node_modules/bootstrap/scss/navbar";
// @import "../node_modules/bootstrap/scss/offcanvas";
// @import "../node_modules/bootstrap/scss/pagination";
Expand Down
121 changes: 55 additions & 66 deletions assets/src/components/nav/navMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import React from "react"
import { Link, NavLink } from "react-router-dom"
import { Link } from "react-router-dom"
import { Nav } from "react-bootstrap"
import { displayHelp } from "../../helpers/appCue"
import { openDrift } from "../../helpers/drift"
import {
OldCloseIcon,
LogoIcon,
QuestionMarkIcon,
RefreshIcon,
SettingsIcon,
SpeechBubbleIcon,
} from "../../helpers/icon"
import { OldCloseIcon, LogoIcon } from "../../helpers/icon"
import * as BsIcon from "../../helpers/bsIcons"
import { joinClasses } from "../../helpers/dom"
import { reload } from "../../models/browser"

interface Props {
Expand All @@ -22,10 +18,12 @@ const NavMenu: React.FC<Props> = ({ mobileMenuIsOpen, toggleMobileMenu }) => {
<>
<div
data-testid="nav-menu"
className={
"c-nav-menu" +
(mobileMenuIsOpen ? " c-nav-menu--open" : " c-nav-menu--closed")
}
className={joinClasses([
"c-nav-menu",
mobileMenuIsOpen ? "c-nav-menu--open" : "c-nav-menu--closed",
"inherit-box",
"border-box",
])}
>
<div className="c-nav-menu__header">
<Link
Expand All @@ -45,59 +43,50 @@ const NavMenu: React.FC<Props> = ({ mobileMenuIsOpen, toggleMobileMenu }) => {
<OldCloseIcon className="c-nav-menu__close-icon" />
</button>
</div>
<ul className="c-nav-menu__links">
<li>
<button
className="c-nav-menu__button"
onClick={reload}
title="Refresh"
>
<RefreshIcon className="c-nav-menu__icon" />
Refresh
</button>
</li>
<li>
<button
className="c-nav-menu__button"
onClick={() => {
openDrift()
toggleMobileMenu()
}}
title="Support"
>
<SpeechBubbleIcon className="c-nav-menu__icon" />
Support
</button>
</li>
<li>
<button
className="c-nav-menu__button"
onClick={() => {
displayHelp(location)
toggleMobileMenu()
}}
title="About Skate"
>
<QuestionMarkIcon className="c-nav-menu__icon" />
About Skate
</button>
</li>

<li>
<NavLink
className={({ isActive }) =>
"c-nav-menu__link" +
(isActive ? " c-nav-menu__link--active" : "")
}
title="Settings"
to="/settings"
onClick={toggleMobileMenu}
>
<SettingsIcon className="c-nav-menu__icon" />
Settings
</NavLink>
</li>
</ul>
<div className="p-3">
<Nav className="flex-column" as="ul">
<Nav.Item>
<Nav.Link as="button" onClick={reload} className="icon-link">
<BsIcon.ArrowClockwise /> Refresh
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link
className="icon-link"
as="button"
onClick={() => {
openDrift()
toggleMobileMenu()
}}
>
<BsIcon.ChatFill /> Support
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link
className="icon-link"
as="button"
onClick={() => {
displayHelp(location)
toggleMobileMenu()
}}
>
<BsIcon.QuestionFill /> About Skate
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link
as={Link}
onClick={toggleMobileMenu}
title="Settings"
to="/settings"
className="icon-link"
>
<BsIcon.GearFill /> Settings
</Nav.Link>
</Nav.Item>
</Nav>
</div>
</div>
{mobileMenuIsOpen && (
<div
Expand Down
97 changes: 97 additions & 0 deletions assets/src/helpers/bsIcons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from "react"
import { ComponentPropsWithoutRef } from "react"

/*!
* This file contains icons exported from https://icons.getbootstrap.com/icons/ using the `Copy HTML` button.
*
* The process of adding a icon is as follows
* 1. Create a new exported constant with the title case name of the icon
* 2. Create a react component which takes `SvgProps`
* 3. Paste the value from the `Copy HTML` button as the component's body
* 4. Fix React property values
* - For instance
* - Change `class` => `className`
* - Change `fill-rule` => `fillRule`
* 5. Add extra props to the React `<svg/>` element
* - Add `{...props}` to the root `<svg/>` tag so that properties _can_ be overridden
* - Set `aria-hidden` as default on by adding it _before_ the `{...props}` on the `<svg/>`
* 6. Add a doc comment with a link to the icon
*/

type SvgProps = ComponentPropsWithoutRef<"svg">

/**
* @returns https://icons.getbootstrap.com/icons/arrow-clockwise/
*/
export const ArrowClockwise = (props: SvgProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
className="bi bi-arrow-clockwise"
viewBox="0 0 16 16"
aria-hidden
{...props}
>
<path
fillRule="evenodd"
d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2z"
/>
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466" />
</svg>
)

/**
* @returns https://icons.getbootstrap.com/icons/chat-fill/
*/
export const ChatFill = (props: SvgProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
className="bi bi-chat-fill"
viewBox="0 0 16 16"
aria-hidden
{...props}
>
<path d="M8 15c4.418 0 8-3.134 8-7s-3.582-7-8-7-8 3.134-8 7c0 1.76.743 3.37 1.97 4.6-.097 1.016-.417 2.13-.771 2.966-.079.186.074.394.273.362 2.256-.37 3.597-.938 4.18-1.234A9 9 0 0 0 8 15" />
</svg>
)

/**
* @returns https://icons.getbootstrap.com/icons/gear-fill/
*/
export const GearFill = (props: SvgProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
className="bi bi-gear-fill"
viewBox="0 0 16 16"
aria-hidden
{...props}
>
<path d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872zM8 10.93a2.929 2.929 0 1 1 0-5.86 2.929 2.929 0 0 1 0 5.858z" />
</svg>
)

/**
* @returns https://icons.getbootstrap.com/icons/question-circle-fill/
*/
export const QuestionFill = (props: SvgProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
className="bi bi-question-circle-fill"
viewBox="0 0 16 16"
aria-hidden
{...props}
>
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0M5.496 6.033h.825c.138 0 .248-.113.266-.25.09-.656.54-1.134 1.342-1.134.686 0 1.314.343 1.314 1.168 0 .635-.374.927-.965 1.371-.673.489-1.206 1.06-1.168 1.987l.003.217a.25.25 0 0 0 .25.246h.811a.25.25 0 0 0 .25-.25v-.105c0-.718.273-.927 1.01-1.486.609-.463 1.244-.977 1.244-2.056 0-1.511-1.276-2.241-2.673-2.241-1.267 0-2.655.59-2.75 2.286a.237.237 0 0 0 .241.247m2.325 6.443c.61 0 1.029-.394 1.029-.927 0-.552-.42-.94-1.029-.94-.584 0-1.009.388-1.009.94 0 .533.425.927 1.01.927z" />
</svg>
)
27 changes: 27 additions & 0 deletions assets/stories/skate-components/navMenu.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { Meta, StoryObj } from "@storybook/react"
import NavMenu from "../../src/components/nav/navMenu"
import { MemoryRouter } from "react-router-dom"
import React from "react"

const meta = {
component: NavMenu,
title: "Mobile <NavMenu>",
args: {
mobileMenuIsOpen: true,
},
decorators: [
(StoryFn) => (
<MemoryRouter>
<StoryFn />
</MemoryRouter>
),
],
parameters: {
layout: "fullscreen",
},
} satisfies Meta<typeof NavMenu>
export default meta

type Story = StoryObj<typeof meta>

export const Story: Story = {}
12 changes: 6 additions & 6 deletions assets/tests/components/nav/navMenu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ describe("NavMenu", () => {
</BrowserRouter>
)

await user.click(result.getByTitle("Refresh"))
await user.click(result.getByRole("button", { name: "Refresh" }))

expect(reloadSpy).toHaveBeenCalled()
})
Expand All @@ -100,7 +100,7 @@ describe("NavMenu", () => {
</BrowserRouter>
)

await user.click(result.getByTitle("Support"))
await user.click(result.getByRole("button", { name: "Support" }))

expect(openDrift).toHaveBeenCalled()
})
Expand All @@ -115,7 +115,7 @@ describe("NavMenu", () => {
</BrowserRouter>
)

await user.click(result.getByTitle("Support"))
await user.click(result.getByRole("button", { name: "Support" }))

expect(toggleMobileMenu).toHaveBeenCalled()
})
Expand All @@ -130,7 +130,7 @@ describe("NavMenu", () => {
</BrowserRouter>
)

await user.click(result.getByTitle("Settings"))
await user.click(result.getByRole("link", { name: "Settings" }))

expect(toggleMobileMenu).toHaveBeenCalled()
})
Expand All @@ -145,7 +145,7 @@ describe("NavMenu", () => {
</BrowserRouter>
)

await user.click(result.getByTitle("About Skate"))
await user.click(result.getByRole("button", { name: "About Skate" }))

expect(displayHelp).toHaveBeenCalled()
})
Expand All @@ -160,7 +160,7 @@ describe("NavMenu", () => {
</BrowserRouter>
)

await user.click(result.getByTitle("About Skate"))
await user.click(result.getByRole("button", { name: "About Skate" }))

expect(toggleMobileMenu).toHaveBeenCalled()
})
Expand Down

0 comments on commit 8677c6c

Please sign in to comment.