Description
The HeightAnimation component calculates the height, and animates from auto
to auto
– or from 0
to auto
in height – powered by CSS transition. 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 with 400ms
in duration.
It also re-calculates and changes the height, when the given content changes.
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 may change
- the user may have a larger
font-size
Demos
Animation during height changes
This example shows how you easily can enhance the user experience. Here we also use showOverflow
to avoid hidden overflow during the animation.
const Example = () => { const [showMe, setShowMe] = React.useState(true) return ( <> <HeightAnimation showOverflow> {showMe ? ( <Button onClick={() => { setShowMe(!showMe) }} > Click me! </Button> ) : ( <Anchor onClick={() => { setShowMe(!showMe) }} > No, click me! </Anchor> )} </HeightAnimation> <P top>Look at me 👀</P> </> ) } render(<Example />)
SyntaxError: Unexpected token (1:3)
Basic open/close
This example removes its given children, when open is open={false}
.
const Example = () => { const [openState, setOpenState] = React.useState(false) const [isOpen, setIsOpen] = React.useState(openState) const [contentState, setContentState] = React.useState(false) const onChangeHandler = ({ checked }) => { setOpenState(checked) } return ( <> <ToggleButton checked={openState} on_change={onChangeHandler} right> Open/close </ToggleButton> <ToggleButton checked={contentState || !openState} disabled={!isOpen} on_change={({ checked }) => { setContentState(checked) }} space={{ top: true, bottom: true, }} > Change height inside </ToggleButton> <Section style_type="lavender" top> <HeightAnimation open={openState} onOpen={setIsOpen}> <Section spacing style_type="lavender"> <P space={0}>Your content</P> </Section> {contentState && <P space={0}>More content</P>} </HeightAnimation> </Section> <P top>Look at me 👀</P> </> ) } render(<Example />)
SyntaxError: Unexpected token (1:3)
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
.
const Example = () => { const [openState, setOpenState] = React.useState(true) const [isOpen, setIsOpen] = React.useState(openState) const [contentState, setContentState] = React.useState(false) const onChangeHandler = ({ checked }) => { setOpenState(checked) } return ( <> <ToggleButton checked={openState} on_change={onChangeHandler} right> Open/close </ToggleButton> <ToggleButton checked={contentState || !openState} disabled={!isOpen} on_change={({ checked }) => { setContentState(checked) }} space={{ top: true, bottom: true, }} > Change height inside </ToggleButton> <StyledSection style_type="lavender" top> <HeightAnimation open={openState} keepInDOM={true} duration={1000} onOpen={setIsOpen} > <Section spacing style_type="lavender"> <P space={0}>Your content</P> </Section> {contentState && <P space={0}>More 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 />)
SyntaxError: Unexpected token (1:3)