refactor(breadcrumbs): auto assign separator to crumbs item

docs(breadcrumbs): update docs
This commit is contained in:
unix
2020-06-01 08:57:24 +08:00
parent cab81d1841
commit 22f2b414b1
9 changed files with 130 additions and 169 deletions

View File

@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Breadcrumbs should redefined all separators 1`] = `
"<nav class=\\"\\"><span class=\\"breadcrums-item\\">test-1</span><div class=\\"separator \\">*<style>
"<nav class=\\"\\"><span class=\\"breadcrums-item \\">test-1</span><div class=\\"separator \\">*<style>
.separator {
display: inline-flex;
margin: 0 8px;
@@ -9,93 +9,77 @@ exports[`Breadcrumbs should redefined all separators 1`] = `
pointer-events: none;
align-items: center;
}
</style></div><span class=\\"breadcrums-item\\">test-2</span><div class=\\"separator \\">*<style>
.separator {
display: inline-flex;
margin: 0 8px;
user-select: none;
pointer-events: none;
</style></div><span class=\\"breadcrums-item \\">test-2</span><style>
nav {
margin: 0;
padding: 0;
line-height: inherit;
color: #888;
font-size: 1rem;
box-sizing: border-box;
display: flex;
align-items: center;
}
</style></div><style>
nav {
margin: 0;
padding: 0;
line-height: inherit;
color: #888;
font-size: 1rem;
box-sizing: border-box;
display: flex;
align-items: center;
}
nav :global(.link:hover) {
color: rgba(0, 112, 243, 0.85);
}
nav :global(.link:hover) {
color: rgba(0, 112, 243, 0.85);
}
nav > :global(span:last-of-type) {
color: #444;
}
nav > :global(span:last-of-type) {
color: #444;
}
nav > :global(.separator:last-child) {
display: none;
}
nav > :global(.separator:last-child) {
display: none;
}
nav :global(svg) {
width: 1em;
height: 1em;
margin: 0 4px;
}
nav :global(svg) {
width: 1em;
height: 1em;
margin: 0 4px;
}
nav :global(.breadcrums-item) {
display: inline-flex;
align-items: center;
}
</style></nav>"
nav :global(.breadcrums-item) {
display: inline-flex;
align-items: center;
}
</style></nav>"
`;
exports[`Breadcrumbs should render correctly 1`] = `
"<nav class=\\"\\"><span class=\\"breadcrums-item\\">test-1</span><div class=\\"separator \\">/<style>
.separator {
display: inline-flex;
margin: 0 8px;
user-select: none;
pointer-events: none;
"<nav class=\\"\\"><span class=\\"breadcrums-item \\">test-1</span><style>
nav {
margin: 0;
padding: 0;
line-height: inherit;
color: #888;
font-size: 1rem;
box-sizing: border-box;
display: flex;
align-items: center;
}
</style></div><style>
nav {
margin: 0;
padding: 0;
line-height: inherit;
color: #888;
font-size: 1rem;
box-sizing: border-box;
display: flex;
align-items: center;
}
nav :global(.link:hover) {
color: rgba(0, 112, 243, 0.85);
}
nav :global(.link:hover) {
color: rgba(0, 112, 243, 0.85);
}
nav > :global(span:last-of-type) {
color: #444;
}
nav > :global(span:last-of-type) {
color: #444;
}
nav > :global(.separator:last-child) {
display: none;
}
nav > :global(.separator:last-child) {
display: none;
}
nav :global(svg) {
width: 1em;
height: 1em;
margin: 0 4px;
}
nav :global(svg) {
width: 1em;
height: 1em;
margin: 0 4px;
}
nav :global(.breadcrums-item) {
display: inline-flex;
align-items: center;
}
</style></nav>"
nav :global(.breadcrums-item) {
display: inline-flex;
align-items: center;
}
</style></nav>"
`;

View File

@@ -28,10 +28,8 @@ describe('Breadcrumbs', () => {
it('the specified separator should be redefined', () => {
const wrapper = mount(
<Breadcrumbs separator="*">
<Breadcrumbs.Item>
test-1
<Breadcrumbs.Separator>%</Breadcrumbs.Separator>
</Breadcrumbs.Item>
<Breadcrumbs.Item>test-1</Breadcrumbs.Item>
<Breadcrumbs.Separator>%</Breadcrumbs.Separator>
<Breadcrumbs.Item>test-2</Breadcrumbs.Item>
</Breadcrumbs>,
)

View File

@@ -1,12 +0,0 @@
import React from 'react'
export interface BreadcrumbsConfig {
separator?: string
}
const defaultContext = {}
export const BreadcrumbsContext = React.createContext<BreadcrumbsConfig>(defaultContext)
export const useBreadcrumbsContext = (): BreadcrumbsConfig =>
React.useContext<BreadcrumbsConfig>(BreadcrumbsContext)

View File

@@ -4,7 +4,6 @@ import React, { useMemo } from 'react'
import withDefaults from '../utils/with-defaults'
import { pickChild } from '../utils/collections'
import BreadcrumbsSeparator from './breadcrumbs-separator'
import { useBreadcrumbsContext } from './breadcrumbs-context'
interface Props {
href?: string
@@ -30,41 +29,29 @@ const BreadcrumbsItem = React.forwardRef<
{ href, nextLink, onClick, children, className, ...props },
ref: React.Ref<HTMLAnchorElement>,
) => {
const { separator } = useBreadcrumbsContext()
const isLink = useMemo(() => href !== undefined || nextLink, [href, nextLink])
const [withoutSepChildren, sepChildren] = pickChild(children, BreadcrumbsSeparator)
const composeSeparator = useMemo(() => {
if (React.Children.count(sepChildren) > 0) return sepChildren
return <BreadcrumbsSeparator>{separator}</BreadcrumbsSeparator>
}, [separator])
const [withoutSepChildren] = pickChild(children, BreadcrumbsSeparator)
const clickHandler = (event: React.MouseEvent) => {
onClick && onClick(event)
}
if (!isLink) {
return (
<>
<span className="breadcrums-item" onClick={clickHandler}>
{withoutSepChildren}
</span>
{composeSeparator}
</>
<span className={`breadcrums-item ${className}`} onClick={clickHandler}>
{withoutSepChildren}
</span>
)
}
return (
<>
<Link
className={`breadcrums-item ${className}`}
href={href}
onClick={clickHandler}
ref={ref}
{...props}>
{withoutSepChildren}
</Link>
{composeSeparator}
</>
<Link
className={`breadcrums-item ${className}`}
href={href}
onClick={clickHandler}
ref={ref}
{...props}>
{withoutSepChildren}
</Link>
)
},
)

View File

@@ -1,5 +1,4 @@
import React from 'react'
// import useTheme from '../styles/use-theme'
import withDefaults from '../utils/with-defaults'
interface Props {
@@ -17,8 +16,6 @@ const BreadcrumbsSeparator: React.FC<React.PropsWithChildren<BreadcrumbsProps>>
children,
className,
}) => {
// const theme = useTheme()
return (
<div className={`separator ${className}`}>
{children}

View File

@@ -3,8 +3,7 @@ import useTheme from '../styles/use-theme'
import BreadcrumbsItem from './breadcrumbs-item'
import BreadcrumbsSeparator from './breadcrumbs-separator'
import { addColorAlpha } from '../utils/color'
import { BreadcrumbsContext } from './breadcrumbs-context'
import { NormalSizes } from 'components/utils/prop-types'
import { NormalSizes } from '../utils/prop-types'
interface Props {
size: NormalSizes
@@ -38,55 +37,67 @@ const Breadcrumbs: React.FC<React.PropsWithChildren<BreadcrumbsProps>> = ({
className,
}) => {
const theme = useTheme()
const initialValue = useMemo(
() => ({
separator,
}),
[separator],
)
const fontSize = useMemo(() => getSize(size), [size])
const hoverColor = useMemo(() => {
return addColorAlpha(theme.palette.link, 0.85)
}, [theme.palette.link])
const childrenArray = React.Children.toArray(children)
const withSeparatorChildren = childrenArray.map((item, index) => {
if (!React.isValidElement(item)) return item
const last = childrenArray[index - 1]
const lastIsSeparator = React.isValidElement(last) && last.type === BreadcrumbsSeparator
const currentIsSeparator = item.type === BreadcrumbsSeparator
if (!lastIsSeparator && !currentIsSeparator && index > 0) {
return (
<React.Fragment key={index}>
<BreadcrumbsSeparator>{separator}</BreadcrumbsSeparator>
{item}
</React.Fragment>
)
}
return item
})
return (
<BreadcrumbsContext.Provider value={initialValue}>
<nav className={className}>
{children}
<style jsx>{`
nav {
margin: 0;
padding: 0;
line-height: inherit;
color: ${theme.palette.accents_4};
font-size: ${fontSize};
box-sizing: border-box;
display: flex;
align-items: center;
}
<nav className={className}>
{withSeparatorChildren}
<style jsx>{`
nav {
margin: 0;
padding: 0;
line-height: inherit;
color: ${theme.palette.accents_4};
font-size: ${fontSize};
box-sizing: border-box;
display: flex;
align-items: center;
}
nav :global(.link:hover) {
color: ${addColorAlpha(theme.palette.link, 0.85)};
}
nav :global(.link:hover) {
color: ${hoverColor};
}
nav > :global(span:last-of-type) {
color: ${theme.palette.accents_6};
}
nav > :global(span:last-of-type) {
color: ${theme.palette.accents_6};
}
nav > :global(.separator:last-child) {
display: none;
}
nav > :global(.separator:last-child) {
display: none;
}
nav :global(svg) {
width: 1em;
height: 1em;
margin: 0 4px;
}
nav :global(svg) {
width: 1em;
height: 1em;
margin: 0 4px;
}
nav :global(.breadcrums-item) {
display: inline-flex;
align-items: center;
}
`}</style>
</nav>
</BreadcrumbsContext.Provider>
nav :global(.breadcrums-item) {
display: inline-flex;
align-items: center;
}
`}</style>
</nav>
)
}

File diff suppressed because one or more lines are too long

View File

@@ -64,10 +64,8 @@ Show where users are in the application.
</Breadcrumbs>
<Spacer y={.5} />
<Breadcrumbs separator=">">
<Breadcrumbs.Item>
Home
<Breadcrumbs.Separator>:</Breadcrumbs.Separator>
</Breadcrumbs.Item>
<Breadcrumbs.Item>Home</Breadcrumbs.Item>
<Breadcrumbs.Separator>:</Breadcrumbs.Separator>
<Breadcrumbs.Item href="">Components</Breadcrumbs.Item>
<Breadcrumbs.Item href="">Basic</Breadcrumbs.Item>
<Breadcrumbs.Item>Button</Breadcrumbs.Item>

View File

@@ -64,10 +64,8 @@ export const meta = {
</Breadcrumbs>
<Spacer y={.5} />
<Breadcrumbs separator=">">
<Breadcrumbs.Item>
Home
<Breadcrumbs.Separator>:</Breadcrumbs.Separator>
</Breadcrumbs.Item>
<Breadcrumbs.Item>Home</Breadcrumbs.Item>
<Breadcrumbs.Separator>:</Breadcrumbs.Separator>
<Breadcrumbs.Item href="">Components</Breadcrumbs.Item>
<Breadcrumbs.Item href="">Basic</Breadcrumbs.Item>
<Breadcrumbs.Item >Button</Breadcrumbs.Item>