Skip to content

Commit

Permalink
fix: add animations
Browse files Browse the repository at this point in the history
  • Loading branch information
kyranjamie committed Mar 18, 2024
1 parent 4d3c391 commit 60076ba
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 41 deletions.
File renamed without changes.
1 change: 1 addition & 0 deletions src/app/features/approver/approver.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export const ActionsAlignToBottom: Story = {
title="Action align to bottom of page"
requester="even when there's no content to push it there"
/>

<Approver.Actions
actions={
<>
Expand Down
26 changes: 3 additions & 23 deletions src/app/features/approver/approver.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,21 @@
import { useState } from 'react';

import { css } from 'leather-styles/css';
import { Flex, styled } from 'leather-styles/jsx';

import type { HasChildren } from '@app/common/has-children';

import { ApproverProvider } from './approver.context';
import { ApproverActions } from './components/approver-actions';
import { ApproverAdvanced } from './components/approver-advanced';
import { ApproverContainer } from './components/approver-container';
import { ApproverHeader } from './components/approver-header';
import { ApproverSection } from './components/approver-section';
import { ApproverSubheader } from './components/approver-subheader';

const applyMarginsToLastApproverSection = css({
'& .approver-section:last-child': { mb: 'space.03' },
});

function Approver({ children }: HasChildren) {
function Approver(props: HasChildren) {
const [isDisplayingAdvancedView, setIsDisplayingAdvancedView] = useState(false);

return (
<ApproverProvider value={{ isDisplayingAdvancedView, setIsDisplayingAdvancedView }}>
<styled.main
display="flex"
flexDir="column"
pos="relative"
minH="100%"
maxW="640px"
mx="auto"
className={applyMarginsToLastApproverSection}
alignItems="center"
boxShadow="0px 12px 24px 0px rgba(18, 16, 15, 0.08), 0px 4px 8px 0px rgba(18, 16, 15, 0.08), 0px 0px 2px 0px rgba(18, 16, 15, 0.08)"
>
<Flex flexDir="column" flex={1} background="ink.background-secondary">
{children}
</Flex>
</styled.main>
<ApproverContainer {...props} />
</ApproverProvider>
);
}
Expand Down
22 changes: 11 additions & 11 deletions src/app/features/approver/components/approver-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@ import { Flex, styled } from 'leather-styles/jsx';

import type { HasChildren } from '@app/common/has-children';

import { ApproverActionsAnimation } from './approver-animation';

const stretchChildrenStyles = css({ '& > *': { flex: 1 } });

interface ApproverActionsProps extends HasChildren {
actions: React.ReactNode;
}
export function ApproverActions({ children, actions }: ApproverActionsProps) {
return (
<styled.footer
pos="sticky"
mt="auto"
bottom={0}
background="ink.background-primary"
p="space.05"
>
{children}
<Flex width="100%" gap="space.04" className={stretchChildrenStyles}>
{actions}
</Flex>
<styled.footer pos="sticky" mt="auto" bottom={0} className="skip-animation">
<ApproverActionsAnimation>
<styled.div background="ink.background-primary" p="space.05">
{children}
<Flex width="100%" gap="space.04" className={stretchChildrenStyles}>
{actions}
</Flex>
</styled.div>
</ApproverActionsAnimation>
</styled.footer>
);
}
4 changes: 2 additions & 2 deletions src/app/features/approver/components/approver-advanced.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { Button } from '@app/ui/components/button/button';
import { Flag } from '@app/ui/components/flag/flag';
import { ChevronDownIcon } from '@app/ui/icons';

import { AnimateChangeInHeight } from '../../../components/animate-height';
import { useApproverContext } from '../approver.context';
import { AnimateChangeInHeight } from './animate-height';

const slightPauseForContentEnterAnimation = createDelay(120);

Expand All @@ -23,7 +23,7 @@ export function ApproverAdvanced({ children }: HasChildren) {
setIsDisplayingAdvancedView(!isDisplayingAdvancedView);
if (ref.current && !isDisplayingAdvancedView) {
await slightPauseForContentEnterAnimation();
ref.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
ref.current.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' });
}
}

Expand Down
60 changes: 60 additions & 0 deletions src/app/features/approver/components/approver-animation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { motion, stagger, useAnimate } from 'framer-motion';
import { css } from 'leather-styles/css';

import type { HasChildren } from '@app/common/has-children';
import { useOnMount } from '@app/common/hooks/use-on-mount';

const animationSelector = '& > *:not(.skip-animation)';

export const childElementInitialAnimationState = css({
[animationSelector]: { opacity: 0, transform: 'translateY(-16px)' },
});

const staggerMenuItems = stagger(0.06, { startDelay: 0.32 });

export function useApproverChildrenEntryAnimation() {
const [scope, animate] = useAnimate();

useOnMount(() => {
// Animation throws if there are no children
try {
animate(
animationSelector,
{ opacity: 1, transform: 'translateY(0)' },
{
duration: 0.36,
delay: staggerMenuItems,
ease: 'easeOut',
}
);
} catch (e) {}
});

return scope;
}

const initialState = { x: -20, opacity: 0 } as const;
const animateState = { x: 0, opacity: 1, transition: { duration: 0.32 } } as const;

interface ApproverHeaderAnimationProps extends HasChildren {
delay?: number;
}
export function ApproverHeaderAnimation({ delay = 0, ...props }: ApproverHeaderAnimationProps) {
return (
<motion.div
initial={initialState}
animate={{ ...animateState, transition: { ...animateState, delay } }}
{...props}
/>
);
}

export function ApproverActionsAnimation(props: HasChildren) {
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ ...animateState, transition: { ...animateState.transition, delay: 0.64 } }}
{...props}
/>
);
}
41 changes: 41 additions & 0 deletions src/app/features/approver/components/approver-container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { css } from 'leather-styles/css';
import { Flex, styled } from 'leather-styles/jsx';

import type { HasChildren } from '@app/common/has-children';

import {
childElementInitialAnimationState,
useApproverChildrenEntryAnimation,
} from './approver-animation';

const applyMarginsToLastApproverSection = css({
'& .approver-section:last-child': { mb: 'space.03' },
});

export function ApproverContainer({ children }: HasChildren) {
const scope = useApproverChildrenEntryAnimation();

return (
<styled.main
display="flex"
flexDir="column"
pos="relative"
minH="100%"
maxW="640px"
mx="auto"
className={applyMarginsToLastApproverSection}
alignItems="center"
boxShadow="0px 12px 24px 0px rgba(18, 16, 15, 0.08), 0px 4px 8px 0px rgba(18, 16, 15, 0.08), 0px 0px 2px 0px rgba(18, 16, 15, 0.08)"
>
<Flex
className={childElementInitialAnimationState}
ref={scope}
flexDir="column"
flex={1}
background="ink.background-secondary"
>
{children}
</Flex>
</styled.main>
);
}
16 changes: 11 additions & 5 deletions src/app/features/approver/components/approver-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@ import type { ReactNode } from 'react';

import { styled } from 'leather-styles/jsx';

import { ApproverHeaderAnimation } from './approver-animation';

interface ApproverHeaderProps {
title: ReactNode;
requester: ReactNode;
}
export function ApproverHeader({ title, requester }: ApproverHeaderProps) {
return (
<styled.header px="space.05" py="space.03">
<styled.h1 textStyle="heading.03">{title}</styled.h1>
<styled.p textStyle="label.02" mt="space.03">
Requested by {requester}
</styled.p>
<styled.header px="space.05" py="space.03" className="skip-animation">
<ApproverHeaderAnimation>
<styled.h1 textStyle="heading.03">{title}</styled.h1>
</ApproverHeaderAnimation>
<ApproverHeaderAnimation delay={0.03}>
<styled.p textStyle="label.02" mt="space.03">
Requested by {requester}
</styled.p>
</ApproverHeaderAnimation>
</styled.header>
);
}

0 comments on commit 60076ba

Please sign in to comment.