diff --git a/components/Common/Sidebar/SidebarGroup/index.module.css b/components/Common/Sidebar/SidebarGroup/index.module.css new file mode 100644 index 000000000000..ef0cad9cb873 --- /dev/null +++ b/components/Common/Sidebar/SidebarGroup/index.module.css @@ -0,0 +1,23 @@ +.group { + @apply flex + w-full + flex-col + gap-2; +} + +.groupName { + @apply px-2 + text-xs + font-semibold + text-neutral-800 + dark:text-neutral-200; +} + +.itemList { + @apply m-0 + flex + flex-col + items-start + gap-0.5 + p-0; +} diff --git a/components/Common/Sidebar/SidebarGroup/index.tsx b/components/Common/Sidebar/SidebarGroup/index.tsx new file mode 100644 index 000000000000..a43669477a7c --- /dev/null +++ b/components/Common/Sidebar/SidebarGroup/index.tsx @@ -0,0 +1,35 @@ +import type { ComponentProps, FC } from 'react'; + +import SidebarItem from '@/components/Common/Sidebar/SidebarItem'; + +import styles from './index.module.css'; + +type SidebarGroupProps = { + groupName: string; + items: ComponentProps[]; + activeItem?: ComponentProps; +}; + +const SidebarGroup: FC = ({ + groupName, + items, + activeItem, +}) => ( +
+ +
    + {items.map(({ title, url }) => ( + + ))} +
+
+); + +export default SidebarGroup; diff --git a/components/Common/Sidebar/SidebarItem/index.module.css b/components/Common/Sidebar/SidebarItem/index.module.css new file mode 100644 index 000000000000..5f076a9abc97 --- /dev/null +++ b/components/Common/Sidebar/SidebarItem/index.module.css @@ -0,0 +1,25 @@ +.sideBarItem { + @apply flex + w-full + list-none; + + a { + @apply w-full + p-2 + text-sm + font-regular + text-neutral-800 + dark:text-neutral-200; + } +} + +.active { + @apply rounded + bg-green-600; + + a, + a:hover { + @apply text-white + dark:text-white; + } +} diff --git a/components/Common/Sidebar/SidebarItem/index.tsx b/components/Common/Sidebar/SidebarItem/index.tsx new file mode 100644 index 000000000000..fab6eee211b9 --- /dev/null +++ b/components/Common/Sidebar/SidebarItem/index.tsx @@ -0,0 +1,28 @@ +import classNames from 'classnames'; +import type { FC } from 'react'; + +import Link from '@/components/Link'; + +import styles from './index.module.css'; + +type SidebarItemProps = { + title: string; + url: string; + isActive?: boolean; +}; + +const SidebarItem: FC = ({ + url, + title, + isActive = false, +}) => ( +
  • + {title} +
  • +); + +export default SidebarItem; diff --git a/components/Common/Sidebar/index.module.css b/components/Common/Sidebar/index.module.css new file mode 100644 index 000000000000..a282849847d9 --- /dev/null +++ b/components/Common/Sidebar/index.module.css @@ -0,0 +1,15 @@ +.sideBar { + @apply flex + flex-col + items-start + gap-8 + overflow-auto + border-r + border-r-neutral-200 + bg-white + px-4 + py-6 + dark:border-r-neutral-900 + dark:bg-neutral-950 + md:max-w-xs; +} diff --git a/components/Common/Sidebar/index.stories.tsx b/components/Common/Sidebar/index.stories.tsx new file mode 100644 index 000000000000..59a5da132053 --- /dev/null +++ b/components/Common/Sidebar/index.stories.tsx @@ -0,0 +1,160 @@ +import type { Meta as MetaObj, StoryObj } from '@storybook/react'; + +import Sidebar from '@/components/Common/Sidebar'; + +type Story = StoryObj; +type Meta = MetaObj; + +export const Default: Story = { + args: { + groups: [ + { + groupName: 'About Node.js', + items: [ + { + url: '/item1', + title: 'About Node.js', + }, + { + url: '/item2', + title: 'Project Governance', + }, + { + url: '/item3', + title: 'Releases', + }, + { + url: '/item4', + title: 'Branding', + }, + { + url: '/item5', + title: 'Privacy Policy', + }, + { + url: '/item6', + title: 'Security Reporting', + }, + ], + }, + { + groupName: 'Get Involved', + items: [ + { + url: '/item7', + title: 'Get Involved', + }, + { + url: '/item8', + title: 'Collab Summit', + }, + { + url: '/item9', + title: 'Contribute', + }, + { + url: '/item10', + title: 'Code of Conduct', + }, + ], + }, + { + groupName: 'Download', + items: [ + { + url: '/item11', + title: 'Download', + }, + { + url: '/item12', + title: 'Package Manager', + }, + { + url: '/item13', + title: 'Previous Releases', + }, + ], + }, + ], + }, +}; + +export const ActiveItem: Story = { + args: { + groups: [ + { + groupName: 'About Node.js', + items: [ + { + url: '/item1', + title: 'About Node.js', + }, + { + url: '/item2', + title: 'Project Governance', + }, + { + url: '/item3', + title: 'Releases', + }, + { + url: '/item4', + title: 'Branding', + }, + { + url: '/item5', + title: 'Privacy Policy', + }, + { + url: '/item6', + title: 'Security Reporting', + }, + ], + }, + { + groupName: 'Get Involved', + items: [ + { + url: '/item7', + title: 'Get Involved', + }, + { + url: '/item8', + title: 'Collab Summit', + }, + { + url: '/item9', + title: 'Contribute', + }, + { + url: '/item10', + title: 'Code of Conduct', + }, + ], + }, + { + groupName: 'Download', + items: [ + { + url: '/item11', + title: 'Download', + }, + { + url: '/item12', + title: 'Package Manager', + }, + { + url: '/item13', + title: 'Previous Releases', + }, + ], + }, + ], + activeItem: { + url: '/item1', + title: 'About Node.js', + }, + }, +}; + +export default { component: Sidebar } as Meta; diff --git a/components/Common/Sidebar/index.tsx b/components/Common/Sidebar/index.tsx new file mode 100644 index 000000000000..f6538bf16892 --- /dev/null +++ b/components/Common/Sidebar/index.tsx @@ -0,0 +1,26 @@ +import type { ComponentProps, FC } from 'react'; + +import SidebarGroup from '@/components/Common/Sidebar/SidebarGroup'; +import type SidebarItem from '@/components/Common/Sidebar/SidebarItem'; + +import styles from './index.module.css'; + +type SidebarProps = { + groups: ComponentProps[]; + activeItem?: ComponentProps; +}; + +const SideBar: FC = ({ groups, activeItem }) => ( + +); + +export default SideBar; diff --git a/components/Downloads/DownloadReleasesTable.tsx b/components/Downloads/DownloadReleasesTable.tsx index 437c3d6ced7e..5610d14e811b 100644 --- a/components/Downloads/DownloadReleasesTable.tsx +++ b/components/Downloads/DownloadReleasesTable.tsx @@ -37,7 +37,7 @@ const DownloadReleasesTable: FC = () => { {release.modules} {t('components.downloadReleasesTable.releases')}