@sanity/ui 2.6.7-canary.0 → 2.6.7
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.d.mts +15 -51
- package/dist/index.d.ts +15 -51
- package/dist/index.esm.js +186 -120
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +186 -119
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +186 -120
- package/dist/index.mjs.map +1 -1
- package/dist/theme.d.mts +14 -14
- package/dist/theme.d.ts +14 -14
- package/dist/theme.esm.js.map +1 -1
- package/dist/theme.js.map +1 -1
- package/dist/theme.mjs.map +1 -1
- package/package.json +53 -46
- package/src/core/__workshop__/constants.ts +36 -36
- package/src/core/components/autocomplete/autocomplete.tsx +1 -1
- package/src/core/components/breadcrumbs/breadcrumbs.tsx +6 -15
- package/src/core/components/dialog/dialog.tsx +21 -12
- package/src/core/components/dialog/styles.ts +8 -8
- package/src/core/components/menu/menu.tsx +18 -11
- package/src/core/components/menu/menuButton.tsx +11 -11
- package/src/core/components/menu/menuContext.ts +1 -1
- package/src/core/components/menu/useMenuController.ts +17 -11
- package/src/core/components/tab/tab.tsx +8 -8
- package/src/core/components/tab/tabPanel.tsx +1 -1
- package/src/core/components/toast/styles.ts +1 -2
- package/src/core/components/toast/useToast.ts +0 -1
- package/src/core/components/tree/tree.tsx +0 -1
- package/src/core/components/tree/treeItem.tsx +0 -1
- package/src/core/helpers/focus.ts +0 -1
- package/src/core/helpers/scroll.ts +0 -1
- package/src/core/hooks/_internal/index.ts +1 -0
- package/src/core/hooks/_internal/useUnique.ts +34 -0
- package/src/core/hooks/index.ts +2 -3
- package/src/core/hooks/useClickOutside.ts +72 -38
- package/src/core/hooks/useElementSize.ts +0 -1
- package/src/core/hooks/useMediaIndex/useMediaIndex.ts +10 -2
- package/src/core/hooks/usePrefersDark.ts +55 -10
- package/src/core/hooks/usePrefersReducedMotion.ts +56 -10
- package/src/core/primitives/avatar/styles.ts +42 -42
- package/src/core/primitives/badge/styles.ts +2 -2
- package/src/core/primitives/button/styles.ts +4 -4
- package/src/core/primitives/inline/styles.ts +2 -2
- package/src/core/primitives/popover/__workshop__/AlignedStory.tsx +7 -9
- package/src/core/primitives/popover/constants.ts +4 -4
- package/src/core/primitives/stack/styles.ts +2 -2
- package/src/core/primitives/tooltip/__workshop__/customPortal.tsx +7 -9
- package/src/core/primitives/tooltip/constants.ts +4 -4
- package/src/core/primitives/tooltip/tooltip.tsx +49 -68
- package/src/core/primitives/tooltip/tooltipDelayGroup/tooltipDelayGroupProvider.tsx +0 -1
- package/src/core/styles/font/responsiveFont.ts +8 -8
- package/src/core/theme/__workshop__/debug/story.tsx +11 -11
- package/src/core/utils/layer/layerProvider.tsx +0 -1
- package/src/core/utils/portal/__workshop__/named.tsx +8 -10
- package/src/core/utils/portal/portalProvider.tsx +13 -7
- package/src/theme/build/buildColorTheme.test.ts +13 -13
- package/src/theme/config/tokens/color/types.ts +14 -14
- package/src/theme/defaults/colorTokens.ts +36 -36
- package/src/core/hooks/useMatchMedia.ts +0 -46
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {EllipsisVerticalIcon} from '@sanity/icons'
|
|
2
2
|
import {Button, Card, Flex, Popover, Text, useClickOutside} from '@sanity/ui'
|
|
3
3
|
import {useBoolean, useSelect} from '@sanity/ui-workshop'
|
|
4
|
-
import {useCallback,
|
|
4
|
+
import {useCallback, useState} from 'react'
|
|
5
5
|
import {
|
|
6
6
|
WORKSHOP_FLEX_ALIGN_OPTIONS,
|
|
7
7
|
WORKSHOP_FLEX_JUSTIFY_OPTIONS,
|
|
@@ -20,8 +20,8 @@ export default function AlignedStory() {
|
|
|
20
20
|
|
|
21
21
|
const [open, setOpen] = useState(false)
|
|
22
22
|
const [boundaryElement, setBoundaryElement] = useState<HTMLDivElement | null>(null)
|
|
23
|
-
const
|
|
24
|
-
const
|
|
23
|
+
const [buttonElement, setButtonElement] = useState<HTMLButtonElement | null>(null)
|
|
24
|
+
const [popoverElement, setPopoverElement] = useState<HTMLDivElement | null>(null)
|
|
25
25
|
|
|
26
26
|
const content = (
|
|
27
27
|
<Text>
|
|
@@ -39,11 +39,9 @@ export default function AlignedStory() {
|
|
|
39
39
|
)
|
|
40
40
|
|
|
41
41
|
const handleToggleOpen = useCallback(() => setOpen((v) => !v), [])
|
|
42
|
+
const handleClose = useCallback(() => setOpen(false), [])
|
|
42
43
|
|
|
43
|
-
useClickOutside(
|
|
44
|
-
() => setOpen(false),
|
|
45
|
-
() => [buttonElementRef.current, popoverElementRef.current],
|
|
46
|
-
)
|
|
44
|
+
useClickOutside(handleClose, [buttonElement, popoverElement])
|
|
47
45
|
|
|
48
46
|
return (
|
|
49
47
|
<Card height="fill" padding={[4, 5, 6]} sizing="border" tone="transparent">
|
|
@@ -58,14 +56,14 @@ export default function AlignedStory() {
|
|
|
58
56
|
padding={3}
|
|
59
57
|
portal={portal}
|
|
60
58
|
placement={placement}
|
|
61
|
-
ref={
|
|
59
|
+
ref={setPopoverElement}
|
|
62
60
|
width={width}
|
|
63
61
|
>
|
|
64
62
|
<Button
|
|
65
63
|
icon={EllipsisVerticalIcon}
|
|
66
64
|
mode="bleed"
|
|
67
65
|
onClick={handleToggleOpen}
|
|
68
|
-
ref={
|
|
66
|
+
ref={setButtonElement}
|
|
69
67
|
selected={open}
|
|
70
68
|
/>
|
|
71
69
|
</Popover>
|
|
@@ -7,16 +7,16 @@ export const DEFAULT_POPOVER_ARROW_HEIGHT = 8
|
|
|
7
7
|
export const DEFAULT_POPOVER_ARROW_RADIUS = 2
|
|
8
8
|
export const DEFAULT_POPOVER_MARGINS: PopoverMargins = [0, 0, 0, 0]
|
|
9
9
|
export const DEFAULT_FALLBACK_PLACEMENTS: Record<Placement, Placement[]> = {
|
|
10
|
-
|
|
10
|
+
top: ['bottom', 'left', 'right'],
|
|
11
11
|
'top-start': ['bottom-start', 'left-start', 'right-start'],
|
|
12
12
|
'top-end': ['bottom-end', 'left-end', 'right-end'],
|
|
13
|
-
|
|
13
|
+
bottom: ['top', 'left', 'right'],
|
|
14
14
|
'bottom-start': ['top-start', 'left-start', 'right-start'],
|
|
15
15
|
'bottom-end': ['top-end', 'left-end', 'right-end'],
|
|
16
|
-
|
|
16
|
+
left: ['right', 'top', 'bottom'],
|
|
17
17
|
'left-start': ['right-start', 'top-start', 'bottom-start'],
|
|
18
18
|
'left-end': ['right-end', 'top-end', 'bottom-end'],
|
|
19
|
-
|
|
19
|
+
right: ['left', 'top', 'bottom'],
|
|
20
20
|
'right-start': ['left-start', 'top-start', 'bottom-start'],
|
|
21
21
|
'right-end': ['left-end', 'top-end', 'bottom-end'],
|
|
22
22
|
}
|
|
@@ -12,8 +12,8 @@ const BASE_STYLE: CSSObject = {
|
|
|
12
12
|
'&[data-as="ul"],&[data-as="ol"]': {
|
|
13
13
|
listStyle: 'none',
|
|
14
14
|
},
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
gridTemplateColumns: 'minmax(0, 1fr)',
|
|
16
|
+
gridAutoRows: 'min-content',
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export function stackBaseStyle(): CSSObject {
|
|
@@ -10,13 +10,13 @@ import {
|
|
|
10
10
|
Tooltip,
|
|
11
11
|
} from '@sanity/ui'
|
|
12
12
|
import {useBoolean, useSelect, useText} from '@sanity/ui-workshop'
|
|
13
|
-
import {
|
|
13
|
+
import {useState} from 'react'
|
|
14
14
|
import {WORKSHOP_PLACEMENT_OPTIONS} from '../../../__workshop__/constants'
|
|
15
15
|
|
|
16
16
|
const PORTAL_OPTIONS = {
|
|
17
17
|
'(true)': true,
|
|
18
18
|
'(false)': false,
|
|
19
|
-
|
|
19
|
+
portal1: 'portal1',
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export default function CustomPortalStory() {
|
|
@@ -30,15 +30,13 @@ export default function CustomPortalStory() {
|
|
|
30
30
|
|
|
31
31
|
const [portal1Element, setPortal1Element] = useState<HTMLDivElement | null>(null)
|
|
32
32
|
const [boundaryElement, setBoundaryElement] = useState<HTMLDivElement | null>(null)
|
|
33
|
-
const __unstable_elements = useMemo(
|
|
34
|
-
() => ({
|
|
35
|
-
portal1: portal1Element,
|
|
36
|
-
}),
|
|
37
|
-
[portal1Element],
|
|
38
|
-
)
|
|
39
33
|
|
|
40
34
|
return (
|
|
41
|
-
<PortalProvider
|
|
35
|
+
<PortalProvider
|
|
36
|
+
__unstable_elements={{
|
|
37
|
+
portal1: portal1Element,
|
|
38
|
+
}}
|
|
39
|
+
>
|
|
42
40
|
<Flex align="center" height="fill" justify="center">
|
|
43
41
|
<BoundaryElementProvider element={useBoundaryElement ? boundaryElement : null}>
|
|
44
42
|
<Card
|
|
@@ -8,16 +8,16 @@ export const DEFAULT_TOOLTIP_DISTANCE = 4
|
|
|
8
8
|
export const DEFAULT_TOOLTIP_PADDING = 4
|
|
9
9
|
|
|
10
10
|
export const DEFAULT_FALLBACK_PLACEMENTS: Record<Placement, Placement[]> = {
|
|
11
|
-
|
|
11
|
+
top: ['top-end', 'top-start', 'bottom', 'left', 'right'],
|
|
12
12
|
'top-start': ['top', 'top-end', 'bottom-start', 'left-start', 'right-start'],
|
|
13
13
|
'top-end': ['top', 'top-start', 'bottom-end', 'left-end', 'right-end'],
|
|
14
|
-
|
|
14
|
+
bottom: ['bottom-end', 'bottom-start', 'top', 'left', 'right'],
|
|
15
15
|
'bottom-start': ['bottom', 'bottom-end', 'top-start', 'left-start', 'right-start'],
|
|
16
16
|
'bottom-end': ['bottom', 'bottom-start', 'top-end', 'left-end', 'right-end'],
|
|
17
|
-
|
|
17
|
+
left: ['left-end', 'left-start', 'right', 'top', 'bottom'],
|
|
18
18
|
'left-start': ['left', 'left-end', 'right-start', 'top-start', 'bottom-start'],
|
|
19
19
|
'left-end': ['left', 'left-start', 'right-end', 'top-end', 'bottom-end'],
|
|
20
|
-
|
|
20
|
+
right: ['right-end', 'right-start', 'left', 'top', 'bottom'],
|
|
21
21
|
'right-start': ['right', 'right-end', 'left-start', 'top-start', 'bottom-start'],
|
|
22
22
|
'right-end': ['right', 'right-start', 'left-end', 'top-end', 'bottom-end'],
|
|
23
23
|
}
|
|
@@ -20,11 +20,10 @@ import {
|
|
|
20
20
|
useRef,
|
|
21
21
|
useState,
|
|
22
22
|
useId,
|
|
23
|
+
useSyncExternalStore,
|
|
23
24
|
useImperativeHandle,
|
|
24
|
-
useLayoutEffect,
|
|
25
25
|
} from 'react'
|
|
26
26
|
import {styled} from 'styled-components'
|
|
27
|
-
import {useEffectEvent} from 'use-effect-event'
|
|
28
27
|
import {useArrayProp, usePrefersReducedMotion} from '../../hooks'
|
|
29
28
|
import {useDelayedState} from '../../hooks/useDelayedState'
|
|
30
29
|
import {origin} from '../../middleware/origin'
|
|
@@ -86,8 +85,9 @@ export interface TooltipProps extends Omit<LayerProps, 'as'> {
|
|
|
86
85
|
animate?: boolean
|
|
87
86
|
}
|
|
88
87
|
|
|
89
|
-
const Root = styled(Layer)
|
|
88
|
+
const Root = styled(Layer)<{$maxWidth: number}>`
|
|
90
89
|
pointer-events: none;
|
|
90
|
+
max-width: ${({$maxWidth}) => $maxWidth}px;
|
|
91
91
|
`
|
|
92
92
|
|
|
93
93
|
/**
|
|
@@ -127,7 +127,6 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
127
127
|
const [referenceElement, setReferenceElement] = useState<HTMLElement | null>(null)
|
|
128
128
|
const arrowRef = useRef<HTMLDivElement | null>(null)
|
|
129
129
|
const rootBoundary: RootBoundary = 'viewport'
|
|
130
|
-
const [tooltipMaxWidth, setTooltipMaxWidth] = useState(0)
|
|
131
130
|
|
|
132
131
|
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)
|
|
133
132
|
|
|
@@ -135,6 +134,24 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
135
134
|
const portalElement =
|
|
136
135
|
typeof portalProp === 'string' ? portal.elements?.[portalProp] || null : portal.element
|
|
137
136
|
|
|
137
|
+
const documentBodyOffsetWidth = useSyncExternalStore(
|
|
138
|
+
emptySubscribe,
|
|
139
|
+
() => document.body.offsetWidth,
|
|
140
|
+
// We don't actually know what the width of the body is during SSR, so we'll just assume it's 800px or larger
|
|
141
|
+
() => 800,
|
|
142
|
+
)
|
|
143
|
+
// Get the maximum tooltip width (sans tooltip padding)
|
|
144
|
+
// Tooltip width should never exceed the width of either any supplied boundary or portal element.
|
|
145
|
+
// If both portal and boundary elements are provided, use the smaller width of the two.
|
|
146
|
+
const tooltipWidth = useMemo(() => {
|
|
147
|
+
const availableWidths = [
|
|
148
|
+
...(boundaryElement ? [boundaryElement.offsetWidth] : []),
|
|
149
|
+
portalElement?.offsetWidth || documentBodyOffsetWidth,
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
return Math.min(...availableWidths) - DEFAULT_TOOLTIP_PADDING * 2
|
|
153
|
+
}, [boundaryElement, documentBodyOffsetWidth, portalElement?.offsetWidth])
|
|
154
|
+
|
|
138
155
|
const middleware = useMemo(() => {
|
|
139
156
|
const ret: Middleware[] = []
|
|
140
157
|
|
|
@@ -268,8 +285,31 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
268
285
|
[childProp?.props, handleIsOpenChange],
|
|
269
286
|
)
|
|
270
287
|
|
|
271
|
-
//
|
|
272
|
-
|
|
288
|
+
// Detect whether the mouse is moving outside of the reference element. This is sometimes
|
|
289
|
+
// necessary, because the tooltip might not always close as it should (e.g. when clicking
|
|
290
|
+
// the reference element triggers a CPU-heavy operation.)
|
|
291
|
+
useEffect(() => {
|
|
292
|
+
if (!showTooltip) return
|
|
293
|
+
|
|
294
|
+
function handleWindowMouseMove(event: MouseEvent) {
|
|
295
|
+
if (!referenceElement) return
|
|
296
|
+
|
|
297
|
+
const isHoveringReference =
|
|
298
|
+
referenceElement === event.target ||
|
|
299
|
+
(event.target instanceof Node && referenceElement.contains(event.target))
|
|
300
|
+
|
|
301
|
+
if (!isHoveringReference) {
|
|
302
|
+
handleIsOpenChange(false)
|
|
303
|
+
window.removeEventListener('mousemove', handleWindowMouseMove)
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
window.addEventListener('mousemove', handleWindowMouseMove)
|
|
308
|
+
|
|
309
|
+
return () => {
|
|
310
|
+
window.removeEventListener('mousemove', handleWindowMouseMove)
|
|
311
|
+
}
|
|
312
|
+
}, [showTooltip, referenceElement, handleIsOpenChange])
|
|
273
313
|
|
|
274
314
|
// Close when `disabled` changes to `true`
|
|
275
315
|
useEffect(() => {
|
|
@@ -300,20 +340,6 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
300
340
|
window.removeEventListener('keydown', handleWindowKeyDown)
|
|
301
341
|
}
|
|
302
342
|
}, [handleIsOpenChange, showTooltip])
|
|
303
|
-
|
|
304
|
-
// // Set the max width of the tooltip based on boundaries and portals
|
|
305
|
-
useLayoutEffect(() => {
|
|
306
|
-
// Get the maximum tooltip width (sans tooltip padding)
|
|
307
|
-
// Tooltip width should never exceed the width of either any supplied boundary or portal element.
|
|
308
|
-
// If both portal and boundary elements are provided, use the smaller width of the two.
|
|
309
|
-
const availableWidths = [
|
|
310
|
-
...(boundaryElement ? [boundaryElement.offsetWidth] : []),
|
|
311
|
-
portalElement?.offsetWidth || document.body.offsetWidth,
|
|
312
|
-
]
|
|
313
|
-
|
|
314
|
-
setTooltipMaxWidth(Math.min(...availableWidths) - DEFAULT_TOOLTIP_PADDING * 2)
|
|
315
|
-
}, [boundaryElement, portalElement])
|
|
316
|
-
|
|
317
343
|
const setArrow = useCallback(
|
|
318
344
|
(arrowEl: HTMLDivElement | null) => {
|
|
319
345
|
arrowRef.current = arrowEl
|
|
@@ -376,11 +402,9 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
376
402
|
data-ui="Tooltip"
|
|
377
403
|
{...restProps}
|
|
378
404
|
ref={setFloating}
|
|
379
|
-
style={
|
|
380
|
-
...floatingStyles,
|
|
381
|
-
maxWidth: tooltipMaxWidth > 0 ? `${tooltipMaxWidth}px` : undefined,
|
|
382
|
-
}}
|
|
405
|
+
style={floatingStyles}
|
|
383
406
|
zOffset={zOffset}
|
|
407
|
+
$maxWidth={tooltipWidth}
|
|
384
408
|
>
|
|
385
409
|
<TooltipCard
|
|
386
410
|
{...restProps}
|
|
@@ -430,47 +454,4 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
430
454
|
)
|
|
431
455
|
})
|
|
432
456
|
|
|
433
|
-
|
|
434
|
-
* As `useEffectEvent` should never be passed to other components or hooks, this custom hook groups together the `useEffectEvent` and the `useEffect` hook using it.
|
|
435
|
-
* @see https://19.react.dev/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events:~:text=Never%20pass%20them%20to%20other%20components%20or%20Hooks
|
|
436
|
-
*/
|
|
437
|
-
function useCloseOnMouseLeave({
|
|
438
|
-
handleIsOpenChange,
|
|
439
|
-
referenceElement,
|
|
440
|
-
showTooltip,
|
|
441
|
-
}: {
|
|
442
|
-
handleIsOpenChange: (open: boolean, immediate?: boolean) => void
|
|
443
|
-
referenceElement: HTMLElement | null
|
|
444
|
-
showTooltip: boolean
|
|
445
|
-
}) {
|
|
446
|
-
// Since we don't want the `mouseevent` events to be attached and removed if the `referenceElement` is changed
|
|
447
|
-
// we use a "effect event" (https://19.react.dev/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events)
|
|
448
|
-
// in order to always see the latest `referenceElement` value inside the event handler itself.
|
|
449
|
-
const onMouseMove = useEffectEvent((target: EventTarget | null, teardown: () => void) => {
|
|
450
|
-
if (!referenceElement) return
|
|
451
|
-
|
|
452
|
-
const isHoveringReference =
|
|
453
|
-
referenceElement === target || (target instanceof Node && referenceElement.contains(target))
|
|
454
|
-
|
|
455
|
-
if (!isHoveringReference) {
|
|
456
|
-
handleIsOpenChange(false)
|
|
457
|
-
// Allow removing the event listener eagerly, to avoid race conditions
|
|
458
|
-
teardown()
|
|
459
|
-
}
|
|
460
|
-
})
|
|
461
|
-
|
|
462
|
-
// Detect whether the mouse is moving outside of the reference element. This is sometimes
|
|
463
|
-
// necessary, because the tooltip might not always close as it should (e.g. when clicking
|
|
464
|
-
// the reference element triggers a CPU-heavy operation.)
|
|
465
|
-
useEffect(() => {
|
|
466
|
-
if (!showTooltip) return
|
|
467
|
-
|
|
468
|
-
const handleMouseMove = (event: MouseEvent) => {
|
|
469
|
-
onMouseMove(event.target, () => window.removeEventListener('mousemove', handleMouseMove))
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
window.addEventListener('mousemove', handleMouseMove)
|
|
473
|
-
|
|
474
|
-
return () => window.removeEventListener('mousemove', handleMouseMove)
|
|
475
|
-
}, [onMouseMove, showTooltip])
|
|
476
|
-
}
|
|
457
|
+
const emptySubscribe = () => () => {}
|
|
@@ -36,7 +36,6 @@ export function TooltipDelayGroupProvider(
|
|
|
36
36
|
const openDelay = typeof delay === 'number' ? delay : delay?.open || 0
|
|
37
37
|
const closeDelay = typeof delay === 'number' ? delay : delay?.close || 0
|
|
38
38
|
|
|
39
|
-
// @TODO split out into separate contexts
|
|
40
39
|
const value: TooltipDelayGroupContextValue = useMemo(
|
|
41
40
|
() => ({
|
|
42
41
|
isGroupActive: isGroupActive,
|
|
@@ -21,11 +21,11 @@ export function responsiveFont(
|
|
|
21
21
|
const defaultSize = sizes[2]
|
|
22
22
|
|
|
23
23
|
const base: CSSObject = {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
position: 'relative',
|
|
25
|
+
fontFamily: family,
|
|
26
26
|
fontWeight,
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
padding: '1px 0',
|
|
28
|
+
margin: 0,
|
|
29
29
|
|
|
30
30
|
'&:before': {
|
|
31
31
|
content: '""',
|
|
@@ -75,10 +75,10 @@ export function fontSize(size: ThemeFontSize): CSSObject {
|
|
|
75
75
|
const customIconOffset = (capHeight - customIconSize) / 2
|
|
76
76
|
|
|
77
77
|
return {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
fontSize: rem(fontSize),
|
|
79
|
+
lineHeight: `calc(${lineHeight} / ${fontSize})`,
|
|
80
|
+
letterSpacing: rem(letterSpacing),
|
|
81
|
+
transform: `translateY(${rem(descenderHeight)})`,
|
|
82
82
|
|
|
83
83
|
'&:before': {
|
|
84
84
|
marginTop: `calc(${rem(0 - negHeight)} - 1px)`,
|
|
@@ -191,7 +191,7 @@ function DebugState() {
|
|
|
191
191
|
style={
|
|
192
192
|
{
|
|
193
193
|
'--card-fg-color': 'var(--card-avatar-gray-fg-color)',
|
|
194
|
-
|
|
194
|
+
backgroundColor: 'var(--card-avatar-gray-bg-color)',
|
|
195
195
|
} as any
|
|
196
196
|
}
|
|
197
197
|
>
|
|
@@ -206,7 +206,7 @@ function DebugState() {
|
|
|
206
206
|
style={
|
|
207
207
|
{
|
|
208
208
|
'--card-fg-color': 'var(--card-avatar-red-fg-color)',
|
|
209
|
-
|
|
209
|
+
backgroundColor: 'var(--card-avatar-red-bg-color)',
|
|
210
210
|
} as any
|
|
211
211
|
}
|
|
212
212
|
>
|
|
@@ -221,7 +221,7 @@ function DebugState() {
|
|
|
221
221
|
style={
|
|
222
222
|
{
|
|
223
223
|
'--card-fg-color': 'var(--card-avatar-orange-fg-color)',
|
|
224
|
-
|
|
224
|
+
backgroundColor: 'var(--card-avatar-orange-bg-color)',
|
|
225
225
|
} as any
|
|
226
226
|
}
|
|
227
227
|
>
|
|
@@ -236,7 +236,7 @@ function DebugState() {
|
|
|
236
236
|
style={
|
|
237
237
|
{
|
|
238
238
|
'--card-fg-color': 'var(--card-avatar-yellow-fg-color)',
|
|
239
|
-
|
|
239
|
+
backgroundColor: 'var(--card-avatar-yellow-bg-color)',
|
|
240
240
|
} as any
|
|
241
241
|
}
|
|
242
242
|
>
|
|
@@ -251,7 +251,7 @@ function DebugState() {
|
|
|
251
251
|
style={
|
|
252
252
|
{
|
|
253
253
|
'--card-fg-color': 'var(--card-avatar-green-fg-color)',
|
|
254
|
-
|
|
254
|
+
backgroundColor: 'var(--card-avatar-green-bg-color)',
|
|
255
255
|
} as any
|
|
256
256
|
}
|
|
257
257
|
>
|
|
@@ -266,7 +266,7 @@ function DebugState() {
|
|
|
266
266
|
style={
|
|
267
267
|
{
|
|
268
268
|
'--card-fg-color': 'var(--card-avatar-cyan-fg-color)',
|
|
269
|
-
|
|
269
|
+
backgroundColor: 'var(--card-avatar-cyan-bg-color)',
|
|
270
270
|
} as any
|
|
271
271
|
}
|
|
272
272
|
>
|
|
@@ -281,7 +281,7 @@ function DebugState() {
|
|
|
281
281
|
style={
|
|
282
282
|
{
|
|
283
283
|
'--card-fg-color': 'var(--card-avatar-blue-fg-color)',
|
|
284
|
-
|
|
284
|
+
backgroundColor: 'var(--card-avatar-blue-bg-color)',
|
|
285
285
|
} as any
|
|
286
286
|
}
|
|
287
287
|
>
|
|
@@ -296,7 +296,7 @@ function DebugState() {
|
|
|
296
296
|
style={
|
|
297
297
|
{
|
|
298
298
|
'--card-fg-color': 'var(--card-avatar-purple-fg-color)',
|
|
299
|
-
|
|
299
|
+
backgroundColor: 'var(--card-avatar-purple-bg-color)',
|
|
300
300
|
} as any
|
|
301
301
|
}
|
|
302
302
|
>
|
|
@@ -311,7 +311,7 @@ function DebugState() {
|
|
|
311
311
|
style={
|
|
312
312
|
{
|
|
313
313
|
'--card-fg-color': 'var(--card-avatar-magenta-fg-color)',
|
|
314
|
-
|
|
314
|
+
backgroundColor: 'var(--card-avatar-magenta-bg-color)',
|
|
315
315
|
} as any
|
|
316
316
|
}
|
|
317
317
|
>
|
|
@@ -395,7 +395,7 @@ function getStateVars(state: ThemeColorState_v2) {
|
|
|
395
395
|
'--card-skeleton-from-color': state.skeleton.from,
|
|
396
396
|
'--card-skeleton-to-color': state.skeleton.to,
|
|
397
397
|
|
|
398
|
-
|
|
399
|
-
|
|
398
|
+
backgroundColor: 'var(--card-bg-color)',
|
|
399
|
+
color: 'var(--card-fg-color)',
|
|
400
400
|
} as CSSProperties
|
|
401
401
|
}
|
|
@@ -91,7 +91,6 @@ export function LayerProvider(props: LayerProviderProps): React.ReactElement {
|
|
|
91
91
|
// Register this layer on mount
|
|
92
92
|
useEffect(() => parentRegisterChild?.(level), [level, parentRegisterChild])
|
|
93
93
|
|
|
94
|
-
// @TODO split out into separate contexts
|
|
95
94
|
const value: LayerContextValue = useMemo(
|
|
96
95
|
() => ({
|
|
97
96
|
version: 0.0,
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import {Card, Container, Portal, PortalProvider, Stack, Text} from '@sanity/ui'
|
|
2
|
-
import {
|
|
2
|
+
import {useState} from 'react'
|
|
3
3
|
|
|
4
4
|
export default function NamedStory() {
|
|
5
5
|
const [portal1Element, setPortal1Element] = useState<HTMLDivElement | null>(null)
|
|
6
6
|
const [portal2Element, setPortal2Element] = useState<HTMLDivElement | null>(null)
|
|
7
7
|
const [portal3Element, setPortal3Element] = useState<HTMLDivElement | null>(null)
|
|
8
|
-
const __unstable_elements = useMemo(
|
|
9
|
-
() => ({
|
|
10
|
-
portal1: portal1Element,
|
|
11
|
-
portal2: portal2Element,
|
|
12
|
-
portal3: portal3Element,
|
|
13
|
-
}),
|
|
14
|
-
[portal1Element, portal2Element, portal3Element],
|
|
15
|
-
)
|
|
16
8
|
|
|
17
9
|
return (
|
|
18
|
-
<PortalProvider
|
|
10
|
+
<PortalProvider
|
|
11
|
+
__unstable_elements={{
|
|
12
|
+
portal1: portal1Element,
|
|
13
|
+
portal2: portal2Element,
|
|
14
|
+
portal3: portal3Element,
|
|
15
|
+
}}
|
|
16
|
+
>
|
|
19
17
|
<Container width={1}>
|
|
20
18
|
<Card height="fill" padding={4}>
|
|
21
19
|
<Stack space={2}>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {useMemo} from 'react'
|
|
2
|
-
import {
|
|
1
|
+
import {useMemo, useSyncExternalStore} from 'react'
|
|
2
|
+
import {useUnique} from '../../hooks/_internal'
|
|
3
3
|
import {PortalContext} from './portalContext'
|
|
4
4
|
import {PortalContextValue} from './types'
|
|
5
5
|
|
|
@@ -23,18 +23,24 @@ export interface PortalProviderProps {
|
|
|
23
23
|
* @public
|
|
24
24
|
*/
|
|
25
25
|
export function PortalProvider(props: PortalProviderProps): React.ReactElement {
|
|
26
|
-
const {boundaryElement, children, element, __unstable_elements:
|
|
27
|
-
const
|
|
26
|
+
const {boundaryElement, children, element, __unstable_elements: elementsProp} = props
|
|
27
|
+
const elements = useUnique(elementsProp)
|
|
28
|
+
const fallbackElement = useSyncExternalStore(
|
|
29
|
+
emptySubscribe,
|
|
30
|
+
() => document.body,
|
|
31
|
+
() => null,
|
|
32
|
+
)
|
|
28
33
|
|
|
29
|
-
// @TODO split out into separate contexts
|
|
30
34
|
const value: PortalContextValue = useMemo(() => {
|
|
31
35
|
return {
|
|
32
36
|
version: 0.0,
|
|
33
37
|
boundaryElement: boundaryElement || null,
|
|
34
|
-
element: element ||
|
|
38
|
+
element: element || fallbackElement,
|
|
35
39
|
elements,
|
|
36
40
|
}
|
|
37
|
-
}, [boundaryElement, element, elements,
|
|
41
|
+
}, [boundaryElement, element, elements, fallbackElement])
|
|
38
42
|
|
|
39
43
|
return <PortalContext.Provider value={value}>{children}</PortalContext.Provider>
|
|
40
44
|
}
|
|
45
|
+
|
|
46
|
+
const emptySubscribe = () => () => {}
|
|
@@ -9,23 +9,23 @@ test('buildColorTheme: base', () => {
|
|
|
9
9
|
bg: ['50', '900'],
|
|
10
10
|
fg: ['800', '200'],
|
|
11
11
|
},
|
|
12
|
-
|
|
12
|
+
transparent: {
|
|
13
13
|
bg: ['50', 'black'],
|
|
14
14
|
},
|
|
15
|
-
|
|
15
|
+
default: {
|
|
16
16
|
bg: ['white', '950'],
|
|
17
17
|
fg: ['black', '200'],
|
|
18
18
|
},
|
|
19
|
-
|
|
19
|
+
primary: {
|
|
20
20
|
_hue: 'purple',
|
|
21
21
|
},
|
|
22
|
-
|
|
22
|
+
positive: {
|
|
23
23
|
_hue: 'cyan',
|
|
24
24
|
},
|
|
25
|
-
|
|
25
|
+
caution: {
|
|
26
26
|
_hue: 'yellow',
|
|
27
27
|
},
|
|
28
|
-
|
|
28
|
+
critical: {
|
|
29
29
|
_hue: 'red',
|
|
30
30
|
},
|
|
31
31
|
},
|
|
@@ -100,23 +100,23 @@ test('buildColorTheme: button', () => {
|
|
|
100
100
|
bg: ['50', '900'],
|
|
101
101
|
fg: ['800', '200'],
|
|
102
102
|
},
|
|
103
|
-
|
|
103
|
+
transparent: {
|
|
104
104
|
bg: ['50', 'black'],
|
|
105
105
|
},
|
|
106
|
-
|
|
106
|
+
default: {
|
|
107
107
|
bg: ['white', '950'],
|
|
108
108
|
fg: ['black', '200'],
|
|
109
109
|
},
|
|
110
|
-
|
|
110
|
+
primary: {
|
|
111
111
|
_hue: 'purple',
|
|
112
112
|
},
|
|
113
|
-
|
|
113
|
+
positive: {
|
|
114
114
|
_hue: 'cyan',
|
|
115
115
|
},
|
|
116
|
-
|
|
116
|
+
caution: {
|
|
117
117
|
_hue: 'yellow',
|
|
118
118
|
},
|
|
119
|
-
|
|
119
|
+
critical: {
|
|
120
120
|
_hue: 'red',
|
|
121
121
|
},
|
|
122
122
|
},
|
|
@@ -127,7 +127,7 @@ test('buildColorTheme: button', () => {
|
|
|
127
127
|
bg: ['500', '400'],
|
|
128
128
|
fg: ['white', 'black'],
|
|
129
129
|
},
|
|
130
|
-
|
|
130
|
+
hovered: {
|
|
131
131
|
bg: ['600', '300'],
|
|
132
132
|
},
|
|
133
133
|
},
|
|
@@ -21,15 +21,15 @@ export interface ThemeColorAvatarHueTokens {
|
|
|
21
21
|
/** @public */
|
|
22
22
|
export interface ThemeColorAvatarTokens {
|
|
23
23
|
'*'?: ThemeColorAvatarHueTokens
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
gray?: ThemeColorAvatarHueTokens
|
|
25
|
+
blue?: ThemeColorAvatarHueTokens
|
|
26
|
+
purple?: ThemeColorAvatarHueTokens
|
|
27
|
+
magenta?: ThemeColorAvatarHueTokens
|
|
28
|
+
red?: ThemeColorAvatarHueTokens
|
|
29
|
+
orange?: ThemeColorAvatarHueTokens
|
|
30
|
+
yellow?: ThemeColorAvatarHueTokens
|
|
31
|
+
green?: ThemeColorAvatarHueTokens
|
|
32
|
+
cyan?: ThemeColorAvatarHueTokens
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/** @public */
|
|
@@ -66,11 +66,11 @@ export interface ThemeColorBadgeToneTokens {
|
|
|
66
66
|
/** @public */
|
|
67
67
|
export interface ThemeColorBadgeTokens {
|
|
68
68
|
'*'?: ThemeColorBadgeToneTokens
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
default?: ThemeColorBadgeToneTokens
|
|
70
|
+
primary?: ThemeColorBadgeToneTokens
|
|
71
|
+
positive?: ThemeColorBadgeToneTokens
|
|
72
|
+
caution?: ThemeColorBadgeToneTokens
|
|
73
|
+
critical?: ThemeColorBadgeToneTokens
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
/** @public */
|