Skip to content

Commit

Permalink
feat(HeightAnimation): add new component
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Sep 19, 2022
1 parent d4f26c3 commit e61ea14
Show file tree
Hide file tree
Showing 27 changed files with 672 additions and 170 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: 'HeightAnimation'
description: 'HeightAnimation is a helper component to animate from 0 to height:auto powered by CSS.'
status: 'new'
showTabs: true
---

import HeightAnimationInfo from 'Docs/uilib/components/height-animation/info'
import HeightAnimationDemos from 'Docs/uilib/components/height-animation/demos'

<HeightAnimationInfo />
<HeightAnimationDemos />
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* UI lib Component Example
*
*/

import ComponentBox from 'dnb-design-system-portal/src/shared/tags/ComponentBox'

export function HeightAnimationDefault() {
return (
<ComponentBox useRender>
{
/* jsx */ `
const Example = () => {
const [openState, setOpenState] = React.useState(false)
const onChangeHandler = ({ checked }) => {
setOpenState(checked)
}
return (
<>
<ToggleButton checked={openState} onChange={onChangeHandler} bottom>
Toggle me
</ToggleButton>
<Section style_type="lavender">
<HeightAnimation
open={openState}
>
<P className="content-element" top="large" bottom="large">
Your content
</P>
</HeightAnimation>
</Section>
</>
)
}
render(<Example />)
`
}
</ComponentBox>
)
}

export function HeightAnimationKeepInDOM() {
return (
<ComponentBox useRender>
{
/* jsx */ `
const Example = () => {
const [openState, setOpenState] = React.useState(false)
const onChangeHandler = ({ checked }) => {
setOpenState(checked)
}
return (
<>
<ToggleButton checked={openState} onChange={onChangeHandler} bottom>
Toggle me
</ToggleButton>
<StyledSection style_type="lavender">
<HeightAnimation
open={openState}
keepInDOM={true}
duration={1000}
>
<P className="content-element" space={0}>
Your content
</P>
</HeightAnimation>
</StyledSection>
</>
)
}
const StyledSection = styled(Section)\`
.content-element {
transition: transform 1s var(--easing-default);
transform: translateY(-2rem);
padding: 4rem 0;
}
.dnb-height-animation--parallax .content-element {
transform: translateY(0);
}
\`
render(<Example />)
`
}
</ComponentBox>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
showTabs: true
---

import {
HeightAnimationDefault,
HeightAnimationKeepInDOM,
} from 'Docs/uilib/components/height-animation/Examples'

## Demos

### HeightAnimation

<HeightAnimationDefault />

### Keep in DOM

When providing `keepInDOM={true}`, your nested content will never be removed from the DOM. But rather be "hidden" with `visually: hidden` and `aria-hidden`.

<HeightAnimationKeepInDOM />
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
showTabs: true
---

## Events

No events are supported at the moment.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
showTabs: true
---

## Description

The HeightAnimation component is a helper component to animate from 0px to height:auto powered by CSS. It calculates the height on the fly.

When the animation is done, it sets the element's height to `auto`.

The component can be used as an opt-int replacement instead of vanilla HTML Elements.

The element animation is done with a CSS transition and a `400ms` duration:

## Accessibility

It is important to never animate from 0 to e.g. 64px – because the content may differ based on the viewport width (screen size), the content itself, or the user may even have a larger `font-size`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
showTabs: true
---

## Properties

| Properties | Description |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `open` | _(optional)_ Set to `true` when the view should animate from 0px to auto. Defaults to `false`. |
| `animate` | _(optional)_ Set to `false` to omit the animation. Defaults to `true`. |
| `element` | _(optional)_ Custom HTML element for the component. Defaults to `div` HTML Element. |
| [Space](/uilib/components/space/properties) | _(optional)_ spacing properties like `top` or `bottom` are supported. |
Original file line number Diff line number Diff line change
Expand Up @@ -5,110 +5,13 @@

import React from 'react'
import styled from '@emotion/styled'
import classnames from 'classnames'
import ComponentBox from 'dnb-design-system-portal/src/shared/tags/ComponentBox'
import { useHeightAnimation } from '@dnb/eufemia/src/shared/useHeightAnimation'

// have a limit because this page is used for screenshot tests
const Wrapper = styled.div`
max-width: 40rem;
`

export function HeightAnimationExample() {
return (
<ComponentBox useRender scope={{ useHeightAnimation, classnames }}>
{
/* jsx */ `
const AnimatedContent = ({
open = false,
noAnimation = false,
...rest
}) => {
const animationElement = React.useRef()
const { isOpen, isInDOM, isVisibleParallax } = useHeightAnimation(
animationElement,
{
open,
animate: !noAnimation,
}
)
// Optional: You can also entirely remove it from the DOM
// if (!isInDOM) {
// return null
// }
return (
<AnimatedDiv
className={classnames(
'wrapper-element',
// Optional: will toggle immediately
isOpen && 'is-open',
// Optional: is "true" while the element "should" be in the DOM (during animation)
isInDOM && 'is-in-dom',
// Optional: is "true" when completely opened, and "false" right after closing has started (usefull for additional CSS transitions/parallax effects)
isVisibleParallax && 'is-in-parallax'
)}
style_type="lavender"
{...rest}
>
{isInDOM /* <-- Optional */ && (
<div ref={animationElement} className="animation-element">
<P className="content-element" space={0}>Your content</P>
</div>
)}
</AnimatedDiv>
)
}
const HeightAnimation = ({ open = false, ...rest }) => {
const [openState, setOpenState] = React.useState(open)
const onChangeHandler = ({ checked }) => {
setOpenState(checked)
}
return (
<>
<ToggleButton checked={openState} onChange={onChangeHandler}>
Toggle me
</ToggleButton>
<AnimatedContent top open={openState} />
</>
)
}
const AnimatedDiv = styled(Section)\`
.animation-element {
overflow: hidden;
transition: height 1s var(--easing-default);
}
.content-element {
transition: transform 1s var(--easing-default);
transform: translateY(-2rem);
}
&.is-in-parallax .content-element {
transform: translateY(0);
}
.content-element {
padding: 4rem 0;
}
\`
render(<HeightAnimation />)
`
}
</ComponentBox>
)
}

export function CoreStyleExample() {
return (
<Wrapper className="dnb-spacing">
Expand Down
29 changes: 0 additions & 29 deletions packages/dnb-design-system-portal/src/docs/uilib/helpers/hooks.md

This file was deleted.

14 changes: 14 additions & 0 deletions packages/dnb-eufemia/src/components/HeightAnimation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* ATTENTION: This file is auto generated by using "prepareTemplates".
* Do not change the content!
*
*/

/**
* Library Index height-animation to autogenerate all the components and extensions
* Used by "prepareHeightAnimations"
*/

import HeightAnimation from './height-animation/HeightAnimation'
export * from './height-animation/HeightAnimation'
export default HeightAnimation
Loading

0 comments on commit e61ea14

Please sign in to comment.