From 94a35ff8e045fafc4101f445ca3fd8ff8796b5ce Mon Sep 17 00:00:00 2001 From: Anass Bouassaba Date: Tue, 29 Oct 2024 15:10:03 +0100 Subject: [PATCH] wip: adding more components --- .github/workflows/check-on-pr.yml | 6 +- src/components/account-menu.tsx | 2 +- src/components/app-bar.tsx | 8 +- src/components/auxiliary-drawer.tsx | 4 +- src/components/index.ts | 2 +- .../layout-drawer/layout-drawer-context.ts | 4 +- .../layout-drawer/layout-drawer-item.tsx | 1 - .../layout-drawer/layout-drawer.tsx | 4 +- src/components/nav-bar.tsx | 85 +++++++++++ src/components/navigation-item.tsx | 42 ------ src/components/search-bar.tsx | 2 +- src/components/shell.tsx | 40 ++--- .../layout.stories.tsx} | 12 +- .../components/account-menu.stories.tsx | 37 +++++ src/stories/components/app-bar.stories.tsx | 141 ++++++++++++++++++ .../components/auxilary-drawer.stories.tsx | 30 ++++ .../logo.stories.tsx} | 5 +- src/stories/components/number-tag.stories.tsx | 16 ++ src/stories/components/search-bar.stories.tsx | 18 +++ src/stories/components/shell.stories.tsx | 58 +++++++ 20 files changed, 432 insertions(+), 85 deletions(-) create mode 100644 src/components/nav-bar.tsx delete mode 100644 src/components/navigation-item.tsx rename src/stories/{Shell.stories.tsx => bundles/layout.stories.tsx} (94%) create mode 100644 src/stories/components/account-menu.stories.tsx create mode 100644 src/stories/components/app-bar.stories.tsx create mode 100644 src/stories/components/auxilary-drawer.stories.tsx rename src/stories/{Logo.stories.tsx => components/logo.stories.tsx} (82%) create mode 100644 src/stories/components/number-tag.stories.tsx create mode 100644 src/stories/components/search-bar.stories.tsx create mode 100644 src/stories/components/shell.stories.tsx diff --git a/.github/workflows/check-on-pr.yml b/.github/workflows/check-on-pr.yml index ac25922..4dface5 100644 --- a/.github/workflows/check-on-pr.yml +++ b/.github/workflows/check-on-pr.yml @@ -5,8 +5,8 @@ on: branches: - main paths: - - "**" - - "!README.md" + - '**' + - '!README.md' jobs: lint: @@ -53,4 +53,4 @@ jobs: permissions: contents: read pull-requests: read - checks: write \ No newline at end of file + checks: write diff --git a/src/components/account-menu.tsx b/src/components/account-menu.tsx index 088b0a3..0f95176 100644 --- a/src/components/account-menu.tsx +++ b/src/components/account-menu.tsx @@ -123,7 +123,7 @@ type AvatarButtonProps = { const AvatarButton = forwardRef( ({ name, picture, isActive, hasBadge, ...props }, ref) => (
- + ( @@ -18,7 +18,9 @@ export const AppBar = ({ bar, buttons }: AppBarProps) => ( 'w-full', )} > -
{bar}
+
+ {bar} +
{buttons}
diff --git a/src/components/auxiliary-drawer.tsx b/src/components/auxiliary-drawer.tsx index c278076..77e280a 100644 --- a/src/components/auxiliary-drawer.tsx +++ b/src/components/auxiliary-drawer.tsx @@ -35,7 +35,7 @@ export const AuxiliaryDrawer = ({ }: AuxiliaryDrawerProps) => { const buttonRef = useRef(null) return ( - <> +
{footer} - +
) } diff --git a/src/components/index.ts b/src/components/index.ts index d0b9a91..e5465cf 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -13,6 +13,6 @@ export * from './text' export * from './logo' export * from './app-bar' export * from './auxiliary-drawer' -export * from './navigation-item' +export * from './nav-bar' export * from './search-bar' export * from './account-menu' diff --git a/src/components/layout-drawer/layout-drawer-context.ts b/src/components/layout-drawer/layout-drawer-context.ts index c382907..b42898e 100644 --- a/src/components/layout-drawer/layout-drawer-context.ts +++ b/src/components/layout-drawer/layout-drawer-context.ts @@ -1,11 +1,11 @@ import { createContext } from 'react' -export type DrawerContextType = { +export type LayoutDrawerContextType = { isCollapsed: boolean | undefined isTouched: boolean } -export const LayoutDrawerContext = createContext({ +export const LayoutDrawerContext = createContext({ isCollapsed: undefined, isTouched: false, }) diff --git a/src/components/layout-drawer/layout-drawer-item.tsx b/src/components/layout-drawer/layout-drawer-item.tsx index 9a8e68d..0fbf329 100644 --- a/src/components/layout-drawer/layout-drawer-item.tsx +++ b/src/components/layout-drawer/layout-drawer-item.tsx @@ -8,7 +8,6 @@ export type DrawerItemProps = { href: string primaryText: string secondaryText: string - isActive?: boolean pathnameFn: () => string navigateFn: (href: string) => void } diff --git a/src/components/layout-drawer/layout-drawer.tsx b/src/components/layout-drawer/layout-drawer.tsx index 6548c41..8fa8885 100644 --- a/src/components/layout-drawer/layout-drawer.tsx +++ b/src/components/layout-drawer/layout-drawer.tsx @@ -5,7 +5,7 @@ import { StorageOptions } from '../../types' import { IconChevronLeft, IconChevronRight } from '../icons' import { LayoutDrawerContext } from './layout-drawer-context' -export type DrawerProps = { +export type LayoutDrawerProps = { children?: ReactNode logo?: ReactNode storage?: StorageOptions @@ -19,7 +19,7 @@ export const LayoutDrawer = ({ logo, homeHref, navigateFn, -}: DrawerProps) => { +}: LayoutDrawerProps) => { const [isCollapsed, setIsCollapsed] = useState(undefined) const [isTouched, setIsTouched] = useState(false) const localStorageCollapsedKey = useMemo( diff --git a/src/components/nav-bar.tsx b/src/components/nav-bar.tsx new file mode 100644 index 0000000..0ee4d22 --- /dev/null +++ b/src/components/nav-bar.tsx @@ -0,0 +1,85 @@ +import { useEffect, useState } from 'react' +import { Link as ChakraLink } from '@chakra-ui/react' +import cx from 'classnames' + +export type NavBarProps = { + items: NavItem[] + pathnameFn: () => string + navigateFn: (href: string) => void +} + +export type NavItem = { + title: string + href: string + isActive?: boolean +} + +export const NavBar = ({ items, pathnameFn, navigateFn }: NavBarProps) => { + return ( +
+ {items + ? items.map((item, index) => ( + + )) + : null} +
+ ) +} + +type ItemProps = { + title: string + href: string + pathnameFn: () => string + navigateFn: (href: string) => void +} + +const Item = ({ title, href, pathnameFn, navigateFn }: ItemProps) => { + const pathname = pathnameFn() + const [isActive, setIsActive] = useState(false) + + useEffect(() => { + if ( + (href === '/' && pathname === '/') || + (href !== '/' && pathname.startsWith(href)) + ) { + setIsActive(true) + } else { + setIsActive(false) + } + }, [pathname, href]) + + return ( + navigateFn(href)} + > + {title} + + ) +} diff --git a/src/components/navigation-item.tsx b/src/components/navigation-item.tsx deleted file mode 100644 index 74c3ced..0000000 --- a/src/components/navigation-item.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { Link as ChakraLink } from '@chakra-ui/react' -import cx from 'classnames' -import { Link } from 'react-router-dom' - -export type NavigationItemProps = { - title: string - href: string - isActive: boolean -} - -export const NavigationItem = ({ - title, - href, - isActive, -}: NavigationItemProps) => ( - - {title} - -) diff --git a/src/components/search-bar.tsx b/src/components/search-bar.tsx index 8e26a3a..7f28ddd 100644 --- a/src/components/search-bar.tsx +++ b/src/components/search-bar.tsx @@ -75,7 +75,7 @@ export const SearchBar = ({ }, []) return ( -
+
diff --git a/src/components/shell.tsx b/src/components/shell.tsx index e6bb6a8..05fc23b 100644 --- a/src/components/shell.tsx +++ b/src/components/shell.tsx @@ -3,24 +3,24 @@ import cx from 'classnames' import { StorageOptions } from '../types' import { LayoutDrawer, LayoutDrawerItem } from './layout-drawer' -export type ShellItem = { - href: string - icon: ReactElement - primaryText: string - secondaryText: string -} - export type ShellProps = { storage?: StorageOptions logo: ReactElement topBar: ReactElement - items: ShellItem[] + items?: ShellItem[] children?: ReactElement onContentClick?: (event: MouseEvent) => void pathnameFn: () => string navigateFn: (href: string) => void } +export type ShellItem = { + href: string + icon: ReactElement + primaryText: string + secondaryText: string +} + export const Shell = ({ logo, topBar, @@ -33,17 +33,19 @@ export const Shell = ({ }: ShellProps) => (
- {items.map((item, index) => ( - - ))} + {items + ? items.map((item, index) => ( + + )) + : null}
= { - title: 'Components/Shell', + title: 'Bundles/Layout', component: Shell, parameters: { layout: 'fullscreen', @@ -32,7 +32,7 @@ const meta: Meta = { export default meta type Story = StoryObj -export const Default: Story = { +export const ShellWithAppBar: Story = { render: () => { const location = useLocation() const navigate = useNavigate() @@ -42,7 +42,7 @@ export const Default: Story = { return ( } topBar={ , primaryText: 'Workspaces', secondaryText: 'Isolated containers for files and folders.', @@ -143,7 +143,7 @@ export const Default: Story = { }, ]} pathnameFn={() => location.pathname} - navigateFn={(href: string) => navigate(href)} + navigateFn={navigate} > ) }, diff --git a/src/stories/components/account-menu.stories.tsx b/src/stories/components/account-menu.stories.tsx new file mode 100644 index 0000000..2ac23e0 --- /dev/null +++ b/src/stories/components/account-menu.stories.tsx @@ -0,0 +1,37 @@ +import { MenuItem } from '@chakra-ui/react' +import { Meta, StoryObj } from '@storybook/react' +import cx from 'classnames' +import { Link } from 'react-router-dom' +import { AccountMenu, NumberTag } from '../../components' + +const meta: Meta = { + title: 'Components/Account Menu', + component: AccountMenu, +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: { + name: 'Bruce Wayne', + email: 'bruce.wayne@koupr.com', + hasBadge: true, + menuItems: ( + <> + + Settings + + +
+ Invitations + 5 +
+
+ + Sign Out + + + ), + }, +} diff --git a/src/stories/components/app-bar.stories.tsx b/src/stories/components/app-bar.stories.tsx new file mode 100644 index 0000000..990f486 --- /dev/null +++ b/src/stories/components/app-bar.stories.tsx @@ -0,0 +1,141 @@ +import { useState } from 'react' +import { IconButton } from '@chakra-ui/react' +import { Meta, StoryObj } from '@storybook/react' +import { useLocation, useNavigate } from 'react-router-dom' +import { + AppBar, + IconAdmin, + IconStacks, + IconTune, + IconUpload, + NavBar, + SearchBar, +} from '../../components' + +const meta: Meta = { + title: 'Components/App Bar', + component: AppBar, + parameters: { + layout: 'fullscreen', + }, +} + +export default meta +type Story = StoryObj + +export const WithNavBar: Story = { + render: (args) => { + const location = useLocation() + const navigate = useNavigate() + + return ( + location.pathname} + navigateFn={navigate} + /> + } + buttons={ + <> + } aria-label="Cloud Console" /> + } aria-label="Uploads" /> + } aria-label="Tasks" /> + + } + /> + ) + }, +} + +export const WithSearchBar: Story = { + render: (args) => { + const [query, setQuery] = useState('') + return ( + } aria-label="Filters" />} + onSearch={(value) => setQuery(value)} + onClear={() => setQuery('')} + /> + } + buttons={ + <> + } aria-label="Cloud Console" /> + } aria-label="Uploads" /> + } aria-label="Tasks" /> + + } + /> + ) + }, +} + +export const WithBoth: Story = { + render: (args) => { + const location = useLocation() + const navigate = useNavigate() + const [query, setQuery] = useState('') + + return ( + + location.pathname} + navigateFn={navigate} + /> + } aria-label="Filters" />} + onSearch={(value) => setQuery(value)} + onClear={() => setQuery('')} + /> + + } + buttons={ + <> + } aria-label="Cloud Console" /> + } aria-label="Uploads" /> + } aria-label="Tasks" /> + + } + /> + ) + }, +} diff --git a/src/stories/components/auxilary-drawer.stories.tsx b/src/stories/components/auxilary-drawer.stories.tsx new file mode 100644 index 0000000..a3f4f93 --- /dev/null +++ b/src/stories/components/auxilary-drawer.stories.tsx @@ -0,0 +1,30 @@ +import { useDisclosure } from '@chakra-ui/react' +import { Meta, StoryObj } from '@storybook/react' +import { AuxiliaryDrawer, IconStacks } from '../../components' + +const meta: Meta = { + title: 'Components/Auxiliary Drawer', + component: AuxiliaryDrawer, +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: { + icon: , + header: 'Tasks', + body: <>, + }, + render: (args) => { + const { isOpen, onOpen, onClose } = useDisclosure() + return ( + + ) + }, +} diff --git a/src/stories/Logo.stories.tsx b/src/stories/components/logo.stories.tsx similarity index 82% rename from src/stories/Logo.stories.tsx rename to src/stories/components/logo.stories.tsx index 4f0b711..c03c92c 100644 --- a/src/stories/Logo.stories.tsx +++ b/src/stories/components/logo.stories.tsx @@ -1,16 +1,17 @@ import { Meta, StoryObj } from '@storybook/react' -import { Logo } from '../components' +import { Logo } from '../../components' const meta: Meta = { title: 'Components/Logo', component: Logo, } + export default meta type Story = StoryObj export const Default: Story = { args: { type: 'voltaserve', - size: 'md', + size: 'sm', }, } diff --git a/src/stories/components/number-tag.stories.tsx b/src/stories/components/number-tag.stories.tsx new file mode 100644 index 0000000..dbab59e --- /dev/null +++ b/src/stories/components/number-tag.stories.tsx @@ -0,0 +1,16 @@ +import { Meta, StoryObj } from '@storybook/react' +import { NumberTag } from '../../components' + +const meta: Meta = { + title: 'Components/Number Tag', + component: NumberTag, +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: { + children: '1', + }, +} diff --git a/src/stories/components/search-bar.stories.tsx b/src/stories/components/search-bar.stories.tsx new file mode 100644 index 0000000..2e77c1c --- /dev/null +++ b/src/stories/components/search-bar.stories.tsx @@ -0,0 +1,18 @@ +import { IconButton } from '@chakra-ui/react' +import { Meta, StoryObj } from '@storybook/react' +import { IconTune, SearchBar } from '../../components' + +const meta: Meta = { + title: 'Components/Search Bar', + component: SearchBar, +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: { + placeholder: 'Search', + buttons: } aria-label="Filters" />, + }, +} diff --git a/src/stories/components/shell.stories.tsx b/src/stories/components/shell.stories.tsx new file mode 100644 index 0000000..a038028 --- /dev/null +++ b/src/stories/components/shell.stories.tsx @@ -0,0 +1,58 @@ +import { Meta, StoryObj } from '@storybook/react' +import { useLocation, useNavigate } from 'react-router-dom' +import { + IconFlag, + IconGroup, + IconWorkspaces, + Logo, + Shell, +} from '../../components' + +const meta: Meta = { + title: 'Components/Shell', + component: Shell, + parameters: { + layout: 'fullscreen', + }, +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: { + storage: { prefix: 'shell', namespace: 'main' }, + logo: , + items: [ + { + href: '/', + icon: , + primaryText: 'Workspaces', + secondaryText: 'Isolated containers for files and folders.', + }, + { + href: '/group', + icon: , + primaryText: 'Groups', + secondaryText: 'Allows assigning permissions to a group of users.', + }, + { + href: '/organizations', + icon: , + primaryText: 'Organizations', + secondaryText: 'Umbrellas for workspaces and users.', + }, + ], + }, + render: (args) => { + const location = useLocation() + const navigate = useNavigate() + return ( + location.pathname} + navigateFn={(href: string) => navigate(href)} + /> + ) + }, +}