Skip to content

Commit 942a0a3

Browse files
committedJul 12, 2021
refactor(field): migrate ptdiff annotation, inline-object components to @sanity/ui
1 parent 55c3229 commit 942a0a3

File tree

5 files changed

+152
-184
lines changed

5 files changed

+152
-184
lines changed
 

‎packages/@sanity/field/src/types/portableText/diff/components/Annotation.css

-59
This file was deleted.

‎packages/@sanity/field/src/types/portableText/diff/components/Annotation.tsx

+61-31
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import {useClickOutside} from '@sanity/ui'
1+
import {useClickOutside, Label, Popover, Flex} from '@sanity/ui'
22
import {toString} from '@sanity/util/paths'
3-
import classNames from 'classnames'
43
import {isKeySegment, Path} from '@sanity/types'
5-
import ChevronDownIcon from 'part:@sanity/base/chevron-down-icon'
6-
import {Popover} from 'part:@sanity/components/popover'
74
import React, {useCallback, useEffect, useState} from 'react'
85
import {ConnectorContext, useReportedValues} from '@sanity/base/lib/change-indicators'
6+
import styled from 'styled-components'
7+
import {ChevronDownIcon} from '@sanity/icons'
98
import {
109
ChangeList,
1110
DiffContext,
@@ -16,30 +15,51 @@ import {
1615
} from '../../../../diff'
1716
import {PortableTextChild} from '../types'
1817
import {isEmptyObject} from '../helpers'
19-
import styles from './Annotation.css'
18+
import {InlineBox, InlineText, PopoverContainer, PreviewContainer} from './styledComponents'
2019

2120
interface AnnotationProps {
2221
diff?: ObjectDiff
2322
object: PortableTextChild
24-
children: JSX.Element
2523
schemaType?: ObjectSchemaType
2624
path: Path
25+
children: React.ReactNode
2726
}
2827

28+
const AnnotationWrapper = styled.div`
29+
text-decoration: none;
30+
display: inline;
31+
position: relative;
32+
border: 0;
33+
padding: 0;
34+
border-bottom: 2px dotted currentColor;
35+
box-shadow: inset 0 0 0 1px var(--card-border-color);
36+
white-space: nowrap;
37+
align-items: center;
38+
background-color: color(var(--card-fg-color) a(10%));
39+
40+
&[data-changed] {
41+
cursor: pointer;
42+
}
43+
44+
&[data-removed] {
45+
text-decoration: line-through;
46+
}
47+
48+
&:hover ${PreviewContainer} {
49+
opacity: 1;
50+
}
51+
`
52+
2953
export function Annotation({
3054
children,
3155
diff,
3256
object,
3357
schemaType,
3458
path,
3559
...restProps
36-
}: AnnotationProps & Omit<React.HTMLProps<HTMLSpanElement>, 'onClick'>) {
60+
}: AnnotationProps) {
3761
if (!schemaType) {
38-
return (
39-
<span {...restProps} className={styles.root}>
40-
Unknown schema type
41-
</span>
42-
)
62+
return <AnnotationWrapper {...restProps}>Unknown schema type</AnnotationWrapper>
4363
}
4464
if (diff && diff.action !== 'unchanged') {
4565
return (
@@ -54,14 +74,15 @@ export function Annotation({
5474
</AnnnotationWithDiff>
5575
)
5676
}
57-
return <span className={styles.root}>{children}</span>
77+
return <AnnotationWrapper>{children}</AnnotationWrapper>
5878
}
5979

6080
interface AnnnotationWithDiffProps {
6181
diff: ObjectDiff
6282
object: PortableTextChild
6383
schemaType: ObjectSchemaType
6484
path: Path
85+
children?: React.ReactNode
6586
}
6687

6788
function AnnnotationWithDiff({
@@ -71,18 +92,13 @@ function AnnnotationWithDiff({
7192
schemaType,
7293
path,
7394
...restProps
74-
}: AnnnotationWithDiffProps & Omit<React.HTMLProps<HTMLSpanElement>, 'onClick'>) {
95+
}: AnnnotationWithDiffProps) {
7596
const {onSetFocus} = React.useContext(ConnectorContext)
7697
const {path: fullPath} = React.useContext(DiffContext)
7798
const [popoverElement, setPopoverElement] = useState<HTMLDivElement | null>(null)
7899
const color = useDiffAnnotationColor(diff, [])
79100
const style = color ? {background: color.background, color: color.text} : {}
80101
const isRemoved = diff.action === 'removed'
81-
const className = classNames(
82-
styles.root,
83-
styles.isChanged,
84-
diff.action === 'removed' && styles.removed
85-
)
86102
const [open, setOpen] = useState(false)
87103
const emptyObject = object && isEmptyObject(object)
88104
const markDefPath = [path[0]].concat(['markDefs', {_key: object._key}])
@@ -129,26 +145,40 @@ function AnnnotationWithDiff({
129145

130146
const popoverContent = (
131147
<DiffContext.Provider value={{path: myPath}}>
132-
<div className={styles.popoverContainer}>
133-
<div className={styles.popoverContent}>
134-
{emptyObject && <span className={styles.empty}>Empty {schemaType.title}</span>}
148+
<PopoverContainer padding={3}>
149+
<div>
150+
{emptyObject && (
151+
<Label size={1} muted>
152+
Empty {schemaType.title}
153+
</Label>
154+
)}
135155
{!emptyObject && <ChangeList diff={diff} schemaType={schemaType} />}
136156
</div>
137-
</div>
157+
</PopoverContainer>
138158
</DiffContext.Provider>
139159
)
140160
return (
141-
<span {...restProps} className={className} onClick={handleOpenPopup} style={style}>
142-
<Popover content={popoverContent} open={open} ref={setPopoverElement}>
143-
<span className={styles.previewContainer}>
161+
<AnnotationWrapper
162+
{...restProps}
163+
onClick={handleOpenPopup}
164+
style={style}
165+
data-changed=""
166+
data-removed={diff.action === 'removed' ? '' : undefined}
167+
>
168+
<Popover content={popoverContent} open={open} ref={setPopoverElement} portal>
169+
<PreviewContainer paddingLeft={1}>
144170
<DiffTooltip annotations={annotations} description={`${diff.action} annotation`}>
145-
<span>
171+
<InlineBox style={{display: 'inline-flex'}}>
146172
<span>{children}</span>
147-
<ChevronDownIcon />
148-
</span>
173+
<Flex align="center" paddingX={1}>
174+
<InlineText size={0}>
175+
<ChevronDownIcon />
176+
</InlineText>
177+
</Flex>
178+
</InlineBox>
149179
</DiffTooltip>
150-
</span>
180+
</PreviewContainer>
151181
</Popover>
152-
</span>
182+
</AnnotationWrapper>
153183
)
154184
}

‎packages/@sanity/field/src/types/portableText/diff/components/InlineObject.css

-66
This file was deleted.

‎packages/@sanity/field/src/types/portableText/diff/components/InlineObject.tsx

+54-28
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import {FOCUS_TERMINATOR, toString} from '@sanity/util/paths'
2-
import classNames from 'classnames'
32
import {isKeySegment, Path} from '@sanity/types'
4-
import {useClickOutside, useLayer} from '@sanity/ui'
5-
import ChevronDownIcon from 'part:@sanity/base/chevron-down-icon'
3+
import {Card, Flex, Label, useClickOutside, useLayer} from '@sanity/ui'
64
import SanityPreview from 'part:@sanity/base/preview'
75
import {Popover} from 'part:@sanity/components/popover'
86
import React, {useCallback, useState, useEffect} from 'react'
97
import {ConnectorContext, useReportedValues} from '@sanity/base/lib/change-indicators'
8+
import styled from 'styled-components'
9+
import {ChevronDownIcon} from '@sanity/icons'
1010
import {
1111
ChangeList,
1212
DiffContext,
@@ -17,8 +17,7 @@ import {
1717
} from '../../../../diff'
1818
import {PortableTextChild} from '../types'
1919
import {isEmptyObject} from '../helpers'
20-
21-
import styles from './InlineObject.css'
20+
import {InlineBox, InlineText, PopoverContainer, PreviewContainer} from './styledComponents'
2221

2322
interface InlineObjectProps {
2423
diff?: ObjectDiff
@@ -27,17 +26,29 @@ interface InlineObjectProps {
2726
schemaType?: ObjectSchemaType
2827
}
2928

30-
export function InlineObject({
31-
diff,
32-
object,
33-
schemaType,
34-
...restProps
35-
}: InlineObjectProps & Omit<React.HTMLProps<HTMLSpanElement>, 'onClick'>) {
29+
const InlineObjectWrapper = styled(Card)`
30+
&:not([hidden]) {
31+
display: inline;
32+
cursor: pointer;
33+
white-space: nowrap;
34+
align-items: center;
35+
36+
&[data-removed] {
37+
text-decoration: line-through;
38+
}
39+
40+
${InlineBox} {
41+
display: inline-flex;
42+
}
43+
}
44+
`
45+
46+
export function InlineObject({diff, object, schemaType, ...restProps}: InlineObjectProps) {
3647
if (!schemaType) {
3748
return (
38-
<span {...restProps} className={styles.root}>
49+
<InlineObjectWrapper {...restProps} border radius={1}>
3950
Unknown schema type: {object._type}
40-
</span>
51+
</InlineObjectWrapper>
4152
)
4253
}
4354

@@ -48,9 +59,9 @@ export function InlineObject({
4859
}
4960

5061
return (
51-
<span {...restProps} className={styles.root}>
62+
<InlineObjectWrapper>
5263
<SanityPreview type={schemaType} value={object} layout="inline" />
53-
</span>
64+
</InlineObjectWrapper>
5465
)
5566
}
5667

@@ -67,12 +78,11 @@ function InlineObjectWithDiff({
6778
path,
6879
schemaType,
6980
...restProps
70-
}: InlineObjectWithDiffProps & Omit<React.HTMLProps<HTMLSpanElement>, 'onClick'>) {
81+
}: InlineObjectWithDiffProps) {
7182
const {path: fullPath} = React.useContext(DiffContext)
7283
const {onSetFocus} = React.useContext(ConnectorContext)
7384
const color = useDiffAnnotationColor(diff, [])
7485
const style = color ? {background: color.background, color: color.text} : {}
75-
const className = classNames(styles.root, diff.action === 'removed' && styles.removed)
7686
const [open, setOpen] = useState(false)
7787
const emptyObject = object && isEmptyObject(object)
7888
const isRemoved = diff.action === 'removed'
@@ -126,18 +136,29 @@ function InlineObjectWithDiff({
126136
const annotations = annotation ? [annotation] : []
127137

128138
return (
129-
<span {...restProps} className={className} onClick={handleOpenPopup} style={style}>
139+
<InlineObjectWrapper
140+
{...restProps}
141+
onClick={handleOpenPopup}
142+
style={style}
143+
data-removed={diff.action === 'removed' ? '' : undefined}
144+
border
145+
radius={2}
146+
>
130147
<Popover content={popoverContent} layer open={open} portal>
131-
<span className={styles.previewContainer}>
148+
<PreviewContainer>
132149
<DiffTooltip annotations={annotations} description={`${diff.action} inline object`}>
133-
<span>
150+
<InlineBox>
134151
<SanityPreview type={schemaType} value={object} layout="inline" />
135-
<ChevronDownIcon />
136-
</span>
152+
<Flex align="center" paddingX={1}>
153+
<InlineText size={0}>
154+
<ChevronDownIcon />
155+
</InlineText>
156+
</Flex>
157+
</InlineBox>
137158
</DiffTooltip>
138-
</span>
159+
</PreviewContainer>
139160
</Popover>
140-
</span>
161+
</InlineObjectWrapper>
141162
)
142163
}
143164

@@ -156,16 +177,21 @@ function PopoverContent({
156177
const {isTopLayer} = useLayer()
157178

158179
const handleClickOutside = useCallback(() => {
159-
if (!isTopLayer) return
180+
// Popover doesn't close at all when using this condition
181+
// if (!isTopLayer) return
160182
onClose()
161183
}, [isTopLayer, onClose])
162184

163185
useClickOutside(handleClickOutside, [popoverElement])
164186

165187
return (
166-
<div className={styles.popoverContent} ref={setPopoverElement}>
167-
{emptyObject && <span className={styles.empty}>Empty {schemaType.title}</span>}
188+
<PopoverContainer ref={setPopoverElement} padding={3}>
189+
{emptyObject && (
190+
<Label size={1} muted>
191+
Empty {schemaType.title}
192+
</Label>
193+
)}
168194
{!emptyObject && <ChangeList diff={diff} schemaType={schemaType} />}
169-
</div>
195+
</PopoverContainer>
170196
)
171197
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import styled from 'styled-components'
2+
import {Box, Text} from '@sanity/ui'
3+
4+
export const InlineBox = styled(Box)`
5+
&:not([hidden]) {
6+
display: inline;
7+
align-items: center;
8+
9+
&[data-changed] {
10+
cursor: pointer;
11+
}
12+
}
13+
`
14+
15+
export const InlineText = styled(Text)`
16+
&:not([hidden]) {
17+
display: inline;
18+
color: inherit;
19+
}
20+
`
21+
22+
export const PreviewContainer = styled(Box)`
23+
&:not([hidden]) {
24+
display: inline-flex;
25+
align-items: center;
26+
27+
${InlineBox} [data-ui="Text"] {
28+
opacity: 0.5;
29+
}
30+
}
31+
`
32+
33+
export const PopoverContainer = styled(Box)`
34+
min-width: 160px;
35+
max-height: 40vh;
36+
overflow-y: auto;
37+
`

0 commit comments

Comments
 (0)
Please sign in to comment.