Resizing motion
Animate width and height changes, to be used with caution.This page demonstrates how to animate width, height or both which is notoriously unperformant, (opens new window). Test your app over low powered devices, you may want to avoid this if you can see it impacting FPS.
useResizing
Width
Animates the container width as items are added or removed horizontally.
import { useCallback, useState } from 'react';
import { cssMap, cx, jsx } from '@atlaskit/css';
import { Label } from '@atlaskit/form/label/default';
import { AtlassianIcon } from '@atlaskit/logo/atlassian-icon';
import { useResizing } from '@atlaskit/motion/use-resizing';
import { Box, Inline } from '@atlaskit/primitives/compiled';
import Toggle from '@atlaskit/toggle';
import { token } from '@atlaskit/tokens';
const styles = cssMap({
container: {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: token('radius.xxlarge'),
borderWidth: token('border.width'),
borderStyle: 'solid',
borderColor: token('color.border'),
backgroundColor: token('elevation.surface'),
marginBlockStart: token('space.200'),
},
logo: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'column',
fontWeight: token('font.weight.medium'),
paddingBlockEnd: token('space.100'),
paddingBlockStart: token('space.100'),
paddingInlineEnd: token('space.200'),
paddingInlineStart: token('space.200'),
},
small: {
width: '50px',
},
large: {
width: '100px',
},
});
const MotionResizingWidth = (): JSX.Element => {
const [expand, setExpand] = useState(false);
const toggleExpand = useCallback(() => {
setExpand((expand) => !expand);
}, []);
const resizingProps = useResizing({
dimension: 'width',
duration: token('motion.duration.xxlong'),
easing: token('motion.easing.out.practical'),
});
return (
<Box>
<Inline alignBlock="center">
<Label htmlFor="inline-toggle-expand">Toggle expand</Label>
<Toggle id="inline-toggle-expand" onChange={toggleExpand} />
</Inline>
<Box {...resizingProps} xcss={styles.container}>
<Box xcss={cx(expand ? styles.large : styles.small, styles.logo)}>
<AtlassianIcon size="medium" />
</Box>
</Box>
</Box>
);
};
export default MotionResizingWidth;Height
Animates the container height as items are added or removed vertically.
import { useCallback, useState } from 'react';
import { cssMap, cx, jsx } from '@atlaskit/css';
import { Label } from '@atlaskit/form/label/default';
import { AtlassianIcon } from '@atlaskit/logo/atlassian-icon';
import { useResizing } from '@atlaskit/motion/use-resizing';
import { Box, Inline } from '@atlaskit/primitives/compiled';
import Toggle from '@atlaskit/toggle';
import { token } from '@atlaskit/tokens';
const styles = cssMap({
container: {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: token('radius.xxlarge'),
borderWidth: token('border.width'),
borderStyle: 'solid',
borderColor: token('color.border'),
backgroundColor: token('elevation.surface'),
marginBlockStart: token('space.200'),
},
logo: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'column',
fontWeight: token('font.weight.medium'),
paddingBlockEnd: token('space.100'),
paddingBlockStart: token('space.100'),
paddingInlineEnd: token('space.200'),
paddingInlineStart: token('space.200'),
},
small: {
height: '50px',
},
large: {
height: '100px',
},
});
const MotionResizingHeightNew = (): JSX.Element => {
const [expand, setExpand] = useState(false);
const toggleExpand = useCallback(() => {
setExpand((expand) => !expand);
}, []);
const resizingProps = useResizing({
dimension: 'height',
duration: token('motion.duration.xxlong'),
easing: token('motion.easing.out.practical'),
});
return (
<Box>
<Inline alignBlock="center">
<Label htmlFor="inline-toggle-expand">Toggle expand</Label>
<Toggle id="inline-toggle-expand" onChange={toggleExpand} />
</Inline>
<Box {...resizingProps} xcss={styles.container}>
<Box xcss={cx(expand ? styles.large : styles.small, styles.logo)}>
<AtlassianIcon size="medium" />
</Box>
</Box>
</Box>
);
};
export default MotionResizingHeightNew;Width and Height
Animates both width and height simultaneously as the grid grows or shrinks.
import { useCallback, useState } from 'react';
import { cssMap, cx, jsx } from '@atlaskit/css';
import { Label } from '@atlaskit/form/label/default';
import { AtlassianIcon } from '@atlaskit/logo/atlassian-icon';
import { useResizing } from '@atlaskit/motion/use-resizing';
import { Box, Inline } from '@atlaskit/primitives/compiled';
import Toggle from '@atlaskit/toggle';
import { token } from '@atlaskit/tokens';
const styles = cssMap({
container: {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: token('radius.xxlarge'),
borderWidth: token('border.width'),
borderStyle: 'solid',
borderColor: token('color.border'),
backgroundColor: token('elevation.surface'),
marginBlockStart: token('space.200'),
},
logo: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'column',
fontWeight: token('font.weight.medium'),
paddingBlockEnd: token('space.100'),
paddingBlockStart: token('space.100'),
paddingInlineEnd: token('space.200'),
paddingInlineStart: token('space.200'),
},
small: {
width: '50px',
height: '50px',
},
large: {
width: '100px',
height: '100px',
},
});
const MotionResizingBoth = (): JSX.Element => {
const [expand, setExpand] = useState(false);
const toggleExpand = useCallback(() => {
setExpand((expand) => !expand);
}, []);
const resizingProps = useResizing({
dimension: 'both',
duration: token('motion.duration.xxlong'),
easing: token('motion.easing.out.practical'),
});
return (
<Box>
<Inline alignBlock="center">
<Label htmlFor="inline-toggle-expand">Toggle expand</Label>
<Toggle id="inline-toggle-expand" onChange={toggleExpand} />
</Inline>
<Box {...resizingProps} xcss={styles.container}>
<Box xcss={cx(expand ? styles.large : styles.small, styles.logo)}>
<AtlassianIcon size="medium" />
</Box>
</Box>
</Box>
);
};
export default MotionResizingBoth;useResizingHeight
Caution
We are planning on deprecating useResizingHeight. Please use the useResizing hook instead.
Bitbucket
import { useState } from 'react';
import { css, jsx } from '@compiled/react';
import Button from '@atlaskit/button/default/button';
import { Label } from '@atlaskit/form/label/default';
import { JiraSoftwareIcon } from '@atlaskit/logo/jira-software-icon';
import { BitbucketIcon, ConfluenceIcon, OpsgenieIcon, StatuspageIcon } from '@atlaskit/logo';
import FadeIn from '@atlaskit/motion/fade-in';
import StaggeredEntrance from '@atlaskit/motion/staggered-entrance';
import { useResizingHeight } from '@atlaskit/motion/use-resizing-height';
import { token } from '@atlaskit/tokens';
import { Centered } from '../utils/containers';
const logos = [
[<BitbucketIcon size="small" />, 'Bitbucket'],
[<ConfluenceIcon size="small" />, 'Confluence'],
[<JiraSoftwareIcon size="small" />, 'Jira Software'],
[<OpsgenieIcon size="small" />, 'Opsgenie'],
[<StatuspageIcon size="small" />, 'Statuspage'],
];
const searchTerm: { [key: string]: string } = {
s1: 'dev',
s2: 'design',
s3: 'software',
s4: 'ops',
s5: 'all',
};
const containerStyles = css({
textAlign: 'center',
'> *': {
marginInlineEnd: token('space.025'),
},
});
const centeredContainerStyles = css({
width: '100%',
maxWidth: '500px',
borderRadius: token('radius.small', '3px'),
boxShadow: token('elevation.shadow.overlay'),
marginBlockEnd: token('space.800'),
paddingBlockEnd: token('space.100'),
});
const logoContainerStyles = css({
display: 'flex',
fontSize: '16px',
fontWeight: token('font.weight.medium'),
paddingBlockEnd: token('space.200'),
paddingBlockStart: token('space.200'),
paddingInlineEnd: token('space.200'),
paddingInlineStart: token('space.200'),
'&:hover': {
backgroundColor: token('color.background.accent.gray.subtler'),
},
});
const headerStyles = css({
fontWeight: 300,
marginBlockEnd: token('space.0'),
marginBlockStart: token('space.0'),
marginInlineEnd: token('space.0'),
marginInlineStart: token('space.100'),
});
const inputContainerStyles = css({
marginBlockStart: token('space.300'),
textAlign: 'start',
});
const MotionResizeHeightExample = (): JSX.Element => {
const [num, setNum] = useState(1);
return (
<div>
<div css={containerStyles}>
{[1, 2, 3, 4, 5].map((number) => (
<Button
testId={`button--${number}`}
key={number}
isSelected={num === number}
onClick={() => {
setNum(number);
}}
>
{number}
</Button>
))}
</div>
<Centered>
<div data-testid="menu" {...useResizingHeight()} css={containerStyles}>
<div css={inputContainerStyles}>
<Label htmlFor="input-options">Motion options</Label>
<input
id="input-options"
type="text"
readOnly
value={searchTerm[`s${num}`]}
css={centeredContainerStyles}
/>
</div>
<StaggeredEntrance columns={1}>
{Array(num)
.fill(undefined)
.map((_, index) => (
<FadeIn key={index}>
{(motion) => (
<div
ref={motion.ref}
className={motion.className}
style={motion.style}
css={logoContainerStyles}
>
{logos[index][0]}
<h3 css={headerStyles}>{logos[index][1]}</h3>
</div>
)}
</FadeIn>
))}
</StaggeredEntrance>
</div>
</Centered>
</div>
);
};
export default MotionResizeHeightExample;