From 170dfab6be5dcd662acc5c8aac58f3cc562695cd Mon Sep 17 00:00:00 2001 From: Kar Rui Lau Date: Wed, 15 Feb 2023 14:57:47 +0800 Subject: [PATCH 01/12] feat: add initial Toolbar and subcomponent declarations --- react/src/Toolbar/Toolbar.stories.tsx | 14 +++++++++++ react/src/Toolbar/Toolbar.tsx | 35 +++++++++++++++++++++++++++ react/src/Toolbar/index.ts | 1 + 3 files changed, 50 insertions(+) create mode 100644 react/src/Toolbar/Toolbar.stories.tsx create mode 100644 react/src/Toolbar/Toolbar.tsx create mode 100644 react/src/Toolbar/index.ts diff --git a/react/src/Toolbar/Toolbar.stories.tsx b/react/src/Toolbar/Toolbar.stories.tsx new file mode 100644 index 00000000..b90464e3 --- /dev/null +++ b/react/src/Toolbar/Toolbar.stories.tsx @@ -0,0 +1,14 @@ +import { Meta, StoryFn } from '@storybook/react' + +import { Toolbar, ToolbarProps } from './Toolbar' + +export default { + title: 'Components/Toolbar', + component: Toolbar, + decorators: [], + tags: ['autodocs'], +} as Meta + +const Template: StoryFn = (args) => +export const Default = Template.bind({}) +Default.args = {} diff --git a/react/src/Toolbar/Toolbar.tsx b/react/src/Toolbar/Toolbar.tsx new file mode 100644 index 00000000..e5199551 --- /dev/null +++ b/react/src/Toolbar/Toolbar.tsx @@ -0,0 +1,35 @@ +import { Flex } from '@chakra-ui/react' + +import { Button } from '~/Button' +import { IconButton } from '~/IconButton' + +export interface ToolbarProps {} + +/** + * Container for the toolbar. + */ +export const Toolbar = ({}: ToolbarProps): JSX.Element => { + return +} + +/** + * Component to group togglable buttons to allow selection of only one in a group. + */ +export const ToolbarToggleGroup = () => { + return +} + +export const ToolbarGroup = () => { + return +} + +export const ToolbarToggleButton = () => { + return +} + +export const ToolbarDivider = () => { + return +} + +export const ToolbarButton = Button +export const ToolbarIconButton = IconButton diff --git a/react/src/Toolbar/index.ts b/react/src/Toolbar/index.ts new file mode 100644 index 00000000..d24a005a --- /dev/null +++ b/react/src/Toolbar/index.ts @@ -0,0 +1 @@ +export * from './Toolbar' From a0faf4216ee45a97c2b1c20ebfd44ee561332657 Mon Sep 17 00:00:00 2001 From: Kar Rui Lau Date: Wed, 15 Feb 2023 15:01:04 +0800 Subject: [PATCH 02/12] feat: add initial Toolbar styles structure --- react/src/Toolbar/Toolbar.tsx | 6 +++++- react/src/theme/components/Toolbar.ts | 8 ++++++++ react/src/theme/components/index.ts | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 react/src/theme/components/Toolbar.ts diff --git a/react/src/Toolbar/Toolbar.tsx b/react/src/Toolbar/Toolbar.tsx index e5199551..bb6f2fd9 100644 --- a/react/src/Toolbar/Toolbar.tsx +++ b/react/src/Toolbar/Toolbar.tsx @@ -1,8 +1,12 @@ -import { Flex } from '@chakra-ui/react' +import { createStylesContext, Flex } from '@chakra-ui/react' import { Button } from '~/Button' import { IconButton } from '~/IconButton' +const [ToolbarStylesProvider, useToolbarStyles] = createStylesContext('Toolbar') + +export { useToolbarStyles } + export interface ToolbarProps {} /** diff --git a/react/src/theme/components/Toolbar.ts b/react/src/theme/components/Toolbar.ts new file mode 100644 index 00000000..f76b5ba2 --- /dev/null +++ b/react/src/theme/components/Toolbar.ts @@ -0,0 +1,8 @@ +import { createMultiStyleConfigHelpers } from '@chakra-ui/react' +import { anatomy } from '@chakra-ui/theme-tools' + +const parts = anatomy('toolbar').parts('container') + +const { defineMultiStyleConfig } = createMultiStyleConfigHelpers(parts.keys) + +export const Toolbar = defineMultiStyleConfig({}) diff --git a/react/src/theme/components/index.ts b/react/src/theme/components/index.ts index f31432f8..56e9a8c8 100644 --- a/react/src/theme/components/index.ts +++ b/react/src/theme/components/index.ts @@ -38,6 +38,7 @@ import { Textarea } from './Textarea' import { Tile } from './Tile' import { Toast } from './Toast' import { Toggle } from './Toggle' +import { Toolbar } from './Toolbar' import { Tooltip } from './Tooltip' export const components = { @@ -81,5 +82,6 @@ export const components = { Tile, Toast, Toggle, + Toolbar, Tooltip, } From d7d0aaeb87b9bf48621dc24f194238b7dfc004fc Mon Sep 17 00:00:00 2001 From: Kar Rui Lau Date: Wed, 15 Feb 2023 15:13:59 +0800 Subject: [PATCH 03/12] feat: add getContrastColor util fn to simplify setting colours --- react/src/theme/components/Badge.ts | 7 ++----- react/src/theme/components/Button.ts | 11 +++++------ react/src/theme/utils/contrast.ts | 11 +++++++++++ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/react/src/theme/components/Badge.ts b/react/src/theme/components/Badge.ts index 11d6ae8e..da0a1a39 100644 --- a/react/src/theme/components/Badge.ts +++ b/react/src/theme/components/Badge.ts @@ -1,7 +1,7 @@ import { defineStyle } from '@chakra-ui/react' import { getColor, SystemStyleObject } from '@chakra-ui/theme-tools' -import { meetsWcagAaRatio } from '~/theme/utils/contrast' +import { getContrastColor } from '~/theme/utils/contrast' import { textStyles } from '../textStyles' @@ -27,10 +27,7 @@ const variantSolid = defineStyle((props) => { const bgColor = getColor(theme, solidBgTokenMap[c] ?? `${c}.500`) let textColor = getColor(theme, 'base.content.inverse') - const hasSufficientContrast = meetsWcagAaRatio(textColor, bgColor) - if (!hasSufficientContrast) { - textColor = 'base.content.default' - } + textColor = getContrastColor(textColor, bgColor, 'base.content.default') return { bg: bgColor, diff --git a/react/src/theme/components/Button.ts b/react/src/theme/components/Button.ts index 4ada464b..e3907c01 100644 --- a/react/src/theme/components/Button.ts +++ b/react/src/theme/components/Button.ts @@ -4,7 +4,7 @@ import { merge } from 'lodash' import { layerStyles } from '../layerStyles' import { textStyles } from '../textStyles' -import { meetsWcagAaRatio } from '../utils' +import { getContrastColor } from '../utils' import { hexToRgba } from '../utils/hexToRgba' import { Link } from './Link' @@ -53,14 +53,13 @@ const genVariantSolidColours = ({ } } } - const hasSufficientContrast = meetsWcagAaRatio( + // Note that using the fallback content colour for the button text could still result in bad contrast. + color = getContrastColor( getColor(theme, color), getColor(theme, solidVariantProps.bg), + 'base.content.default', ) - // Note that using the default content colour for the button text could still result in bad contrast. - if (!hasSufficientContrast) { - color = 'base.content.default' - } + return { ...solidVariantProps, color } } diff --git a/react/src/theme/utils/contrast.ts b/react/src/theme/utils/contrast.ts index f0dc38d6..1d57938c 100644 --- a/react/src/theme/utils/contrast.ts +++ b/react/src/theme/utils/contrast.ts @@ -94,3 +94,14 @@ export const getContrast = ( return (Math.max(lum1, lum2) + LUM_FLARE) / (Math.min(lum1, lum2) + LUM_FLARE) } + +export const getContrastColor = ( + fg: string, + bg: string, + fallback: string, +): string => { + if (meetsWcagAaRatio(fg, bg)) { + return fg + } + return fallback +} From 88f5f81fd0a951e52076a900a0e77ced0088e5b7 Mon Sep 17 00:00:00 2001 From: Kar Rui Lau Date: Wed, 15 Feb 2023 15:19:54 +0800 Subject: [PATCH 04/12] feat: add Toolbar container styles --- react/src/Toolbar/Toolbar.stories.tsx | 6 ++- react/src/Toolbar/Toolbar.tsx | 25 +++++++++-- react/src/theme/components/Toolbar.ts | 60 +++++++++++++++++++++++++-- 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/react/src/Toolbar/Toolbar.stories.tsx b/react/src/Toolbar/Toolbar.stories.tsx index b90464e3..7031e405 100644 --- a/react/src/Toolbar/Toolbar.stories.tsx +++ b/react/src/Toolbar/Toolbar.stories.tsx @@ -1,3 +1,4 @@ +import { Text } from '@chakra-ui/react' import { Meta, StoryFn } from '@storybook/react' import { Toolbar, ToolbarProps } from './Toolbar' @@ -11,4 +12,7 @@ export default { const Template: StoryFn = (args) => export const Default = Template.bind({}) -Default.args = {} +Default.args = { + children: Hello, + colorScheme: 'main', +} diff --git a/react/src/Toolbar/Toolbar.tsx b/react/src/Toolbar/Toolbar.tsx index bb6f2fd9..cfc3be87 100644 --- a/react/src/Toolbar/Toolbar.tsx +++ b/react/src/Toolbar/Toolbar.tsx @@ -1,4 +1,12 @@ -import { createStylesContext, Flex } from '@chakra-ui/react' +import { PropsWithChildren } from 'react' +import { + Box, + BoxProps, + createStylesContext, + Flex, + ThemingProps, + useMultiStyleConfig, +} from '@chakra-ui/react' import { Button } from '~/Button' import { IconButton } from '~/IconButton' @@ -7,13 +15,22 @@ const [ToolbarStylesProvider, useToolbarStyles] = createStylesContext('Toolbar') export { useToolbarStyles } -export interface ToolbarProps {} +export interface ToolbarProps extends PropsWithChildren, BoxProps { + colorScheme: ThemingProps<'Toolbar'>['colorScheme'] +} /** * Container for the toolbar. */ -export const Toolbar = ({}: ToolbarProps): JSX.Element => { - return +export const Toolbar = ({ children, ...props }: ToolbarProps): JSX.Element => { + const styles = useMultiStyleConfig('Toolbar', props) + return ( + + + {children} + + + ) } /** diff --git a/react/src/theme/components/Toolbar.ts b/react/src/theme/components/Toolbar.ts index f76b5ba2..fd9f604c 100644 --- a/react/src/theme/components/Toolbar.ts +++ b/react/src/theme/components/Toolbar.ts @@ -1,8 +1,62 @@ import { createMultiStyleConfigHelpers } from '@chakra-ui/react' -import { anatomy } from '@chakra-ui/theme-tools' +import { anatomy, SystemStyleObject } from '@chakra-ui/theme-tools' const parts = anatomy('toolbar').parts('container') -const { defineMultiStyleConfig } = createMultiStyleConfigHelpers(parts.keys) +const { defineMultiStyleConfig, definePartsStyle } = + createMultiStyleConfigHelpers(parts.keys) -export const Toolbar = defineMultiStyleConfig({}) +const baseStyle = definePartsStyle({ + container: { + textStyle: 'subhead-2', + }, +}) + +const getSolidVariantContainerStyles = (c: string): SystemStyleObject => { + switch (c) { + case 'main': + return { + bg: 'interaction.main.default', + color: 'white', + } + case 'neutral': + return { + bg: 'interaction.neutral-subtle.default', + color: 'base.content.default', + } + default: + return { + bg: 'base.bg.default', + } + } +} + +const variantSolid = definePartsStyle(({ colorScheme: c }) => { + return { + container: getSolidVariantContainerStyles(c), + } +}) + +const variants = { + solid: variantSolid, +} + +const sizes = { + md: definePartsStyle({ + container: { + py: '0.625rem', + px: '1rem', + }, + }), +} + +export const Toolbar = defineMultiStyleConfig({ + baseStyle, + variants, + sizes, + defaultProps: { + colorScheme: 'main', + variant: 'solid', + size: 'md', + }, +}) From 248c030fac97ea2f798b8e9126bd39e5b93d2ba0 Mon Sep 17 00:00:00 2001 From: Kar Rui Lau Date: Wed, 15 Feb 2023 15:40:38 +0800 Subject: [PATCH 05/12] fix: correct fontSizes of Buttons at various sizes --- react/src/theme/components/Button.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/react/src/theme/components/Button.ts b/react/src/theme/components/Button.ts index e3907c01..74e02ead 100644 --- a/react/src/theme/components/Button.ts +++ b/react/src/theme/components/Button.ts @@ -295,18 +295,22 @@ const baseStyle = defineStyle({ const sizes = { xs: defineStyle({ + ...textStyles['subhead-2'], minH: '2.25rem', minW: '2.25rem', }), sm: defineStyle({ + ...textStyles['subhead-1'], minH: '2.5rem', minW: '2.5rem', }), md: defineStyle({ + ...textStyles['subhead-1'], minH: '2.75rem', minW: '2.75rem', }), lg: defineStyle({ + ...textStyles['subhead-1'], minH: '3rem', minW: '3rem', }), From 3b31e089f897d63a472f2b5c72ea9363c32825e9 Mon Sep 17 00:00:00 2001 From: Kar Rui Lau Date: Wed, 15 Feb 2023 15:57:01 +0800 Subject: [PATCH 06/12] feat: add ToolbarButton component and styles --- react/src/Toolbar/Toolbar.stories.tsx | 19 +++++++++++-- react/src/Toolbar/Toolbar.tsx | 14 ++++------ react/src/Toolbar/ToolbarButton.tsx | 18 ++++++++++++ react/src/Toolbar/index.ts | 1 + react/src/index.ts | 1 + react/src/theme/components/Toolbar.ts | 40 +++++++++++++++++++++++---- 6 files changed, 76 insertions(+), 17 deletions(-) create mode 100644 react/src/Toolbar/ToolbarButton.tsx diff --git a/react/src/Toolbar/Toolbar.stories.tsx b/react/src/Toolbar/Toolbar.stories.tsx index 7031e405..d70d794d 100644 --- a/react/src/Toolbar/Toolbar.stories.tsx +++ b/react/src/Toolbar/Toolbar.stories.tsx @@ -1,7 +1,10 @@ -import { Text } from '@chakra-ui/react' +import { Spacer, Text } from '@chakra-ui/react' import { Meta, StoryFn } from '@storybook/react' +import { BxUpload } from '..' + import { Toolbar, ToolbarProps } from './Toolbar' +import { ToolbarButton } from './ToolbarButton' export default { title: 'Components/Toolbar', @@ -10,9 +13,19 @@ export default { tags: ['autodocs'], } as Meta -const Template: StoryFn = (args) => +const Template: StoryFn = ({ children, ...args }) => { + return ( + + 1 item selected + + {children} + }> + Button + + + ) +} export const Default = Template.bind({}) Default.args = { - children: Hello, colorScheme: 'main', } diff --git a/react/src/Toolbar/Toolbar.tsx b/react/src/Toolbar/Toolbar.tsx index cfc3be87..0eed3446 100644 --- a/react/src/Toolbar/Toolbar.tsx +++ b/react/src/Toolbar/Toolbar.tsx @@ -1,22 +1,19 @@ import { PropsWithChildren } from 'react' import { - Box, - BoxProps, createStylesContext, Flex, - ThemingProps, + FlexProps, useMultiStyleConfig, } from '@chakra-ui/react' -import { Button } from '~/Button' import { IconButton } from '~/IconButton' const [ToolbarStylesProvider, useToolbarStyles] = createStylesContext('Toolbar') export { useToolbarStyles } -export interface ToolbarProps extends PropsWithChildren, BoxProps { - colorScheme: ThemingProps<'Toolbar'>['colorScheme'] +export interface ToolbarProps extends PropsWithChildren, FlexProps { + colorScheme: 'main' | 'neutral' } /** @@ -26,9 +23,9 @@ export const Toolbar = ({ children, ...props }: ToolbarProps): JSX.Element => { const styles = useMultiStyleConfig('Toolbar', props) return ( - + {children} - + ) } @@ -52,5 +49,4 @@ export const ToolbarDivider = () => { return } -export const ToolbarButton = Button export const ToolbarIconButton = IconButton diff --git a/react/src/Toolbar/ToolbarButton.tsx b/react/src/Toolbar/ToolbarButton.tsx new file mode 100644 index 00000000..eb28a977 --- /dev/null +++ b/react/src/Toolbar/ToolbarButton.tsx @@ -0,0 +1,18 @@ +import { useMemo } from 'react' +import { merge } from 'lodash' + +import { Button, ButtonProps } from '~/Button' + +import { useToolbarStyles } from './Toolbar' + +export type ToolbarButtonProps = ButtonProps + +export const ToolbarButton = (props: ToolbarButtonProps): JSX.Element => { + const styles = useToolbarStyles() + const buttonStyles = useMemo( + () => merge({}, styles.button, props.sx), + [styles.button, props.sx], + ) + + return + + + + + + + + + + + + + + + + +)