From 8715a21cf3426e47a1201c4f5ca81f090a36efd2 Mon Sep 17 00:00:00 2001 From: Bryan Jennings Date: Thu, 8 Sep 2022 04:07:01 -0700 Subject: [PATCH 1/3] Make AdminLessonNav more generic --- .../__snapshots__/storyshots.test.js.snap | 78 +++++++++---------- .../[lessonSlug]/[pageName]/modules.test.js | 2 +- components/NavCard.tsx | 46 +++++++++++ .../lessons/AdminLessonSideNavLayout.tsx | 25 ------ .../lessons/[lessonSlug]/[pageName]/index.tsx | 33 ++------ ...sonNav.module.scss => navCard.module.scss} | 16 ++-- .../AdminLessonSideNavLayout.stories.tsx | 55 ------------- stories/components/NavCard.stories.tsx | 29 +++++++ 8 files changed, 125 insertions(+), 159 deletions(-) create mode 100644 components/NavCard.tsx delete mode 100644 components/admin/lessons/AdminLessonSideNavLayout.tsx rename scss/{adminLessonNav.module.scss => navCard.module.scss} (83%) delete mode 100644 stories/components/AdminLessonSideNavLayout.stories.tsx create mode 100644 stories/components/NavCard.stories.tsx diff --git a/__tests__/__snapshots__/storyshots.test.js.snap b/__tests__/__snapshots__/storyshots.test.js.snap index 56c73e1ae..bc233d808 100644 --- a/__tests__/__snapshots__/storyshots.test.js.snap +++ b/__tests__/__snapshots__/storyshots.test.js.snap @@ -866,46 +866,6 @@ Array [ ] `; -exports[`Storyshots Components/AdminLessonNav Basic 1`] = ` -
-
-
- - INTRODUCTION - - - MODULES - - - CHALLENGES - -
-
-
-`; - exports[`Storyshots Components/AdminLessonSideNav Basic 1`] = `
`; +exports[`Storyshots Components/NavCard Basic 1`] = ` +
+
+ + INTRODUCTION + + + MODULES + + + CHALLENGES + +
+
+`; + exports[`Storyshots Components/NavLink Active Link 1`] = ` Array [ { await act(() => new Promise(res => setTimeout(res, 0))) expect(screen.getByText('MODULES').className).not.toEqual( - 'lessons_tabsNav__nav__item' + 'navCard__tabsNav__nav__item' ) }) }) diff --git a/components/NavCard.tsx b/components/NavCard.tsx new file mode 100644 index 000000000..1dd848fd8 --- /dev/null +++ b/components/NavCard.tsx @@ -0,0 +1,46 @@ +import Link from 'next/link' +import React from 'react' +import styles from '../scss/navCard.module.scss' + +type Tab = { + text: string + url: string + isSelected: boolean +} + +type NavCardProps = { + tabs: Tab[] +} + +const NavCard = ({ tabs }: NavCardProps) => { + return ( +
+
+ {tabs.map((tab, i) => ( + + ))} +
+
+ ) +} + +type NavCardItemProps = { + tab: Tab +} + +const NavCardItem = ({ tab }: NavCardItemProps) => { + const className = + styles[ + tab.isSelected + ? 'navCard__tabsNav__nav__item' + : 'navCard__tabsNav__nav__item--inactive' + ] + + return ( + +
{tab.text.toUpperCase()} + + ) +} + +export default NavCard diff --git a/components/admin/lessons/AdminLessonSideNavLayout.tsx b/components/admin/lessons/AdminLessonSideNavLayout.tsx deleted file mode 100644 index 3827fe4cb..000000000 --- a/components/admin/lessons/AdminLessonSideNavLayout.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React, { FunctionComponent } from 'react' -import styles from '../../../scss/adminLessonNav.module.scss' - -type Tab = { tabName: string; urlPageName: string } - -type Props = { - tabs: Tab[] - Component: FunctionComponent<{ tab: Tab }> -} - -const AdminLessonNav: React.FC = ({ tabs, Component }: Props) => { - return ( -
-
-
- {tabs.map((tab, i) => ( - - ))} -
-
-
- ) -} - -export default AdminLessonNav diff --git a/pages/admin/lessons/[lessonSlug]/[pageName]/index.tsx b/pages/admin/lessons/[lessonSlug]/[pageName]/index.tsx index ed7b7283f..b98c978a6 100644 --- a/pages/admin/lessons/[lessonSlug]/[pageName]/index.tsx +++ b/pages/admin/lessons/[lessonSlug]/[pageName]/index.tsx @@ -1,18 +1,15 @@ import { gql, useQuery } from '@apollo/client' import { GetAppProps, withGetApp } from '../../../../../graphql' -import { toUpper } from 'lodash' import React, { useMemo, useState } from 'react' -import AdminLessonNav from '../../../../../components/admin/lessons/AdminLessonSideNavLayout' import AdminLessonSideNav from '../../../../../components/admin/lessons/AdminLessonSideNav' import AdminLessonInputs from '../../../../../components/admin/lessons/AdminLessonInputs' import { Props } from '../../../../../components/admin/lessons/AdminLessonInputs/AdminLessonInputs' import Breadcrumbs from '../../../../../components/Breadcrumbs' import styles from '../../../../../scss/modules.module.scss' -import navStyles from '../../../../../scss/adminLessonNav.module.scss' import { AdminLayout } from '../../../../../components/admin/AdminLayout' import { useRouter } from 'next/router' -import Link from 'next/link' import { compose, filter, get, sortBy } from 'lodash/fp' +import NavCard from '../../../../../components/NavCard' const MAIN_PATH = '/admin/lessons' @@ -114,26 +111,6 @@ const Lessons = ({ data }: GetAppProps) => { return sortModules(modulesData) }, [lesson.id, get('modules', modulesData)]) - const LessonNav = ({ - tab - }: { - tab: { tabName: string; urlPageName: string } - }) => { - const isSelected = tab.urlPageName === pageName - const className = - navStyles[ - isSelected - ? 'lessons_tabsNav__nav__item' - : 'lessons_tabsNav__nav__item--inactive' - ] - - return ( - - {toUpper(tab.tabName)} - - ) - } - return (
@@ -148,14 +125,14 @@ const Lessons = ({ data }: GetAppProps) => { />
-
diff --git a/scss/adminLessonNav.module.scss b/scss/navCard.module.scss similarity index 83% rename from scss/adminLessonNav.module.scss rename to scss/navCard.module.scss index bd05a1baa..7f2985c0c 100644 --- a/scss/adminLessonNav.module.scss +++ b/scss/navCard.module.scss @@ -6,7 +6,7 @@ $light: hsl(0, 0%, 98.4%); $dark_primary: color.adjust(variables.$primary, $lightness: -20%); $light_primary: color.adjust(variables.$primary, $lightness: 28%); -.lessons_tabsNav { +.navCard__tabsNav { font-family: 'PT Mono'; max-width: fit-content; padding: 8px 16px; @@ -20,7 +20,7 @@ $light_primary: color.adjust(variables.$primary, $lightness: 28%); border: 1px solid $light_primary; } -.lessons__tabsNav__nav { +.navCard__tabsNav__nav { display: flex; column-gap: 20px; justify-content: center; @@ -28,7 +28,7 @@ $light_primary: color.adjust(variables.$primary, $lightness: 28%); flex-wrap: nowrap; } -.lessons_tabsNav__nav__item { +.navCard__tabsNav__nav__item { padding: 7px 16px; border-radius: 4px; background-color: variables.$primary; @@ -39,11 +39,11 @@ $light_primary: color.adjust(variables.$primary, $lightness: 28%); font-size: 14px; } -.lessons_tabsNav__nav__item:hover { +.navCard__tabsNav__nav__item:hover { color: white; } -.lessons_tabsNav__nav__item--inactive { +.navCard__tabsNav__nav__item--inactive { padding: 7px 16px; border-radius: 4px; color: $dark_primary; @@ -55,12 +55,8 @@ $light_primary: color.adjust(variables.$primary, $lightness: 28%); font-size: 14px; } -.lessons_tabsNav__nav__item--inactive:hover { +.navCard__tabsNav__nav__item--inactive:hover { background-color: color.change(variables.$primary, $lightness: 95%); color: $dark_primary; transition: background-color 0.3s ease-out; } - -.lessons_tabs { - margin-top: 40px; -} diff --git a/stories/components/AdminLessonSideNavLayout.stories.tsx b/stories/components/AdminLessonSideNavLayout.stories.tsx deleted file mode 100644 index af9004995..000000000 --- a/stories/components/AdminLessonSideNavLayout.stories.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { toUpper } from 'lodash' -import Link from 'next/link' -import { useRouter } from 'next/router' -import * as React from 'react' -import AdminLessonNav from '../../components/admin/lessons/AdminLessonSideNavLayout' -import styles from '../../scss/adminLessonNav.module.scss' - -export default { - component: AdminLessonNav, - title: 'Components/AdminLessonNav' -} - -export const Basic = () => { - const router = useRouter() - - const SideNavComponent = ({ - tab - }: { - tab: { tabName: string; urlPageName: string } - }) => { - const isSelected = router.asPath.split('/').slice(-1)[0] === tab.urlPageName - - const className = - styles[ - isSelected - ? 'lessons_tabsNav__nav__item' - : 'lessons_tabsNav__nav__item--inactive' - ] - - return ( - - {toUpper(tab.tabName)} - - ) - } - - return ( - - ) -} - -const parameters = { - nextRouter: { - asPath: 'c0d3.com/admin/lessons/1/introduction' - } -} - -Basic.parameters = parameters diff --git a/stories/components/NavCard.stories.tsx b/stories/components/NavCard.stories.tsx new file mode 100644 index 000000000..bc3a925b6 --- /dev/null +++ b/stories/components/NavCard.stories.tsx @@ -0,0 +1,29 @@ +import { useRouter } from 'next/router' +import * as React from 'react' +import NavCard from '../../components/NavCard' + +export default { + component: NavCard, + title: 'Components/NavCard' +} + +export const Basic = () => { + const router = useRouter() + const pageName = router.asPath.split('/').slice(-1)[0] + const tabTexts = ['introduction', 'modules', 'challenges'] + const textToTab = (text: string) => ({ + text, + url: `/admin/lessons/1/${text}`, + isSelected: text === pageName + }) + + return +} + +const parameters = { + nextRouter: { + asPath: 'c0d3.com/admin/lessons/1/introduction' + } +} + +Basic.parameters = parameters From 5416344310aee487bc291a42b7db0ca8e9c7d2f7 Mon Sep 17 00:00:00 2001 From: Bryan Jennings Date: Thu, 8 Sep 2022 23:55:54 -0700 Subject: [PATCH 2/3] Use tabSelected in NavCard to make invalid states impossible --- components/NavCard.tsx | 11 ++++++----- .../lessons/[lessonSlug]/[pageName]/index.tsx | 18 +++++++++--------- stories/components/NavCard.stories.tsx | 6 +++--- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/components/NavCard.tsx b/components/NavCard.tsx index 1dd848fd8..de01356c8 100644 --- a/components/NavCard.tsx +++ b/components/NavCard.tsx @@ -5,19 +5,19 @@ import styles from '../scss/navCard.module.scss' type Tab = { text: string url: string - isSelected: boolean } type NavCardProps = { + tabSelected: number tabs: Tab[] } -const NavCard = ({ tabs }: NavCardProps) => { +const NavCard = ({ tabSelected, tabs }: NavCardProps) => { return (
{tabs.map((tab, i) => ( - + ))}
@@ -25,13 +25,14 @@ const NavCard = ({ tabs }: NavCardProps) => { } type NavCardItemProps = { + isSelected: boolean tab: Tab } -const NavCardItem = ({ tab }: NavCardItemProps) => { +const NavCardItem = ({ isSelected, tab }: NavCardItemProps) => { const className = styles[ - tab.isSelected + isSelected ? 'navCard__tabsNav__nav__item' : 'navCard__tabsNav__nav__item--inactive' ] diff --git a/pages/admin/lessons/[lessonSlug]/[pageName]/index.tsx b/pages/admin/lessons/[lessonSlug]/[pageName]/index.tsx index b98c978a6..1a1bd9001 100644 --- a/pages/admin/lessons/[lessonSlug]/[pageName]/index.tsx +++ b/pages/admin/lessons/[lessonSlug]/[pageName]/index.tsx @@ -111,6 +111,14 @@ const Lessons = ({ data }: GetAppProps) => { return sortModules(modulesData) }, [lesson.id, get('modules', modulesData)]) + const tabs = [ + { + text: 'modules', + url: `${MAIN_PATH}/${lesson.slug}/modules` + } + ] + const tabSelected = tabs.findIndex(tab => tab.text === pageName) + return (
@@ -125,15 +133,7 @@ const Lessons = ({ data }: GetAppProps) => { />
- +
{ const router = useRouter() const pageName = router.asPath.split('/').slice(-1)[0] const tabTexts = ['introduction', 'modules', 'challenges'] + const tabSelected = tabTexts.findIndex(text => text === pageName) const textToTab = (text: string) => ({ text, - url: `/admin/lessons/1/${text}`, - isSelected: text === pageName + url: `/admin/lessons/1/${text}` }) - return + return } const parameters = { From 69472f95777c1ad0771276354df908525ac71620 Mon Sep 17 00:00:00 2001 From: Bryan Jennings Date: Fri, 9 Sep 2022 00:04:46 -0700 Subject: [PATCH 3/3] Refactor NavCard.stories.tsx --- stories/components/NavCard.stories.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/stories/components/NavCard.stories.tsx b/stories/components/NavCard.stories.tsx index 339d0b1b3..62b96ef9a 100644 --- a/stories/components/NavCard.stories.tsx +++ b/stories/components/NavCard.stories.tsx @@ -10,14 +10,13 @@ export default { export const Basic = () => { const router = useRouter() const pageName = router.asPath.split('/').slice(-1)[0] - const tabTexts = ['introduction', 'modules', 'challenges'] - const tabSelected = tabTexts.findIndex(text => text === pageName) - const textToTab = (text: string) => ({ + const tabs = ['introduction', 'modules', 'challenges'].map(text => ({ text, url: `/admin/lessons/1/${text}` - }) + })) + const tabSelected = tabs.findIndex(tab => tab.text === pageName) - return + return } const parameters = {