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}
+ >
+
+
+
+
+
+
+
+
+
+ Item
+
+
+
+
+
+ )
+}
diff --git a/src/core/components/breadcrumbs/__workshop__/example.tsx b/src/core/components/breadcrumbs/__workshop__/example.tsx
index 446bb3241..df3b0c9ad 100644
--- a/src/core/components/breadcrumbs/__workshop__/example.tsx
+++ b/src/core/components/breadcrumbs/__workshop__/example.tsx
@@ -17,15 +17,17 @@ export default function Example() {
useSelect('Max. length', BREADCRUMBS_MAX_LENGTH_OPTIONS, 0, 'Props') || undefined
return (
-
+
/
}
- space={2}
+ // space={2}
>
Root
diff --git a/src/core/components/breadcrumbs/__workshop__/index.ts b/src/core/components/breadcrumbs/__workshop__/index.ts
index bd5385907..eec0e7793 100644
--- a/src/core/components/breadcrumbs/__workshop__/index.ts
+++ b/src/core/components/breadcrumbs/__workshop__/index.ts
@@ -10,5 +10,10 @@ export default defineScope({
title: 'Example',
component: lazy(() => import('./example')),
},
+ {
+ name: 'buttons',
+ title: 'Buttons',
+ component: lazy(() => import('./buttons')),
+ },
],
})
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 || /}}
+
+ ))}
+
)
})
diff --git a/src/core/primitives/button/__workshop__/mixedChildren.tsx b/src/core/primitives/button/__workshop__/mixedChildren.tsx
index 614a2498d..b586a02a7 100644
--- a/src/core/primitives/button/__workshop__/mixedChildren.tsx
+++ b/src/core/primitives/button/__workshop__/mixedChildren.tsx
@@ -5,7 +5,7 @@ export default function MixedChildrenStory() {
return (
)
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 (
-
+
diff --git a/src/core/primitives/button/__workshop__/sanityUploadButton.tsx b/src/core/primitives/button/__workshop__/sanityUploadButton.tsx
index ff30eacc3..0ed0497be 100644
--- a/src/core/primitives/button/__workshop__/sanityUploadButton.tsx
+++ b/src/core/primitives/button/__workshop__/sanityUploadButton.tsx
@@ -18,7 +18,7 @@ const SanityUploadButton = styled(Button).attrs({forwardedAs: 'label'})`
width: stretch;
}
- & span:nth-child(2) {
+ & > span:nth-child(2) {
width: 0;
flex: none;
padding: 0;
diff --git a/src/core/primitives/button/__workshop__/stacked.tsx b/src/core/primitives/button/__workshop__/stacked.tsx
index d93c751eb..4017c348f 100644
--- a/src/core/primitives/button/__workshop__/stacked.tsx
+++ b/src/core/primitives/button/__workshop__/stacked.tsx
@@ -13,14 +13,14 @@ import {
export default function StackedStory() {
const tones = Object.entries(WORKSHOP_BUTTON_TONE_OPTIONS)
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')
const mode = useSelect('Mode', WORKSHOP_BUTTON_MODE_OPTIONS, 'default', 'Props')
const onClick = useAction('onClick')
- const paddingX = useSelect('Padding X', WORKSHOP_SPACE_OPTIONS, 3, 'Props')
- const paddingY = useSelect('Padding Y', WORKSHOP_SPACE_OPTIONS, 3, 'Props')
+ const paddingX = useSelect('Padding X', WORKSHOP_SPACE_OPTIONS, 2, 'Props')
+ const paddingY = useSelect('Padding Y', WORKSHOP_SPACE_OPTIONS, 2, 'Props')
const selected = useBoolean('Selected', false, 'Props')
const space = useSelect('Space', WORKSHOP_SPACE_OPTIONS, 3, 'Props')
diff --git a/src/core/primitives/button/button.tsx b/src/core/primitives/button/button.tsx
index 96e684cf7..009bdb3d9 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,8 @@ export interface ButtonProps extends ResponsivePaddingProps, ResponsiveRadiusPro
textAlign?: ButtonTextAlign
muted?: boolean
text?: React.ReactNode
+ textOverflow?: TextProps['textOverflow']
+ textWeight?: TextProps['weight']
tone?: ButtonTone
type?: 'button' | 'reset' | 'submit'
width?: ButtonWidth
@@ -85,6 +87,8 @@ export const Button = forwardRef(function Button(
space: spaceProp = 3,
text,
textAlign,
+ textOverflow = 'ellipsis',
+ textWeight,
tone = 'default',
type = 'button',
muted = false,
@@ -104,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,
@@ -139,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;
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 (
{children}
+ } else {
+ children = {children}
}
return (
@@ -80,7 +82,7 @@ export const Text = forwardRef(function Text(
$size={useArrayProp(size)}
$weight={weight}
>
- {children}
+ {children}
)
})
diff --git a/src/core/styles/flex/flexStyle.ts b/src/core/styles/flex/flexStyle.ts
index 3ec7e244a..a4f3b15f8 100644
--- a/src/core/styles/flex/flexStyle.ts
+++ b/src/core/styles/flex/flexStyle.ts
@@ -16,6 +16,8 @@ export function responsiveFlexStyle(): Array<
BASE_STYLE,
responsiveFlexAlignStyle,
responsiveFlexGapStyle,
+ responsiveFlexGapXStyle,
+ responsiveFlexGapYStyle,
responsiveFlexWrapStyle,
responsiveFlexJustifyStyle,
responsiveFlexDirectionStyle,
@@ -40,6 +42,22 @@ function responsiveFlexGapStyle(props: ResponsiveFlexStyleProps & ThemeProps) {
}))
}
+function responsiveFlexGapXStyle(props: ResponsiveFlexStyleProps & ThemeProps) {
+ const {media, space} = getTheme_v2(props.theme)
+
+ return _responsive(media, props.$gapX, (gapX) => ({
+ 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[]
}