diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-10-09 16:31:00 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-11-11 18:14:41 +0100 |
| commit | 891441a76173c708c6604fa203b175aefa222333 (patch) | |
| tree | 27295311bb01a4e44dcc4f68422975cd705a24b8 /src/components/templates | |
| parent | f11a906420975e833f278a08470d8f9783c76f73 (diff) | |
refactor(components): rewrite Branding component
The component should only be responsible of the layout for the logo,
the name and the optional baseline. Also, the homepage url could
be different from `/` so the consumer should give the right url.
Diffstat (limited to 'src/components/templates')
| -rw-r--r-- | src/components/templates/layout/layout.module.scss | 67 | ||||
| -rw-r--r-- | src/components/templates/layout/layout.tsx | 68 |
2 files changed, 119 insertions, 16 deletions
diff --git a/src/components/templates/layout/layout.module.scss b/src/components/templates/layout/layout.module.scss index 223fb93..4f00742 100644 --- a/src/components/templates/layout/layout.module.scss +++ b/src/components/templates/layout/layout.module.scss @@ -2,10 +2,66 @@ @use "../../../styles/abstracts/mixins" as mix; @use "../../../styles/abstracts/placeholders"; +%typing-animation { + --typing-animation: none; + + width: fit-content; + position: relative; + overflow: hidden; + + &::after { + content: "|"; + display: block; + width: 100%; + height: 100%; + position: absolute; + top: 0; + right: 0; + background: var(--color-bg); + color: var(--color-primary-darker); + font-weight: 400; + text-align: left; + visibility: hidden; + transform: translateX(100%); + transform-origin: right; + animation: var(--typing-animation); + + :global { + animation: var(--typing-animation); + } + } +} + .header { border-bottom: fun.convert-px(3) solid var(--color-border-light); } +.brand { + &__logo { + --logo-size: #{clamp( + fun.convert-px(95), + calc(120px - 5vw), + fun.convert-px(120) + )}; + + animation: flip-logo 9s ease-in 0s 1; + } + + &__title { + font-size: var(--font-size-2xl); + + @extend %typing-animation; + } + + &__baseline { + color: var(--color-fg-light); + font-size: var(--font-size-lg); + font-weight: 600; + + @extend %typing-animation; + } +} + .main { flex: 1; } @@ -66,3 +122,14 @@ } } } + +@keyframes flip-logo { + 0%, + 90% { + transform: rotateY(180deg); + } + + 100% { + transform: rotateY(0deg); + } +} diff --git a/src/components/templates/layout/layout.tsx b/src/components/templates/layout/layout.tsx index 3e1eb63..25dcf4a 100644 --- a/src/components/templates/layout/layout.tsx +++ b/src/components/templates/layout/layout.tsx @@ -7,6 +7,7 @@ import { type ReactNode, useRef, useState, + type CSSProperties, } from 'react'; import { useIntl } from 'react-intl'; import type { Person, SearchAction, WebSite, WithContext } from 'schema-dts'; @@ -17,7 +18,7 @@ import { useScrollPosition, useSettings, } from '../../../utils/hooks'; -import { ButtonLink, Icon, Logo, Main } from '../../atoms'; +import { ButtonLink, Heading, Icon, Logo, Main } from '../../atoms'; import { SiteFooter, type SiteFooterProps, @@ -25,17 +26,24 @@ import { type SiteHeaderProps, } from '../../organisms'; import styles from './layout.module.scss'; +import { FlippingLogo } from 'src/components/molecules'; export type QueryAction = SearchAction & { 'query-input': string; }; -export type LayoutProps = Pick<SiteHeaderProps, 'isHome'> & { +export type LayoutProps = { /** * The layout main content. */ children: ReactNode; /** + * Is it homepage? + * + * @default false + */ + isHome?: boolean; + /** * Determine if article has a comments section. */ withExtraPadding?: boolean; @@ -230,6 +238,15 @@ export const Layout: FC<LayoutProps> = ({ useRouteChange(giveFocusToTopRef); + const brandingTitleStyles = { + '--typing-animation': + 'blink 0.7s ease-in-out 0s 2, typing 4.3s linear 0s 1', + } as CSSProperties; + const brandingBaselineStyles = { + '--typing-animation': + 'hide-text 4.25s linear 0s 1, blink 0.8s ease-in-out 4.25s 2, typing 3.8s linear 4.25s 1', + } as CSSProperties; + return ( <> <Script @@ -254,25 +271,44 @@ export const Layout: FC<LayoutProps> = ({ <SiteHeader // eslint-disable-next-line react/jsx-no-literals -- Storage key allowed ackeeStorageKey="ackee-tracking" - baseline={baseline} + baseline={ + <div + className={styles.brand__baseline} + style={brandingBaselineStyles} + > + {baseline} + </div> + } className={styles.header} - isHome={isHome} - logo={<Logo heading={logoTitle} />} + logo={ + <FlippingLogo + back={<Logo heading={logoTitle} />} + className={styles.brand__logo} + front={ + <NextImage + alt={photoAltText} + height={120} + src="/armand-philippot.jpg" + width={120} + /> + } + /> + } // eslint-disable-next-line react/jsx-no-literals -- Storage key allowed motionStorageKey="reduced-motion" - nav={mainNav} - photo={ - <NextImage - alt={photoAltText} - height={100} - // eslint-disable-next-line react/jsx-no-literals -- Photo allowed - src="/armand-philippot.jpg" - width={100} - /> + name={ + <Heading + className={styles.brand__title} + isFake={!isHome} + level={1} + style={brandingTitleStyles} + > + {name} + </Heading> } + nav={mainNav} searchPage={ROUTES.SEARCH} - title={name} - withLink={true} + url="/" /> <Main id="main" className={styles.main}> <article |
