@sanity/ui 2.0.0-alpha.2 → 2.0.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.mjs +28 -0
- package/dist/index.d.ts +476 -12
- package/dist/index.esm.js +1326 -524
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1353 -523
- package/dist/index.js.map +1 -1
- package/package.json +6 -8
- package/src/components/autocomplete/autocomplete.tsx +6 -0
- package/src/components/dialog/constants.ts +4 -0
- package/src/components/dialog/dialog.tsx +79 -15
- package/src/components/hotkeys/hotkeys.tsx +2 -0
- package/src/components/menu/menu.tsx +2 -0
- package/src/components/menu/menuButton.tsx +2 -0
- package/src/components/menu/menuGroup.tsx +22 -23
- package/src/components/menu/menuItem.tsx +29 -35
- package/src/components/tab/tab.tsx +4 -1
- package/src/components/toast/toast.tsx +4 -0
- package/src/primitives/_selectable/style.ts +2 -1
- package/src/primitives/avatar/avatar.tsx +16 -9
- package/src/primitives/avatar/avatarCounter.tsx +3 -3
- package/src/primitives/avatar/styles.ts +1 -1
- package/src/primitives/badge/badge.tsx +7 -3
- package/src/primitives/box/box.tsx +3 -0
- package/src/primitives/button/__workshop__/sanityUploadButton.tsx +2 -1
- package/src/primitives/button/button.tsx +7 -3
- package/src/primitives/button/styles.ts +9 -2
- package/src/primitives/card/card.tsx +4 -0
- package/src/primitives/card/styles.ts +2 -0
- package/src/primitives/checkbox/checkbox.tsx +2 -0
- package/src/primitives/code/code.tsx +1 -0
- package/src/primitives/container/container.tsx +2 -0
- package/src/primitives/flex/flex.tsx +2 -0
- package/src/primitives/grid/grid.tsx +2 -0
- package/src/primitives/heading/heading.tsx +2 -0
- package/src/primitives/inline/inline.tsx +3 -0
- package/src/primitives/kbd/kbd.tsx +2 -0
- package/src/primitives/label/label.tsx +2 -0
- package/src/primitives/popover/popover.tsx +6 -1
- package/src/primitives/radio/radio.tsx +2 -0
- package/src/primitives/select/select.tsx +2 -0
- package/src/primitives/select/styles.ts +2 -0
- package/src/primitives/spinner/spinner.tsx +2 -0
- package/src/primitives/stack/stack.tsx +2 -0
- package/src/primitives/switch/switch.tsx +4 -0
- package/src/primitives/text/text.tsx +3 -0
- package/src/primitives/textArea/textArea.tsx +4 -1
- package/src/primitives/textInput/textInput.tsx +10 -1
- package/src/primitives/tooltip/__workshop__/customPortal.tsx +99 -0
- package/src/primitives/tooltip/__workshop__/index.ts +15 -0
- package/src/primitives/tooltip/__workshop__/overflowingBoundary.tsx +73 -0
- package/src/primitives/tooltip/__workshop__/resizableBoundary.tsx +85 -0
- package/src/primitives/tooltip/constants.ts +1 -0
- package/src/primitives/tooltip/tooltip.test.tsx +192 -0
- package/src/primitives/tooltip/tooltip.tsx +109 -33
- package/src/primitives/types.ts +4 -0
- package/src/styles/input/textInputStyle.ts +11 -6
- package/src/theme/_internal/__workshop__/build/story.tsx +288 -0
- package/src/theme/_internal/__workshop__/build/theme.ts +3 -0
- package/src/theme/_internal/__workshop__/index.ts +14 -0
- package/src/theme/_internal/build/buildTheme.test.ts +78 -0
- package/src/theme/_internal/build/buildTheme.ts +16 -0
- package/src/theme/_internal/build/colorTheme/buildColorTheme.test.ts +185 -0
- package/src/theme/_internal/build/colorTheme/buildColorTheme.ts +164 -0
- package/src/theme/_internal/build/colorTheme/renderColorTheme.ts +242 -0
- package/src/theme/_internal/build/colorTheme/resolveColorTokens.ts +121 -0
- package/src/theme/_internal/build/defaults/colorPalette.ts +8 -0
- package/src/theme/_internal/build/defaults/colorTokens.ts +147 -0
- package/src/theme/_internal/build/helpers.ts +65 -0
- package/src/theme/_internal/build/index.ts +1 -0
- package/src/theme/_internal/config/helpers.ts +47 -0
- package/src/theme/_internal/config/index.ts +3 -0
- package/src/theme/_internal/config/token/index.ts +2 -0
- package/src/theme/_internal/config/token/parseTokenKey.test.ts +72 -0
- package/src/theme/_internal/config/token/parseTokenKey.ts +88 -0
- package/src/theme/_internal/config/token/parseTokenValue.test.ts +45 -0
- package/src/theme/_internal/config/token/parseTokenValue.ts +123 -0
- package/src/theme/_internal/config/types.ts +137 -0
- package/src/theme/_internal/constants.ts +48 -0
- package/src/theme/_internal/helpers.ts +19 -0
- package/src/theme/_internal/index.ts +5 -0
- package/src/theme/_internal/types.ts +91 -0
- package/src/theme/index.ts +1 -0
- package/src/theme/lib/color-fns/blend/multiply.ts +2 -2
- package/src/theme/lib/color-fns/blend/screen.ts +2 -2
- package/src/theme/lib/color-fns/convert.ts +15 -1
- package/src/theme/lib/color-fns/parse.ts +7 -3
- package/src/theme/lib/color-fns/types.ts +11 -0
- package/src/theme/lib/theme/avatar.ts +2 -0
- package/src/theme/lib/theme/color/_legacy/createColorTheme.ts +7 -0
- package/src/theme/lib/theme/color/_legacy/index.ts +1 -0
- package/src/theme/lib/theme/color/_legacy/legacyColor.ts +3997 -0
- package/src/theme/studioTheme/color.ts +98 -82
- package/src/theme/studioTheme/helpers.ts +15 -1
- package/src/theme/studioTheme/theme.ts +5 -5
- package/src/theme/studioTheme/tints.ts +244 -84
- package/src/types/button.ts +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/ui",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.21",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"source": "./src/index.ts",
|
|
@@ -44,15 +44,15 @@
|
|
|
44
44
|
"test": "jest",
|
|
45
45
|
"test:browser": "start-server-and-test 'run-s workshop:build workshop:start' http://localhost:1337 'run-s cypress:run'",
|
|
46
46
|
"watch": "pkg watch --strict",
|
|
47
|
-
"workshop:build": "
|
|
48
|
-
"workshop:dev": "
|
|
47
|
+
"workshop:build": "workshop build",
|
|
48
|
+
"workshop:dev": "workshop dev",
|
|
49
49
|
"workshop:start": "http-server -a localhost -c-0 -p 1337 -s -P http://localhost:1337/index.html? dist",
|
|
50
50
|
"storybook": "storybook dev -p 6006",
|
|
51
51
|
"build-storybook": "storybook build"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@floating-ui/react-dom": "2.0.0",
|
|
55
|
-
"@sanity/color": "
|
|
55
|
+
"@sanity/color": "3.0.0-beta.6",
|
|
56
56
|
"@sanity/icons": "^2.4.1",
|
|
57
57
|
"csstype": "^3.1.2",
|
|
58
58
|
"framer-motion": "^10.16.2",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"@juggle/resize-observer": "^3.4.0",
|
|
69
69
|
"@sanity/pkg-utils": "^2.4.8",
|
|
70
70
|
"@sanity/semantic-release-preset": "^4.1.4",
|
|
71
|
-
"@sanity/ui-workshop": "^
|
|
71
|
+
"@sanity/ui-workshop": "^2.0.0",
|
|
72
72
|
"@storybook/addon-a11y": "^7.4.5",
|
|
73
73
|
"@storybook/addon-docs": "^7.4.5",
|
|
74
74
|
"@storybook/addon-essentials": "^7.4.5",
|
|
@@ -100,8 +100,6 @@
|
|
|
100
100
|
"cypress": "^13.1.0",
|
|
101
101
|
"cypress-real-events": "^1.10.1",
|
|
102
102
|
"cz-conventional-changelog": "^3.3.0",
|
|
103
|
-
"esbuild": "^0.19.2",
|
|
104
|
-
"esbuild-register": "^3.4.2",
|
|
105
103
|
"eslint": "^8.48.0",
|
|
106
104
|
"eslint-config-prettier": "^9.0.0",
|
|
107
105
|
"eslint-plugin-import": "^2.28.1",
|
|
@@ -126,7 +124,7 @@
|
|
|
126
124
|
"rimraf": "^5.0.1",
|
|
127
125
|
"semantic-release": "^21.1.1",
|
|
128
126
|
"start-server-and-test": "^2.0.0",
|
|
129
|
-
"storybook": "^7.
|
|
127
|
+
"storybook": "^7.5.2",
|
|
130
128
|
"styled-components": "^6.0.7",
|
|
131
129
|
"tsconfig-paths": "^4.2.0",
|
|
132
130
|
"typescript": "^5.2.2"
|
|
@@ -60,6 +60,7 @@ export interface AutocompleteProps<Option extends BaseAutocompleteOption = BaseA
|
|
|
60
60
|
onSelect?: (value: string) => void
|
|
61
61
|
/** @beta */
|
|
62
62
|
openButton?: boolean | AutocompleteOpenButtonProps
|
|
63
|
+
/** The options to render. */
|
|
63
64
|
options?: Option[]
|
|
64
65
|
padding?: number | number[]
|
|
65
66
|
popover?: Omit<PopoverProps, 'content' | 'onMouseEnter' | 'onMouseLeave' | 'open'> &
|
|
@@ -68,6 +69,7 @@ export interface AutocompleteProps<Option extends BaseAutocompleteOption = BaseA
|
|
|
68
69
|
radius?: Radius | Radius[]
|
|
69
70
|
/** @beta */
|
|
70
71
|
relatedElements?: HTMLElement[]
|
|
72
|
+
/** The callback function for rendering each option. */
|
|
71
73
|
renderOption?: (option: Option) => ReactElement
|
|
72
74
|
/** @beta */
|
|
73
75
|
renderPopover?: (
|
|
@@ -82,6 +84,7 @@ export interface AutocompleteProps<Option extends BaseAutocompleteOption = BaseA
|
|
|
82
84
|
) => ReactNode
|
|
83
85
|
renderValue?: (value: string, option?: Option) => string
|
|
84
86
|
suffix?: ReactNode
|
|
87
|
+
/** The current value. */
|
|
85
88
|
value?: string
|
|
86
89
|
}
|
|
87
90
|
|
|
@@ -684,6 +687,9 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
|
|
|
684
687
|
})
|
|
685
688
|
|
|
686
689
|
/**
|
|
690
|
+
* The Autocomplete component is typically used for search components.
|
|
691
|
+
* It consists of a text input for writing a query, and properties for rendering suggestions.
|
|
692
|
+
*
|
|
687
693
|
* @public
|
|
688
694
|
*/
|
|
689
695
|
export const Autocomplete = InnerAutocomplete as <Option extends BaseAutocompleteOption>(
|
|
@@ -8,12 +8,13 @@ import {
|
|
|
8
8
|
isHTMLElement,
|
|
9
9
|
} from '../../helpers'
|
|
10
10
|
import {useArrayProp, useClickOutside, useForwardedRef, useGlobalKeyDown} from '../../hooks'
|
|
11
|
-
import {Box, Button, Card, Container, Flex, Text} from '../../primitives'
|
|
11
|
+
import {Box, Button, Card, CardProps, Container, Flex, Text} from '../../primitives'
|
|
12
12
|
import {ResponsivePaddingProps, ResponsiveWidthProps} from '../../primitives/types'
|
|
13
13
|
import {responsivePaddingStyle, ResponsivePaddingStyleProps} from '../../styles/internal'
|
|
14
14
|
import {ThemeColorSchemeKey, useTheme} from '../../theme'
|
|
15
15
|
import {DialogPosition, Radius} from '../../types'
|
|
16
16
|
import {Layer, LayerProps, Portal, useBoundaryElement, useLayer, usePortal} from '../../utils'
|
|
17
|
+
import {BORDER_OFFSET_X} from './constants'
|
|
17
18
|
import {
|
|
18
19
|
dialogStyle,
|
|
19
20
|
responsiveDialogPositionStyle,
|
|
@@ -71,6 +72,15 @@ interface DialogCardProps extends ResponsiveWidthProps {
|
|
|
71
72
|
shadow: number | number[]
|
|
72
73
|
}
|
|
73
74
|
|
|
75
|
+
interface DialogHeaderProps extends CardProps {
|
|
76
|
+
$hasScrolledFromTop: boolean
|
|
77
|
+
$isContentScrollable: boolean
|
|
78
|
+
}
|
|
79
|
+
interface DialogFooterProps extends CardProps {
|
|
80
|
+
$hasScrolledToBottom: boolean
|
|
81
|
+
$isContentScrollable: boolean
|
|
82
|
+
}
|
|
83
|
+
|
|
74
84
|
function isTargetWithinScope(
|
|
75
85
|
boundaryElement: HTMLElement | null,
|
|
76
86
|
portalElement: HTMLElement | null,
|
|
@@ -118,7 +128,7 @@ const DialogLayout = styled(Flex)`
|
|
|
118
128
|
width: 100%;
|
|
119
129
|
`
|
|
120
130
|
|
|
121
|
-
const DialogHeader = styled(
|
|
131
|
+
const DialogHeader = styled(Box)<DialogHeaderProps>`
|
|
122
132
|
position: relative;
|
|
123
133
|
z-index: 2;
|
|
124
134
|
|
|
@@ -126,10 +136,13 @@ const DialogHeader = styled(Card)`
|
|
|
126
136
|
content: '';
|
|
127
137
|
display: block;
|
|
128
138
|
position: absolute;
|
|
129
|
-
left:
|
|
130
|
-
right:
|
|
139
|
+
left: ${BORDER_OFFSET_X}px;
|
|
140
|
+
right: ${BORDER_OFFSET_X}px;
|
|
131
141
|
bottom: -1px;
|
|
132
|
-
border-bottom: 1px solid var(--card-
|
|
142
|
+
border-bottom: 1px solid var(--card-border-color);
|
|
143
|
+
width: auto;
|
|
144
|
+
opacity: ${(props) => (props.$isContentScrollable && props.$hasScrolledFromTop ? 1 : 0)};
|
|
145
|
+
transition: opacity 200ms ease-in;
|
|
133
146
|
}
|
|
134
147
|
`
|
|
135
148
|
|
|
@@ -140,10 +153,22 @@ const DialogContent = styled(Box)`
|
|
|
140
153
|
outline: none;
|
|
141
154
|
`
|
|
142
155
|
|
|
143
|
-
const DialogFooter = styled(Box)
|
|
156
|
+
const DialogFooter = styled(Box)<DialogFooterProps>`
|
|
144
157
|
position: relative;
|
|
145
158
|
z-index: 3;
|
|
146
|
-
|
|
159
|
+
|
|
160
|
+
&:before {
|
|
161
|
+
content: '';
|
|
162
|
+
display: block;
|
|
163
|
+
position: absolute;
|
|
164
|
+
left: ${BORDER_OFFSET_X}px;
|
|
165
|
+
right: ${BORDER_OFFSET_X}px;
|
|
166
|
+
top: -1px;
|
|
167
|
+
border-top: 1px solid var(--card-border-color);
|
|
168
|
+
width: auto;
|
|
169
|
+
opacity: ${(props) => (props.$isContentScrollable && !props.$hasScrolledToBottom ? 1 : 0)};
|
|
170
|
+
transition: opacity 200ms ease-in;
|
|
171
|
+
}
|
|
147
172
|
`
|
|
148
173
|
|
|
149
174
|
const DialogCard = forwardRef(function DialogCard(
|
|
@@ -180,6 +205,9 @@ const DialogCard = forwardRef(function DialogCard(
|
|
|
180
205
|
const labelId = `${id}_label`
|
|
181
206
|
const showCloseButton = Boolean(onClose) && hideCloseButton === false
|
|
182
207
|
const showHeader = Boolean(header) || showCloseButton
|
|
208
|
+
const [isContentScrollable, setIsContentScrollable] = useState(false)
|
|
209
|
+
const [hasScrolledFromTop, setHasScrolledFromTop] = useState(false)
|
|
210
|
+
const [hasScrolledToBottom, setHasScrolledToBottom] = useState(false)
|
|
183
211
|
|
|
184
212
|
useEffect(() => {
|
|
185
213
|
if (!autoFocus) return
|
|
@@ -248,29 +276,56 @@ const DialogCard = forwardRef(function DialogCard(
|
|
|
248
276
|
[contentRef],
|
|
249
277
|
)
|
|
250
278
|
|
|
279
|
+
const handleContentUpdate = useCallback(() => {
|
|
280
|
+
if (localContentRef.current) {
|
|
281
|
+
setIsContentScrollable(
|
|
282
|
+
localContentRef.current.clientHeight < localContentRef.current.scrollHeight,
|
|
283
|
+
)
|
|
284
|
+
setHasScrolledFromTop(localContentRef.current.scrollTop > 0)
|
|
285
|
+
setHasScrolledToBottom(
|
|
286
|
+
localContentRef.current.scrollTop >=
|
|
287
|
+
localContentRef.current.scrollHeight - localContentRef.current.clientHeight,
|
|
288
|
+
)
|
|
289
|
+
}
|
|
290
|
+
}, [])
|
|
291
|
+
|
|
292
|
+
useEffect(() => {
|
|
293
|
+
const resizeObserver = new ResizeObserver(handleContentUpdate)
|
|
294
|
+
|
|
295
|
+
if (localContentRef.current) {
|
|
296
|
+
resizeObserver.observe(localContentRef.current)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return () => {
|
|
300
|
+
resizeObserver.disconnect()
|
|
301
|
+
}
|
|
302
|
+
}, [contentRef, handleContentUpdate])
|
|
303
|
+
|
|
251
304
|
return (
|
|
252
305
|
<DialogContainer data-ui="DialogCard" width={width}>
|
|
253
306
|
<DialogCardRoot radius={radius} ref={setRef} scheme={scheme} shadow={shadow}>
|
|
254
307
|
<DialogLayout direction="column">
|
|
255
308
|
{showHeader && (
|
|
256
|
-
<DialogHeader
|
|
257
|
-
|
|
258
|
-
|
|
309
|
+
<DialogHeader
|
|
310
|
+
$isContentScrollable={isContentScrollable}
|
|
311
|
+
$hasScrolledFromTop={hasScrolledFromTop}
|
|
312
|
+
>
|
|
313
|
+
<Flex align="center">
|
|
314
|
+
<Box flex={1} margin={1} padding={4}>
|
|
259
315
|
{header && (
|
|
260
|
-
<Text id={labelId} weight="
|
|
316
|
+
<Text id={labelId} size={1} weight="medium">
|
|
261
317
|
{header}
|
|
262
318
|
</Text>
|
|
263
319
|
)}
|
|
264
320
|
</Box>
|
|
265
321
|
{showCloseButton && (
|
|
266
|
-
<Box padding={
|
|
322
|
+
<Box padding={3}>
|
|
267
323
|
<Button
|
|
268
324
|
aria-label="Close dialog"
|
|
269
325
|
disabled={!onClose}
|
|
270
326
|
icon={CloseIcon}
|
|
271
327
|
mode="bleed"
|
|
272
328
|
onClick={onClose}
|
|
273
|
-
padding={3}
|
|
274
329
|
/>
|
|
275
330
|
</Box>
|
|
276
331
|
)}
|
|
@@ -278,11 +333,18 @@ const DialogCard = forwardRef(function DialogCard(
|
|
|
278
333
|
</DialogHeader>
|
|
279
334
|
)}
|
|
280
335
|
|
|
281
|
-
<DialogContent flex={1} ref={setContentRef} tabIndex={-1}>
|
|
336
|
+
<DialogContent flex={1} ref={setContentRef} tabIndex={-1} onScroll={handleContentUpdate}>
|
|
282
337
|
{children}
|
|
283
338
|
</DialogContent>
|
|
284
339
|
|
|
285
|
-
{footer &&
|
|
340
|
+
{footer && (
|
|
341
|
+
<DialogFooter
|
|
342
|
+
$isContentScrollable={isContentScrollable}
|
|
343
|
+
$hasScrolledToBottom={hasScrolledToBottom}
|
|
344
|
+
>
|
|
345
|
+
{footer}
|
|
346
|
+
</DialogFooter>
|
|
347
|
+
)}
|
|
286
348
|
</DialogLayout>
|
|
287
349
|
</DialogCardRoot>
|
|
288
350
|
</DialogContainer>
|
|
@@ -290,6 +352,8 @@ const DialogCard = forwardRef(function DialogCard(
|
|
|
290
352
|
})
|
|
291
353
|
|
|
292
354
|
/**
|
|
355
|
+
* The Dialog component.
|
|
356
|
+
*
|
|
293
357
|
* @public
|
|
294
358
|
*/
|
|
295
359
|
export const Dialog = forwardRef(function Dialog(
|
|
@@ -4,6 +4,7 @@ import {isValidElementType} from 'react-is'
|
|
|
4
4
|
import {useArrayProp} from '../../hooks'
|
|
5
5
|
import {Box, Flex, Popover, PopoverProps, Text} from '../../primitives'
|
|
6
6
|
import {Selectable} from '../../primitives/_selectable'
|
|
7
|
+
import {useRootTheme} from '../../theme'
|
|
7
8
|
import {Radius, SelectableTone} from '../../types'
|
|
8
9
|
import {Menu} from './menu'
|
|
9
10
|
import {useMenu} from './useMenu'
|
|
@@ -33,7 +34,7 @@ export function MenuGroup(
|
|
|
33
34
|
const {
|
|
34
35
|
as = 'button',
|
|
35
36
|
children,
|
|
36
|
-
fontSize,
|
|
37
|
+
fontSize = 1,
|
|
37
38
|
icon,
|
|
38
39
|
onClick,
|
|
39
40
|
padding = 3,
|
|
@@ -45,6 +46,7 @@ export function MenuGroup(
|
|
|
45
46
|
...restProps
|
|
46
47
|
} = props
|
|
47
48
|
const menu = useMenu()
|
|
49
|
+
const {scheme} = useRootTheme()
|
|
48
50
|
const {
|
|
49
51
|
activeElement,
|
|
50
52
|
mount,
|
|
@@ -166,6 +168,7 @@ export function MenuGroup(
|
|
|
166
168
|
data-selected={!withinMenu && active ? '' : undefined}
|
|
167
169
|
$radius={useArrayProp(radius)}
|
|
168
170
|
$tone={tone}
|
|
171
|
+
$scheme={scheme}
|
|
169
172
|
onClick={handleClick}
|
|
170
173
|
onKeyDown={handleKeyDown}
|
|
171
174
|
onMouseEnter={handleMouseEnter}
|
|
@@ -173,28 +176,24 @@ export function MenuGroup(
|
|
|
173
176
|
tabIndex={-1}
|
|
174
177
|
type={as === 'button' ? 'button' : undefined}
|
|
175
178
|
>
|
|
176
|
-
<
|
|
177
|
-
|
|
178
|
-
{
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
<
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
</Text>
|
|
195
|
-
</Box>
|
|
196
|
-
</Flex>
|
|
197
|
-
</Box>
|
|
179
|
+
<Flex gap={space} padding={padding}>
|
|
180
|
+
{icon && (
|
|
181
|
+
<Text size={fontSize}>
|
|
182
|
+
{isValidElement(icon) && icon}
|
|
183
|
+
{isValidElementType(icon) && createElement(icon)}
|
|
184
|
+
</Text>
|
|
185
|
+
)}
|
|
186
|
+
|
|
187
|
+
<Box flex={1}>
|
|
188
|
+
<Text size={fontSize} textOverflow="ellipsis" weight="medium">
|
|
189
|
+
{text}
|
|
190
|
+
</Text>
|
|
191
|
+
</Box>
|
|
192
|
+
|
|
193
|
+
<Text size={fontSize}>
|
|
194
|
+
<ChevronRightIcon />
|
|
195
|
+
</Text>
|
|
196
|
+
</Flex>
|
|
198
197
|
</Selectable>
|
|
199
198
|
</Popover>
|
|
200
199
|
)
|
|
@@ -12,6 +12,7 @@ import {useArrayProp, useForwardedRef} from '../../hooks'
|
|
|
12
12
|
import {Box, Flex, Text} from '../../primitives'
|
|
13
13
|
import {Selectable} from '../../primitives/_selectable'
|
|
14
14
|
import {ResponsivePaddingProps, ResponsiveRadiusProps} from '../../primitives/types'
|
|
15
|
+
import {useRootTheme} from '../../theme'
|
|
15
16
|
import {SelectableTone} from '../../types/selectable'
|
|
16
17
|
import {Hotkeys} from '../hotkeys'
|
|
17
18
|
import {useMenu} from './useMenu'
|
|
@@ -44,7 +45,7 @@ export const MenuItem = forwardRef(function MenuItem(
|
|
|
44
45
|
as = 'button',
|
|
45
46
|
children,
|
|
46
47
|
disabled,
|
|
47
|
-
fontSize =
|
|
48
|
+
fontSize = 1,
|
|
48
49
|
hotkeys,
|
|
49
50
|
icon,
|
|
50
51
|
iconRight,
|
|
@@ -64,6 +65,7 @@ export const MenuItem = forwardRef(function MenuItem(
|
|
|
64
65
|
tone = 'default',
|
|
65
66
|
...restProps
|
|
66
67
|
} = props
|
|
68
|
+
const {scheme} = useRootTheme()
|
|
67
69
|
const menu = useMenu()
|
|
68
70
|
const {
|
|
69
71
|
activeElement,
|
|
@@ -120,7 +122,8 @@ export const MenuItem = forwardRef(function MenuItem(
|
|
|
120
122
|
forwardedAs={as}
|
|
121
123
|
$radius={useArrayProp(radius)}
|
|
122
124
|
$padding={useArrayProp(0)}
|
|
123
|
-
$tone={tone}
|
|
125
|
+
$tone={disabled ? 'default' : tone}
|
|
126
|
+
$scheme={scheme}
|
|
124
127
|
disabled={disabled}
|
|
125
128
|
onClick={handleClick}
|
|
126
129
|
onMouseEnter={onItemMouseEnter}
|
|
@@ -131,43 +134,34 @@ export const MenuItem = forwardRef(function MenuItem(
|
|
|
131
134
|
type={as === 'button' ? 'button' : undefined}
|
|
132
135
|
>
|
|
133
136
|
{(icon || text || iconRight) && (
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
{
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
)}
|
|
137
|
+
<Flex as="span" gap={space} align="center" {...paddingProps}>
|
|
138
|
+
{icon && (
|
|
139
|
+
<Text size={fontSize}>
|
|
140
|
+
{isValidElement(icon) && icon}
|
|
141
|
+
{isValidElementType(icon) && createElement(icon)}
|
|
142
|
+
</Text>
|
|
143
|
+
)}
|
|
142
144
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
{text}
|
|
151
|
-
</Text>
|
|
152
|
-
</Box>
|
|
153
|
-
)}
|
|
145
|
+
{text && (
|
|
146
|
+
<Box flex={1}>
|
|
147
|
+
<Text size={fontSize} textOverflow="ellipsis" weight="medium">
|
|
148
|
+
{text}
|
|
149
|
+
</Text>
|
|
150
|
+
</Box>
|
|
151
|
+
)}
|
|
154
152
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
</Box>
|
|
159
|
-
)}
|
|
153
|
+
{hotkeys && (
|
|
154
|
+
<Hotkeys fontSize={fontSize} keys={hotkeys} style={{marginTop: -4, marginBottom: -4}} />
|
|
155
|
+
)}
|
|
160
156
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
</Box>
|
|
157
|
+
{iconRight && (
|
|
158
|
+
<Text size={fontSize}>
|
|
159
|
+
{isValidElement(iconRight) && iconRight}
|
|
160
|
+
{isValidElementType(iconRight) && createElement(iconRight)}
|
|
161
|
+
</Text>
|
|
162
|
+
)}
|
|
163
|
+
</Flex>
|
|
169
164
|
)}
|
|
170
|
-
|
|
171
165
|
{children && (
|
|
172
166
|
<Box as="span" {...paddingProps}>
|
|
173
167
|
{children}
|
|
@@ -31,7 +31,10 @@ const CustomButton = styled(Button)`
|
|
|
31
31
|
*/
|
|
32
32
|
export const Tab = forwardRef(function Tab(
|
|
33
33
|
props: TabProps &
|
|
34
|
-
Omit<
|
|
34
|
+
Omit<
|
|
35
|
+
React.HTMLProps<HTMLButtonElement>,
|
|
36
|
+
'aria-controls' | 'as' | 'id' | 'label' | 'type' | 'width'
|
|
37
|
+
>,
|
|
35
38
|
forwardedRef: React.ForwardedRef<HTMLButtonElement>,
|
|
36
39
|
) {
|
|
37
40
|
const {
|
|
@@ -37,6 +37,10 @@ const TextBox = styled(Flex)`
|
|
|
37
37
|
`
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
+
* The `Toast` component gives feedback to users when an action has taken place.
|
|
41
|
+
*
|
|
42
|
+
* Toasts can be closed with a close button, or auto-dismiss after a certain timeout.
|
|
43
|
+
*
|
|
40
44
|
* @public
|
|
41
45
|
*/
|
|
42
46
|
export function Toast(
|
|
@@ -22,6 +22,8 @@ export function selectableBaseStyle(): ReturnType<typeof css> {
|
|
|
22
22
|
font: inherit;
|
|
23
23
|
text-align: inherit;
|
|
24
24
|
border: 0;
|
|
25
|
+
width: -moz-available;
|
|
26
|
+
width: -webkit-fill-available;
|
|
25
27
|
width: stretch;
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -99,7 +101,6 @@ export function selectableColorStyle(
|
|
|
99
101
|
&:hover {
|
|
100
102
|
${_colorVarsStyle(base, tone.hovered)}
|
|
101
103
|
}
|
|
102
|
-
|
|
103
104
|
&:active {
|
|
104
105
|
${_colorVarsStyle(base, tone.pressed)}
|
|
105
106
|
}
|
|
@@ -11,6 +11,8 @@ import {avatarStyle, responsiveAvatarSizeStyle} from './styles'
|
|
|
11
11
|
* @public
|
|
12
12
|
*/
|
|
13
13
|
export interface AvatarProps {
|
|
14
|
+
/** @beta */
|
|
15
|
+
__unstable_hideInnerStroke?: boolean
|
|
14
16
|
animateArrowFrom?: AvatarPosition
|
|
15
17
|
arrowPosition?: AvatarPosition
|
|
16
18
|
as?: React.ElementType | keyof JSX.IntrinsicElements
|
|
@@ -41,6 +43,8 @@ const Stroke = styled.ellipse(avatarStyle.stroke)
|
|
|
41
43
|
const Initials = styled.div(avatarStyle.initials)
|
|
42
44
|
|
|
43
45
|
/**
|
|
46
|
+
* Avatars are used to represent people and other agents (e.g. bots).
|
|
47
|
+
*
|
|
44
48
|
* @public
|
|
45
49
|
*/
|
|
46
50
|
export const Avatar = forwardRef(function Avatar(
|
|
@@ -48,6 +52,7 @@ export const Avatar = forwardRef(function Avatar(
|
|
|
48
52
|
ref: React.ForwardedRef<HTMLDivElement>,
|
|
49
53
|
) {
|
|
50
54
|
const {
|
|
55
|
+
__unstable_hideInnerStroke,
|
|
51
56
|
as: asProp,
|
|
52
57
|
color: colorKey = 'gray',
|
|
53
58
|
src,
|
|
@@ -140,13 +145,15 @@ export const Avatar = forwardRef(function Avatar(
|
|
|
140
145
|
</defs>
|
|
141
146
|
|
|
142
147
|
<circle cx={_radius} cy={_radius} r={_radius} fill={`url(#${imageId})`} />
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
{!__unstable_hideInnerStroke && (
|
|
149
|
+
<BgStroke
|
|
150
|
+
cx={_radius}
|
|
151
|
+
cy={_radius}
|
|
152
|
+
rx={_radius}
|
|
153
|
+
ry={_radius}
|
|
154
|
+
vectorEffect="non-scaling-stroke"
|
|
155
|
+
/>
|
|
156
|
+
)}
|
|
150
157
|
<Stroke
|
|
151
158
|
cx={_radius}
|
|
152
159
|
cy={_radius}
|
|
@@ -161,8 +168,8 @@ export const Avatar = forwardRef(function Avatar(
|
|
|
161
168
|
{(imageFailed || !src) && initials && (
|
|
162
169
|
<>
|
|
163
170
|
<Initials>
|
|
164
|
-
<Text as="span" size={initialsSize}>
|
|
165
|
-
|
|
171
|
+
<Text as="span" size={initialsSize} weight="medium">
|
|
172
|
+
{initials}
|
|
166
173
|
</Text>
|
|
167
174
|
</Initials>
|
|
168
175
|
</>
|
|
@@ -36,7 +36,7 @@ function _avatarCounterBaseStyle(props: ThemeProps) {
|
|
|
36
36
|
background: var(--card-bg-color);
|
|
37
37
|
box-shadow:
|
|
38
38
|
0 0 0 1px var(--card-bg-color),
|
|
39
|
-
inset 0 0 0
|
|
39
|
+
inset 0 0 0 1px var(--card-hairline-hard-color);
|
|
40
40
|
padding: 0 ${rem(theme.sanity.space[2])};
|
|
41
41
|
|
|
42
42
|
&:not([hidden]) {
|
|
@@ -73,8 +73,8 @@ export const AvatarCounter = forwardRef(function AvatarCounter(
|
|
|
73
73
|
|
|
74
74
|
return (
|
|
75
75
|
<Root $size={size} data-ui="AvatarCounter" ref={ref}>
|
|
76
|
-
<Text as="span" size={counterSize}>
|
|
77
|
-
|
|
76
|
+
<Text as="span" size={counterSize} weight="medium">
|
|
77
|
+
{count}
|
|
78
78
|
</Text>
|
|
79
79
|
</Root>
|
|
80
80
|
)
|
|
@@ -4,7 +4,7 @@ import {useArrayProp} from '../../hooks'
|
|
|
4
4
|
import {responsiveRadiusStyle, ResponsiveRadiusStyleProps} from '../../styles/internal'
|
|
5
5
|
import {BadgeMode, BadgeTone} from '../../types'
|
|
6
6
|
import {Box, BoxProps} from '../box'
|
|
7
|
-
import {
|
|
7
|
+
import {Text} from '../text'
|
|
8
8
|
import {ResponsiveRadiusProps} from '../types'
|
|
9
9
|
import {badgeStyle} from './styles'
|
|
10
10
|
import {BadgeStyleProps} from './types'
|
|
@@ -25,6 +25,8 @@ const Root = styled(Box)<BadgeStyleProps & ResponsiveRadiusStyleProps>(
|
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
+
* Badges are used to tag resources.
|
|
29
|
+
*
|
|
28
30
|
* @public
|
|
29
31
|
*/
|
|
30
32
|
export const Badge = forwardRef(function Badge(
|
|
@@ -33,7 +35,7 @@ export const Badge = forwardRef(function Badge(
|
|
|
33
35
|
) {
|
|
34
36
|
const {
|
|
35
37
|
children,
|
|
36
|
-
fontSize,
|
|
38
|
+
fontSize = 1,
|
|
37
39
|
mode = 'default',
|
|
38
40
|
padding = 1,
|
|
39
41
|
radius = 2,
|
|
@@ -51,7 +53,9 @@ export const Badge = forwardRef(function Badge(
|
|
|
51
53
|
padding={useArrayProp(padding)}
|
|
52
54
|
ref={ref}
|
|
53
55
|
>
|
|
54
|
-
<
|
|
56
|
+
<Text size={fontSize} weight="medium">
|
|
57
|
+
{children}
|
|
58
|
+
</Text>
|
|
55
59
|
</Root>
|
|
56
60
|
)
|
|
57
61
|
})
|