aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/templates
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-10-09 16:31:00 +0200
committerArmand Philippot <git@armandphilippot.com>2023-11-11 18:14:41 +0100
commit891441a76173c708c6604fa203b175aefa222333 (patch)
tree27295311bb01a4e44dcc4f68422975cd705a24b8 /src/components/templates
parentf11a906420975e833f278a08470d8f9783c76f73 (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.scss67
-rw-r--r--src/components/templates/layout/layout.tsx68
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