Skip to content

Commit

Permalink
feat(useHeightAnimation): add hook to make height (auto) animations e…
Browse files Browse the repository at this point in the history
…asy (for internal use as of now)
  • Loading branch information
tujoworker committed Sep 14, 2022
1 parent c18b021 commit 45495f7
Show file tree
Hide file tree
Showing 5 changed files with 415 additions and 18 deletions.
2 changes: 2 additions & 0 deletions packages/dnb-design-system-portal/src/docs/uilib/helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ tabs:
key: /uilib/helpers/classes
- title: Functions
key: /uilib/helpers/functions
- title: Hooks
key: /uilib/helpers/hooks
redirect_from:
- /uilib/helper-classes
---
Expand Down
121 changes: 103 additions & 18 deletions packages/dnb-design-system-portal/src/docs/uilib/helpers/Examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,114 @@

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, inInParallax } = 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)
inInParallax && '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">
<ComponentBox
reactLive
hideCode
data-visual-test="helper-core-style"
>
<ComponentBox hideCode data-visual-test="helper-core-style">
{
/* jsx */ `
<div className="dnb-core-style">
Expand All @@ -39,7 +132,7 @@ export function CoreStyleExample() {
export function TabFocusExample() {
return (
<Wrapper className="dnb-spacing">
<ComponentBox reactLive hideCode data-visual-test="helper-tap-focus">
<ComponentBox hideCode data-visual-test="helper-tap-focus">
{
/* jsx */ `
<details>
Expand All @@ -59,11 +152,7 @@ export function TabFocusExample() {
export function UnstyledListExample() {
return (
<Wrapper className="dnb-spacing">
<ComponentBox
reactLive
hideCode
data-visual-test="helper-unstyled-list"
>
<ComponentBox hideCode data-visual-test="helper-unstyled-list">
{
/* jsx */ `
<ul className="dnb-unstyled-list">
Expand All @@ -84,7 +173,7 @@ export function UnstyledListExample() {
export function ScreenReaderOnlyExample() {
return (
<Wrapper className="dnb-spacing">
<ComponentBox reactLive hideCode data-visual-test="helper-sr-only">
<ComponentBox hideCode data-visual-test="helper-sr-only">
{
/* jsx */ `
<p className="dnb-p">
Expand All @@ -104,11 +193,7 @@ export function ScreenReaderOnlyExample() {
export function NoScreenReaderExample() {
return (
<Wrapper className="dnb-spacing">
<ComponentBox
reactLive
hideCode
data-visual-test="helper-not-sr-only"
>
<ComponentBox hideCode data-visual-test="helper-not-sr-only">
{
/* jsx */ `
<p className="dnb-p dnb-sr-only dnb-not-sr-only">
Expand All @@ -125,7 +210,7 @@ export function NoScreenReaderExample() {
export function SelectionExample() {
return (
<Wrapper className="dnb-spacing">
<ComponentBox reactLive hideCode data-visual-test="helper-selection">
<ComponentBox hideCode data-visual-test="helper-selection">
{
/* jsx */ `
<p className="dnb-selection dnb-p__size--basis">
Expand Down
29 changes: 29 additions & 0 deletions packages/dnb-design-system-portal/src/docs/uilib/helpers/hooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
showTabs: true
---

import {
HeightAnimationExample,
} from 'Docs/uilib/helpers/Examples'
import SkipLinkExample from 'Docs/uilib/usage/accessibility/examples/skip-link-example.js'

## Description

These React Hooks are internally used in the components, and are with that a good choice when it comes to save bandwidth in the final production bundle.

## `useHeightAnimation`

In many places we want to animate the content in and out. The challenge is to never define a fixed height, because of an unknown content size and users' different font sizes.

The `useHeightAnimation` hook takes an HTML Element, and animates it from 0 to the current content. When the animation is done, it sets the element's height to `auto`.

The element animation is done with a CSS transition, e.g.:

```css
.animation-element {
overflow: hidden;
transition: height 1s var(--easing-default);
}
```

<HeightAnimationExample />
Loading

0 comments on commit 45495f7

Please sign in to comment.