Skip to content

Commit

Permalink
feat(core): initial tree editing breadcrumbs (#6677)
Browse files Browse the repository at this point in the history
* feat(core): initial tree editing breadcrumbs

* fix(core): remove comment
  • Loading branch information
hermanwikner committed May 15, 2024
1 parent 12d401c commit 0856eef
Show file tree
Hide file tree
Showing 16 changed files with 472 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Container, Flex} from '@sanity/ui'

import {TreeEditingBreadCrumbs} from '../components'
import {TreeEditingBreadcrumbs} from '../components'
import {type TreeEditingBreadcrumb} from '../types'

function noop() {
Expand All @@ -11,34 +11,40 @@ const ITEMS: TreeEditingBreadcrumb[] = [
{
title: 'First',
path: ['first'],
children: [],
},
{
title: 'Second',
path: ['first', 'second'],
children: [],
},
{
title: 'Third',
path: ['first', 'second', 'third'],
children: [],
},
{
title: 'Fourth',
path: ['first', 'second', 'third', 'fourth'],
children: [],
},
{
title: 'Fifth',
path: ['first', 'second', 'third', 'fourth', 'fifth'],
children: [],
},
{
title: 'Sixth',
path: ['first', 'second', 'third', 'fourth', 'fifth', 'sixth'],
children: [],
},
]

export default function TreeEditingBreadCrumbsStory(): JSX.Element {
export default function TreeEditingBreadcrumbsStory(): JSX.Element {
return (
<Flex align="center" height="fill">
<Container width={0}>
<TreeEditingBreadCrumbs items={ITEMS} onPathSelect={noop} />
<TreeEditingBreadcrumbs items={ITEMS} onPathSelect={noop} selectedPath={[]} />
</Container>
</Flex>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// eslint-disable-next-line no-restricted-imports
import {Button, Flex} from '@sanity/ui'
import {useState} from 'react'
import {type Path} from 'sanity'

import {TreeEditingBreadcrumbsMenuButton} from '../components'
import {type TreeEditingBreadcrumb} from '../types'

const ITEMS: TreeEditingBreadcrumb[] = [...Array(100).keys()].map((index) => ({
title: `Item ${index}`,
path: [`${index}-item`],
children: [],
}))

export default function TreeEditingBreadcrumbsMenuButtonStory(): JSX.Element {
const [selectedPath, setSelectedPath] = useState<Path>(['second-item'])

return (
<Flex align="center" justify="center" height="fill">
<TreeEditingBreadcrumbsMenuButton
items={ITEMS}
onPathSelect={setSelectedPath}
selectedPath={selectedPath}
button={<Button text="Open menu" />}
/>
</Flex>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {Container, Flex} from '@sanity/ui'
import {useState} from 'react'
import {type Path} from 'sanity'

import {TreeEditingBreadcrumbsMenu} from '../components'
import {type TreeEditingBreadcrumb} from '../types'

const items: TreeEditingBreadcrumb[] = [
{
title: 'First item',
path: ['first-item'],
children: [],
},
{
title: 'Second item',
path: ['second-item'],
children: [],
},
{
title: 'Third item',
path: ['third-item'],
children: [],
},
]

export default function TreeEditingBreadcrumbsMenuStory(): JSX.Element {
const [selectedPath, setSelectedPath] = useState<Path>(['second-item'])

return (
<Flex align="center" height="fill">
<Container width={0}>
<TreeEditingBreadcrumbsMenu
items={items}
onPathSelect={setSelectedPath}
selectedPath={selectedPath}
textInputElement={null}
/>
</Container>
</Flex>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ export default function TreeEditingLayoutStory(): JSX.Element {
const [selectedPath, setSelectedPath] = useState<Path>(EMPTY_ARRAY)

const handlePathSelect = useCallback((path: Path) => {
const next = path?.map((segment) => ({title: segment.toString(), path: [] as Path})) || []
const next: TreeEditingBreadcrumb[] =
path?.map((segment) => ({title: segment.toString(), path: [] as Path, children: []})) || []

setBreadcrumbs(next)
setSelectedPath(path)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,18 @@ export default defineScope({

{
name: 'tree-editing-breadcrumbs',
title: 'TreeEditingBreadCrumbs',
component: lazy(() => import('./TreeEditingBreadCrumbsStory')),
title: 'TreeEditingBreadcrumbs',
component: lazy(() => import('./TreeEditingBreadcrumbsStory')),
},
{
name: 'tree-editing-breadcrumbs-menu',
title: 'TreeEditingBreadcrumbsMenu',
component: lazy(() => import('./TreeEditingBreadcrumbsMenuStory')),
},
{
name: 'tree-editing-breadcrumbs-menu-button',
title: 'TreeEditingBreadcrumbsMenuButtonStory',
component: lazy(() => import('./TreeEditingBreadcrumbsMenuButtonStory')),
},
{
name: 'tree-menu-items-build-debug',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
/* eslint-disable @sanity/i18n/no-attribute-string-literals */
/* eslint-disable i18next/no-literal-string */
import {Card, Code, Dialog, Flex, Text} from '@sanity/ui'
import {Button, Card, Code, Dialog, Flex, Text} from '@sanity/ui'
import {type Theme} from '@sanity/ui/theme'
import {toString} from '@sanity/util/paths'
import {AnimatePresence, motion, type Variants} from 'framer-motion'
import {AnimatePresence, motion, type Transition, type Variants} from 'framer-motion'
import {debounce, type DebounceSettings, isEqual} from 'lodash'
import {useCallback, useEffect, useMemo, useState} from 'react'
import {
FormInput,
type InputProps,
isDev,
type ObjectInputProps,
type ObjectSchemaType,
type Path,
Expand All @@ -24,7 +26,7 @@ import {
import {handleNavigate} from '../utils/handleNavigate'
import {TreeEditingLayout} from './TreeEditingLayout'

const DEBUG_RELATIVE_PATH = true
const DEBUG_RELATIVE_PATH = isDev

const EMPTY_ARRAY: [] = []

Expand All @@ -34,6 +36,8 @@ const ANIMATION_VARIANTS: Variants = {
exit: {opacity: 0},
}

const ANIMATION_TRANSITION: Transition = {duration: 0.15, ease: 'easeInOut'}

const DEBOUNCE_SETTINGS: DebounceSettings = {leading: true, trailing: true}

function renderDefault(props: InputProps) {
Expand Down Expand Up @@ -133,6 +137,13 @@ export function TreeEditingDialog(props: TreeEditingDialogProps): JSX.Element |
onPathSelect={onHandlePathSelect}
selectedPath={relativePath}
title={rootTitle}
footer={
<Card borderTop>
<Flex align="center" justify="flex-end" paddingX={3} paddingY={2} sizing="border">
<Button text="Done" onClick={onClose} />
</Flex>
</Card>
}
>
{DEBUG_RELATIVE_PATH && (
<Card
Expand Down Expand Up @@ -181,6 +192,7 @@ export function TreeEditingDialog(props: TreeEditingDialogProps): JSX.Element |
initial="initial"
key={toString(relativePath)}
overflow="hidden"
transition={ANIMATION_TRANSITION}
variants={ANIMATION_VARIANTS}
>
<FormInput
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @sanity/i18n/no-attribute-string-literals */
/* eslint-disable i18next/no-literal-string */
import {PanelLeftIcon} from '@sanity/icons'
import {Card, Container, Flex, Stack, Text} from '@sanity/ui'
Expand All @@ -7,8 +8,8 @@ import styled from 'styled-components'

import {Button} from '../../../../../ui-components'
import {type TreeEditingBreadcrumb, type TreeEditingMenuItem} from '../types'
import {TreeEditingBreadcrumbs} from './breadcrumbs'
import {Resizable} from './resizer'
import {TreeEditingBreadCrumbs} from './TreeEditingBreadCrumbs'
import {TreeEditingMenu} from './TreeEditingMenu'

const FixedHeightFlex = styled(Flex).attrs({padding: 2, align: 'center', sizing: 'border'})`
Expand Down Expand Up @@ -83,6 +84,7 @@ const Sidebar = memo(function Sidebar(props: SidebarProps) {
interface TreeEditingLayoutProps {
breadcrumbs: TreeEditingBreadcrumb[]
children: ReactNode
footer?: ReactNode
items: TreeEditingMenuItem[]
onPathSelect: (path: Path) => void
selectedPath: Path
Expand All @@ -92,11 +94,11 @@ interface TreeEditingLayoutProps {
export const TreeEditingLayout = memo(function TreeEditingLayout(
props: TreeEditingLayoutProps,
): JSX.Element {
const {breadcrumbs, children, items, selectedPath, onPathSelect, title} = props
const {breadcrumbs, children, items, selectedPath, onPathSelect, title, footer} = props
const scrollElementRef = useRef<HTMLDivElement | null>(null)
const containerElementRef = useRef<HTMLDivElement | null>(null)

const [open, setOpen] = useState<boolean>(true)
const [open, setOpen] = useState<boolean>(false)

const toggleOpen = useCallback(() => setOpen((v) => !v), [])

Expand All @@ -113,20 +115,22 @@ export const TreeEditingLayout = memo(function TreeEditingLayout(

<Flex direction="column" flex={1} overflow="hidden">
<FixedHeightFlex align="center" sizing="border" gap={2} paddingX={4}>
<TreeEditingBreadCrumbs items={breadcrumbs} onPathSelect={onPathSelect} />
<TreeEditingBreadcrumbs
items={breadcrumbs}
onPathSelect={onPathSelect}
selectedPath={selectedPath}
/>
</FixedHeightFlex>

<Card
flex={1}
id="tree-editing-form"
overflow="auto"
paddingX={3}
paddingY={5}
ref={scrollElementRef}
sizing="border"
>
<Card flex={1} id="tree-editing-form" overflow="auto" ref={scrollElementRef}>
{children && (
<Container width={1} ref={containerElementRef}>
<Container
width={1}
ref={containerElementRef}
paddingX={5}
paddingY={5}
sizing="border"
>
<VirtualizerScrollInstanceProvider
containerElement={containerElementRef}
scrollElement={scrollElementRef.current}
Expand All @@ -136,6 +140,8 @@ export const TreeEditingLayout = memo(function TreeEditingLayout(
</Container>
)}
</Card>

{footer}
</Flex>
</Flex>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function MenuItem(props: TreeEditingMenuItemProps) {
}, [hasChildren, open])

return (
<Stack key={title} space={1}>
<Stack as="li" key={title} space={1}>
<Button
fontSize={1}
iconRight={icon}
Expand All @@ -56,7 +56,7 @@ function MenuItem(props: TreeEditingMenuItemProps) {
/>

{open && hasChildren && (
<Stack paddingLeft={3} marginTop={1} space={1}>
<Stack as="ul" paddingLeft={3} marginTop={1} space={1}>
{children.map((child) => (
<MenuItem
item={child}
Expand All @@ -83,7 +83,7 @@ export const TreeEditingMenu = memo(function TreeEditingMenu(
const {items, onPathSelect, selectedPath} = props

return (
<Stack space={3}>
<Stack as="ul" space={3}>
{items.map((item, index) => (
<MenuItem
item={item}
Expand Down
Loading

0 comments on commit 0856eef

Please sign in to comment.