Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 54 additions & 13 deletions src/components/BrainAgeActivity/BrainAgeActivity.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
.buttonContainer {
display: flex;
gap: 70px;
position: relative;
padding-bottom: 8px;
}

.ageButton {
Expand All @@ -45,23 +47,31 @@
font-size: 32px;
font-family: Aboreto-Regular, sans-serif;
font-weight: 700;
padding: 0;
transition: color 280ms cubic-bezier(0.4, 0, 0.2, 1);

svg path {
transition: fill 280ms cubic-bezier(0.4, 0, 0.2, 1);
}
}

.selectedButton {
color: #ce2128;
display: flex;
flex-direction: column;
align-items: center;

&::after {
content: '';
display: block;
width: 36px;
height: 4px;
background-image: url('/keepsimple_/assets/longevity/line.svg');
background-size: contain;
background-repeat: no-repeat;
}
}

.indicator {
position: absolute;
bottom: 0;
left: 0;
height: 4px;
background-image: url('/keepsimple_/assets/longevity/line.svg');
background-size: contain;
background-repeat: no-repeat;
pointer-events: none;
transition:
transform 360ms cubic-bezier(0.4, 0, 0.2, 1),
width 360ms cubic-bezier(0.4, 0, 0.2, 1);
will-change: transform, width;
}

.result {
Expand Down Expand Up @@ -215,3 +225,34 @@
}
}
}

.fadeSwap {
display: inline-flex;
align-items: center;
animation: brainAgeFade 360ms cubic-bezier(0.4, 0, 0.2, 1) both;
}

@keyframes brainAgeFade {
from {
opacity: 0;
transform: translateY(4px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

@media (prefers-reduced-motion: reduce) {
.section {
.ageButton,
.ageButton svg path,
.indicator {
transition: none !important;
}
}

.fadeSwap {
animation: none !important;
}
}
63 changes: 58 additions & 5 deletions src/components/BrainAgeActivity/BrainAgeActivity.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import cn from 'classnames';
import { FC, ReactNode, useCallback, useMemo, useState } from 'react';
import {
FC,
ReactNode,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';

import { BRAIN_AGE_TABLE } from '@constants/longevity';

Expand All @@ -17,6 +25,32 @@ const BrainAgeActivity: FC<BrainAgeActivityProps> = ({ locale }) => {
const { totalWeeklyActivity } = longevityData[locale];

const [selectedBaseline, setSelectedBaseline] = useState<number>(32);
const buttonRefs = useRef<Array<HTMLButtonElement | null>>([]);
const buttonContainerRef = useRef<HTMLDivElement | null>(null);
const [indicator, setIndicator] = useState<{
left: number;
width: number;
} | null>(null);

const updateIndicator = useCallback(() => {
const idx = BRAIN_AGE_TABLE.findIndex(r => r.baseline === selectedBaseline);
const btn = buttonRefs.current[idx];
const container = buttonContainerRef.current;
if (!btn || !container) return;
const btnRect = btn.getBoundingClientRect();
const containerRect = container.getBoundingClientRect();
setIndicator({
left: btnRect.left - containerRect.left,
width: btnRect.width,
});
}, [selectedBaseline]);

useEffect(() => {
updateIndicator();
window.addEventListener('resize', updateIndicator);
return () => window.removeEventListener('resize', updateIndicator);
}, [updateIndicator]);

const formatDelta = useCallback(
(delta: number): ReactNode => {
const sign = delta > 0 ? '+ ' : '';
Expand Down Expand Up @@ -75,10 +109,13 @@ const BrainAgeActivity: FC<BrainAgeActivityProps> = ({ locale }) => {
showLeftIcon={false}
className={styles.subHeading}
/>
<div className={styles.buttonContainer}>
{BRAIN_AGE_TABLE.map(row => (
<div className={styles.buttonContainer} ref={buttonContainerRef}>
{BRAIN_AGE_TABLE.map((row, idx) => (
<button
key={row.baseline}
ref={el => {
buttonRefs.current[idx] = el;
}}
onClick={() => setSelectedBaseline(row.baseline)}
className={cn(styles.ageButton, {
[styles.selectedButton]: selectedBaseline === row.baseline,
Expand All @@ -90,6 +127,16 @@ const BrainAgeActivity: FC<BrainAgeActivityProps> = ({ locale }) => {
<Digit value={row.baseline} size={32} />
</button>
))}
{indicator && (
<span
className={styles.indicator}
style={{
transform: `translateX(${indicator.left}px)`,
width: `${indicator.width}px`,
}}
aria-hidden
/>
)}
</div>
<div>
{result && (
Expand All @@ -112,7 +159,10 @@ const BrainAgeActivity: FC<BrainAgeActivityProps> = ({ locale }) => {
)}
</p>
<div className={styles.valueWrapper}>
<span className={styles.passive}>
<span
key={`passive-${selectedBaseline}`}
className={cn(styles.passive, styles.fadeSwap)}
>
<Digit value={result.sedentary} size={24} />{' '}
{result.sedentaryDeltaText}
</span>
Expand All @@ -131,7 +181,10 @@ const BrainAgeActivity: FC<BrainAgeActivityProps> = ({ locale }) => {
)}
</p>
<div className={styles.valueWrapper}>
<span className={styles.active}>
<span
key={`active-${selectedBaseline}`}
className={cn(styles.active, styles.fadeSwap)}
>
<Digit value={result.active} size={24} />
</span>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
.environmentSubSection {
padding: 20px 60px 0 40px;
opacity: 0;
transform: translateX(-32px);
transition:
opacity 600ms cubic-bezier(0.4, 0, 0.2, 1),
transform 600ms cubic-bezier(0.4, 0, 0.2, 1);
will-change: opacity, transform;

&.visible {
opacity: 1;
transform: translateX(0);
}

.titleAndIcon {
display: flex;
Expand Down Expand Up @@ -68,3 +79,11 @@
}
}
}

@media (prefers-reduced-motion: reduce) {
.environmentSubSection {
opacity: 1;
transform: none;
transition: none !important;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import cn from 'classnames';
import Image from 'next/image';
import { FC } from 'react';

import useInView from '@hooks/useInView';

import { EnvironmentSubSectionProps } from './EnvironmentSubSection.types';

import styles from './EnvironmentSubSection.module.scss';
Expand All @@ -10,9 +13,15 @@ const EnvironmentSubSection: FC<EnvironmentSubSectionProps> = ({
description,
iconUrl,
}) => {
// TODO: Add alt text
const { ref, inView } = useInView<HTMLDivElement>();

return (
<div className={styles.environmentSubSection}>
<div
ref={ref}
className={cn(styles.environmentSubSection, {
[styles.visible]: inView,
})}
>
<div className={styles.titleAndIcon}>
<Image src={iconUrl} alt={''} width={24} height={24} unoptimized />
<span className={styles.title}> {name}</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
clip-path: inset(0 100% 0 0);
animation: drawRedLine 1.4s cubic-bezier(0.4, 0, 0.2, 1) forwards;
animation-delay: 0.2s;
animation-iteration-count: 1;
}
}

Expand Down Expand Up @@ -249,3 +250,13 @@
filter: drop-shadow(0px 0px 18px rgba(53, 35, 13, 0.2));
}
}

@media (prefers-reduced-motion: reduce) {
.subSection {
.habitTooltip,
.habitTooltip::after,
.dateTxt::after {
animation: none !important;
}
}
}
53 changes: 49 additions & 4 deletions src/components/longevity/Navigation/Navigation.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
background-repeat: no-repeat;
background-size: cover;
opacity: 0;
transition: opacity 200ms ease;
transition: opacity 320ms cubic-bezier(0.4, 0, 0.2, 1);
}

&:hover::after {
Expand All @@ -46,11 +46,27 @@
}

.subItem {
position: relative;
background-image: url('/keepsimple_/assets/longevity/nav-sub-bg.png');

&:hover {
&::before {
content: '';
position: absolute;
inset: 0;
background-image: url('/keepsimple_/assets/longevity/nav-sub-bg-hover.png');
background-repeat: no-repeat;
background-size: cover;
opacity: 0;
transition: opacity 320ms cubic-bezier(0.4, 0, 0.2, 1);
pointer-events: none;
z-index: 0;
}

&:hover::before {
opacity: 1;
}

&:hover {
.link,
.subLink {
color: #b67636;
Expand Down Expand Up @@ -116,6 +132,13 @@
justify-content: center;
align-items: center;
gap: 8px;
transition: color 320ms cubic-bezier(0.4, 0, 0.2, 1);

svg {
path {
transition: fill 320ms cubic-bezier(0.4, 0, 0.2, 1);
}
}
}
}

Expand Down Expand Up @@ -150,12 +173,12 @@
justify-content: center;
align-items: center;
gap: 4px;
transition: color 200ms ease;
transition: color 320ms cubic-bezier(0.4, 0, 0.2, 1);

svg {
path {
fill: #bdbdbd;
transition: fill 200ms ease;
transition: fill 320ms cubic-bezier(0.4, 0, 0.2, 1);
}
}
}
Expand Down Expand Up @@ -185,3 +208,25 @@
margin: 0 15px;
}
}

@media (prefers-reduced-motion: reduce) {
.ul,
.subUl {
.item::after,
.subItem::before,
.link,
.subLink,
.link svg path,
.subLink svg path {
transition: none !important;
}
}

.subNav {
.curtains,
.subLink,
.subLink svg path {
transition: none !important;
}
}
}
Loading
Loading