From bacfc7890f18bade3d0a98baef16f188877d8431 Mon Sep 17 00:00:00 2001 From: Kushal <44560227+ksolanki7@users.noreply.github.com> Date: Tue, 10 Dec 2024 09:52:44 +1100 Subject: [PATCH 01/14] feat: #218 v5 Table Container and Table Toolbar (#234) * Initial commit - Table Container / Table Toolbar * feat: #218 v5 Table Container and Toolbar * Rename folder/file name to hypen case * Fix issue with import names in mdx file --- src/components/skeleton/styles.ts | 2 +- .../table-container.test.tsx.snap | 24 ++++ .../__tests__/table-container.test.tsx | 14 ++ src/components/table/table-container/index.ts | 2 + .../table/table-container/styles.ts | 3 + .../table/table-container/table-container.mdx | 13 ++ .../table-container.stories.tsx | 51 +++++++ .../table/table-container/table-container.tsx | 10 ++ .../__snapshots__/table-toolbar.test.tsx.snap | 20 +++ .../__tests__/table-toolbar.test.tsx | 9 ++ src/components/table/table-toolbar/index.ts | 2 + src/components/table/table-toolbar/styles.ts | 24 ++++ .../table/table-toolbar/table-toolbar.mdx | 33 +++++ .../table-toolbar/table-toolbar.stories.tsx | 128 ++++++++++++++++++ .../table/table-toolbar/table-toolbar.tsx | 16 +++ src/index.ts | 2 + 16 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 src/components/table/table-container/__tests__/__snapshots__/table-container.test.tsx.snap create mode 100644 src/components/table/table-container/__tests__/table-container.test.tsx create mode 100644 src/components/table/table-container/index.ts create mode 100644 src/components/table/table-container/styles.ts create mode 100644 src/components/table/table-container/table-container.mdx create mode 100644 src/components/table/table-container/table-container.stories.tsx create mode 100644 src/components/table/table-container/table-container.tsx create mode 100644 src/components/table/table-toolbar/__tests__/__snapshots__/table-toolbar.test.tsx.snap create mode 100644 src/components/table/table-toolbar/__tests__/table-toolbar.test.tsx create mode 100644 src/components/table/table-toolbar/index.ts create mode 100644 src/components/table/table-toolbar/styles.ts create mode 100644 src/components/table/table-toolbar/table-toolbar.mdx create mode 100644 src/components/table/table-toolbar/table-toolbar.stories.tsx create mode 100644 src/components/table/table-toolbar/table-toolbar.tsx diff --git a/src/components/skeleton/styles.ts b/src/components/skeleton/styles.ts index 108d9fa6..869c58b3 100644 --- a/src/components/skeleton/styles.ts +++ b/src/components/skeleton/styles.ts @@ -1,7 +1,7 @@ import { styled } from '@linaria/react' export const ElSkeleton = styled.span` - display: inline-block; + display: flex; background: var(--fill-default-light, #e5e9ed); animation: blink 1.5s infinite; diff --git a/src/components/table/table-container/__tests__/__snapshots__/table-container.test.tsx.snap b/src/components/table/table-container/__tests__/__snapshots__/table-container.test.tsx.snap new file mode 100644 index 00000000..4289fe2c --- /dev/null +++ b/src/components/table/table-container/__tests__/__snapshots__/table-container.test.tsx.snap @@ -0,0 +1,24 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Table Container > should match snapshot 1`] = ` + +
+
+
+ 125 Properties +
+
+ Page Size menu component goes here +
+
+
+
+`; diff --git a/src/components/table/table-container/__tests__/table-container.test.tsx b/src/components/table/table-container/__tests__/table-container.test.tsx new file mode 100644 index 00000000..ef86e16a --- /dev/null +++ b/src/components/table/table-container/__tests__/table-container.test.tsx @@ -0,0 +1,14 @@ +import { render } from '@testing-library/react' +import { TableContainer } from '../index' +import { TableToolbar } from '../../table-toolbar' + +describe('Table Container', () => { + test('should match snapshot', () => { + const { asFragment } = render( + + + , + ) + expect(asFragment()).toMatchSnapshot() + }) +}) diff --git a/src/components/table/table-container/index.ts b/src/components/table/table-container/index.ts new file mode 100644 index 00000000..faa6cc2a --- /dev/null +++ b/src/components/table/table-container/index.ts @@ -0,0 +1,2 @@ +export * from './styles' +export * from './table-container' diff --git a/src/components/table/table-container/styles.ts b/src/components/table/table-container/styles.ts new file mode 100644 index 00000000..81ca4401 --- /dev/null +++ b/src/components/table/table-container/styles.ts @@ -0,0 +1,3 @@ +import { styled } from '@linaria/react' + +export const ElTableContainer = styled.div`` diff --git a/src/components/table/table-container/table-container.mdx b/src/components/table/table-container/table-container.mdx new file mode 100644 index 00000000..e5ddcb2f --- /dev/null +++ b/src/components/table/table-container/table-container.mdx @@ -0,0 +1,13 @@ +import { Meta, Canvas, Controls } from '@storybook/blocks' +import { RenderHtmlMarkup } from '../../../storybook/render-html-markup' +import * as TableContainerStories from './table-container.stories' + + + +# Table Container + +## Basic Usage + + + + diff --git a/src/components/table/table-container/table-container.stories.tsx b/src/components/table/table-container/table-container.stories.tsx new file mode 100644 index 00000000..745056c8 --- /dev/null +++ b/src/components/table/table-container/table-container.stories.tsx @@ -0,0 +1,51 @@ +import { Meta } from '@storybook/react' +// import { figmaDesignUrls } from '../../storybook/figma' +import { TableContainer } from './table-container' +import { TableToolbar } from '../table-toolbar' +import { Menu, MenuItem, MenuItemGroup, MenuList } from '../../menu' +import { MenuPopover, MenuTrigger } from '#src/components/menu/menu-popover' +import { Button } from '../../button' +import { Icon } from '../../icon' + +const meta: Meta = { + title: 'Components/TableContainer', + component: TableContainer, +} + +export default meta + +export const BasicUsage = { + render: ({}) => ( + + + + {({ getTriggerProps }) => ( + // To do: Once Button component is update with more props for no-padding, please make updates here + + )} + + + + + 25 + 50 + 100 + + + + + } + /> + + ), +} diff --git a/src/components/table/table-container/table-container.tsx b/src/components/table/table-container/table-container.tsx new file mode 100644 index 00000000..17685b58 --- /dev/null +++ b/src/components/table/table-container/table-container.tsx @@ -0,0 +1,10 @@ +import { HTMLAttributes, ReactNode } from 'react' +import { ElTableContainer } from './styles' + +interface TableContainerProps extends HTMLAttributes { + children: ReactNode +} + +export const TableContainer: React.FC = ({ children, ...rest }) => { + return {children} +} diff --git a/src/components/table/table-toolbar/__tests__/__snapshots__/table-toolbar.test.tsx.snap b/src/components/table/table-toolbar/__tests__/__snapshots__/table-toolbar.test.tsx.snap new file mode 100644 index 00000000..0b971cc2 --- /dev/null +++ b/src/components/table/table-toolbar/__tests__/__snapshots__/table-toolbar.test.tsx.snap @@ -0,0 +1,20 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Table Toolbar > should match snapshot 1`] = ` + +
+
+ 125 Properties +
+
+ Page Size menu +
+
+
+`; diff --git a/src/components/table/table-toolbar/__tests__/table-toolbar.test.tsx b/src/components/table/table-toolbar/__tests__/table-toolbar.test.tsx new file mode 100644 index 00000000..f59d614f --- /dev/null +++ b/src/components/table/table-toolbar/__tests__/table-toolbar.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@testing-library/react' +import { TableToolbar } from '../index' + +describe('Table Toolbar', () => { + test('should match snapshot', () => { + const { asFragment } = render() + expect(asFragment()).toMatchSnapshot() + }) +}) diff --git a/src/components/table/table-toolbar/index.ts b/src/components/table/table-toolbar/index.ts new file mode 100644 index 00000000..ebf191de --- /dev/null +++ b/src/components/table/table-toolbar/index.ts @@ -0,0 +1,2 @@ +export * from './styles' +export * from './table-toolbar' diff --git a/src/components/table/table-toolbar/styles.ts b/src/components/table/table-toolbar/styles.ts new file mode 100644 index 00000000..8a113ca2 --- /dev/null +++ b/src/components/table/table-toolbar/styles.ts @@ -0,0 +1,24 @@ +import { styled } from '@linaria/react' + +export const ElTableToolbar = styled.div` + display: flex; + width: 100%; + background: var(--fill-white); + padding: var(--spacing-2) 0px var(--spacing-2) 0px; + gap: 0px; + justify-content: space-between; + align-items: center; +` + +export const ElTableToolbarDescription = styled.div` + font-family: var(--font-family); + font-size: var(--font-size-sm); + font-weight: 400; + color: var(--text-colour-text-primary); + line-height: var(--line-height-sm); + letter-spacing: var(--letter-spacing-sm); + text-align: left; + gap: var(--spacing-1); +` + +export const ElTableToolbarActions = styled.div`` diff --git a/src/components/table/table-toolbar/table-toolbar.mdx b/src/components/table/table-toolbar/table-toolbar.mdx new file mode 100644 index 00000000..08105321 --- /dev/null +++ b/src/components/table/table-toolbar/table-toolbar.mdx @@ -0,0 +1,33 @@ +import { Meta, Canvas, Controls, Description } from '@storybook/blocks' +import { RenderHtmlMarkup } from '../../../storybook/render-html-markup' +import * as TableToolbarStories from './table-toolbar.stories' + + + +# Table Toolbar + + + +## Basic Usage + + + + + + + +## With Bulk Actions + + + + + + + +## Toolbar Skeleton + + + + + + diff --git a/src/components/table/table-toolbar/table-toolbar.stories.tsx b/src/components/table/table-toolbar/table-toolbar.stories.tsx new file mode 100644 index 00000000..d64b3fdf --- /dev/null +++ b/src/components/table/table-toolbar/table-toolbar.stories.tsx @@ -0,0 +1,128 @@ +import { Meta } from '@storybook/react' +// import { figmaDesignUrls } from '../../storybook/figma' +import { TableToolbar } from './table-toolbar.js' +import { Button } from '#src/components/button/button' +import { Icon } from '#src/components/icon/icon-component' +import { Menu } from '#src/components/menu/menu' +import { MenuPopover, MenuTrigger } from '#src/components/menu/menu-popover' +import { MenuItem, MenuItemGroup, MenuList } from '#src/components/menu/menu.atoms' +import { ButtonGroup } from '#src/components/button-group/button-group' +import { Skeleton } from '#src/components/skeleton/skeleton' + +const meta: Meta = { + title: 'Components/TableToolbar', + component: TableToolbar, +} + +export default meta + +/** A simple toolbar for tables. + * When no items are selected, it displays the total item count and default actions. + */ + +export const BasicUsage = { + render: ({}) => ( + + + {({ getTriggerProps }) => ( + // To do: Once Button component is update with more props for no-padding, please make updates here + + )} + + + + + 25 + 50 + 100 + + + + + } + /> + ), +} + +/** + * In tables with batch actions, when one or more items have been selected, + * the toolbar changes to display the number of selected items and the available actions + */ +export const WithBulkActions = { + render: ({}) => ( + + + + + + + {({ getTriggerProps }) => ( + + + } + /> + ), +} + +/** Skeleton state for the table toolbar + * To display until the data is retrieved and rendered in tabel + */ + +export const ToolbarSkeleton = { + render: ({}) => ( + } + actions={ + + + {({ getTriggerProps }) => ( + // To do: Once Button component is update with more props for no-padding, please make updates here + + )} + + + + + 25 + 50 + 100 + + + + + } + /> + ), +} diff --git a/src/components/table/table-toolbar/table-toolbar.tsx b/src/components/table/table-toolbar/table-toolbar.tsx new file mode 100644 index 00000000..7333923e --- /dev/null +++ b/src/components/table/table-toolbar/table-toolbar.tsx @@ -0,0 +1,16 @@ +import { HTMLAttributes, ReactNode } from 'react' +import { ElTableToolbar, ElTableToolbarActions, ElTableToolbarDescription } from './styles' + +interface TableToolbarProps extends HTMLAttributes { + description?: ReactNode + actions?: ReactNode +} + +export const TableToolbar: React.FC = ({ description, actions }) => { + return ( + + {description} + {actions} + + ) +} diff --git a/src/index.ts b/src/index.ts index 7b9e7339..7993408d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -57,6 +57,8 @@ export * from './components/menu' export * from './components/dialog' export * from './components/avatar' export * from './components/skeleton' +export * from './components/table/table-container' +export * from './components/table/table-toolbar' export * from './hooks/use-portal' export * from './hooks/use-snack' From 76eb8dc6a51695b844a60bb0731b394315c4330e Mon Sep 17 00:00:00 2001 From: Kushal <44560227+ksolanki7@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:00:29 +1100 Subject: [PATCH 02/14] fix: #249 using correct size variables matching DS figma (#250) * fix: #249 using correct size variables matching DS figma * Updated usage of size variable across the repo with correct values reflecting DS figma --- src/components/avatar-rectangle/styles.ts | 10 +++--- src/components/avatar/styles.ts | 8 ++--- src/components/bottom-bar-item/styles.ts | 4 +-- src/components/mobile-nav-item/styles.ts | 4 +-- src/components/nav-icon-item/styles.ts | 4 +-- src/components/top-bar/styles.ts | 2 +- src/tokens/build.mjs | 6 ++-- src/tokens/payprop/tokens.css | 29 ++++++++-------- src/tokens/payprop/tokens.ts | 29 ++++++++-------- src/tokens/reapit/tokens.css | 29 ++++++++-------- src/tokens/reapit/tokens.ts | 29 ++++++++-------- src/tokens/tokens.json | 40 ++++++++++++++++------- 12 files changed, 112 insertions(+), 82 deletions(-) diff --git a/src/components/avatar-rectangle/styles.ts b/src/components/avatar-rectangle/styles.ts index 5f42b9bd..be2e8022 100644 --- a/src/components/avatar-rectangle/styles.ts +++ b/src/components/avatar-rectangle/styles.ts @@ -7,23 +7,23 @@ import CommercialBottomImage from './icons/bottom-commercial-image.svg?react' import CommercialSmallBottomImage from './icons/bottom-commercial-image-small.svg?react' const baseAvatarRectMediumSize = ` - width: var(--size-size-12, 72px); + width: var(--size-18); height: 54px; ` const baseAvatarRectSmallSize = ` - width: var(--size-size-11, 64px); - height: var(--size-size-9, 48px); + width: var(--size-16); + height: var(--size-12); ` // The commercial consists of two sections: the commercial image and the bottom placeholder. const baseCommercialMediumImagesSize = ` width: 54px; - height: var(--size-size-8, 40px); + height: var(--size-10); ` const baseCommercialBottomSmallPlaceholderSize = ` - width: var(--size-size-9, 48px); + width: var(--size-12); height: 36px; ` diff --git a/src/components/avatar/styles.ts b/src/components/avatar/styles.ts index d017e0bf..8a9e4a07 100644 --- a/src/components/avatar/styles.ts +++ b/src/components/avatar/styles.ts @@ -5,8 +5,8 @@ const baseCircleStyle = ` ` const baseMediumSizeStyle = ` - width: var(--size-8, 40px); - height: var(--size-8, 40px); + width: var(--size-10); + height: var(--size-10); font-size: var(--font-size-base, 15px); line-height: var(--line-height-base, 24px); letter-spacing: var(--letter-spacing-base, -0.15px); @@ -50,8 +50,8 @@ export const ElAvatar = styled.span` } &[data-size='small'] { - width: var(--size-7, 32px); - height: var(--size-7, 32px); + width: var(--size-8); + height: var(--size-8); font-size: var(--font-size-2xs, 12px); line-height: var(--line-height-2xs, 16px); letter-spacing: var(--letter-spacing-2xs, -0.12px); diff --git a/src/components/bottom-bar-item/styles.ts b/src/components/bottom-bar-item/styles.ts index d52dc753..d1e76d5d 100644 --- a/src/components/bottom-bar-item/styles.ts +++ b/src/components/bottom-bar-item/styles.ts @@ -48,8 +48,8 @@ export const ElBottomBarItemBadge = styled.span` position: absolute; top: -3px; right: -3px; - width: var(--size-2, 8px); - height: var(--size-2, 8px); + width: var(--size-2); + height: var(--size-2); background-color: var(--icon-error, #f01830); border-radius: 100%; ` diff --git a/src/components/mobile-nav-item/styles.ts b/src/components/mobile-nav-item/styles.ts index 3bf272ab..8becdc2e 100644 --- a/src/components/mobile-nav-item/styles.ts +++ b/src/components/mobile-nav-item/styles.ts @@ -55,8 +55,8 @@ export const ElMobileNavItemContent = styled.span` export const ElMobileNavItemBadge = styled.span` display: block; - width: var(--size-2, 8px); - height: var(--size-2, 8px); + width: var(--size-2); + height: var(--size-2); background-color: var(--icon-error, #f01830); border-radius: 100%; ` diff --git a/src/components/nav-icon-item/styles.ts b/src/components/nav-icon-item/styles.ts index ecb44b43..8c88f7fb 100644 --- a/src/components/nav-icon-item/styles.ts +++ b/src/components/nav-icon-item/styles.ts @@ -41,8 +41,8 @@ export const ElNavIconItemBadge = styled.span` position: absolute; right: 5px; top: 5px; - width: var(--size-2, 8px); - height: var(--size-2, 8px); + width: var(--size-2); + height: var(--size-2); background-color: var(--icon-error, #f01830); border-radius: 100%; ` diff --git a/src/components/top-bar/styles.ts b/src/components/top-bar/styles.ts index fadffe93..2acacd26 100644 --- a/src/components/top-bar/styles.ts +++ b/src/components/top-bar/styles.ts @@ -29,7 +29,7 @@ export const ElTopBarSecondaryNav = styled(ElButtonGroup)` export const ElTopBar = styled.div` display: flex; align-items: center; - height: var(--size-10, 56px); + height: var(--size-14); padding: var(--spacing-2, 8px) var(--spacing-5, 20px); border-bottom: var(--border-default, 1px) solid var(--outline-default, #e5e9ed); background: var(--fill-white, #fff); diff --git a/src/tokens/build.mjs b/src/tokens/build.mjs index dd29167c..55fc9044 100644 --- a/src/tokens/build.mjs +++ b/src/tokens/build.mjs @@ -5,7 +5,7 @@ const themes = ['Reapit', 'PayProp'] const getStyleDictionaryConfig = (theme) => { const lowerCasedTheme = theme.toLowerCase() return { - source: ['./tokens/tokens.json'], + source: ['./src/tokens/tokens.json'], parsers: [ { pattern: /\.json$/, @@ -27,7 +27,7 @@ const getStyleDictionaryConfig = (theme) => { ], platforms: { css: { - buildPath: `tokens/${lowerCasedTheme}/`, + buildPath: `src/tokens/${lowerCasedTheme}/`, files: [ { destination: 'tokens.css', @@ -36,7 +36,7 @@ const getStyleDictionaryConfig = (theme) => { ], }, ts: { - buildPath: `tokens/${lowerCasedTheme}/`, + buildPath: `src/tokens/${lowerCasedTheme}/`, files: [ { destination: 'tokens.ts', diff --git a/src/tokens/payprop/tokens.css b/src/tokens/payprop/tokens.css index 7e36fcdc..e7568429 100644 --- a/src/tokens/payprop/tokens.css +++ b/src/tokens/payprop/tokens.css @@ -1,6 +1,6 @@ /** * Do not edit directly - * Generated on Tue, 02 Jul 2024 10:36:54 GMT + * Generated on Tue, 10 Dec 2024 06:08:05 GMT */ :root { @@ -281,18 +281,21 @@ --size-4: 1rem; --size-5: 1.25rem; --size-6: 1.5rem; - --size-7: 2rem; - --size-8: 2.5rem; - --size-9: 3rem; - --size-10: 3.5rem; - --size-11: 4rem; - --size-12: 4.5rem; - --size-13: 5rem; - --size-14: 6rem; - --size-15: 7rem; - --size-16: 8rem; - --size-17: 9rem; - --size-18: 10rem; + --size-7: 1.75rem; + --size-8: 2rem; + --size-9: 2.25rem; + --size-10: 2.5rem; + --size-11: 2.75rem; + --size-12: 3rem; + --size-14: 3.5rem; + --size-16: 4rem; + --size-18: 4.5rem; + --size-20: 5rem; + --size-24: 6rem; + --size-28: 7rem; + --size-32: 8rem; + --size-36: 9rem; + --size-40: 10rem; --size-px: 0.0625rem; --icon-xs: 0.75rem; --icon-sm: 1rem; diff --git a/src/tokens/payprop/tokens.ts b/src/tokens/payprop/tokens.ts index d13e90dc..6f853b27 100644 --- a/src/tokens/payprop/tokens.ts +++ b/src/tokens/payprop/tokens.ts @@ -1,6 +1,6 @@ /** * Do not edit directly - * Generated on Tue, 02 Jul 2024 10:36:54 GMT + * Generated on Tue, 10 Dec 2024 06:08:05 GMT */ export const neutral900 = '#222b33' @@ -280,18 +280,21 @@ export const sizeSize3 = '0.75rem' export const sizeSize4 = '1rem' export const sizeSize5 = '1.25rem' export const sizeSize6 = '1.5rem' -export const sizeSize7 = '2rem' -export const sizeSize8 = '2.5rem' -export const sizeSize9 = '3rem' -export const sizeSize10 = '3.5rem' -export const sizeSize11 = '4rem' -export const sizeSize12 = '4.5rem' -export const sizeSize13 = '5rem' -export const sizeSize14 = '6rem' -export const sizeSize15 = '7rem' -export const sizeSize16 = '8rem' -export const sizeSize17 = '9rem' -export const sizeSize18 = '10rem' +export const sizeSize7 = '1.75rem' +export const sizeSize8 = '2rem' +export const sizeSize9 = '2.25rem' +export const sizeSize10 = '2.5rem' +export const sizeSize11 = '2.75rem' +export const sizeSize12 = '3rem' +export const sizeSize14 = '3.5rem' +export const sizeSize16 = '4rem' +export const sizeSize18 = '4.5rem' +export const sizeSize20 = '5rem' +export const sizeSize24 = '6rem' +export const sizeSize28 = '7rem' +export const sizeSize32 = '8rem' +export const sizeSize36 = '9rem' +export const sizeSize40 = '10rem' export const sizeSizePx = '0.0625rem' export const iconSizeIconXs = '0.75rem' export const iconSizeIconSm = '1rem' diff --git a/src/tokens/reapit/tokens.css b/src/tokens/reapit/tokens.css index 7e36fcdc..e7568429 100644 --- a/src/tokens/reapit/tokens.css +++ b/src/tokens/reapit/tokens.css @@ -1,6 +1,6 @@ /** * Do not edit directly - * Generated on Tue, 02 Jul 2024 10:36:54 GMT + * Generated on Tue, 10 Dec 2024 06:08:05 GMT */ :root { @@ -281,18 +281,21 @@ --size-4: 1rem; --size-5: 1.25rem; --size-6: 1.5rem; - --size-7: 2rem; - --size-8: 2.5rem; - --size-9: 3rem; - --size-10: 3.5rem; - --size-11: 4rem; - --size-12: 4.5rem; - --size-13: 5rem; - --size-14: 6rem; - --size-15: 7rem; - --size-16: 8rem; - --size-17: 9rem; - --size-18: 10rem; + --size-7: 1.75rem; + --size-8: 2rem; + --size-9: 2.25rem; + --size-10: 2.5rem; + --size-11: 2.75rem; + --size-12: 3rem; + --size-14: 3.5rem; + --size-16: 4rem; + --size-18: 4.5rem; + --size-20: 5rem; + --size-24: 6rem; + --size-28: 7rem; + --size-32: 8rem; + --size-36: 9rem; + --size-40: 10rem; --size-px: 0.0625rem; --icon-xs: 0.75rem; --icon-sm: 1rem; diff --git a/src/tokens/reapit/tokens.ts b/src/tokens/reapit/tokens.ts index d13e90dc..6f853b27 100644 --- a/src/tokens/reapit/tokens.ts +++ b/src/tokens/reapit/tokens.ts @@ -1,6 +1,6 @@ /** * Do not edit directly - * Generated on Tue, 02 Jul 2024 10:36:54 GMT + * Generated on Tue, 10 Dec 2024 06:08:05 GMT */ export const neutral900 = '#222b33' @@ -280,18 +280,21 @@ export const sizeSize3 = '0.75rem' export const sizeSize4 = '1rem' export const sizeSize5 = '1.25rem' export const sizeSize6 = '1.5rem' -export const sizeSize7 = '2rem' -export const sizeSize8 = '2.5rem' -export const sizeSize9 = '3rem' -export const sizeSize10 = '3.5rem' -export const sizeSize11 = '4rem' -export const sizeSize12 = '4.5rem' -export const sizeSize13 = '5rem' -export const sizeSize14 = '6rem' -export const sizeSize15 = '7rem' -export const sizeSize16 = '8rem' -export const sizeSize17 = '9rem' -export const sizeSize18 = '10rem' +export const sizeSize7 = '1.75rem' +export const sizeSize8 = '2rem' +export const sizeSize9 = '2.25rem' +export const sizeSize10 = '2.5rem' +export const sizeSize11 = '2.75rem' +export const sizeSize12 = '3rem' +export const sizeSize14 = '3.5rem' +export const sizeSize16 = '4rem' +export const sizeSize18 = '4.5rem' +export const sizeSize20 = '5rem' +export const sizeSize24 = '6rem' +export const sizeSize28 = '7rem' +export const sizeSize32 = '8rem' +export const sizeSize36 = '9rem' +export const sizeSize40 = '10rem' export const sizeSizePx = '0.0625rem' export const iconSizeIconXs = '0.75rem' export const iconSizeIconSm = '1rem' diff --git a/src/tokens/tokens.json b/src/tokens/tokens.json index 751b5f64..5e95ad2c 100644 --- a/src/tokens/tokens.json +++ b/src/tokens/tokens.json @@ -647,72 +647,90 @@ "description": "Used for sizing shapes except icons. For icons use icon sizes" }, "size-7": { - "value": "{unit-8}", + "value": "{unit-7}", "type": "dimension", "parent": "Semantic variables/Reapit", "description": "Used for sizing shapes except icons. For icons use icon sizes" }, "size-8": { - "value": "{unit-10}", + "value": "{unit-8}", "type": "dimension", "parent": "Semantic variables/Reapit", "description": "Used for sizing shapes except icons. For icons use icon sizes" }, "size-9": { - "value": "{unit-12}", + "value": "{unit-9}", "type": "dimension", "parent": "Semantic variables/Reapit", "description": "Used for sizing shapes except icons. For icons use icon sizes" }, "size-10": { - "value": "{unit-14}", + "value": "{unit-10}", "type": "dimension", "parent": "Semantic variables/Reapit", "description": "Used for sizing shapes except icons. For icons use icon sizes" }, "size-11": { - "value": "{unit-16}", + "value": "{unit-11}", "type": "dimension", "parent": "Semantic variables/Reapit", "description": "Used for sizing shapes except icons. For icons use icon sizes" }, "size-12": { + "value": "{unit-12}", + "type": "dimension", + "parent": "Semantic variables/Reapit", + "description": "Used for sizing shapes except icons. For icons use icon sizes" + }, + "size-14": { + "value": "{unit-14}", + "type": "dimension", + "parent": "Semantic variables/Reapit", + "description": "Used for sizing shapes except icons. For icons use icon sizes" + }, + "size-16": { + "value": "{unit-16}", + "type": "dimension", + "parent": "Semantic variables/Reapit", + "description": "Used for sizing shapes except icons. For icons use icon sizes" + }, + "size-18": { "value": "{unit-18}", "type": "dimension", "parent": "Semantic variables/Reapit", "description": "Used for sizing shapes except icons. For icons use icon sizes" }, - "size-13": { + "size-20": { "value": "{unit-20}", "type": "dimension", "parent": "Semantic variables/Reapit", "description": "Used for sizing shapes except icons. For icons use icon sizes" }, - "size-14": { + "size-24": { "value": "{unit-24}", "type": "dimension", "parent": "Semantic variables/Reapit", "description": "Used for sizing shapes except icons. For icons use icon sizes" }, - "size-15": { + "size-28": { "value": "{unit-28}", "type": "dimension", "parent": "Semantic variables/Reapit", "description": "Used for sizing shapes except icons. For icons use icon sizes" }, - "size-16": { + "size-32": { "value": "{unit-32}", "type": "dimension", "parent": "Semantic variables/Reapit", "description": "Used for sizing shapes except icons. For icons use icon sizes" }, - "size-17": { + "size-36": { "value": "{unit-36}", "type": "dimension", "parent": "Semantic variables/Reapit", "description": "Used for sizing shapes except icons. For icons use icon sizes" }, - "size-18": { + "size-40": { "value": "{unit-40}", "type": "dimension", "parent": "Semantic variables/Reapit", From 9066a35247c91c38c04a6685fd6ce5ef6b1801d7 Mon Sep 17 00:00:00 2001 From: Nur M <106480336+nurm717123@users.noreply.github.com> Date: Fri, 13 Dec 2024 09:24:10 +0700 Subject: [PATCH 03/14] feat: #153 v5 top bar update docs (#240) * fix: update default top-bar popover y offset * feat: update docs to include different viewport --- src/components/top-bar/styles.ts | 10 +- src/components/top-bar/top-bar.mdx | 19 +- src/components/top-bar/top-bar.stories.tsx | 248 ++++++---- .../figma/guidelines-images/index.ts | 3 +- .../figma/guidelines-images/top-bar.svg | 442 ------------------ src/storybook/figma/index.tsx | 2 +- src/styles/media.ts | 4 +- 7 files changed, 172 insertions(+), 556 deletions(-) delete mode 100644 src/storybook/figma/guidelines-images/top-bar.svg diff --git a/src/components/top-bar/styles.ts b/src/components/top-bar/styles.ts index 2acacd26..e216a470 100644 --- a/src/components/top-bar/styles.ts +++ b/src/components/top-bar/styles.ts @@ -1,5 +1,5 @@ import { styled } from '@linaria/react' -import { isDesktop, isDesktopOrBelow, isTablet, isTabletOrBelow } from '../../styles/media' +import { isBelowWideScreen, isTablet, isBelowDesktop, isWideScreen } from '../../styles/media' import { ElButtonGroup } from '../button-group' import { css } from '@linaria/core' @@ -34,7 +34,7 @@ export const ElTopBar = styled.div` border-bottom: var(--border-default, 1px) solid var(--outline-default, #e5e9ed); background: var(--fill-white, #fff); - ${isDesktopOrBelow} { + ${isBelowWideScreen} { padding: var(--spacing-2, 8px) var(--spacing-4, 16px); ${ElTopBarLogo} { @@ -46,7 +46,7 @@ export const ElTopBar = styled.div` } } - ${isTabletOrBelow} { + ${isBelowDesktop} { ${ElTopBarProfile} { display: none; } @@ -66,7 +66,7 @@ export const ElTopBarMobileNav = styled.div` display: inline-block; padding-right: var(--spacing-2, 8px); - ${isDesktop} { + ${isWideScreen} { display: none; } ` @@ -74,5 +74,5 @@ export const ElTopBarMobileNav = styled.div` export const elTopBarMenuPopover = css` // To adjust the menu popover's Y offset so it appears below the top bar instead of directly below the button. // The "important" rule is used to override the Menu's auto-anchor yOffset. - top: 44px !important; + top: var(--spacing-10) !important; ` diff --git a/src/components/top-bar/top-bar.mdx b/src/components/top-bar/top-bar.mdx index 558ddd32..73a61247 100644 --- a/src/components/top-bar/top-bar.mdx +++ b/src/components/top-bar/top-bar.mdx @@ -1,24 +1,25 @@ import { Canvas, Controls, Meta } from '@storybook/blocks' import { RenderHtmlMarkup } from '../../storybook/render-html-markup' import * as TopBarStories from './top-bar.stories' -import { GuidelinesImage } from '../../storybook/figma' - +# Top bar -## Styles Only Usage +Top bar component is part of the element's navigation, It is composed of several components to easily create a top navigation structure. -To display `TopBar` with vanilla usage, you will need to compose your component using `.el-top-bar, .el-top-bar-main-nav, .el-top-bar-search, .el-top-bar-secondary-nav, and .el-top-bar-profile` classes as the example below. +## Default - +To display `TopBar` with vanilla usage, you will need to compose your component using `.el-top-bar, .el-top-bar-main-nav, .el-top-bar-search, .el-top-bar-secondary-nav, and .el-top-bar-profile` classes or respective component for each class for React usage as the example below. - + + + ## React Usage -In React version, you will need to use `TopBar` compound component to compose the `TopBar` as shown below. +In the React usage, you can utilize `CSSContainerQuery` component to conditionally render the Main navigation section based on the viewport size, as demonstrated below (on wider screens all buttons should visible). - + - + diff --git a/src/components/top-bar/top-bar.stories.tsx b/src/components/top-bar/top-bar.stories.tsx index 186b5fe1..cc8319fc 100644 --- a/src/components/top-bar/top-bar.stories.tsx +++ b/src/components/top-bar/top-bar.stories.tsx @@ -1,124 +1,127 @@ import { figmaDesignUrls } from '#src/storybook/figma/index' import type { Meta, StoryObj } from '@storybook/react' -import { ElAvatar } from '../avatar' -import { AvatarButton, ElAvatarButton } from '../avatar-button' +import { AvatarButton } from '../avatar-button' import { elIcon } from '../button' import { CSSContainerQuery } from '../container-query/container-query' import { Icon } from '../icon' -import { ElMenu, ElMenuItemAnchor, ElMenuItemButton, ElMenuList, ElMenuPopover, Menu } from '../menu' -import { ElNavDropdownButton, NavDropdownButton } from '../nav-dropdown-button' -import { ElButtonNavIconItem, NavIconItem } from '../nav-icon-item' -import { ElNavItemAnchor, ElNavItemLabelContainer, NavItem } from '../nav-item' +import { Menu } from '../menu' +import { NavDropdownButton } from '../nav-dropdown-button' +import { NavIconItem } from '../nav-icon-item' +import { NavItem } from '../nav-item' import { NavSearchButton } from '../nav-search-button/nav-search-button' -import { - ElNavSearchButton, - ElNavSearchButtonContainer, - ElNavSearchButtonIcon, - ElNavSearchButtonPlaceholder, - ElNavSearchButtonShortcutText, -} from '../nav-search-button/styles' import { ReapitLogo } from '../reapit-logo' -import reapitLogoIconUrl from '../reapit-logo/icons/brand-reapit.svg' import MenuIcon from './icons/menu-icon.svg?react' -import { - ElTopBar, - ElTopBarLogo, - ElTopBarMainNav, - ElTopBarMobileNav, - ElTopBarProfile, - ElTopBarSearch, - ElTopBarSecondaryNav, - elTopBarMenuPopover, -} from './styles' +import { elTopBarMenuPopover } from './styles' import { TopBar } from './top-bar' +import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport' + +const viewports: typeof INITIAL_VIEWPORTS = { + superWideScreen: { + name: 'Super Wide Screen', + type: 'desktop', + styles: { + width: '1920px', + height: '1500px', + }, + }, + wideScreen: { + name: 'Wide Screen', + type: 'desktop', + styles: { + width: '1440px', + height: '900px', + }, + }, + desktop: { + name: 'Desktop', + type: 'desktop', + styles: { + width: '1024px', + height: '900px', + }, + }, + ipad11p: INITIAL_VIEWPORTS.ipad11p, + iphone14: INITIAL_VIEWPORTS.iphone14, +} export default { title: 'Components/Top bar', component: TopBar, + parameters: { + viewport: { defaultViewport: 'responsive', viewports }, + }, } as Meta -export const StylesOnlyUsage: StoryObj = { +type Story = StoryObj + +export const Default: Story = { + // NOTE: this version is without `CSSContainerQuery` so the non react user doesn't see it in the docs render: () => { return ( - + + + + {({ getTriggerProps, isOpen }) => } + + + + User menu 1 + User menu 2 + User menu 3 + + + + + ) }, parameters: { design: { type: 'figma', url: figmaDesignUrls.appBar, + allowFullscreen: true, }, }, } -export const ReactUsage: StoryObj = { + +export const ResponsiveMainNav: Story = { render: () => { return ( @@ -166,12 +169,22 @@ export const ReactUsage: StoryObj = { - + + + {({ getTriggerProps, isOpen }) => } + + + + User menu 1 + User menu 2 + User menu 3 + + + ) }, - parameters: { design: { type: 'figma', @@ -180,3 +193,48 @@ export const ReactUsage: StoryObj = { }, }, } + +export const Mobile: Story = { + render: ResponsiveMainNav.render, + parameters: { + ...ResponsiveMainNav.parameters, + viewport: { defaultViewport: 'iphone14' }, + }, +} + +export const Tablet: Story = { + render: ResponsiveMainNav.render, + parameters: { + ...ResponsiveMainNav.parameters, + viewport: { defaultViewport: 'ipad11p' }, + }, +} +export const Desktop: Story = { + render: ResponsiveMainNav.render, + parameters: { + ...ResponsiveMainNav.parameters, + viewport: { + defaultViewport: 'desktop', + }, + }, +} + +export const WideScreen: Story = { + render: ResponsiveMainNav.render, + parameters: { + ...ResponsiveMainNav.parameters, + viewport: { + defaultViewport: 'wideScreen', + }, + }, +} + +export const SuperWideScreen: Story = { + render: ResponsiveMainNav.render, + parameters: { + ...ResponsiveMainNav.parameters, + viewport: { + defaultViewport: 'superWideScreen', + }, + }, +} diff --git a/src/storybook/figma/guidelines-images/index.ts b/src/storybook/figma/guidelines-images/index.ts index b0e8e769..cf2be470 100644 --- a/src/storybook/figma/guidelines-images/index.ts +++ b/src/storybook/figma/guidelines-images/index.ts @@ -1,7 +1,6 @@ import Accordion from './accordion.svg' import ButtonGroup from './button-group.svg' -import TopBar from './top-bar.svg' +// TODO: can delete this, as we're not planning to use Design Guidelines docs as a documentation for developer export { Accordion } -export { TopBar } export { ButtonGroup } diff --git a/src/storybook/figma/guidelines-images/top-bar.svg b/src/storybook/figma/guidelines-images/top-bar.svg deleted file mode 100644 index 40abdac1..00000000 --- a/src/storybook/figma/guidelines-images/top-bar.svg +++ /dev/null @@ -1,442 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/storybook/figma/index.tsx b/src/storybook/figma/index.tsx index d141b9db..199003c2 100644 --- a/src/storybook/figma/index.tsx +++ b/src/storybook/figma/index.tsx @@ -11,7 +11,7 @@ export const GuidelinesImage: FC = ({ name }) => ( export const figmaDesignUrls = { appBar: - 'https://www.figma.com/design/6CaivqdlTX0UkFYJkpBKDu/Reapit-DS?node-id=428-7209&node-type=frame&t=RHaBJeesRCccFe53-0', + 'https://www.figma.com/design/XJ6qcAV8gHscsUodqJMNEF/Reapit-Elements-production-ready-components?node-id=16-4840&m=dev', accordion: 'https://www.figma.com/design/6CaivqdlTX0UkFYJkpBKDu/Reapit-DS?node-id=141-4180&t=k8kHuB2wp3KZoKMw-4', buttonGroup: 'https://www.figma.com/design/6CaivqdlTX0UkFYJkpBKDu/Reapit-DS?node-id=428-7408&t=8GcgX59FmafMRAda-4', } diff --git a/src/styles/media.ts b/src/styles/media.ts index 5b494dc9..2bfdae1e 100644 --- a/src/styles/media.ts +++ b/src/styles/media.ts @@ -5,5 +5,5 @@ export const isWideScreen = '@media screen and (min-width: 1440px)' export const isSuperWideScreen = '@media screen and (min-width: 1920px)' export const is4KScreen = '@media screen and (min-width: 2560px)' -export const isDesktopOrBelow = '@media screen and (max-width: 1024px)' -export const isTabletOrBelow = '@media screen and (max-width: 768px)' +export const isBelowWideScreen = '@media screen and (max-width: 1439px)' +export const isBelowDesktop = '@media screen and (max-width: 1023px) ' From 48452c6e5ed894a86cb43625c07b4a165fe65dad Mon Sep 17 00:00:00 2001 From: Nur M <106480336+nurm717123@users.noreply.github.com> Date: Fri, 13 Dec 2024 13:28:39 +0700 Subject: [PATCH 04/14] chore: fix css var name and remove fallback value (#251) --- src/components/avatar-button/styles.ts | 4 ++-- src/components/avatar/styles.ts | 30 +++++++++++++------------- src/components/menu/styles.ts | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/components/avatar-button/styles.ts b/src/components/avatar-button/styles.ts index 37c62b04..242fc7d6 100644 --- a/src/components/avatar-button/styles.ts +++ b/src/components/avatar-button/styles.ts @@ -14,11 +14,11 @@ export const ElAvatarButton = styled.button` ${ElAvatar} { box-shadow: 0px 0px 0px 1px #fff, - 0px 0px 0px 4px var(--Colours-Purple-purple-300, #7e9bfa); + 0px 0px 0px 4px var(--purple-300); } } &:hover ${ElAvatar} { - background: var(--fill-colour-fill-action-light, #d6e1ff); + background: var(--fill-action-light); } ` diff --git a/src/components/avatar/styles.ts b/src/components/avatar/styles.ts index 8a9e4a07..f1d6ca2d 100644 --- a/src/components/avatar/styles.ts +++ b/src/components/avatar/styles.ts @@ -1,24 +1,24 @@ import { styled } from '@linaria/react' const baseCircleStyle = ` - border-radius: var(--corner-3xl, 24px); + border-radius: var(--corner-3xl); ` const baseMediumSizeStyle = ` width: var(--size-10); height: var(--size-10); - font-size: var(--font-size-base, 15px); - line-height: var(--line-height-base, 24px); - letter-spacing: var(--letter-spacing-base, -0.15px); + font-size: var(--font-size-base); + line-height: var(--line-height-base); + letter-spacing: var(--letter-spacing-base); ` const baseColourDefaultStyle = ` - background: var(--fill-default-medium, #9faebc); - color: var(--text-white, #fff); + background: var(--fill-default-medium); + color: var(--text-white); /* override Icon element colour */ svg { - color: var(--text-white, #fff); + color: var(--text-white); } ` @@ -28,7 +28,7 @@ export const ElAvatar = styled.span` justify-content: center; align-items: center; text-align: center; - font-family: var(--font-family, Inter); + font-family: var(--font-family); font-style: normal; font-weight: 600; @@ -37,23 +37,23 @@ export const ElAvatar = styled.span` ${baseMediumSizeStyle} &[data-shape='square'] { - border-radius: var(--corner-lg, 8px); + border-radius: var(--corner-lg); } &[data-colour='purple'] { - background: var(--fill-action-lightest, #ecf3ff); - color: var(--text-action, #4e56ea); + background: var(--fill-action-lightest); + color: var(--text-action); /* override Icon element colour */ svg { - color: var(--text-action, #4e56ea); + color: var(--text-action); } } &[data-size='small'] { width: var(--size-8); height: var(--size-8); - font-size: var(--font-size-2xs, 12px); - line-height: var(--line-height-2xs, 16px); - letter-spacing: var(--letter-spacing-2xs, -0.12px); + font-size: var(--font-size-2xs); + line-height: var(--line-height-2xs); + letter-spacing: var(--letter-spacing-2xs); } ` diff --git a/src/components/menu/styles.ts b/src/components/menu/styles.ts index 9633f59c..e9eaad00 100644 --- a/src/components/menu/styles.ts +++ b/src/components/menu/styles.ts @@ -79,7 +79,7 @@ export const ElMenuItemGroupTitle = styled.div` text-transform: uppercase; display: flex; height: 32px; - padding: var(--spacing-none, 0px) var(--spacing-4, 16px); + padding: var(--spacing-none) var(--spacing-4); align-items: center; align-self: stretch; ` From 7783d9e7d7bc9a1556055e0771dff3956db6955a Mon Sep 17 00:00:00 2001 From: Dimas M <96416644+ss-dimasm@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:39:33 +0700 Subject: [PATCH 05/14] feat: add bottom bar component (#233) * refactor: ui tweak to make badge position fixed * feat: add bottom bar navigation * refactor: redundant state setter * chore: exclude snapshot * chore: change css variable reference * chore: resolve feedbacks * fix: ts issue * chore: avoid descendants component styling * refactor: resolve pr feedback * chore: add snapshpt --- src/components/bottom-bar-item/styles.ts | 2 +- .../__snapshots__/bottom-bar.test.tsx.snap | 260 ++++++++++++++++++ .../bottom-bar/__tests__/bottom-bar.test.tsx | 35 +++ .../use-bottom-bar-visibility.test.ts | 54 ++++ .../bottom-bar/bottom-bar.atoms.tsx | 31 +++ src/components/bottom-bar/bottom-bar.mdx | 34 +++ .../bottom-bar/bottom-bar.stories.tsx | 85 ++++++ src/components/bottom-bar/bottom-bar.tsx | 43 +++ src/components/bottom-bar/index.ts | 4 + src/components/bottom-bar/styles.ts | 33 +++ .../bottom-bar/use-bottom-bar-visibility.ts | 47 ++++ 11 files changed, 627 insertions(+), 1 deletion(-) create mode 100644 src/components/bottom-bar/__tests__/__snapshots__/bottom-bar.test.tsx.snap create mode 100644 src/components/bottom-bar/__tests__/bottom-bar.test.tsx create mode 100644 src/components/bottom-bar/__tests__/use-bottom-bar-visibility.test.ts create mode 100644 src/components/bottom-bar/bottom-bar.atoms.tsx create mode 100644 src/components/bottom-bar/bottom-bar.mdx create mode 100644 src/components/bottom-bar/bottom-bar.stories.tsx create mode 100644 src/components/bottom-bar/bottom-bar.tsx create mode 100644 src/components/bottom-bar/index.ts create mode 100644 src/components/bottom-bar/styles.ts create mode 100644 src/components/bottom-bar/use-bottom-bar-visibility.ts diff --git a/src/components/bottom-bar-item/styles.ts b/src/components/bottom-bar-item/styles.ts index d1e76d5d..f7f0a4c3 100644 --- a/src/components/bottom-bar-item/styles.ts +++ b/src/components/bottom-bar-item/styles.ts @@ -12,7 +12,7 @@ export const ElBottomBarItemLabel = styled.span` color: inherit; text-align: center; font-family: var(--font-family, Inter); - font-size: var(--font-size-2xs, 12px); + font-size: var(--font-size-3xs, 10px); font-style: normal; font-weight: var(--font-weight-regular, Regular); line-height: var(--line-height-3xs, 12px); diff --git a/src/components/bottom-bar/__tests__/__snapshots__/bottom-bar.test.tsx.snap b/src/components/bottom-bar/__tests__/__snapshots__/bottom-bar.test.tsx.snap new file mode 100644 index 00000000..5028fa8f --- /dev/null +++ b/src/components/bottom-bar/__tests__/__snapshots__/bottom-bar.test.tsx.snap @@ -0,0 +1,260 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`BottomBar > can render 4 items and an overflow menu 1`] = ` + +
+ + + + +
+ +
+
+
+`; + +exports[`BottomBar > can render 5 items 1`] = ` + +
+ + + + + +
+
+`; diff --git a/src/components/bottom-bar/__tests__/bottom-bar.test.tsx b/src/components/bottom-bar/__tests__/bottom-bar.test.tsx new file mode 100644 index 00000000..fd4c6ff9 --- /dev/null +++ b/src/components/bottom-bar/__tests__/bottom-bar.test.tsx @@ -0,0 +1,35 @@ +import { render } from '@testing-library/react' +import { BottomBar } from '../bottom-bar' + +describe('BottomBar', () => { + it('can render 5 items', () => { + expect( + render( + + mock icon}>Menu 1 + mock icon}>Menu 2 + mock icon}>Menu 3 + mock icon}>Menu 4 + mock icon}>Menu 5 + , + ).asFragment(), + ).toMatchSnapshot() + }) + + it('can render 4 items and an overflow menu', () => { + expect( + render( + + mock icon}>Menu 1 + mock icon}>Menu 2 + mock icon}>Menu 3 + mock icon}>Menu 4 + + Menu 5 + Menu 6 + + , + ).asFragment(), + ).toMatchSnapshot() + }) +}) diff --git a/src/components/bottom-bar/__tests__/use-bottom-bar-visibility.test.ts b/src/components/bottom-bar/__tests__/use-bottom-bar-visibility.test.ts new file mode 100644 index 00000000..81bba8bd --- /dev/null +++ b/src/components/bottom-bar/__tests__/use-bottom-bar-visibility.test.ts @@ -0,0 +1,54 @@ +import { RefObject } from 'react' +import { handleChangeBottomBarVisibility, useBottomBarVisibility } from '../use-bottom-bar-visibility' +import { renderHook } from '@testing-library/react-hooks' +import { act } from '@testing-library/react' + +describe('handleChangeBottomBarVisibility', () => { + afterEach(() => { + vi.clearAllMocks() + }) + + it('should call the setScrollStates function while acting to scroll down', () => { + const mockSetScrollStates = vi.fn().mockImplementation(() => ({ previousTopPosition: 0 })) + + handleChangeBottomBarVisibility({ scrollTop: 10 } as any, mockSetScrollStates) + + expect(mockSetScrollStates).toHaveBeenCalledWith(expect.any(Function)) + }) + + it('should call the setScrollStates function while acting to scroll up', () => { + const mockSetScrollStates = vi.fn().mockImplementation(() => ({ previousTopPosition: 10 })) + + handleChangeBottomBarVisibility({ scrollTop: 0 } as any, mockSetScrollStates) + + expect(mockSetScrollStates).toHaveBeenCalledWith(expect.any(Function)) + }) +}) + +describe('useBottomBarVisibility', () => { + it('should trigger the scroll event listener', () => { + const abort = vi.fn() + vi.spyOn(AbortController.prototype, 'abort').mockImplementation(abort) as any + + const mockUseRef = { + current: { + scrollTop: 0, + addEventListener: vi.fn(), + }, + } as unknown as RefObject + + const render = renderHook(() => useBottomBarVisibility(mockUseRef)) + + expect(mockUseRef.current?.addEventListener).toHaveBeenCalledWith('scroll', expect.any(Function), { + signal: expect.any(AbortSignal), + }) + + expect(abort).not.toHaveBeenCalled() + + act(() => { + render.unmount() + }) + + expect(abort).toHaveBeenCalledTimes(1) + }) +}) diff --git a/src/components/bottom-bar/bottom-bar.atoms.tsx b/src/components/bottom-bar/bottom-bar.atoms.tsx new file mode 100644 index 00000000..3539ed8c --- /dev/null +++ b/src/components/bottom-bar/bottom-bar.atoms.tsx @@ -0,0 +1,31 @@ +import type { FC, ReactNode } from 'react' + +import { Menu, MenuItemProps } from '../menu' +import { BottomBarItem } from '../bottom-bar-item' +import { Icon } from '../icon' + +export interface BottomBarMoreMenuProps { + children: ReactNode +} + +export const BottomBarMoreMenu: FC = ({ children }) => { + return ( + + + {({ getTriggerProps }) => ( + }> + More + + )} + + + {children} + + + ) +} + +export type BottomBarMoreMenuItemProps = MenuItemProps +export const BottomBarMoreMenuItem: FC = (args) => { + return +} diff --git a/src/components/bottom-bar/bottom-bar.mdx b/src/components/bottom-bar/bottom-bar.mdx new file mode 100644 index 00000000..8d767f42 --- /dev/null +++ b/src/components/bottom-bar/bottom-bar.mdx @@ -0,0 +1,34 @@ +import { Meta, Canvas, Controls } from '@storybook/blocks' +import { RenderHtmlMarkup } from '../../storybook/render-html-markup' +import * as BottomBarItemStories from './bottom-bar.stories' + + + +# Bottom Bar + +A component designed to render a navigation bar at the bottom of the screen + +This component is also capable of sliding up and down as the user scrolls the parent element + +`BottomBar` have additional export that can be used to render the following components: + +- `Item`: Renders a single item +- `MoreMenu`: Renders an expandable menu +- `MoreMenuItem`: Renders an expandable menu item + +There are two variants of the `BottomBar` component: + +- Fixed: The `BottomBar` component that only contains less or equal to 5 items +- Expandable: The `BottomBar` component is expandable and can contain more than 5 items + +## Fixed Usage + +Demonstrates how to render the fixed usage of the `BottomBar` component that contains 5 items + + + +## Expandable Usage + +Demonstrates how to render the expandable usage of the `BottomBar` component that contains more than 5 items + + diff --git a/src/components/bottom-bar/bottom-bar.stories.tsx b/src/components/bottom-bar/bottom-bar.stories.tsx new file mode 100644 index 00000000..ebc450f3 --- /dev/null +++ b/src/components/bottom-bar/bottom-bar.stories.tsx @@ -0,0 +1,85 @@ +import { action } from '@storybook/addon-actions' +import type { Meta, StoryObj } from '@storybook/react' +import { useRef } from 'react' +import { Icon } from '../icon' +import { BottomBar } from './bottom-bar' + +const meta = { + title: 'Components/Bottom Bar', + component: BottomBar, + parameters: { + layout: 'fullscreen', + }, + args: { + children: null, + parentRef: null, + }, +} satisfies Meta + +export default meta +type Story = StoryObj + +export const Standard: Story = { + render: () => { + const ref = useRef(null) + + return ( +
+
+
long content
+
short content
+ + } isActive onClick={action('clicked')}> + Menu 1 + + } onClick={action('clicked')} hasBadge> + Menu 2 + + } onClick={action('clicked')}> + Menu 3 + + } onClick={action('clicked')}> + Menu 4 + + } onClick={action('clicked')}> + Menu 5 + + +
+
+ ) + }, +} + +export const WithOverflowMenu: Story = { + render: () => { + const ref = useRef(null) + + return ( +
+
+
long content
+
short content
+ + } isActive onClick={action('clicked')}> + Menu 1 + + } onClick={action('clicked')} hasBadge> + Menu 2 + + } onClick={action('clicked')}> + Menu 3 + + } onClick={action('clicked')}> + Menu 4 + + + Menu 5 + Menu 6 + + +
+
+ ) + }, +} diff --git a/src/components/bottom-bar/bottom-bar.tsx b/src/components/bottom-bar/bottom-bar.tsx new file mode 100644 index 00000000..247a9689 --- /dev/null +++ b/src/components/bottom-bar/bottom-bar.tsx @@ -0,0 +1,43 @@ +import type { FC, HTMLAttributes, ReactNode, RefObject } from 'react' + +import { BottomBarItem } from '../bottom-bar-item' + +import { BottomBarMoreMenu, BottomBarMoreMenuItem } from './bottom-bar.atoms' +import { ElBottomBar } from './styles' +import { useBottomBarVisibility } from './use-bottom-bar-visibility' + +export interface BottomBarProps extends HTMLAttributes { + /** + * The children of the bottom bar + **/ + children: ReactNode + + /** + * The reference of the parent element that the bottom bar is attached to + * + * @description see the story for an example + */ + parentRef: RefObject | null +} + +type BottomBarFC = FC & { + Item: typeof BottomBarItem + MoreMenu: typeof BottomBarMoreMenu + MoreMenuItem: typeof BottomBarMoreMenuItem +} + +const BottomBar: BottomBarFC = ({ children, parentRef, ...rest }) => { + const { isOpen } = useBottomBarVisibility(parentRef) + + return ( + + {children} + + ) +} + +BottomBar.Item = BottomBarItem +BottomBar.MoreMenu = BottomBarMoreMenu +BottomBar.MoreMenuItem = BottomBarMoreMenuItem + +export { BottomBar } diff --git a/src/components/bottom-bar/index.ts b/src/components/bottom-bar/index.ts new file mode 100644 index 00000000..a590b73e --- /dev/null +++ b/src/components/bottom-bar/index.ts @@ -0,0 +1,4 @@ +export * from './bottom-bar' +export * from './bottom-bar.atoms' +export * from './styles' +export * from './use-bottom-bar-visibility' diff --git a/src/components/bottom-bar/styles.ts b/src/components/bottom-bar/styles.ts new file mode 100644 index 00000000..bf572f64 --- /dev/null +++ b/src/components/bottom-bar/styles.ts @@ -0,0 +1,33 @@ +import { styled } from '@linaria/react' + +export const ElBottomBar = styled.div` + display: flex; + padding: var(--spacing-2, 8px); + justify-content: center; + align-items: center; + align-self: stretch; + border-top: var(--border-default, 1px) solid var(--outline-default, #e5e9ed); + background: var(--fill-white, #fff); + + position: absolute; + bottom: 0; + left: 0; + z-index: 5; + overflow: visible; + margin-top: auto; + width: 100%; + + transition: + transform 0.3s ease-in-out, + visibility 0.3s ease-in-out; + + &[data-is-open='true'] { + transform: translateY(0); + visibility: visible; + } + + &[data-is-open='false'] { + transform: translateY(100%); + visibility: hidden; + } +` diff --git a/src/components/bottom-bar/use-bottom-bar-visibility.ts b/src/components/bottom-bar/use-bottom-bar-visibility.ts new file mode 100644 index 00000000..0a4d39ba --- /dev/null +++ b/src/components/bottom-bar/use-bottom-bar-visibility.ts @@ -0,0 +1,47 @@ +import { Dispatch, RefObject, SetStateAction, useEffect, useState } from 'react' + +type BottomBarVisibility = { + isOpen: boolean | undefined + previousTopPosition: number +} + +export const handleChangeBottomBarVisibility = ( + element: HTMLElement, + setScrollStates: Dispatch>, +) => { + const { scrollTop } = element ?? {} + + setScrollStates((state) => ({ + isOpen: state.previousTopPosition > scrollTop, + previousTopPosition: scrollTop, + })) +} + +/** + * Hook to get the vertical scroll direction of the parent element + */ +export const useBottomBarVisibility = (ref: RefObject | null): BottomBarVisibility => { + const [scrollStates, setScrollStates] = useState({ + isOpen: undefined, + previousTopPosition: 0, + }) + + useEffect( + function handleScrollListenerRegistry() { + const element = ref?.current + if (!element) return + const abortController = new AbortController() + + element.addEventListener('scroll', () => handleChangeBottomBarVisibility(element, setScrollStates), { + signal: abortController.signal, + }) + + return () => { + abortController.abort() + } + }, + [ref], + ) + + return scrollStates +} From 08ee3777ea9b9a61c5fc0da5331144d93343f334 Mon Sep 17 00:00:00 2001 From: Nur M <106480336+nurm717123@users.noreply.github.com> Date: Tue, 17 Dec 2024 09:54:11 +0700 Subject: [PATCH 06/14] chore: fix top-bar style var name and remove fallback (#259) --- src/components/nav-item/styles.ts | 26 +++++++++++++------------- src/components/top-bar/styles.ts | 22 +++++++++++----------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/components/nav-item/styles.ts b/src/components/nav-item/styles.ts index dd5c4bb4..37a1ef7c 100644 --- a/src/components/nav-item/styles.ts +++ b/src/components/nav-item/styles.ts @@ -2,33 +2,33 @@ import { styled } from '@linaria/react' export const ElNavItemLabelContainer = styled.span` display: flex; - padding: var(--spacing-spacing-half, 2px); + padding: var(--spacing-half); align-items: flex-start; - font-family: var(--font-family, Inter); - font-size: var(--font-size-sm, 14px); + font-family: var(--font-family); + font-size: var(--font-size-sm); font-style: normal; font-weight: 500; - line-height: var(--line-height-sm, 20px); - letter-spacing: var(--letter-spacing-sm, -0.14px); + line-height: var(--line-height-sm); + letter-spacing: var(--letter-spacing-sm); ` const baseNavItemStyle = ` display: inline-flex; - padding: var(--spacing-spacing-1, 4px) var(--spacing-spacing-3, 12px); + padding: var(--spacing-1) var(--spacing-3); align-items: center; - border-radius: var(--corner-radius-corner-default, 4px); - background: var(--fill-colour-fill-white, #fff); + border-radius: var(--corner-default); + background: var(--fill-white); &:focus { box-shadow: 0px 0px 0px 1px #fff, - 0px 0px 0px 4px var(--Colours-Purple-purple-300, #7e9bfa); + 0px 0px 0px 4px var(--purple-300); } &:hover { - background: var(--fill-colour-fill-default-lightest, #f2f4f6); + background: var(--fill-default-lightest); } &:active { - background: var(--fill-colour-fill-default-lightest, #f2f4f6); + background: var(--fill-default-lightest); } &:focus-visible { outline: none; @@ -36,9 +36,9 @@ const baseNavItemStyle = ` cursor: pointer; border: none; - color: var(--text-colour-text-secondary, #607890); + color: var(--text-secondary); &:active, &[aria-current="true"], &[aria-current="page"] { - color: var(--text-colour-text-action, #4e56ea); + color: var(--text-action); } white-space: nowrap diff --git a/src/components/top-bar/styles.ts b/src/components/top-bar/styles.ts index e216a470..10415fe4 100644 --- a/src/components/top-bar/styles.ts +++ b/src/components/top-bar/styles.ts @@ -4,38 +4,38 @@ import { ElButtonGroup } from '../button-group' import { css } from '@linaria/core' export const ElTopBarLogo = styled.a` - padding-right: var(--spacing-2, 8px); + padding-right: var(--spacing-2); display: inline-flex; ` export const ElTopBarProfile = styled.div` - padding: var(--spacing-1, 4px) var(--spacing-none, 0px); + padding: var(--spacing-1) var(--spacing-none); ` export const ElTopBarMainNav = styled(ElButtonGroup)` display: flex; flex-direction: row; align-items: center; - padding-left: var(--spacing-6, 24px); + padding-left: var(--spacing-6); flex-grow: 1; container-type: inline-size; ` export const ElTopBarSecondaryNav = styled(ElButtonGroup)` flex-wrap: nowrap; - padding-right: var(--spacing-2, 8px); + padding-right: var(--spacing-2); ` export const ElTopBar = styled.div` display: flex; align-items: center; height: var(--size-14); - padding: var(--spacing-2, 8px) var(--spacing-5, 20px); - border-bottom: var(--border-default, 1px) solid var(--outline-default, #e5e9ed); - background: var(--fill-white, #fff); + padding: var(--spacing-2) var(--spacing-5); + border-bottom: var(--border-default) solid var(--outline-default); + background: var(--fill-white); ${isBelowWideScreen} { - padding: var(--spacing-2, 8px) var(--spacing-4, 16px); + padding: var(--spacing-2) var(--spacing-4); ${ElTopBarLogo} { margin-right: auto; @@ -54,17 +54,17 @@ export const ElTopBar = styled.div` ` export const ElTopBarSearch = styled.div` - padding-right: var(--spacing-2, 8px); + padding-right: var(--spacing-2); ${isTablet} { width: 216px; - padding: var(--spacing-1, 4px) var(--spacing-4, 16px) var(--spacing-1, 4px) var(--spacing-none, 0px); + padding: var(--spacing-1) var(--spacing-4) var(--spacing-1) var(--spacing-none); } ` export const ElTopBarMobileNav = styled.div` display: inline-block; - padding-right: var(--spacing-2, 8px); + padding-right: var(--spacing-2); ${isWideScreen} { display: none; From 61885a191a92c9046b972b0cb7bf8fcbedcb96d0 Mon Sep 17 00:00:00 2001 From: Dimas M <96416644+ss-dimasm@users.noreply.github.com> Date: Tue, 17 Dec 2024 10:07:56 +0700 Subject: [PATCH 07/14] chore: remove fallback css variables `NavIconItem` (#257) * chore: remove css variables fallback values for `NavIconItem` * chore: amend comma * chore: update heading mdx doc * chore: update storybook --- .../nav-icon-item/nav-icon-item.mdx | 42 +++------- .../nav-icon-item/nav-icon-item.stories.tsx | 76 +++---------------- src/components/nav-icon-item/styles.ts | 32 ++++---- 3 files changed, 36 insertions(+), 114 deletions(-) diff --git a/src/components/nav-icon-item/nav-icon-item.mdx b/src/components/nav-icon-item/nav-icon-item.mdx index 76c9c79b..07710a17 100644 --- a/src/components/nav-icon-item/nav-icon-item.mdx +++ b/src/components/nav-icon-item/nav-icon-item.mdx @@ -12,56 +12,36 @@ A versatile component designed to render navigation icon items within an AppBar -## Default State +## Default The default appearance of the `NavIconItem` -## Active State +## Active The visual state of the `NavIconItem` when it's currently selected or active - + -## Badge State +## With Badge The visual state of the `NavIconItem` when it's currently selected or active with a badge - + -## Style Anchor Usage - -Demonstrates how to use the `NavIconItem` using a standard `HTMLAnchorElement` - -**note:** to make the `NavIconItem` have an "active" state, you must pass the `aria-current` attribute with a value of `page` - - - - - -## Style Button Usage - -Demonstrates how to use the `NavIconItem` using a standard `HTMLButtonElement` - -**note:** to make the `NavIconItem` have an "active" state, you must pass the `aria-current` attribute with a value of `true` - - - - - -## React Anchor Usage +## With Href Demonstrates how to render the `NavIconItem` using a anchor version - + - + -## React Button Usage +## With OnClick Demonstrates how to render the `NavIconItem` using a button version - + - + diff --git a/src/components/nav-icon-item/nav-icon-item.stories.tsx b/src/components/nav-icon-item/nav-icon-item.stories.tsx index b5d5c0ca..3ed98727 100644 --- a/src/components/nav-icon-item/nav-icon-item.stories.tsx +++ b/src/components/nav-icon-item/nav-icon-item.stories.tsx @@ -2,7 +2,6 @@ import type { Meta, StoryObj } from '@storybook/react' import { NavIconItem } from './nav-icon-item' import { Icon } from '../icon' import { FlexContainer } from '../layout' -import { ElAnchorNavIconItem, ElButtonNavIconItem, ElNavIconItemBadge } from './styles' import { action } from '@storybook/addon-actions' const meta = { @@ -55,91 +54,33 @@ export const Default: Story = { onClick: action('handleOnClick'), }, render: (args) => { - return ( - - {args?.icon} - - ) + return }, } -export const ActiveState: Story = { +export const Active: Story = { args: { icon: , onClick: action('handleOnClick'), + isActive: true, }, render: (args) => { - return ( - - {args?.icon} - - ) + return }, } -export const BadgeState: Story = { +export const WithBadge: Story = { args: { icon: , onClick: action('handleOnClick'), hasBadge: true, }, render: (args) => { - return ( - - {args?.icon} - - - ) - }, -} - -export const StyleAnchorUsage: Story = { - args: { - icon: , - href: '#', - }, - render: (args) => { - return ( - - - {args?.icon} - - - {args?.icon} - - - {args?.icon} - - - - ) - }, -} - -export const StyleButtonUsage: Story = { - args: { - icon: , - onClick: action('handleClick'), - }, - render: (args) => { - return ( - - - {args?.icon} - - - {args?.icon} - - - {args?.icon} - - - - ) + return }, } -export const ReactAnchorUsage: Story = { +export const WithHref: Story = { args: { icon: , href: '#', @@ -155,7 +96,8 @@ export const ReactAnchorUsage: Story = { }, } -export const ReactButtonUsage: Story = { +export const WithOnClick: Story = { + name: 'With OnClick', args: { icon: , onClick: action('handleClick'), diff --git a/src/components/nav-icon-item/styles.ts b/src/components/nav-icon-item/styles.ts index 8c88f7fb..dd5b7f72 100644 --- a/src/components/nav-icon-item/styles.ts +++ b/src/components/nav-icon-item/styles.ts @@ -6,34 +6,34 @@ import { ElIcon } from '../icon' const baseStyles = ` position: relative; display: inline-flex; - padding: var(--space-2, 8px); + padding: var(--spacing-2); justify-content: center; align-items: center; - gap: var(--space-none, 0px); - border-radius: var(--corner-default, 4px); - background: var(--fill-white, #ffffff); - border: var(--border-none, 0px); - color: var(--icon-app_bar-default, #798da1); + gap: var(--spacing-none); + border-radius: var(--corner-defaul); + background: var(--fill-white); + border: var(--border-none); + color: var(--icon-app_bar-default); outline: none; &:focus-visible { - border-radius: var(--corner-default, 4px); - background: var(--fill-white, #ffffff); + border-radius: var(--corner-default); + background: var(--fill-white); box-shadow: - 0px 0px 0px 1px #fff, - 0px 0px 0px 4px var(--icon-button_primary-hover, #7e9bfa); + 0px 0px 0px 1px var(--fill-white), + 0px 0px 0px 4px var(--icon-button_primary-hover); } &:hover { cursor: pointer; - border-radius: var(--corner-default, 4px); - background: var(--fill-default-lightest, #f2f4f6); + border-radius: var(--corner-default); + background: var(--fill-default-lightest); } &:active, &[aria-current="page"], &[aria-current="true"] { - color: var(--fill-action-dark, #4e56ea); - border-radius: var(--corner-default, 4px); - background: var(--fill-default-lightest, #f2f4f6); + color: var(--fill-action-dark); + border-radius: var(--corner-default); + background: var(--fill-default-lightest); } ` @@ -43,7 +43,7 @@ export const ElNavIconItemBadge = styled.span` top: 5px; width: var(--size-2); height: var(--size-2); - background-color: var(--icon-error, #f01830); + background-color: var(--icon-error); border-radius: 100%; ` From 8e5182c7bca5163d7e76f2c39588b7892606b37e Mon Sep 17 00:00:00 2001 From: Dimas M <96416644+ss-dimasm@users.noreply.github.com> Date: Tue, 17 Dec 2024 10:20:37 +0700 Subject: [PATCH 08/14] chore: remove fallback css variables for `BottomBarItem` and update token variable (#256) * chore: update css token * chore: remove css fallback variable for bottom bar item * chore: update heading name * chore: update storybook --- .../bottom-bar-item/bottom-bar-item.mdx | 38 +++------ .../bottom-bar-item.stories.tsx | 83 ++----------------- src/components/bottom-bar-item/styles.ts | 28 +++---- src/tokens/payprop/tokens.css | 3 +- src/tokens/payprop/tokens.ts | 3 +- src/tokens/reapit/tokens.css | 3 +- src/tokens/reapit/tokens.ts | 3 +- src/tokens/tokens.json | 6 ++ 8 files changed, 47 insertions(+), 120 deletions(-) diff --git a/src/components/bottom-bar-item/bottom-bar-item.mdx b/src/components/bottom-bar-item/bottom-bar-item.mdx index 28f485ae..16358b8f 100644 --- a/src/components/bottom-bar-item/bottom-bar-item.mdx +++ b/src/components/bottom-bar-item/bottom-bar-item.mdx @@ -12,52 +12,36 @@ A versatile component designed to render navigation icon items within a `BottomB -## Default State +## Default The default appearance of the `BottomBarItem` -## Active State +## Active The visual state of the `BottomBarItem` when it's currently selected or active - + -## Badge State +## With Badge The visual state of the `BottomBarItem` when it's currently selected or active with a badge - + -## Style Anchor Usage - -Demonstrates how to use the `BottomBarItem` using a standard `HTMLAnchorElement` - - - - - -## Style Button Usage - -Demonstrates how to use the `BottomBarItem` using a standard `HTMLButtonElement` - - - - - -## React Anchor Usage +## With Href Demonstrates how to render the `BottomBarItem` using a anchor version - + - + -## React Button Usage +## With OnClick Demonstrates how to render the `BottomBarItem` using a button version - + - + diff --git a/src/components/bottom-bar-item/bottom-bar-item.stories.tsx b/src/components/bottom-bar-item/bottom-bar-item.stories.tsx index a69a78e5..9fe81ea6 100644 --- a/src/components/bottom-bar-item/bottom-bar-item.stories.tsx +++ b/src/components/bottom-bar-item/bottom-bar-item.stories.tsx @@ -1,17 +1,9 @@ -import type { Meta, StoryObj } from '@storybook/react' import { action } from '@storybook/addon-actions' +import type { Meta, StoryObj } from '@storybook/react' -import { BottomBarItem } from './bottom-bar-item' -import { FlexContainer } from '../layout' import { Icon } from '../icon' -import { - ElAnchorBottomBarItemContainer, - ElBottomBarItemBadge, - ElBottomBarItemContent, - ElBottomBarItemIcon, - ElBottomBarItemLabel, - ElButtonBottomBarItemContainer, -} from './styles' +import { FlexContainer } from '../layout' +import { BottomBarItem } from './bottom-bar-item' const meta = { title: 'Components/Bottom Bar Item', @@ -62,7 +54,7 @@ export const Default: Story = { }, } -export const ActiveState: Story = { +export const Active: Story = { args: { isActive: true, children: 'Label', @@ -70,75 +62,15 @@ export const ActiveState: Story = { }, } -export const BadgeState: Story = { +export const WithBadge: Story = { args: { children: 'Label', icon: , hasBadge: true, }, } -export const StyleAnchorUsage: Story = { - args: { - href: '#', - children: 'Label', - icon: , - }, - render: (args) => { - return ( - - - {args?.icon} - {args?.children} - - - - {args?.icon} - {args?.children} - - - - - {args?.icon} - - - {args?.children} - - - ) - }, -} - -export const StyleButtonUsage: Story = { - args: { - children: 'Label', - icon: , - }, - render: (args) => { - return ( - - - {args?.icon} - {args?.children} - - - - {args?.icon} - {args?.children} - - - - - {args?.icon} - - - {args?.children}{' '} - - - ) - }, -} -export const ReactAnchorUsage: Story = { +export const WithHref: Story = { args: { href: '#', icon: , @@ -155,7 +87,8 @@ export const ReactAnchorUsage: Story = { }, } -export const ReactButtonUsage: Story = { +export const WithOnClick: Story = { + name: 'With OnClick', args: { onClick: action('handleClick'), icon: , diff --git a/src/components/bottom-bar-item/styles.ts b/src/components/bottom-bar-item/styles.ts index f7f0a4c3..234360d4 100644 --- a/src/components/bottom-bar-item/styles.ts +++ b/src/components/bottom-bar-item/styles.ts @@ -3,40 +3,40 @@ import { AnchorHTMLAttributes, ButtonHTMLAttributes } from 'react' import { ElIcon } from '../icon' export const ElBottomBarItemIcon = styled.div` - width: var(--icon-default, 24px); - height: var(--icon-default, 24px); + width: var(--icon-default); + height: var(--icon-default); color: inherit; ` export const ElBottomBarItemLabel = styled.span` color: inherit; text-align: center; - font-family: var(--font-family, Inter); - font-size: var(--font-size-3xs, 10px); + font-family: var(--font-family); + font-size: var(--font-size-3xs); font-style: normal; - font-weight: var(--font-weight-regular, Regular); - line-height: var(--line-height-3xs, 12px); - letter-spacing: var(--letter-spacing-2xs, 0px); + font-weight: var(--font-weight-regular); + line-height: var(--line-height-3xs); + letter-spacing: var(--letter-spacing-2xs); ` const baseStyles = ` - background-color: var(--fill-white, white); + background-color: var(--fill-white); outline: none; width: 44px; - border: var(--border-none, 0); + border: var(--border-none); display: flex; cursor: pointer; - padding: var(--space-half, 2px) var(--space-none, 0px); + padding: var(--spacing-half) var(--spacing-none); flex-direction: column; align-items: center; - gap: var(--space-half, 2px); + gap: var(--spacing-half); position: relative; flex: 1 0 0; - color: var(--icon-secondary, #607890); + color: var(--icon-secondary); &:active, &[aria-current="true"], &[aria-current="page"] { - color: var(--icon-action, #4e56ea) + color: var(--icon-action) } ` @@ -50,7 +50,7 @@ export const ElBottomBarItemBadge = styled.span` right: -3px; width: var(--size-2); height: var(--size-2); - background-color: var(--icon-error, #f01830); + background-color: var(--icon-error); border-radius: 100%; ` diff --git a/src/tokens/payprop/tokens.css b/src/tokens/payprop/tokens.css index e7568429..cda5f97b 100644 --- a/src/tokens/payprop/tokens.css +++ b/src/tokens/payprop/tokens.css @@ -1,6 +1,6 @@ /** * Do not edit directly - * Generated on Tue, 10 Dec 2024 06:08:05 GMT + * Generated on Mon, 16 Dec 2024 06:57:57 GMT */ :root { @@ -139,6 +139,7 @@ --font-size-sm: 0.875rem; --font-size-xs: 0.8125rem; --font-size-2xs: 0.75rem; + --font-size-3xs: 0.625rem; --line-height-3xl: 2.5rem; --line-height-2xl: 2rem; --line-height-xl: 1.75rem; diff --git a/src/tokens/payprop/tokens.ts b/src/tokens/payprop/tokens.ts index 6f853b27..50b6fe64 100644 --- a/src/tokens/payprop/tokens.ts +++ b/src/tokens/payprop/tokens.ts @@ -1,6 +1,6 @@ /** * Do not edit directly - * Generated on Tue, 10 Dec 2024 06:08:05 GMT + * Generated on Mon, 16 Dec 2024 06:57:57 GMT */ export const neutral900 = '#222b33' @@ -138,6 +138,7 @@ export const fontSizeBase = '0.9375rem' export const fontSizeSm = '0.875rem' export const fontSizeXs = '0.8125rem' export const fontSize2xs = '0.75rem' +export const fontSize3xs = '0.625rem' export const lineHeight3xl = '2.5rem' export const lineHeight2xl = '2rem' export const lineHeightXl = '1.75rem' diff --git a/src/tokens/reapit/tokens.css b/src/tokens/reapit/tokens.css index e7568429..cda5f97b 100644 --- a/src/tokens/reapit/tokens.css +++ b/src/tokens/reapit/tokens.css @@ -1,6 +1,6 @@ /** * Do not edit directly - * Generated on Tue, 10 Dec 2024 06:08:05 GMT + * Generated on Mon, 16 Dec 2024 06:57:57 GMT */ :root { @@ -139,6 +139,7 @@ --font-size-sm: 0.875rem; --font-size-xs: 0.8125rem; --font-size-2xs: 0.75rem; + --font-size-3xs: 0.625rem; --line-height-3xl: 2.5rem; --line-height-2xl: 2rem; --line-height-xl: 1.75rem; diff --git a/src/tokens/reapit/tokens.ts b/src/tokens/reapit/tokens.ts index 6f853b27..50b6fe64 100644 --- a/src/tokens/reapit/tokens.ts +++ b/src/tokens/reapit/tokens.ts @@ -1,6 +1,6 @@ /** * Do not edit directly - * Generated on Tue, 10 Dec 2024 06:08:05 GMT + * Generated on Mon, 16 Dec 2024 06:57:57 GMT */ export const neutral900 = '#222b33' @@ -138,6 +138,7 @@ export const fontSizeBase = '0.9375rem' export const fontSizeSm = '0.875rem' export const fontSizeXs = '0.8125rem' export const fontSize2xs = '0.75rem' +export const fontSize3xs = '0.625rem' export const lineHeight3xl = '2.5rem' export const lineHeight2xl = '2rem' export const lineHeightXl = '1.75rem' diff --git a/src/tokens/tokens.json b/src/tokens/tokens.json index 5e95ad2c..77f2056a 100644 --- a/src/tokens/tokens.json +++ b/src/tokens/tokens.json @@ -1581,6 +1581,12 @@ "parent": "_Primitives/Value", "description": "" }, + "font-size-3xs": { + "value": "0.625rem", + "type": "dimension", + "parent": "_Primitives/Value", + "description": "" + }, "line-height-3xl": { "value": "2.5rem", "type": "dimension", From 2660c86568870297ddbce4912cd566c2ab0ed3e8 Mon Sep 17 00:00:00 2001 From: Dimas M <96416644+ss-dimasm@users.noreply.github.com> Date: Tue, 17 Dec 2024 10:38:14 +0700 Subject: [PATCH 09/14] chore: remove fallback css variables for `MobileNavItem` and amend the stories (#255) * chore: remove fallback css variables for `MobileNavMenu` and amend the stories * chore: update storybook --- .../mobile-nav-item/mobile-nav-item.mdx | 9 ++--- .../mobile-nav-item.stories.tsx | 14 +++---- src/components/mobile-nav-item/styles.ts | 38 +++++++++---------- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/components/mobile-nav-item/mobile-nav-item.mdx b/src/components/mobile-nav-item/mobile-nav-item.mdx index d2e9a949..e252e813 100644 --- a/src/components/mobile-nav-item/mobile-nav-item.mdx +++ b/src/components/mobile-nav-item/mobile-nav-item.mdx @@ -29,14 +29,13 @@ A basic `MobileNavItem` without any special styling or interactions -**With Badge** - - +**Active** -**With Active State** + - +**With Badge** + ## Expandable Variant **Basic Usage** diff --git a/src/components/mobile-nav-item/mobile-nav-item.stories.tsx b/src/components/mobile-nav-item/mobile-nav-item.stories.tsx index 72666a58..73f13088 100644 --- a/src/components/mobile-nav-item/mobile-nav-item.stories.tsx +++ b/src/components/mobile-nav-item/mobile-nav-item.stories.tsx @@ -19,19 +19,19 @@ export default meta type Story = StoryObj export const Simple: Story = { - render: () => , + render: ({}) => , } -export const SimpleWithBadge: Story = { - render: () => , +export const Active: Story = { + render: ({}) => , } -export const SimpleWithActiveState: Story = { - render: () => , +export const WithBadge: Story = { + render: ({}) => , } export const Expandable: Story = { - render: () => ( + render: ({}) => ( @@ -41,7 +41,7 @@ export const Expandable: Story = { } export const DefaultExpanded: Story = { - render: () => ( + render: ({}) => ( diff --git a/src/components/mobile-nav-item/styles.ts b/src/components/mobile-nav-item/styles.ts index 8becdc2e..fa7212aa 100644 --- a/src/components/mobile-nav-item/styles.ts +++ b/src/components/mobile-nav-item/styles.ts @@ -10,26 +10,26 @@ const baseStyles = ` border-radius: inherit; border: 4px solid transparent; background: inherit; - padding: var(--space-2, 8px) var(--space-4, 16px); - font-family: var(--font-family, Inter); - font-size: var(--font-size-base, 15px); + padding: var(--spacing-2) var(--spacing-4); + font-family: var(--font-family); + font-size: var(--font-size-base); font-style: normal; - font-weight: var(--font-weight-regular, Regular); - line-height: var(--line-height-base, 24px); - letter-spacing: var(--letter-spacing-base, -0.15px); + font-weight: var(--font-weight-regular); + line-height: var(--line-height-base); + letter-spacing: var(--letter-spacing-base); &:hover { - background: var(--fill-default-light, #e5e9ed); + background: var(--fill-default-light); } &:focus-visible { - border: 4px solid var(--purple-300, #7e9bfa); + border: 4px solid var(--purple-300); } &:active, &[aria-current='true'], &[aria-current='page'] { - color: var(--text-action, #4e56ea); + color: var(--text-action); } ` @@ -49,7 +49,7 @@ export const ElMobileNavItemContent = styled.span` display: flex; align-items: center; justify-content: flex-start; - gap: var(--space-2, 8px); + gap: var(--spacing-2); flex-grow: 1; ` @@ -57,7 +57,7 @@ export const ElMobileNavItemBadge = styled.span` display: block; width: var(--size-2); height: var(--size-2); - background-color: var(--icon-error, #f01830); + background-color: var(--icon-error); border-radius: 100%; ` @@ -70,25 +70,25 @@ export const ElMobileNavSubItemUnorderedList = styled.ul` export const ElMobileNavItemListItem = styled.li` display: flex; flex-direction: column; - background: var(--fill-white, #fff); - border-radius: var(--corner-lg, 8px); + background: var(--fill-white); + border-radius: var(--corner-lg); &[data-is-expanded='true'] { - background: var(--fill-default-lightest, #f2f4f6); + background: var(--fill-default-lightest); > ${ElMobileNavItemExpanderButton} { - border-radius: var(--corner-lg, 8px) var(--corner-lg, 8px) var(--corner-none, 0) var(--corner-none, 0); + border-radius: var(--corner-lg) var(--corner-lg) var(--corner-none) var(--corner-none); } ${ElMobileNavSubItemUnorderedList} > * { - background: var(--fill-default-lightest, #f2f4f6); - border-radius: var(--corner-none, 0px); + background: var(--fill-default-lightest); + border-radius: var(--corner-none); } ${ElMobileNavSubItemUnorderedList} > :last-child { - border-radius: var(--corner-none, 0) var(--corner-none, 0) var(--corner-lg, 8px) var(--corner-lg, 8px); + border-radius: var(--corner-none) var(--corner-none) var(--corner-lg) var(--corner-lg); } ${ElMobileNavItemAnchor}, ${ElMobileNavItemExpanderButton} { &:hover { - background: var(--fill-default-light, #e5e9ed); + background: var(--fill-default-light); } } } From 34b4daff167423aab8fb7595c9e9fd8fd6d29ba4 Mon Sep 17 00:00:00 2001 From: Nur M <106480336+nurm717123@users.noreply.github.com> Date: Wed, 18 Dec 2024 13:33:24 +0700 Subject: [PATCH 10/14] chore: v5 update Avatar docs (#262) * chore: update avatar docs to be more aligned with existing convention --- .../avatar-rectangle/avatar-rectangle.mdx | 22 +++---- .../avatar-rectangle.stories.tsx | 45 +++++--------- src/components/avatar/avatar.mdx | 42 ++++++------- src/components/avatar/avatar.stories.tsx | 62 +++++++++---------- 4 files changed, 72 insertions(+), 99 deletions(-) diff --git a/src/components/avatar-rectangle/avatar-rectangle.mdx b/src/components/avatar-rectangle/avatar-rectangle.mdx index c6a97f57..89bc30f7 100644 --- a/src/components/avatar-rectangle/avatar-rectangle.mdx +++ b/src/components/avatar-rectangle/avatar-rectangle.mdx @@ -1,4 +1,4 @@ -import { Meta, Canvas, Controls } from '@storybook/blocks' +import { Meta, Canvas, Controls, Description } from '@storybook/blocks' import { RenderHtmlMarkup } from '../../storybook/render-html-markup' import * as AvatarRectangleStories from './avatar-rectangle.stories' @@ -10,30 +10,24 @@ A versatile component designed to render property image. -## Default Usage - -The default usage use the residential variant and medium size, each can be set using the `data-` attribute. +## Default + +## Avatar Rectangle Variant + + + + ## Using Residential Placeholder -## Using Commercial Variant - - - ## Using Commercial Placeholder - -## React Usage - - - - diff --git a/src/components/avatar-rectangle/avatar-rectangle.stories.tsx b/src/components/avatar-rectangle/avatar-rectangle.stories.tsx index 945652c3..0c2cefd3 100644 --- a/src/components/avatar-rectangle/avatar-rectangle.stories.tsx +++ b/src/components/avatar-rectangle/avatar-rectangle.stories.tsx @@ -1,11 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react' import { AvatarRectangle } from '.' -import { - ElAvatarRectangle, - ElAvatarRectResidentialPlaceholder, - ElAvatarRectBottomImage, - ElAvatarRectCommercialPlaceholder, -} from './styles' +import { ElAvatarRectResidentialPlaceholder, ElAvatarRectCommercialPlaceholder } from './styles' export default { title: 'Components/Avatar Rectangle', @@ -13,6 +8,7 @@ export default { args: { variant: 'residential', size: 'medium', + src: 'https://picsum.photos/id/206/100/100', }, argTypes: { variant: { @@ -26,36 +22,23 @@ export default { }, } as Meta -const exampleImageUrl = 'https://picsum.photos/id/206/100/100' +type Story = StoryObj -export const DefaultUsage = { - render: ({}) => ( - - example - - ), -} +/** + * The default usage use the residential variant and medium size, each can be set using the `data-` attribute. + */ +export const DefaultUsage: Story = {} -export const UsingResidentialPlaceholder = { - render: ({}) => , +export const AvatarRectangleVariant: Story = { + args: { + variant: 'commercial', + }, } -export const UsingCommercialVariant = { - render: ({}) => ( - - example - - ), +export const UsingResidentialPlaceholder = { + render: () => , } export const UsingCommercialPlaceholder = { - render: ({}) => , -} - -export const ReactUsage: StoryObj = { - args: { - src: exampleImageUrl, - }, - render: (props) => , + render: () => , } diff --git a/src/components/avatar/avatar.mdx b/src/components/avatar/avatar.mdx index f8cd7f69..53c26bf5 100644 --- a/src/components/avatar/avatar.mdx +++ b/src/components/avatar/avatar.mdx @@ -1,4 +1,5 @@ -import { Meta, Story, Canvas, Controls } from '@storybook/blocks' +import { Meta, Story, Canvas, Controls, Description +} from '@storybook/blocks' import { RenderHtmlMarkup } from '../../storybook/render-html-markup' import * as AvatarStories from './avatar.stories' @@ -6,42 +7,37 @@ import * as AvatarStories from './avatar.stories' # Avatar -An avatar component to be used typically with a `Card` or `Nav` component. The default variant renders a circle with children. + -There are multiple variants that can be used by utilizing the data props, such as size, colour, and shape (see the HTML version of React usage). In addition to text, it also accepts an Icon as a child. - -## Style Only Usage - - + - +## Default - + - + -## With Colour +## Avatar with Icon - + - + -## With Square Shape - +## Avatar Colour - + -## With Small Size + - +## Avatar Shape - + -## React Usage + - +## Avatar Size - + -WithColourWithColour + diff --git a/src/components/avatar/avatar.stories.tsx b/src/components/avatar/avatar.stories.tsx index f4ded079..bc9a6d1d 100644 --- a/src/components/avatar/avatar.stories.tsx +++ b/src/components/avatar/avatar.stories.tsx @@ -1,49 +1,49 @@ -import type { StoryObj } from '@storybook/react' -import { Avatar, ElAvatar } from '.' +import type { Meta, StoryObj } from '@storybook/react' +import { Avatar } from '.' import { Icon } from '../icon' export default { title: 'Components/Avatar', component: Avatar, -} + args: { + children: 'AD', + }, +} as Meta -export const StyleOnlyUsage = { - render: ({}) => AD, -} +type Story = StoryObj + +/** + * An avatar component to be used typically with a `Card` or `Nav` component. + * The default variant renders a circle with children. + * + * There are multiple variants that can be used by utilizing the `data-` props + * such as `size`, `colour`, and `shape` (see the HTML version of each version). + * In addition to text, it also accepts an Icon as a child. + */ +export const Default: Story = {} -export const WithIconUsage = { - render: ({}) => ( - +export const AvatarWithIcon: Story = { + render: (props) => ( + - + ), } -export const WithColour = { - render: ({}) => AD, - name: 'Colour: Purple', -} - -export const WithSquareShape = { - render: ({}) => AD, - name: 'Shape: Square', +export const AvatarColour: Story = { + args: { + colour: 'purple', + }, } -export const WithSmallSize = { - render: ({}) => ( - - - - ), - name: 'Size: Small', +export const AvatarShape: Story = { + args: { + shape: 'square', + }, } -export const ReactUsage: StoryObj = { +export const AvatarSize: Story = { args: { - shape: 'circle', - size: 'medium', - colour: 'default', - children: 'AD', + size: 'small', }, - render: (props) => {props.children}, } From 7be95415e7a5ea87ddbc23e694e3273d9552f493 Mon Sep 17 00:00:00 2001 From: Nur M <106480336+nurm717123@users.noreply.github.com> Date: Wed, 18 Dec 2024 17:25:12 +0700 Subject: [PATCH 11/14] feat: #253 new app-bar (existing app switcher) (#261) * feat: init top-bar's app-switcher --- src/components/nav/__styles__/index.ts | 8 +++++ src/components/nav/nav-responsive.tsx | 4 ++- .../__snapshots__/top-bar.test.tsx.snap | 19 +++++++----- .../top-bar/__test__/top-bar.test.tsx | 1 + src/components/top-bar/styles.ts | 8 +++++ src/components/top-bar/top-bar.stories.tsx | 31 +++++++++++++++++++ src/components/top-bar/top-bar.tsx | 3 ++ 7 files changed, 66 insertions(+), 8 deletions(-) diff --git a/src/components/nav/__styles__/index.ts b/src/components/nav/__styles__/index.ts index f49eb048..61225539 100644 --- a/src/components/nav/__styles__/index.ts +++ b/src/components/nav/__styles__/index.ts @@ -350,3 +350,11 @@ export const ElNavResponsiveAppSwitcherIconWrap = styled.div` } } ` + +export const elNewTopBarAppSwitcher = css` + ${ElNavResponsiveAppSwitcherIconWrap} { + margin-right: 0; + padding: var(--spacing-half); + box-sizing: content-box; + } +` diff --git a/src/components/nav/nav-responsive.tsx b/src/components/nav/nav-responsive.tsx index 70f88fe1..a017ac8b 100644 --- a/src/components/nav/nav-responsive.tsx +++ b/src/components/nav/nav-responsive.tsx @@ -72,6 +72,7 @@ export interface NavResponsiveAvatarProps { export interface NavResponsiveAppSwitcherProps { options: NavResponsiveAppSwitcherOption[] + className?: string // Note: probably only required for new AppBar } export type LogoIcon = 'reapitLogoSelectedMenu' | 'reapitLogoMenu' @@ -141,7 +142,7 @@ export const NavResponsiveAvatar: FC = ({ options, isH ) } -export const NavResponsiveAppSwitcher: FC = ({ options }) => { +export const NavResponsiveAppSwitcher: FC = ({ options, className }) => { const [appSwitcherOpen, setAppSwitcherOpen] = useState(false) const marketplaceCallback = () => { @@ -164,6 +165,7 @@ export const NavResponsiveAppSwitcher: FC = ({ op onKeyDown={handleKeyboardEvent('Enter', handleToggleMenu(setAppSwitcherOpen))} role="button" tabIndex={0} + className={className} > diff --git a/src/components/top-bar/__test__/__snapshots__/top-bar.test.tsx.snap b/src/components/top-bar/__test__/__snapshots__/top-bar.test.tsx.snap index 1fb79a21..ef11a0ab 100644 --- a/src/components/top-bar/__test__/__snapshots__/top-bar.test.tsx.snap +++ b/src/components/top-bar/__test__/__snapshots__/top-bar.test.tsx.snap @@ -4,45 +4,50 @@ exports[`TopBar Snapshot > should match snapshot 1`] = `