From f3a4ff93eb8aa9e3f23ff032b565ae906750ed0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20Lundga=CC=8Ard?= Date: Thu, 28 Nov 2024 12:29:36 +0100 Subject: [PATCH 1/7] feat: add `gapX` and `gapY` property to `Flex` primitive --- src/core/primitives/flex/flex.tsx | 6 +++++- src/core/styles/flex/flexStyle.ts | 18 ++++++++++++++++++ src/core/styles/flex/types.ts | 2 ++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/core/primitives/flex/flex.tsx b/src/core/primitives/flex/flex.tsx index 286d885ce..e34820d35 100644 --- a/src/core/primitives/flex/flex.tsx +++ b/src/core/primitives/flex/flex.tsx @@ -18,6 +18,8 @@ export interface FlexProps ResponsiveFlexProps, ResponsiveFlexItemProps { gap?: number | number[] + gapX?: number | number[] + gapY?: number | number[] } const Root = styled(Box)( @@ -34,7 +36,7 @@ export const Flex = forwardRef(function Flex( props: FlexProps & Omit, 'as' | 'wrap'>, ref: React.ForwardedRef, ) { - const {align, as, direction = 'row', gap, justify, wrap, ...restProps} = props + const {align, as, direction = 'row', gap, gapX, gapY, justify, wrap, ...restProps} = props return ( ({ + columnGap: gapX ? rem(space[gapX]) : undefined, + })) +} + +function responsiveFlexGapYStyle(props: ResponsiveFlexStyleProps & ThemeProps) { + const {media, space} = getTheme_v2(props.theme) + + return _responsive(media, props.$gapY, (gapY) => ({ + rowGap: gapY ? rem(space[gapY]) : undefined, + })) +} + export function responsiveFlexWrapStyle(props: ResponsiveFlexStyleProps & ThemeProps): CSSObject[] { const {media} = getTheme_v2(props.theme) diff --git a/src/core/styles/flex/types.ts b/src/core/styles/flex/types.ts index 062a422d1..9ba94fe93 100644 --- a/src/core/styles/flex/types.ts +++ b/src/core/styles/flex/types.ts @@ -7,6 +7,8 @@ export interface ResponsiveFlexStyleProps { $align: FlexAlign[] $direction: FlexDirection[] $gap: number[] + $gapX: number[] + $gapY: number[] $justify: FlexJustify[] $wrap: FlexWrap[] } From ea58993d65d983a5ca0edde71474566ae672e442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20Lundga=CC=8Ard?= Date: Thu, 28 Nov 2024 12:32:58 +0100 Subject: [PATCH 2/7] feat: support `textOverflow="none"` --- src/core/primitives/button/button.tsx | 6 ++++-- src/core/primitives/heading/heading.tsx | 2 +- src/core/primitives/label/label.tsx | 2 +- src/core/primitives/text/text.tsx | 6 ++++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/core/primitives/button/button.tsx b/src/core/primitives/button/button.tsx index 96e684cf7..242259d4c 100644 --- a/src/core/primitives/button/button.tsx +++ b/src/core/primitives/button/button.tsx @@ -9,7 +9,7 @@ import {ButtonMode, ButtonTextAlign, ButtonTone, ButtonWidth, FlexJustify} from import {Box} from '../box' import {Flex} from '../flex' import {Spinner} from '../spinner' -import {Text} from '../text' +import {Text, TextProps} from '../text' import {ResponsivePaddingProps, ResponsiveRadiusProps} from '../types' import {buttonBaseStyles, buttonColorStyles} from './styles' @@ -32,6 +32,7 @@ export interface ButtonProps extends ResponsivePaddingProps, ResponsiveRadiusPro textAlign?: ButtonTextAlign muted?: boolean text?: React.ReactNode + textOverflow?: TextProps['textOverflow'] tone?: ButtonTone type?: 'button' | 'reset' | 'submit' width?: ButtonWidth @@ -85,6 +86,7 @@ export const Button = forwardRef(function Button( space: spaceProp = 3, text, textAlign, + textOverflow = 'ellipsis', tone = 'default', type = 'button', muted = false, @@ -154,7 +156,7 @@ export const Button = forwardRef(function Button( muted={muted} align={textAlign} size={fontSize} - textOverflow="ellipsis" + textOverflow={textOverflow} weight={button.textWeight} > {text} diff --git a/src/core/primitives/heading/heading.tsx b/src/core/primitives/heading/heading.tsx index c5d2eecd1..a1b5cb4b9 100644 --- a/src/core/primitives/heading/heading.tsx +++ b/src/core/primitives/heading/heading.tsx @@ -26,7 +26,7 @@ export interface HeadingProps { * Use `textOverflow="ellipsis"` to render text as a single line which is concatenated with a `…` symbol. * @beta */ - textOverflow?: 'ellipsis' + textOverflow?: 'ellipsis' | 'none' weight?: ThemeFontWeightKey } diff --git a/src/core/primitives/label/label.tsx b/src/core/primitives/label/label.tsx index cdfc5ec32..028bd1084 100644 --- a/src/core/primitives/label/label.tsx +++ b/src/core/primitives/label/label.tsx @@ -20,7 +20,7 @@ export interface LabelProps { * Use `textOverflow="ellipsis"` to render text as a single line which is concatenated with a `…` symbol. * @beta */ - textOverflow?: 'ellipsis' + textOverflow?: 'ellipsis' | 'none' weight?: ThemeFontWeightKey } diff --git a/src/core/primitives/text/text.tsx b/src/core/primitives/text/text.tsx index 09acafd76..8c1dacfc6 100644 --- a/src/core/primitives/text/text.tsx +++ b/src/core/primitives/text/text.tsx @@ -25,7 +25,7 @@ export interface TextProps { * Use `textOverflow="ellipsis"` to render text as a single line which is concatenated with a `…` symbol. * @beta */ - textOverflow?: 'ellipsis' + textOverflow?: 'ellipsis' | 'none' weight?: ThemeFontWeightKey } @@ -67,6 +67,8 @@ export const Text = forwardRef(function Text( if (textOverflow === 'ellipsis') { children = {children} + } else { + children = {children} } return ( @@ -80,7 +82,7 @@ export const Text = forwardRef(function Text( $size={useArrayProp(size)} $weight={weight} > - {children} + {children} ) }) From 3aa5c3bcb81956e0db944d283e0fe300344bcadd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20Lundga=CC=8Ard?= Date: Thu, 28 Nov 2024 12:31:43 +0100 Subject: [PATCH 3/7] feat: add `textWeight` property to `Button` --- src/core/primitives/button/button.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/primitives/button/button.tsx b/src/core/primitives/button/button.tsx index 242259d4c..bd5bd66bf 100644 --- a/src/core/primitives/button/button.tsx +++ b/src/core/primitives/button/button.tsx @@ -33,6 +33,7 @@ export interface ButtonProps extends ResponsivePaddingProps, ResponsiveRadiusPro muted?: boolean text?: React.ReactNode textOverflow?: TextProps['textOverflow'] + textWeight?: TextProps['weight'] tone?: ButtonTone type?: 'button' | 'reset' | 'submit' width?: ButtonWidth @@ -87,6 +88,7 @@ export const Button = forwardRef(function Button( text, textAlign, textOverflow = 'ellipsis', + textWeight, tone = 'default', type = 'button', muted = false, @@ -157,7 +159,7 @@ export const Button = forwardRef(function Button( align={textAlign} size={fontSize} textOverflow={textOverflow} - weight={button.textWeight} + weight={textWeight ?? button.textWeight} > {text} From 172c7b8052b275b8091ef457da822dc5339d619e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20Lundga=CC=8Ard?= Date: Thu, 28 Nov 2024 12:38:50 +0100 Subject: [PATCH 4/7] fix(text): fix default text styling --- src/core/primitives/text/styles.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/primitives/text/styles.ts b/src/core/primitives/text/styles.ts index 858732806..efe0c8479 100644 --- a/src/core/primitives/text/styles.ts +++ b/src/core/primitives/text/styles.ts @@ -9,6 +9,7 @@ export function textBaseStyle( const {font} = getTheme_v2(props.theme) return css` + min-width: 0; color: var(--card-fg-color); ${$accent && From bf29e2a2e1b644cb332bcceac4f0b896ce15ff0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20Lundga=CC=8Ard?= Date: Thu, 28 Nov 2024 13:05:01 +0100 Subject: [PATCH 5/7] fix(button): improve flex layout --- src/core/primitives/button/button.tsx | 55 ++++++++++++++------------- src/core/primitives/button/styles.ts | 2 +- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/core/primitives/button/button.tsx b/src/core/primitives/button/button.tsx index bd5bd66bf..009bdb3d9 100644 --- a/src/core/primitives/button/button.tsx +++ b/src/core/primitives/button/button.tsx @@ -108,9 +108,8 @@ export const Button = forwardRef(function Button( const radius = useArrayProp(radiusProp) const space = useArrayProp(spaceProp) - const boxProps = useMemo( + const paddingProps = useMemo( () => ({ - // flex: 1, padding, paddingX, paddingY, @@ -143,45 +142,49 @@ export const Button = forwardRef(function Button( )} {(IconComponent || text || IconRightComponent) && ( - - - {IconComponent && ( - + + {IconComponent && ( + + {isValidElement(IconComponent) && IconComponent} {isValidElementType(IconComponent) && } - )} + + )} - {text && ( - - - {text} - - - )} + {text && ( + + + {text} + + + )} - {IconRightComponent && ( - + {IconRightComponent && ( + + {isValidElement(IconRightComponent) && IconRightComponent} {isValidElementType(IconRightComponent) && } - )} - - + + )} + )} {children && ( - + {children} )} ) }) + Button.displayName = 'ForwardRef(Button)' diff --git a/src/core/primitives/button/styles.ts b/src/core/primitives/button/styles.ts index 89760eeb2..154e3414f 100644 --- a/src/core/primitives/button/styles.ts +++ b/src/core/primitives/button/styles.ts @@ -29,8 +29,8 @@ export function buttonBaseStyles( border: 0; box-sizing: border-box; padding: 0; + overflow: hidden; margin: 0; - white-space: nowrap; text-align: left; position: relative; vertical-align: top; From 4ac85982f620e5a26744f08a0865696236497eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20Lundga=CC=8Ard?= Date: Thu, 28 Nov 2024 13:47:14 +0100 Subject: [PATCH 6/7] fix(breadcrumbs): improve `Breadcrumbs` component --- .../breadcrumbs/breadcrumbs.styles.ts | 14 +--- .../components/breadcrumbs/breadcrumbs.tsx | 65 ++++++++++++------- 2 files changed, 44 insertions(+), 35 deletions(-) diff --git a/src/core/components/breadcrumbs/breadcrumbs.styles.ts b/src/core/components/breadcrumbs/breadcrumbs.styles.ts index 6d69d939a..5af78c328 100644 --- a/src/core/components/breadcrumbs/breadcrumbs.styles.ts +++ b/src/core/components/breadcrumbs/breadcrumbs.styles.ts @@ -1,17 +1,5 @@ import {styled} from 'styled-components' -import {Button} from '../../primitives' -export const Root = styled.ol` - margin: 0; - padding: 0; - display: flex; - list-style: none; - align-items: center; - white-space: nowrap; +export const Root = styled.nav` line-height: 0; ` - -export const ExpandButton = styled(Button)` - appearance: none; - margin: -4px; -` diff --git a/src/core/components/breadcrumbs/breadcrumbs.tsx b/src/core/components/breadcrumbs/breadcrumbs.tsx index 4a184e444..3e5985592 100644 --- a/src/core/components/breadcrumbs/breadcrumbs.tsx +++ b/src/core/components/breadcrumbs/breadcrumbs.tsx @@ -1,26 +1,36 @@ import { Children, + CSSProperties, forwardRef, - Fragment, isValidElement, useCallback, useMemo, useRef, useState, } from 'react' -import {useArrayProp, useClickOutsideEvent} from '../../hooks' -import {Box, Popover, Stack, Text} from '../../primitives' -import {ExpandButton, Root} from './breadcrumbs.styles' +import {useClickOutsideEvent} from '../../hooks' +import {Box, Button, ButtonProps, Flex, Popover, Stack, Text} from '../../primitives' +import {Root} from './breadcrumbs.styles' /** * @beta */ export interface BreadcrumbsProps { + expandButton?: Omit & {style?: CSSProperties} + gap?: number | number[] + gapX?: number | number[] + gapY?: number | number[] maxLength?: number separator?: React.ReactNode + /** @deprecated - Use `gap`, `gapX`, `gapY` instead */ space?: number | number[] } +const DEFAULT_EXPAND_BUTTON_PROPS: BreadcrumbsProps['expandButton'] = { + padding: 1, + style: {margin: '-4px 0'}, +} + /** * @beta */ @@ -28,8 +38,19 @@ export const Breadcrumbs = forwardRef(function Breadcrumbs( props: BreadcrumbsProps & Omit, 'as' | 'ref' | 'type'>, ref: React.ForwardedRef, ) { - const {children, maxLength, separator, space: spaceRaw = 2, ...restProps} = props - const space = useArrayProp(spaceRaw) + const { + children, + expandButton: expandButtonProps = DEFAULT_EXPAND_BUTTON_PROPS, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + gap: _gapProp, + gapX = props.gap ?? props.space ?? 2, + gapY = props.gap ?? props.space ?? 2, + maxLength, + separator, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + space: _spaceProp, + ...restProps + } = props const [open, setOpen] = useState(false) const expandElementRef = useRef(null) const popoverElementRef = useRef(null) @@ -53,24 +74,24 @@ export const Breadcrumbs = forwardRef(function Breadcrumbs( + {rawItems.slice(beforeLength - 1, len - afterLength)} } key="button" open={open} + padding={2} placement="top" portal ref={popoverElementRef} > - , ...rawItems.slice(len - afterLength), @@ -78,20 +99,20 @@ export const Breadcrumbs = forwardRef(function Breadcrumbs( } return rawItems - }, [collapse, expand, maxLength, open, rawItems, space]) + }, [collapse, expand, expandButtonProps, gapY, maxLength, open, rawItems]) + + const len = items.length return ( - {items.map((item, itemIndex) => ( - - {itemIndex > 0 && ( - - {separator || /} - - )} - {item} - - ))} + + {items.map((item, itemIndex) => ( + + {item} + {itemIndex < len - 1 && {separator || /}} + + ))} + ) }) From 36b6a13afbebf77d079741a7cfdc2f89f5fe76b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20Lundga=CC=8Ard?= Date: Thu, 28 Nov 2024 13:41:30 +0100 Subject: [PATCH 7/7] test: update workshop stories --- src/core/__workshop__/constants.ts | 4 +- .../breadcrumbs/__workshop__/buttons.tsx | 58 +++++++++++++++++++ .../breadcrumbs/__workshop__/example.tsx | 6 +- .../breadcrumbs/__workshop__/index.ts | 5 ++ .../button/__workshop__/mixedChildren.tsx | 2 +- .../primitives/button/__workshop__/props.tsx | 12 +++- .../__workshop__/sanityUploadButton.tsx | 2 +- .../button/__workshop__/stacked.tsx | 6 +- .../primitives/label/__workshop__/plain.tsx | 2 +- 9 files changed, 85 insertions(+), 12 deletions(-) create mode 100644 src/core/components/breadcrumbs/__workshop__/buttons.tsx diff --git a/src/core/__workshop__/constants.ts b/src/core/__workshop__/constants.ts index fa1df6c49..0b0cfd391 100644 --- a/src/core/__workshop__/constants.ts +++ b/src/core/__workshop__/constants.ts @@ -251,8 +251,8 @@ export const WORKSHOP_TEXT_INPUT_TYPE_OPTIONS: {[key: string]: TextInputType} = 'color': 'color', } -export const WORKSHOP_TEXT_OVERFLOW_OPTIONS: {[key: string]: 'ellipsis' | ''} = { - None: '', +export const WORKSHOP_TEXT_OVERFLOW_OPTIONS: {[key: string]: 'ellipsis' | 'none'} = { + None: 'none', Ellipsis: 'ellipsis', } diff --git a/src/core/components/breadcrumbs/__workshop__/buttons.tsx b/src/core/components/breadcrumbs/__workshop__/buttons.tsx new file mode 100644 index 000000000..2cd7cfe59 --- /dev/null +++ b/src/core/components/breadcrumbs/__workshop__/buttons.tsx @@ -0,0 +1,58 @@ +import {ChevronRightIcon} from '@sanity/icons' +import {Box, Breadcrumbs, Button, Card, Flex, Text} from '@sanity/ui' +import {useSelect} from '@sanity/ui-workshop' + +const BREADCRUMBS_MAX_LENGTH_OPTIONS = { + '(none)': 0, + '1': 1, + '2': 2, + '3': 3, + '4': 4, + '5': 5, + '6': 6, + '7': 7, +} + +export default function Example() { + const maxLength = + useSelect('Max. length', BREADCRUMBS_MAX_LENGTH_OPTIONS, 0, 'Props') || undefined + + return ( + + + + + + + + } + // space={0} + > + ) diff --git a/src/core/primitives/button/__workshop__/props.tsx b/src/core/primitives/button/__workshop__/props.tsx index ecca2863e..6e167ddf9 100644 --- a/src/core/primitives/button/__workshop__/props.tsx +++ b/src/core/primitives/button/__workshop__/props.tsx @@ -9,11 +9,12 @@ import { WORKSHOP_ICON_SYMBOL_OPTIONS, WORKSHOP_TEXT_SIZE_OPTIONS, WORKSHOP_SPACE_OPTIONS, + WORKSHOP_TEXT_OVERFLOW_OPTIONS, } from '../../../__workshop__/constants' export default function ButtonStory() { const disabled = useBoolean('Disabled', false, 'Props') - const fontSize = useSelect('Font size', WORKSHOP_TEXT_SIZE_OPTIONS, 2, 'Props') + const fontSize = useSelect('Font size', WORKSHOP_TEXT_SIZE_OPTIONS, 1, 'Props') const icon = useSelect('Icon', WORKSHOP_ICON_SYMBOL_OPTIONS, 'add-circle', 'Props') const iconRight = useSelect('Icon (right)', WORKSHOP_ICON_SYMBOL_OPTIONS, '', 'Props') const justify = useSelect('Justify', WORKSHOP_FLEX_JUSTIFY_OPTIONS, 'center', 'Props') @@ -26,9 +27,15 @@ export default function ButtonStory() { const textAlign = useSelect('Text align', WORKSHOP_BUTTON_TEXT_ALIGN_OPTIONS, undefined, 'Props') || undefined const textProp = useText('Text', 'Label', 'Props') + const textOverflow = useSelect( + 'Text overflow', + WORKSHOP_TEXT_OVERFLOW_OPTIONS, + 'ellipsis', + 'Props', + ) return ( - +