@sanity/ui 1.9.0 → 1.9.1
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.esm.js +21 -37
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +20 -36
- package/dist/index.js.map +1 -1
- package/package.json +4 -6
- package/src/primitives/tooltip/__workshop__/index.ts +10 -0
- package/src/primitives/tooltip/__workshop__/overflowingBoundary.tsx +53 -0
- package/src/primitives/tooltip/__workshop__/resizableBoundary.tsx +85 -0
- package/src/primitives/tooltip/constants.ts +1 -0
- package/src/primitives/tooltip/tooltip.tsx +10 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/ui",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"source": "./src/index.ts",
|
|
@@ -44,8 +44,8 @@
|
|
|
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
|
},
|
|
51
51
|
"dependencies": {
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"@juggle/resize-observer": "^3.4.0",
|
|
67
67
|
"@sanity/pkg-utils": "^2.4.8",
|
|
68
68
|
"@sanity/semantic-release-preset": "^4.1.4",
|
|
69
|
-
"@sanity/ui-workshop": "^
|
|
69
|
+
"@sanity/ui-workshop": "^2.0.0",
|
|
70
70
|
"@testing-library/dom": "^9.3.1",
|
|
71
71
|
"@testing-library/jest-dom": "^5.17.0",
|
|
72
72
|
"@testing-library/react": "^14.0.0",
|
|
@@ -84,8 +84,6 @@
|
|
|
84
84
|
"cypress": "^13.1.0",
|
|
85
85
|
"cypress-real-events": "^1.10.1",
|
|
86
86
|
"cz-conventional-changelog": "^3.3.0",
|
|
87
|
-
"esbuild": "^0.19.2",
|
|
88
|
-
"esbuild-register": "^3.4.2",
|
|
89
87
|
"eslint": "^8.48.0",
|
|
90
88
|
"eslint-config-prettier": "^9.0.0",
|
|
91
89
|
"eslint-plugin-import": "^2.28.1",
|
|
@@ -10,5 +10,15 @@ export default defineScope({
|
|
|
10
10
|
title: 'Props',
|
|
11
11
|
component: lazy(() => import('./props')),
|
|
12
12
|
},
|
|
13
|
+
{
|
|
14
|
+
name: 'resizableBoundary',
|
|
15
|
+
title: 'Resizable Boundary',
|
|
16
|
+
component: lazy(() => import('./resizableBoundary')),
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'overflowBoundary',
|
|
20
|
+
title: 'Overflowing Boundary',
|
|
21
|
+
component: lazy(() => import('./overflowingBoundary')),
|
|
22
|
+
},
|
|
13
23
|
],
|
|
14
24
|
})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {BoundaryElementProvider, Button, Card, Code, Flex, Text, Tooltip} from '@sanity/ui'
|
|
2
|
+
import {useBoolean, useSelect, useText} from '@sanity/ui-workshop'
|
|
3
|
+
import {useState} from 'react'
|
|
4
|
+
import {WORKSHOP_PLACEMENT_OPTIONS} from '../../../__workshop__/constants'
|
|
5
|
+
|
|
6
|
+
export default function OverflowingBoundaryStory() {
|
|
7
|
+
const content = useText(
|
|
8
|
+
'Content',
|
|
9
|
+
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut mollis consectetur malesuada. Sed lobortis est dolor, eget imperdiet velit placerat et. Aenean posuere mi non aliquet iaculis. Donec fermentum pulvinar purus at sagittis. Ut tincidunt massa odio, sed finibus justo ullamcorper id. Nam venenatis justo non ligula elementum cursus. Pellentesque laoreet justo in mollis sagittis. In lacinia ornare ultrices. Suspendisse potenti.',
|
|
10
|
+
)
|
|
11
|
+
const placement = useSelect('Placement', WORKSHOP_PLACEMENT_OPTIONS, 'top')
|
|
12
|
+
const portal = useBoolean('Portal', false)
|
|
13
|
+
const useBoundaryElement = useBoolean('Use boundary element', true)
|
|
14
|
+
|
|
15
|
+
const [boundaryElement, setBoundaryElement] = useState<HTMLDivElement | null>(null)
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Flex align="center" height="fill" justify="center" style={{height: '200vh'}}>
|
|
19
|
+
<BoundaryElementProvider element={useBoundaryElement ? boundaryElement : null}>
|
|
20
|
+
<Card
|
|
21
|
+
border
|
|
22
|
+
ref={setBoundaryElement}
|
|
23
|
+
style={{
|
|
24
|
+
height: 'calc(100vh - 100px)',
|
|
25
|
+
overflow: 'hidden',
|
|
26
|
+
position: 'relative',
|
|
27
|
+
resize: 'both',
|
|
28
|
+
width: '500px',
|
|
29
|
+
}}
|
|
30
|
+
>
|
|
31
|
+
<Flex align="center" height="fill" justify="center">
|
|
32
|
+
<Flex justify="center">
|
|
33
|
+
<Code size={1}>Placement: {placement}</Code>
|
|
34
|
+
</Flex>
|
|
35
|
+
</Flex>
|
|
36
|
+
|
|
37
|
+
<Tooltip
|
|
38
|
+
content={<Text size={1}>{content}</Text>}
|
|
39
|
+
padding={2}
|
|
40
|
+
placement={placement}
|
|
41
|
+
portal={portal}
|
|
42
|
+
>
|
|
43
|
+
<Button
|
|
44
|
+
mode="bleed"
|
|
45
|
+
style={{position: 'absolute', top: 10, right: 10}}
|
|
46
|
+
text="Tooltip"
|
|
47
|
+
/>
|
|
48
|
+
</Tooltip>
|
|
49
|
+
</Card>
|
|
50
|
+
</BoundaryElementProvider>
|
|
51
|
+
</Flex>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {BoundaryElementProvider, Button, Card, Code, Flex, Text, Tooltip} from '@sanity/ui'
|
|
2
|
+
import {useBoolean, useSelect, useText} from '@sanity/ui-workshop'
|
|
3
|
+
import {useState} from 'react'
|
|
4
|
+
import {WORKSHOP_PLACEMENT_OPTIONS} from '../../../__workshop__/constants'
|
|
5
|
+
|
|
6
|
+
export default function ResizableBoundaryStory() {
|
|
7
|
+
const content = useText(
|
|
8
|
+
'Content',
|
|
9
|
+
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut mollis consectetur malesuada. Sed lobortis est dolor, eget imperdiet velit placerat et. Aenean posuere mi non aliquet iaculis. Donec fermentum pulvinar purus at sagittis. Ut tincidunt massa odio, sed finibus justo ullamcorper id. Nam venenatis justo non ligula elementum cursus. Pellentesque laoreet justo in mollis sagittis. In lacinia ornare ultrices. Suspendisse potenti.',
|
|
10
|
+
)
|
|
11
|
+
const placement = useSelect('Placement', WORKSHOP_PLACEMENT_OPTIONS, 'right')
|
|
12
|
+
const portal = useBoolean('Portal', true)
|
|
13
|
+
const useBoundaryElement = useBoolean('Use boundary element', true)
|
|
14
|
+
|
|
15
|
+
const [boundaryElement, setBoundaryElement] = useState<HTMLDivElement | null>(null)
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Flex align="center" height="fill" justify="center">
|
|
19
|
+
<BoundaryElementProvider element={useBoundaryElement ? boundaryElement : null}>
|
|
20
|
+
<Card
|
|
21
|
+
border
|
|
22
|
+
ref={setBoundaryElement}
|
|
23
|
+
style={{
|
|
24
|
+
height: 'calc(100vh - 100px)',
|
|
25
|
+
overflow: 'hidden',
|
|
26
|
+
position: 'relative',
|
|
27
|
+
resize: 'both',
|
|
28
|
+
width: '500px',
|
|
29
|
+
}}
|
|
30
|
+
>
|
|
31
|
+
<Flex align="center" height="fill" justify="center">
|
|
32
|
+
<Flex justify="center">
|
|
33
|
+
<Code size={1}>Placement: {placement}</Code>
|
|
34
|
+
</Flex>
|
|
35
|
+
</Flex>
|
|
36
|
+
|
|
37
|
+
<Tooltip
|
|
38
|
+
content={<Text size={1}>{content}</Text>}
|
|
39
|
+
padding={2}
|
|
40
|
+
placement={placement}
|
|
41
|
+
portal={portal}
|
|
42
|
+
>
|
|
43
|
+
<Button mode="bleed" style={{position: 'absolute', top: 10, left: 10}} text="Tooltip" />
|
|
44
|
+
</Tooltip>
|
|
45
|
+
<Tooltip
|
|
46
|
+
content={<Text size={1}>{content}</Text>}
|
|
47
|
+
padding={2}
|
|
48
|
+
placement={placement}
|
|
49
|
+
portal={portal}
|
|
50
|
+
>
|
|
51
|
+
<Button
|
|
52
|
+
mode="bleed"
|
|
53
|
+
style={{position: 'absolute', top: 10, right: 10}}
|
|
54
|
+
text="Tooltip"
|
|
55
|
+
/>
|
|
56
|
+
</Tooltip>
|
|
57
|
+
<Tooltip
|
|
58
|
+
content={<Text size={1}>{content}</Text>}
|
|
59
|
+
padding={2}
|
|
60
|
+
placement={placement}
|
|
61
|
+
portal={portal}
|
|
62
|
+
>
|
|
63
|
+
<Button
|
|
64
|
+
mode="bleed"
|
|
65
|
+
style={{position: 'absolute', bottom: 10, left: 10}}
|
|
66
|
+
text="Tooltip"
|
|
67
|
+
/>
|
|
68
|
+
</Tooltip>
|
|
69
|
+
<Tooltip
|
|
70
|
+
content={<Text size={1}>{content}</Text>}
|
|
71
|
+
padding={2}
|
|
72
|
+
placement={placement}
|
|
73
|
+
portal={portal}
|
|
74
|
+
>
|
|
75
|
+
<Button
|
|
76
|
+
mode="bleed"
|
|
77
|
+
style={{position: 'absolute', bottom: 10, right: 10}}
|
|
78
|
+
text="Tooltip"
|
|
79
|
+
/>
|
|
80
|
+
</Tooltip>
|
|
81
|
+
</Card>
|
|
82
|
+
</BoundaryElementProvider>
|
|
83
|
+
</Flex>
|
|
84
|
+
)
|
|
85
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {Placement} from '@floating-ui/react-dom'
|
|
2
2
|
|
|
3
|
+
export const DEFAULT_TOOLTIP_PADDING = 4
|
|
3
4
|
export const DEFAULT_FALLBACK_PLACEMENTS: Record<Placement, Placement[]> = {
|
|
4
5
|
top: ['bottom', 'left', 'right'],
|
|
5
6
|
'top-start': ['bottom-start', 'left-start', 'right-start'],
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
useFloating,
|
|
9
9
|
Middleware,
|
|
10
10
|
RootBoundary,
|
|
11
|
-
size,
|
|
12
11
|
} from '@floating-ui/react-dom'
|
|
13
12
|
import {
|
|
14
13
|
cloneElement,
|
|
@@ -31,7 +30,7 @@ import {Placement} from '../../types'
|
|
|
31
30
|
import {Layer, LayerProps, Portal, useBoundaryElement} from '../../utils'
|
|
32
31
|
import {Card} from '../card'
|
|
33
32
|
import {Delay} from '../types'
|
|
34
|
-
import {DEFAULT_FALLBACK_PLACEMENTS} from './constants'
|
|
33
|
+
import {DEFAULT_FALLBACK_PLACEMENTS, DEFAULT_TOOLTIP_PADDING} from './constants'
|
|
35
34
|
import {TooltipArrow} from './tooltipArrow'
|
|
36
35
|
import {useTooltipDelayGroup} from './tooltipDelayGroup'
|
|
37
36
|
|
|
@@ -63,6 +62,9 @@ export interface TooltipProps extends Omit<LayerProps, 'as'> {
|
|
|
63
62
|
|
|
64
63
|
const Root = styled(Layer)`
|
|
65
64
|
pointer-events: none;
|
|
65
|
+
// Note that 100vw doesn't exclude system scrollbars.
|
|
66
|
+
// This should be sufficiently small enough to not trigger overflow-x scrollbars when portalled.
|
|
67
|
+
max-width: calc(100vw - ${DEFAULT_TOOLTIP_PADDING * 10}px);
|
|
66
68
|
`
|
|
67
69
|
|
|
68
70
|
/**
|
|
@@ -102,35 +104,22 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
102
104
|
// Flip the floating element when leaving the boundary box
|
|
103
105
|
ret.push(
|
|
104
106
|
flip({
|
|
105
|
-
boundary: boundaryElement || undefined,
|
|
107
|
+
boundary: portal ? undefined : boundaryElement || undefined,
|
|
106
108
|
fallbackPlacements,
|
|
107
|
-
padding:
|
|
109
|
+
padding: DEFAULT_TOOLTIP_PADDING,
|
|
108
110
|
rootBoundary,
|
|
109
|
-
mainAxis: false,
|
|
110
111
|
}),
|
|
111
112
|
)
|
|
112
113
|
|
|
113
114
|
// Define distance between reference and floating element
|
|
114
115
|
ret.push(offset({mainAxis: 3}))
|
|
115
116
|
|
|
116
|
-
//
|
|
117
|
-
ret.push(
|
|
118
|
-
size({
|
|
119
|
-
apply({availableWidth, availableHeight, elements}) {
|
|
120
|
-
Object.assign(elements.floating.style, {
|
|
121
|
-
maxWidth: `${availableWidth - 4 * 2}px`, // the padding is `4px`
|
|
122
|
-
maxHeight: `${availableHeight - 4 * 2}px`, // the padding is `4px`
|
|
123
|
-
})
|
|
124
|
-
},
|
|
125
|
-
}),
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
// Shift the tooltip so its sits with the boundary eleement
|
|
117
|
+
// Shift the tooltip so its sits with the boundary element
|
|
129
118
|
ret.push(
|
|
130
119
|
shift({
|
|
131
|
-
boundary: boundaryElement || undefined,
|
|
120
|
+
boundary: portal ? undefined : boundaryElement || undefined,
|
|
132
121
|
rootBoundary,
|
|
133
|
-
padding:
|
|
122
|
+
padding: DEFAULT_TOOLTIP_PADDING,
|
|
134
123
|
}),
|
|
135
124
|
)
|
|
136
125
|
|
|
@@ -138,7 +127,7 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
138
127
|
ret.push(arrow({element: arrowRef, padding: 2}))
|
|
139
128
|
|
|
140
129
|
return ret
|
|
141
|
-
}, [boundaryElement, fallbackPlacements])
|
|
130
|
+
}, [boundaryElement, fallbackPlacements, portal])
|
|
142
131
|
|
|
143
132
|
const {floatingStyles, placement, middlewareData, refs, update} = useFloating({
|
|
144
133
|
middleware,
|