From 44d94e9f3f57895bea2c48e36eca497bfbf49778 Mon Sep 17 00:00:00 2001 From: Ida Marie Andreassen <43541032+idamand@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:31:14 +0100 Subject: [PATCH 1/4] v3 - Add translation to roles for employees (#947) --- .../customerCaseEmployeeCard/CustomerCaseEmployeeCard.tsx | 5 ++++- src/components/employeeCard/EmployeeCard.tsx | 4 +++- src/components/employeePage/EmployeePage.tsx | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/components/customerCaseEmployeeCard/CustomerCaseEmployeeCard.tsx b/src/components/customerCaseEmployeeCard/CustomerCaseEmployeeCard.tsx index bab24148b..7ea34672d 100644 --- a/src/components/customerCaseEmployeeCard/CustomerCaseEmployeeCard.tsx +++ b/src/components/customerCaseEmployeeCard/CustomerCaseEmployeeCard.tsx @@ -1,4 +1,5 @@ import Image from "next/image"; +import { useTranslations } from "next-intl"; import Text from "src/components/text/Text"; import formatPhoneNumber from "src/components/utils/formatPhoneNumber"; @@ -15,6 +16,8 @@ export interface CustomerCaseEmployeeCardProps { export default function CustomerCaseEmployeeCard({ employee, }: CustomerCaseEmployeeCardProps) { + const t = useTranslations("employee_card"); + return ( employee.imageThumbUrl && employee.name && @@ -38,7 +41,7 @@ export default function CustomerCaseEmployeeCard({ type="labelRegular" key={competence} > - {competence} + {t(competence)} ))} diff --git a/src/components/employeeCard/EmployeeCard.tsx b/src/components/employeeCard/EmployeeCard.tsx index b9999e7aa..f380657a9 100644 --- a/src/components/employeeCard/EmployeeCard.tsx +++ b/src/components/employeeCard/EmployeeCard.tsx @@ -1,5 +1,6 @@ import Image from "next/image"; import Link from "next/link"; +import { useTranslations } from "next-intl"; import Text from "src/components/text/Text"; import formatPhoneNumber from "src/components/utils/formatPhoneNumber"; @@ -19,6 +20,7 @@ export default function EmployeeCard({ employeePageSlug, language, }: EmployeeCardProps) { + const t = useTranslations("employee_card"); return ( employee.imageUrl && employee.name && @@ -56,7 +58,7 @@ export default function EmployeeCard({ key={competence} as="span" > - {competence} + {t(competence)} ))} diff --git a/src/components/employeePage/EmployeePage.tsx b/src/components/employeePage/EmployeePage.tsx index 6e94cdde4..b85793e4a 100644 --- a/src/components/employeePage/EmployeePage.tsx +++ b/src/components/employeePage/EmployeePage.tsx @@ -1,4 +1,5 @@ import Image from "next/image"; +import { useTranslations } from "next-intl"; import Text from "src/components/text/Text"; import formatPhoneNumber from "src/components/utils/formatPhoneNumber"; @@ -12,6 +13,7 @@ export interface EmployeePageProps { export default function EmployeePage({ employee }: EmployeePageProps) { const image = employee.imageUrl ?? employee.imageThumbUrl ?? null; + const t = useTranslations("employee_card"); return ( employee.name && ( @@ -47,7 +49,7 @@ export default function EmployeePage({ employee }: EmployeePageProps) { )} {employee.competences.map((competence) => ( - {competence} + {t(competence)} ))} From 18f2e3e9543c4f71d9ced3aad8deb85cee8a24b1 Mon Sep 17 00:00:00 2001 From: Ida Marie Andreassen <43541032+idamand@users.noreply.github.com> Date: Thu, 5 Dec 2024 09:30:13 +0100 Subject: [PATCH 2/4] V3 update header (#944) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add new header design with transistions * New header design works on desktop * Add mobile and tablet version of header * Working mobile and tablet version ✨ * Add aria-label to menu button * Fix: Remove breadcrumbs from PageHeader * Remove todos * Fix colors --- public/_assets/dot.svg | 5 + public/_assets/green-dot.svg | 5 + public/_assets/menu-close.svg | 8 +- public/_assets/menu.svg | 9 +- src/app/(main)/[locale]/[...path]/page.tsx | 9 +- src/app/(main)/[locale]/page.tsx | 2 - .../languageSwitcher/LanguageSwitcher.tsx | 15 ++- .../languageSwitcher.module.css | 40 ++++++- src/components/link/CustomLink.tsx | 98 +++++++++------- src/components/link/link.module.css | 50 +++++--- src/components/navigation/header/Header.tsx | 111 +++++++++--------- .../navigation/header/HeaderPreview.tsx | 6 - .../navigation/header/PageHeader.tsx | 8 -- .../navigation/header/header.module.css | 102 +++++++++++----- src/styles/global.css | 1 + src/utils/hooks/useScrollDirection.ts | 27 +++++ 16 files changed, 316 insertions(+), 180 deletions(-) create mode 100644 public/_assets/dot.svg create mode 100644 public/_assets/green-dot.svg create mode 100644 src/utils/hooks/useScrollDirection.ts diff --git a/public/_assets/dot.svg b/public/_assets/dot.svg new file mode 100644 index 000000000..7db8e7676 --- /dev/null +++ b/public/_assets/dot.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/_assets/green-dot.svg b/public/_assets/green-dot.svg new file mode 100644 index 000000000..aff7b014b --- /dev/null +++ b/public/_assets/green-dot.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/_assets/menu-close.svg b/public/_assets/menu-close.svg index a96e8cd5c..55927f7f4 100644 --- a/public/_assets/menu-close.svg +++ b/public/_assets/menu-close.svg @@ -1,6 +1,6 @@ - - - - + + + + diff --git a/public/_assets/menu.svg b/public/_assets/menu.svg index f495871d4..6e9f2b1e0 100644 --- a/public/_assets/menu.svg +++ b/public/_assets/menu.svg @@ -1,3 +1,6 @@ - - - \ No newline at end of file + + + + + + diff --git a/src/app/(main)/[locale]/[...path]/page.tsx b/src/app/(main)/[locale]/[...path]/page.tsx index b3be90347..8caf1a233 100644 --- a/src/app/(main)/[locale]/[...path]/page.tsx +++ b/src/app/(main)/[locale]/[...path]/page.tsx @@ -86,16 +86,11 @@ async function Page({ params }: Props) { return Page404; } - const { queryResponse, docType, pathTitles, pathTranslations } = pageData; + const { queryResponse, docType, pathTranslations } = pageData; return ( <> - +
{(() => { switch (docType) { diff --git a/src/app/(main)/[locale]/page.tsx b/src/app/(main)/[locale]/page.tsx index 82b7a25d6..ddf7a4f64 100644 --- a/src/app/(main)/[locale]/page.tsx +++ b/src/app/(main)/[locale]/page.tsx @@ -74,8 +74,6 @@ const Home = async ({ params }: Props) => {
{initialLandingPage.data.sections.map((section, index) => ( diff --git a/src/components/languageSwitcher/LanguageSwitcher.tsx b/src/components/languageSwitcher/LanguageSwitcher.tsx index e61c0a096..587671b3d 100644 --- a/src/components/languageSwitcher/LanguageSwitcher.tsx +++ b/src/components/languageSwitcher/LanguageSwitcher.tsx @@ -21,23 +21,22 @@ export default function LanguageSwitcher({ if (pathTranslation._key === undefined) { return null; } - const linkText = ( - - {pathTranslation._key.toUpperCase()} - - ); return (
  • {pathTranslation._key !== currentLanguage ? ( - {linkText} + + {pathTranslation._key.toUpperCase()} + ) : ( - linkText + + {pathTranslation._key.toUpperCase()} + )}
  • {index < pathTranslations.length - 1 && ( diff --git a/src/components/languageSwitcher/languageSwitcher.module.css b/src/components/languageSwitcher/languageSwitcher.module.css index bb36ccc36..090a16be8 100644 --- a/src/components/languageSwitcher/languageSwitcher.module.css +++ b/src/components/languageSwitcher/languageSwitcher.module.css @@ -1,17 +1,47 @@ .list { display: flex; - gap: 1rem; + gap: 0.25rem; list-style: none; padding: 0; - margin: 0; + margin: auto 0; } .divider { - border-left: 1px solid var(--text-primary-light); - /* Todo: fix correct color */ + border-left: 1px solid var(--text-primary); flex-grow: 1; } .link { - color: var(--text-primary-light) !important; + color: var(--text-primary) !important; + letter-spacing: 0.1rem; + line-height: 120%; + font-weight: 300; + + &:hover { + text-decoration: underline; + } +} + +.selectedLink { + color: var(--text-primary) !important; + letter-spacing: 0.1rem; + line-height: 120%; + font-weight: 600; + + &:hover { + text-decoration: underline; + } + + &:active { + font-weight: 600; + text-decoration: none; + } +} + +.notSelected { + text-decoration: none; + + &:hover { + text-decoration: underline; + } } diff --git a/src/components/link/CustomLink.tsx b/src/components/link/CustomLink.tsx index 135757ec0..d30fb9dfb 100644 --- a/src/components/link/CustomLink.tsx +++ b/src/components/link/CustomLink.tsx @@ -27,47 +27,65 @@ const CustomLink = ({ const newTab = link.newTab; const target = newTab ? "_blank" : undefined; const rel = newTab ? "noopener noreferrer" : undefined; - const className = - type === "headerLink" - ? `${styles.headerLink} ${isSelected ? styles.selected : ""}` - : styles.footerLink; - return ( - link.linkTitle && - (type === "link" ? ( -
    - - {link.linkTitle} - -
    - ) : ( - - {link.linkTitle} - - )) - ); + switch (type) { + case "link": + return ( + link.linkTitle && ( +
    + + {link.linkTitle} + +
    + ) + ); + case "headerLink": + return ( + link.linkTitle && ( + + + {link.linkTitle} + + ) + ); + case "footerLink": + return ( + link.linkTitle && ( + + + {link.linkTitle} + + ) + ); + } }; export default CustomLink; diff --git a/src/components/link/link.module.css b/src/components/link/link.module.css index 112a51589..43eff49b1 100644 --- a/src/components/link/link.module.css +++ b/src/components/link/link.module.css @@ -140,26 +140,38 @@ } .headerLink { - color: var(--background-bg-light-primary); + color: var(--text-primary); cursor: pointer; text-decoration: none; font-family: var(--font-britti-sans); font-size: 1.125rem; font-weight: 500; + display: inline-flex; + padding: 0.75rem 1rem 0.75rem 0.75rem; + justify-content: center; + align-items: center; + gap: 0.375rem; + position: relative; +} - &:hover { - font-size: 1.125rem; - font-style: normal; - font-weight: 600; - line-height: normal; - } +.dot { + position: absolute; + top: 50%; + left: -8px; + transform: translateY(-50%); + width: 0.375rem; + height: 0.375rem; + background-image: url("/_assets/dot.svg"); + background-size: 0.375rem 0.375rem; + opacity: 0; + transition: + left 0.2s ease-in-out, + opacity 0.2s ease-in-out; +} - &:active { - font-size: 1.125rem; - font-style: normal; - font-weight: 700; - line-height: normal; - } +.headerLink:hover .dot { + left: 0; + opacity: 1; } .footerLink { @@ -180,7 +192,13 @@ } .selected { - color: var(--text-primary-light); - font-weight: 700; - line-height: normal; + font-weight: 600; +} + +.selected .dot { + left: 0; + opacity: 1; + transition: none; + background-image: url("/_assets/green-dot.svg"); + background-size: 0.375rem 0.375rem; } diff --git a/src/components/navigation/header/Header.tsx b/src/components/navigation/header/Header.tsx index 1247dfc51..64e6cf6b5 100644 --- a/src/components/navigation/header/Header.tsx +++ b/src/components/navigation/header/Header.tsx @@ -11,8 +11,8 @@ import Button from "src/components/buttons/Button"; import LanguageSwitcher from "src/components/languageSwitcher/LanguageSwitcher"; import CustomLink from "src/components/link/CustomLink"; import LinkButton from "src/components/linkButton/LinkButton"; -import { BreadCrumbMenu } from "src/components/navigation/breadCrumbMenu/BreadCrumbMenu"; import Text from "src/components/text/Text"; +import useScrollDirection from "src/utils/hooks/useScrollDirection"; import { getHref } from "src/utils/link"; import { Announcement } from "studio/lib/interfaces/announcement"; import { BrandAssets } from "studio/lib/interfaces/brandAssets"; @@ -28,9 +28,7 @@ export interface IHeader { assets: BrandAssets; announcement: Announcement | null; currentLanguage: string; - pathTitles: string[]; pathTranslations: InternationalizedString; - showBreadcrumbs: boolean; } const filterLinks = (data: ILink[], type: string) => @@ -40,14 +38,14 @@ export const Header = ({ navigation, announcement, currentLanguage, - pathTitles, pathTranslations, - showBreadcrumbs, }: IHeader) => { const pathname = usePathname(); const [isOpen, setIsOpen] = useState(false); const sidebarData = navigation.sidebar || navigation.main; + const scrollDirection = useScrollDirection(); + const links = filterLinks(navigation.main, linkID); const ctas = filterLinks(navigation.main, callToActionFieldID); @@ -92,51 +90,63 @@ export const Header = ({ className={`${styles.focusOn} ${isOpen && styles.isOpen}`} >
    +
    {showAnnouncement && (
    @@ -156,13 +166,6 @@ export const Header = ({ )}
    - {showBreadcrumbs && ( - - )} ); }; diff --git a/src/components/navigation/header/HeaderPreview.tsx b/src/components/navigation/header/HeaderPreview.tsx index 3fe13023d..bd2ce2201 100644 --- a/src/components/navigation/header/HeaderPreview.tsx +++ b/src/components/navigation/header/HeaderPreview.tsx @@ -18,17 +18,13 @@ export default function HeaderPreview({ initialBrandAssets, initialAnnouncement, currentLanguage, - pathTitles, pathTranslations, - showBreadcrumbs, }: { initialNav: QueryResponseInitial; initialBrandAssets: QueryResponseInitial; initialAnnouncement: QueryResponseInitial; currentLanguage: string; - pathTitles: string[]; pathTranslations: InternationalizedString; - showBreadcrumbs: boolean; }) { const { data: newNav } = useQuery( NAV_QUERY, @@ -54,9 +50,7 @@ export default function HeaderPreview({ assets={newBrandAssets} announcement={newAnnouncement} currentLanguage={currentLanguage} - pathTitles={pathTitles} pathTranslations={pathTranslations} - showBreadcrumbs={showBreadcrumbs} /> ) ); diff --git a/src/components/navigation/header/PageHeader.tsx b/src/components/navigation/header/PageHeader.tsx index e3008095e..e4d8eb76f 100644 --- a/src/components/navigation/header/PageHeader.tsx +++ b/src/components/navigation/header/PageHeader.tsx @@ -16,16 +16,12 @@ import HeaderPreview from "./HeaderPreview"; interface PageHeaderProps { language: string; - pathTitles: string[]; pathTranslations: InternationalizedString; - showBreadcrumbs: boolean; } export default async function PageHeader({ language, - pathTitles, pathTranslations, - showBreadcrumbs, }: PageHeaderProps) { const { perspective, isDraftMode } = getDraftModeInfo(); @@ -56,9 +52,7 @@ export default async function PageHeader({ initialBrandAssets={initialBrandAssets} initialAnnouncement={initialAnnouncement} currentLanguage={language} - pathTitles={pathTitles} pathTranslations={pathTranslations} - showBreadcrumbs={showBreadcrumbs} /> ) : (
    )) ); diff --git a/src/components/navigation/header/header.module.css b/src/components/navigation/header/header.module.css index 948c2f6f4..18fe8bfe9 100644 --- a/src/components/navigation/header/header.module.css +++ b/src/components/navigation/header/header.module.css @@ -1,52 +1,81 @@ .focusOn { - position: sticky; top: 0; overflow: hidden; z-index: 9999; - background-color: var(--background-bg-dark); } .isOpen { - height: 100vh; + height: 100%; display: flex; flex-direction: column; @media (max-width: 1024px) { - background: var(--background-bg-dark); + background: var(--background-bg-light-primary); & > header { - flex: 1; display: flex; flex-direction: column; - padding: 1rem 2.5rem; & > nav { flex: 1; display: flex; flex-direction: column; - justify-content: flex-end; } } } } +.spacer { + height: 8rem; + width: 100%; +} + .wrapper { display: flex; - justify-content: space-between; + flex-direction: column; + position: fixed; + top: 0rem; + margin: 1.5rem 0; + justify-content: center; align-items: center; - padding: 16px 24px; + min-height: 5rem; + padding: 0rem 3rem 0rem 3rem; + border-radius: 0.75rem; + background: var(--background-header-light-transparent); + box-shadow: 0px 0.5px 2px 0px #eaeaea; + backdrop-filter: blur(40px); + max-width: 960px; + width: calc(100vw - 2rem); + justify-self: center; + transition-property: top; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 500ms; + left: 50%; + transform: translate(-50%, 0); + z-index: 9998; + + @media (max-width: 375px) { + width: 100vw; + } } -.logo { - overflow: hidden; - width: auto; +.wrapper.hidden { + top: -6.5rem; +} + +.desktopWrapper { display: flex; - max-width: 100%; - height: 1.25rem; + justify-content: space-between; + align-self: stretch; + align-items: center; +} + +.wrapper:has(.mobileMenu) .desktopWrapper { + padding-top: 1.25rem; } .list { - width: fit-content; + width: 100%; list-style-type: none; margin: 0; padding: 0; @@ -77,13 +106,18 @@ } .desktopLinks { - composes: listDesktop; - gap: 1.5rem; + list-style-type: none; + width: 100%; + display: flex; + flex-direction: row; + gap: 0.25rem; + justify-items: center; justify-content: center; - align-self: stretch; + margin: 0; + padding: 0; - @media (min-width: 1200px) { - gap: 3rem; + @media (max-width: 834px) { + display: none; } } @@ -104,21 +138,35 @@ } } +.divider { + border: 0; + height: 1px; + background: var(--background-bg-light-secondary); + margin: 1rem 0; + width: 100%; +} + .mobileMenu { - flex: 1; display: flex; flex-direction: column; align-items: flex-start; - justify-content: flex-end; - gap: 5rem; - padding-top: 7.5rem; - padding-bottom: 7.5rem; + justify-content: flex-start; + width: 100%; + min-height: 5rem; + padding: 1.5rem 0; @media (min-width: 1024px) { display: none; } } +.mobileButtons { + display: flex; + flex-direction: row-reverse; + justify-content: space-between; + align-self: stretch; +} + /* MOBILE BUTTON */ .button { cursor: pointer; @@ -168,8 +216,8 @@ } .logo { - width: 130px; + width: 9rem; height: 37px; - background-color: var(--background-bg-light-primary); + background-color: var(--text-primary); -webkit-mask: url("/_assets/variant-logo.svg") no-repeat 50% 50%; } diff --git a/src/styles/global.css b/src/styles/global.css index 7aa42779c..e49b663c1 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -97,6 +97,7 @@ html { --background-bg-blue: var(--Blue-500); --background-bg-yellow: var(--Yellow-500); --background-disabled: var(--Light-700); + --background-header-light-transparent: #fafafabf; --stroke-primary: var(--Dark-700); --stroke-secondary: var(--Dark-400); diff --git a/src/utils/hooks/useScrollDirection.ts b/src/utils/hooks/useScrollDirection.ts new file mode 100644 index 000000000..b955d57f6 --- /dev/null +++ b/src/utils/hooks/useScrollDirection.ts @@ -0,0 +1,27 @@ +import { useEffect, useState } from "react"; + +export default function useScrollDirection() { + const [scrollDirection, setScrollDirection] = useState(null); + + useEffect(() => { + let lastScrollY = window.scrollY; + + const updateScrollDirection = () => { + const scrollY = window.scrollY; + const direction = scrollY > lastScrollY ? "down" : "up"; + if ( + direction !== scrollDirection && + (scrollY - lastScrollY > 10 || scrollY - lastScrollY < -10) + ) { + setScrollDirection(direction); + } + lastScrollY = scrollY > 0 ? scrollY : 0; + }; + window.addEventListener("scroll", updateScrollDirection); + return () => { + window.removeEventListener("scroll", updateScrollDirection); + }; + }, [scrollDirection]); + + return scrollDirection; +} From 9c90ce41413566507b5cf6ac64b44baaf41acadb Mon Sep 17 00:00:00 2001 From: Jacob Berglund Date: Thu, 5 Dec 2024 14:29:34 +0100 Subject: [PATCH 3/4] v3 - Header CSS refactor (#949) * refactor: enhance header component structure and styling * Remove bg color on isOpen --------- Co-authored-by: Ida Marie Andreassen --- src/components/navigation/header/Header.tsx | 120 ++++++++---------- .../navigation/header/header.module.css | 96 ++++++-------- src/styles/global.css | 8 ++ 3 files changed, 103 insertions(+), 121 deletions(-) diff --git a/src/components/navigation/header/Header.tsx b/src/components/navigation/header/Header.tsx index 64e6cf6b5..0dede3c83 100644 --- a/src/components/navigation/header/Header.tsx +++ b/src/components/navigation/header/Header.tsx @@ -50,7 +50,6 @@ export const Header = ({ const ctas = filterLinks(navigation.main, callToActionFieldID); const sidebarLinks = filterLinks(sidebarData, linkID); - const sidebarCtas = filterLinks(sidebarData, callToActionFieldID); const sidebarID = "sidebar"; @@ -85,86 +84,77 @@ export const Header = ({ <> -
    -
    - - {showAnnouncement && ( -
    -
    - {announcement.text} - {announcement.link && announcement.link.linkTitle && ( -
    - -
    - )} -
    -
    - )} -
    + + )}
    ); diff --git a/src/components/navigation/header/header.module.css b/src/components/navigation/header/header.module.css index 18fe8bfe9..c4e95800e 100644 --- a/src/components/navigation/header/header.module.css +++ b/src/components/navigation/header/header.module.css @@ -1,17 +1,8 @@ -.focusOn { - top: 0; - overflow: hidden; - z-index: 9999; -} - .isOpen { height: 100%; display: flex; flex-direction: column; - - @media (max-width: 1024px) { - background: var(--background-bg-light-primary); - + @media (max-width: 834px) { & > header { display: flex; flex-direction: column; @@ -25,55 +16,51 @@ } } -.spacer { - height: 8rem; +.nav { + --nav-height: 5rem; + max-width: min(960px, calc(100vw - 2rem)); + min-height: var(--nav-height); + position: relative; + margin-inline: auto; width: 100%; } +.header { + position: sticky; + top: 0; + z-index: 9999; + padding-top: 1.5rem; + transition-property: transform; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 500ms; +} + +.header:is(.hidden) { + transform: translateY(-100%); +} + .wrapper { - display: flex; - flex-direction: column; - position: fixed; - top: 0rem; - margin: 1.5rem 0; - justify-content: center; - align-items: center; - min-height: 5rem; + position: absolute; padding: 0rem 3rem 0rem 3rem; border-radius: 0.75rem; background: var(--background-header-light-transparent); box-shadow: 0px 0.5px 2px 0px #eaeaea; backdrop-filter: blur(40px); - max-width: 960px; - width: calc(100vw - 2rem); + max-width: min(960px, calc(100vw - 2rem)); + width: 100%; justify-self: center; - transition-property: top; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 500ms; - left: 50%; - transform: translate(-50%, 0); - z-index: 9998; + display: grid; + grid-template-rows: var(--nav-height); @media (max-width: 375px) { width: 100vw; } } - -.wrapper.hidden { - top: -6.5rem; -} - .desktopWrapper { display: flex; - justify-content: space-between; - align-self: stretch; align-items: center; } -.wrapper:has(.mobileMenu) .desktopWrapper { - padding-top: 1.25rem; -} - .list { width: 100%; list-style-type: none; @@ -88,7 +75,7 @@ flex-direction: column; gap: 1.5rem; - @media (min-width: 1024px) { + @media (min-width: 834px) { display: none; } } @@ -97,7 +84,7 @@ composes: list; display: none; - @media (min-width: 1024px) { + @media (min-width: 834px) { display: flex; flex-direction: row; align-items: center; @@ -111,7 +98,6 @@ display: flex; flex-direction: row; gap: 0.25rem; - justify-items: center; justify-content: center; margin: 0; padding: 0; @@ -131,7 +117,7 @@ .languageSwitcher { display: none; - @media (min-width: 1024px) { + @media (min-width: 834px) { align-items: center; gap: 0.75rem; display: flex; @@ -147,15 +133,9 @@ } .mobileMenu { - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: flex-start; - width: 100%; - min-height: 5rem; padding: 1.5rem 0; - @media (min-width: 1024px) { + @media (min-width: 834px) { display: none; } } @@ -169,6 +149,7 @@ /* MOBILE BUTTON */ .button { + margin-left: auto; cursor: pointer; width: 2.5rem; height: 2.5rem; @@ -176,7 +157,7 @@ background-color: transparent; border: none; - @media (min-width: 1024px) { + @media (min-width: 834px) { display: none; } } @@ -203,7 +184,7 @@ display: flex; gap: 2rem; - @media (max-width: 1024px) { + @media (max-width: 834px) { align-items: center; flex-direction: column; gap: 0.5rem; @@ -216,8 +197,11 @@ } .logo { - width: 9rem; - height: 37px; - background-color: var(--text-primary); - -webkit-mask: url("/_assets/variant-logo.svg") no-repeat 50% 50%; + height: 1.5rem; + aspect-ratio: 101 / 24; + display: block; + mask-image: url(/_assets/variant-logo.svg); + mask-repeat: no-repeat; + mask-size: cover; + background: currentColor; } diff --git a/src/styles/global.css b/src/styles/global.css index e49b663c1..a41301a01 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -8,6 +8,14 @@ html { box-sizing: inherit; } +:where(.debug) { + *, + *::before, + *::after { + outline: 1px solid lime; + } +} + :root { --Blue-500: #3840ff; --Blue-700: #0014cd; From 7d8c494e79b9ddeed4a987ad190c861a2b2f0ad5 Mon Sep 17 00:00:00 2001 From: Petter Hohle Date: Thu, 5 Dec 2024 14:39:25 +0100 Subject: [PATCH 4/4] Add Employee Highlight section (#943) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ Add Employee highlight section * 💄 Update styles * Use internationalizedArrayText for description field * 💄 Update styles for responsiveness * 🔥 hotspot: true * 📱 Change flex direction on tablets --- .../employeeHighlight/EmployeeHighlight.tsx | 32 +++++++++ .../employeeHighlight.module.css | 69 +++++++++++++++++++ src/utils/renderSection.tsx | 3 + studio/lib/interfaces/pages.ts | 12 +++- studio/lib/queries/pages.ts | 4 ++ studio/schema.ts | 2 + studio/schemas/documents/pageBuilder.ts | 2 + .../objects/sections/employeeHighlight.ts | 59 ++++++++++++++++ 8 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 src/components/sections/employeeHighlight/EmployeeHighlight.tsx create mode 100644 src/components/sections/employeeHighlight/employeeHighlight.module.css create mode 100644 studio/schemas/objects/sections/employeeHighlight.ts diff --git a/src/components/sections/employeeHighlight/EmployeeHighlight.tsx b/src/components/sections/employeeHighlight/EmployeeHighlight.tsx new file mode 100644 index 000000000..77af34328 --- /dev/null +++ b/src/components/sections/employeeHighlight/EmployeeHighlight.tsx @@ -0,0 +1,32 @@ +import { SanityImage } from "src/components/image/SanityImage"; +import Text from "src/components/text/Text"; +import { EmployeeHighlightSection } from "studio/lib/interfaces/pages"; + +import styles from "./employeeHighlight.module.css"; + +export interface EmployeeHighlightProps { + section: EmployeeHighlightSection; +} + +export default function EmployeeHighLight({ section }: EmployeeHighlightProps) { + return ( +
    +
    + +
    +
    +
    + + {section.basicTitle} + +
    + + {section.name} + +
    +
    + {section.description} +
    +
    + ); +} diff --git a/src/components/sections/employeeHighlight/employeeHighlight.module.css b/src/components/sections/employeeHighlight/employeeHighlight.module.css new file mode 100644 index 000000000..ee99d935d --- /dev/null +++ b/src/components/sections/employeeHighlight/employeeHighlight.module.css @@ -0,0 +1,69 @@ +.wrapper { + display: flex; + flex-direction: row; + justify-content: center; + padding: 0 2rem; + max-width: 64rem; + margin: 5rem auto; + gap: 1.5rem; + color: var(--text-primary); + + @media (max-width: 834px) { + flex-direction: column; + margin-left: 2rem; + margin-right: 2rem; + } +} + +.image { + min-width: 20rem; + width: 100%; + height: auto; + object-fit: cover; + + & img { + border-radius: 0.375rem; + } + + @media (max-width: 834px) { + max-width: 60%; + } +} + +.textContainer { + display: flex; + flex-direction: column; + gap: 0.625rem; +} + +.titleContainer { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 0; +} + +.title { + padding: 0.25rem 1rem; + border-radius: 0.25rem 0.25rem 0rem 0rem; + background-color: var(--Violet-700); + color: var(--text-primary-light); +} + +.nameContainer { + display: flex; + flex-direction: column; + align-items: flex-start; + padding: 0.25rem; + gap: 0.5rem; + border-radius: 0rem 0.25rem 0.25rem 0.25rem; + background: var(--Purple-700, #7022d6); +} + +.name { + display: flex; + flex-direction: column; + padding: 0.25rem 0.75rem 0.125rem 0.75rem; + border-radius: 1.5rem; + background-color: var(--text-primary-light); +} diff --git a/src/utils/renderSection.tsx b/src/utils/renderSection.tsx index 5239578f6..1908e8fd9 100644 --- a/src/utils/renderSection.tsx +++ b/src/utils/renderSection.tsx @@ -7,6 +7,7 @@ import CalloutPreview from "src/components/sections/callout/CalloutPreview"; import CallToAction from "src/components/sections/callToAction/CallToAction"; import CallToActionPreview from "src/components/sections/callToAction/CallToActionPreview"; import ContactBox from "src/components/sections/contact-box/ContactBox"; +import EmployeeHighlight from "src/components/sections/employeeHighlight/EmployeeHighlight"; import Employees from "src/components/sections/employees/Employees"; import Grid from "src/components/sections/grid/Grid"; import GridPreview from "src/components/sections/grid/GridPreview"; @@ -258,6 +259,8 @@ const SectionRenderer = ({ return ; case "jobs": return ; + case "employeeHighlight": + return ; default: return null; } diff --git a/studio/lib/interfaces/pages.ts b/studio/lib/interfaces/pages.ts index 59466a7d6..01c692109 100644 --- a/studio/lib/interfaces/pages.ts +++ b/studio/lib/interfaces/pages.ts @@ -116,6 +116,15 @@ export interface JobsSection { subtitle: string; } +export interface EmployeeHighlightSection { + _type: "employeeHighlight"; + _key: string; + basicTitle: string; + name: string; + description: string; + employeePhoto: IImage; +} + export type Section = | HeroSection | LogoSaladSection @@ -128,7 +137,8 @@ export type Section = | GridSection | ContactBoxSection | EmployeesSection - | JobsSection; + | JobsSection + | EmployeeHighlightSection; export interface PageBuilder { _createdAt: string; diff --git a/studio/lib/queries/pages.ts b/studio/lib/queries/pages.ts index 573c59f60..06bcf9d4e 100644 --- a/studio/lib/queries/pages.ts +++ b/studio/lib/queries/pages.ts @@ -53,6 +53,10 @@ const SECTIONS_FRAGMENT = groq` _type == "jobs" => { "basicTitle": ${translatedFieldFragment("basicTitle")}, "subtitle": ${translatedFieldFragment("subtitle")} + }, + _type == "employeeHighlight" => { + "basicTitle": ${translatedFieldFragment("basicTitle")}, + "description": ${translatedFieldFragment("description")}, } } `; diff --git a/studio/schema.ts b/studio/schema.ts index 8fbc2f74e..96d364e35 100644 --- a/studio/schema.ts +++ b/studio/schema.ts @@ -20,6 +20,7 @@ import benefitsByLocation from "./schemas/objects/compensations/benefitsByLocati import { footerSection } from "./schemas/objects/footerSection"; import jobPosting from "./schemas/objects/jobPosting"; import { link } from "./schemas/objects/link"; +import { employeeHighlightSection } from "./schemas/objects/sections/employeeHighlight"; import seo from "./schemas/objects/seo"; import { socialMedia } from "./schemas/objects/socialMedia"; @@ -47,5 +48,6 @@ export const schema: { types: SchemaTypeDefinition[] } = { announcement, jobPosting, jobPostings, + employeeHighlightSection, ], }; diff --git a/studio/schemas/documents/pageBuilder.ts b/studio/schemas/documents/pageBuilder.ts index 3a9734f8d..855b3cc9f 100644 --- a/studio/schemas/documents/pageBuilder.ts +++ b/studio/schemas/documents/pageBuilder.ts @@ -6,6 +6,7 @@ import article from "studio/schemas/objects/sections/article"; import callout from "studio/schemas/objects/sections/callout"; import callToAction from "studio/schemas/objects/sections/callToAction"; import contactBox from "studio/schemas/objects/sections/contact-box"; +import { employeeHighlightSection } from "studio/schemas/objects/sections/employeeHighlight"; import { employees } from "studio/schemas/objects/sections/employees"; import grid from "studio/schemas/objects/sections/grid"; import hero from "studio/schemas/objects/sections/hero"; @@ -55,6 +56,7 @@ const pageBuilder = defineType({ employees, contactBox, jobs, + employeeHighlightSection, ], }), ], diff --git a/studio/schemas/objects/sections/employeeHighlight.ts b/studio/schemas/objects/sections/employeeHighlight.ts new file mode 100644 index 000000000..779a785d2 --- /dev/null +++ b/studio/schemas/objects/sections/employeeHighlight.ts @@ -0,0 +1,59 @@ +import { defineField } from "sanity"; + +import { isInternationalizedString } from "studio/lib/interfaces/global"; +import { titleID } from "studio/schemas/fields/text"; +import { firstTranslation } from "studio/utils/i18n"; + +export const employeeHighlightID = "employeeHighlight"; + +export const employeeHighlightSection = defineField({ + name: employeeHighlightID, + title: "Employee Highlight", + type: "object", + fields: [ + { + name: titleID.basic, + type: "internationalizedArrayString", + title: "Title", + description: "The title/prefix that will appear above the name block.", + }, + { + name: "name", + type: "string", + title: "Name", + description: "The name of the employee.", + }, + { + name: "description", + type: "internationalizedArrayText", + title: "Description", + description: "The body text in the section.", + }, + { + name: "employeePhoto", + type: "image", + title: "Employee photo", + description: "A photo of the employee,", + options: { + hotspot: true, + }, + }, + ], + preview: { + select: { + title: "basicTitle", + name: "name", + }, + prepare({ title, name }) { + if (!isInternationalizedString(title)) { + throw new TypeError( + `Expected 'title' to be InternationalizedString, was ${typeof title}`, + ); + } + return { + title: `${firstTranslation(title) ?? ""} ${name}`, + subtitle: "Employee highlight", + }; + }, + }, +});