Skip to content

Commit

Permalink
feat(Breadcrumb): add animation when in collapse mode
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Sep 20, 2022
1 parent 72b1da5 commit 2f86df0
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const BreadcrumbMultipleData = () => (
];
return (
<Breadcrumb data={pages} spacing/>
<Breadcrumb data={pages} spacing />
)
}
`
Expand Down Expand Up @@ -89,7 +89,7 @@ export const BreadcrumbVariants = () => (
return (
// Try changing variant here
<Breadcrumb variant="collapse" data={pages} spacing/>
<Breadcrumb variant="collapse" data={pages} spacing />
)
}
`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,8 @@ describe('babel build', () => {
'utf-8'
)
expect(content).toContain('export default Breadcrumb;')
expect(content).toContain('core-js/modules/es')
expect(content).toContain(
'import "core-js/modules/es.array.map.js";'
'import _extends from "@babel/runtime/helpers/esm/extends";'
)
}
}
Expand Down
53 changes: 28 additions & 25 deletions packages/dnb-eufemia/src/components/breadcrumb/Breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
convertJsxToString,
validateDOMAttributes,
} from '../../shared/component-helper'
import { BreadcrumbMultiple } from './BreadcrumbMultiple'

export interface BreadcrumbProps {
/**
Expand Down Expand Up @@ -111,6 +112,12 @@ export interface BreadcrumbProps {
* Default: false
*/
spacing?: boolean

/**
* Will disable the height animation
* Default: false
*/
noAnimation?: boolean
}

export const defaultProps = {
Expand All @@ -128,6 +135,7 @@ export const defaultProps = {
const Breadcrumb = (localProps: BreadcrumbProps & ISpacingProps) => {
// Every component should have a context
const context = React.useContext(Context)

// Extract additional props from global context
const allProps = usePropsWithContext(
localProps,
Expand All @@ -136,10 +144,11 @@ const Breadcrumb = (localProps: BreadcrumbProps & ISpacingProps) => {
context?.Breadcrumb,
{ skeleton: context?.skeleton }
)

const {
className,
skeleton,
children: childrenItems,
children: items,
variant,
onClick,
navText, // has a translation in context
Expand All @@ -150,22 +159,23 @@ const Breadcrumb = (localProps: BreadcrumbProps & ISpacingProps) => {
collapsedStyleType,
isCollapsed: overrideIsCollapsed,
spacing,
noAnimation,
data,
href,
...props
} = allProps
const skeletonClasses = createSkeletonClass('font', skeleton, context)
const spacingClasses = createSpacingClasses(props)

const [isCollapsed, setCollapse] = useState(true)
const [isCollapsed, setCollapse] = useState(overrideIsCollapsed)
const isSmallScreen = useMediaQuery({
matchOnSSR: true,
when: { max: 'medium' },
})

let currentVariant = variant
if (!variant) {
if (childrenItems || data) {
if (items || data) {
currentVariant = isSmallScreen ? 'collapse' : 'multiple'
} else {
currentVariant = 'single'
Expand All @@ -176,24 +186,6 @@ const Breadcrumb = (localProps: BreadcrumbProps & ISpacingProps) => {
setCollapse(overrideIsCollapsed)
}, [overrideIsCollapsed])

const MultipleCrumbs = () => (
<ol className="dnb-breadcrumb__list">
{data?.map((breadcrumbItem, i) => (
<BreadcrumbItem
key={`${breadcrumbItem.text}`}
variant={
(i == 0 && 'home') ||
(i == data.length - 1 && 'current') ||
null
}
{...breadcrumbItem}
/>
))}

{childrenItems}
</ol>
)

validateDOMAttributes(allProps, props)

return (
Expand Down Expand Up @@ -237,16 +229,27 @@ const Breadcrumb = (localProps: BreadcrumbProps & ISpacingProps) => {
/>
)}

{currentVariant === 'multiple' && <MultipleCrumbs />}
{currentVariant === 'multiple' && (
<BreadcrumbMultiple
data={data}
items={items}
isCollapsed={false}
noAnimation={noAnimation}
/>
)}
</Section>

{currentVariant === 'collapse' && !isCollapsed && (
{currentVariant === 'collapse' && (
<Section
style_type={collapsedStyleType}
className="dnb-breadcrumb__collapse"
data-testid="breadcrumb-collapse"
>
<MultipleCrumbs />
<BreadcrumbMultiple
data={data}
items={items}
isCollapsed={isCollapsed}
noAnimation={noAnimation}
/>
</Section>
)}
</nav>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export interface BreadcrumbItemProps {
* Default: null
*/
skeleton?: SkeletonShow

style?: React.CSSProperties
}

const defaultProps = {
Expand All @@ -72,7 +74,7 @@ const BreadcrumbItem = (localProps: BreadcrumbItemProps) => {
} = context

// Extract additional props from global context
const { text, href, icon, onClick, variant, skeleton, ...props } =
const { text, href, icon, onClick, variant, skeleton, style, ...props } =
usePropsWithContext(localProps, defaultProps, context?.BreadcrumbItem)

const currentIcon: IconPrimaryIcon =
Expand All @@ -85,6 +87,7 @@ const BreadcrumbItem = (localProps: BreadcrumbItemProps) => {
className="dnb-breadcrumb__item"
data-testid="breadcrumb-item"
aria-current={variant === 'current' ? 'page' : undefined}
style={style}
>
{isInteractive ? (
<Button
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react'
import HeightAnimation from '../height-animation/HeightAnimation'
import BreadcrumbItem, { BreadcrumbItemProps } from './BreadcrumbItem'

type BreadcrumbMultipleProps = {
isCollapsed: boolean
noAnimation: boolean
data: Array<BreadcrumbItemProps>
items: React.ReactNode
}

export const BreadcrumbMultiple = ({
isCollapsed,
items,
noAnimation,
data,
}: BreadcrumbMultipleProps) => {
return (
<HeightAnimation
open={!isCollapsed}
animate={!noAnimation}
data-testid="breadcrumb-collapse"
className="dnb-breadcrumb__animation"
>
<ol className="dnb-breadcrumb__list">
{data?.map((breadcrumbItem, i) => {
const style = { '--delay': String(i) } as React.CSSProperties
return (
<BreadcrumbItem
key={`${breadcrumbItem.text}`}
variant={
(i == 0 && 'home') ||
(i == data.length - 1 && 'current') ||
null
}
style={style}
{...breadcrumbItem}
/>
)
})}

{items}
</ol>
</HeightAnimation>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,24 @@ exports[`Breadcrumb scss have to match snapshot 1`] = `
.dnb-breadcrumb__item__span__icon {
margin-left: calc(var(--button-icon-size) / 2);
margin-right: 0.5rem; }
.dnb-breadcrumb__collapse {
.dnb-breadcrumb__animation {
display: flex;
flex-direction: column;
padding: 0 var(--spacing-large); }
overflow: hidden;
transition: height 400ms cubic-bezier(0.42, 0, 0, 1); }
.dnb-breadcrumb__animation .dnb-breadcrumb__item {
transition: transform 400ms cubic-bezier(0.42, 0, 0, 1) calc(var(--delay) * 50ms);
transform: translateX(-1rem); }
.dnb-breadcrumb__animation--parallax .dnb-breadcrumb__item {
transform: translateX(0); }
.dnb-breadcrumb__collapse {
display: flex;
flex-direction: column; }
.dnb-breadcrumb__collapse .dnb-breadcrumb__list {
flex-direction: column;
align-items: flex-start; }
.dnb-breadcrumb--spacing .dnb-breadcrumb__collapse {
align-items: flex-start;
padding: 0 var(--spacing-large); }
.dnb-breadcrumb--spacing .dnb-breadcrumb__collapse .dnb-breadcrumb__list {
padding: var(--spacing-x-small) var(--spacing-large); }
"
`;
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,32 @@
}
}

&__animation {
display: flex;
flex-direction: column;

overflow: hidden;
transition: height 400ms #{$defaultEasing};
}
&__animation &__item {
transition: transform 400ms #{$defaultEasing} calc(var(--delay) * 50ms);
transform: translateX(-1rem);
}
&__animation.dnb-height-animation--parallax &__item {
transform: translateX(0);
}

&__collapse {
display: flex;
flex-direction: column;
padding: 0 var(--spacing-large);
}
&__collapse &__list {
flex-direction: column;
align-items: flex-start;

padding: 0 var(--spacing-large);
}
&--spacing &__collapse {
&--spacing &__collapse &__list {
padding: var(--spacing-x-small) var(--spacing-large);
}
}

0 comments on commit 2f86df0

Please sign in to comment.