diff --git a/src/components/elements.tsx b/src/components/elements.tsx index 1348baa6..559f340f 100644 --- a/src/components/elements.tsx +++ b/src/components/elements.tsx @@ -30,30 +30,30 @@ export const LI: React.FC> = (props) => ( // title is: fixed sizes here meant an h2 that matched the title at 640px and // overtook it below that, so the deeper heading looked like the page heading. export const H1: React.FC> = ({ className, ...props }) => ( -

+

); export const H2: React.FC> = (props) => ( -

+

); export const H3: React.FC> = (props) => ( -

+

); export const H4: React.FC> = (props) => ( -

+

); // h5 and h6 land on the body size rather than below it. A heading set smaller // than the text it introduces reads as a caption; weight and the display face // carry the distinction at this depth instead. export const H5: React.FC> = (props) => ( -
+
); export const H6: React.FC> = (props) => ( -
+
); export const P: React.FC> = (props) => ( diff --git a/src/components/footer.tsx b/src/components/footer.tsx index 20939a13..4bf98427 100644 --- a/src/components/footer.tsx +++ b/src/components/footer.tsx @@ -50,7 +50,7 @@ const Footer = () => { > ELIXIR - {' '} the European infrastructure for life science data. + {' '}– the European infrastructure for life science data.

{socials.map(({ name, href, icon: Icon }) => ( diff --git a/src/components/hero.tsx b/src/components/hero.tsx index 33794796..bd698f73 100644 --- a/src/components/hero.tsx +++ b/src/components/hero.tsx @@ -1,4 +1,4 @@ -import { MotionConfig, motion, useReducedMotion } from 'framer-motion'; +import { AnimatePresence, MotionConfig, motion, useReducedMotion } from 'framer-motion'; import React, { useState, useEffect } from 'react'; import { ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline'; import { PauseIcon, PlayIcon } from '@heroicons/react/20/solid'; @@ -6,35 +6,37 @@ import Button from './button'; import HeroVideo from './hero-video'; import type { HeroCopy } from '../lib/site'; -const FLIP_MS = 600; +const SWAP = { duration: 0.5, ease: [0.22, 1, 0.36, 1] } as const; // Multi-word phrases stay a little longer than single fields so they can be read. const dwellMs = (word: string, words: string[]) => (word.includes(' ') && word !== words[0] ? 2600 : 2300); function RotatingWord({ words, playing }: { words: string[]; playing: boolean }) { - const [{ current, leaving }, setFlip] = useState<{ current: number; leaving: number | null }>({ current: 0, leaving: null }); + const [current, setCurrent] = useState(0); useEffect(() => { if (!playing) return; - const id = setTimeout(() => { - setFlip(({ current }) => ({ current: (current + 1) % words.length, leaving: current })); - }, FLIP_MS + dwellMs(words[current], words)); + const id = setTimeout(() => setCurrent((i) => (i + 1) % words.length), SWAP.duration * 1000 + dwellMs(words[current], words)); return () => clearTimeout(id); }, [playing, current, words]); - useEffect(() => { - if (leaving === null) return; - const id = setTimeout(() => setFlip(flip => ({ ...flip, leaving: null })), FLIP_MS); - return () => clearTimeout(id); - }, [leaving]); - return ( ); } diff --git a/src/components/navigation.tsx b/src/components/navigation.tsx index 04ca8527..1339a1e4 100644 --- a/src/components/navigation.tsx +++ b/src/components/navigation.tsx @@ -113,16 +113,18 @@ export const Navigation = ({ pathname }: { pathname: string }) => { return ( -
+ {/* Floats inset from the edges at the top of the page; once merged it becomes a full-width + bar, padded so the logo and actions keep the same place across the edges. Both sit + below the site banner, which stays pinned to the top. */} +
- +