From 44f5580978128deedd1b4832247aa9dca5660854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lloren=C3=A7?= Date: Fri, 28 Jun 2024 15:55:10 +0200 Subject: [PATCH] Introduce new Landing Page layout --- .../src/components/authenticateBox.ts | 35 +++- src/frontend/src/components/landingPage.ts | 58 ++++++ src/frontend/src/styles/main.css | 171 +++++++++++++++++- src/showcase/src/pages/manageNewLanding.astro | 15 ++ .../src/pages/managePickManyNewLanding.astro | 17 ++ .../src/pages/managePickNewLanding.astro | 17 ++ 6 files changed, 301 insertions(+), 12 deletions(-) create mode 100644 src/frontend/src/components/landingPage.ts create mode 100644 src/showcase/src/pages/manageNewLanding.astro create mode 100644 src/showcase/src/pages/managePickManyNewLanding.astro create mode 100644 src/showcase/src/pages/managePickNewLanding.astro diff --git a/src/frontend/src/components/authenticateBox.ts b/src/frontend/src/components/authenticateBox.ts index f1e87685cd..a9328bb082 100644 --- a/src/frontend/src/components/authenticateBox.ts +++ b/src/frontend/src/components/authenticateBox.ts @@ -48,6 +48,7 @@ import { promptUserNumber } from "./promptUserNumber"; import { DerEncodedPublicKey } from "@dfinity/agent"; import copyJson from "./authenticateBox.json"; +import { landingPage } from "./landingPage"; /** Template used for rendering specific authentication screens. See `authnScreens` below * for meaning of "firstTime", "useExisting" and "pick". */ @@ -562,12 +563,22 @@ export const authnPages = (i18n: I18n, props: AuthnTemplates) => { const templates = authnTemplates(i18n, props); return { - firstTime: (opts: Parameters[0]) => - page(templates.firstTime(opts)), + firstTime: ( + opts: Parameters[0], + // TODO: remove this parameter once the landing page is ready. + landingPageTemplate: boolean = false + ) => + // TODO: Use the landing page template always when ready. + page(templates.firstTime(opts), landingPageTemplate), useExisting: (opts: Parameters[0]) => page(templates.useExisting(opts)), - pick: (opts: Parameters[0]) => - page(templates.pick(opts)), + pick: ( + opts: Parameters[0], + // TODO: remove this parameter once the landing page is ready. + landingPageTemplate: boolean = false + ) => + // TODO: Use the landing page template always when ready. + page(templates.pick(opts), landingPageTemplate), }; }; @@ -615,12 +626,16 @@ export const authnScreens = (i18n: I18n, props: AuthnTemplates) => { }; // Wrap the template with header & footer and render the page -const page = (slot: TemplateResult) => { - const template = mainWindow({ - slot: html` -

Internet Identity

- ${slot}`, - }); +const page = (slot: TemplateResult, landingPageTemplate: boolean = false) => { + const template = landingPageTemplate + ? landingPage({ + slot, + }) + : mainWindow({ + slot: html` +

Internet Identity

+ ${slot}`, + }); const container = document.getElementById("pageContent") as HTMLElement; render(template, container); }; diff --git a/src/frontend/src/components/landingPage.ts b/src/frontend/src/components/landingPage.ts new file mode 100644 index 0000000000..8f1ccd0cf7 --- /dev/null +++ b/src/frontend/src/components/landingPage.ts @@ -0,0 +1,58 @@ +import { html, TemplateResult } from "lit-html"; +import { navigationLink } from "./footer"; +import { githubIcon, icLogo, questionIcon } from "./icons"; + +/** + * Landing page template + * + * It is a component with split panes left and right in desktop view. + * To the left there is some static content, and to the right there is a slot. + * + * In movile view, the static content is below the slot. + * + */ +export const landingPage = ({ + slot, +}: { + slot: TemplateResult; +}): TemplateResult => { + return html`
+ +
+
+
${slot}
+
+
+
+
+

+ Secure, seamless & privacy-preserving digital identity +

+

+ Internet Identity is a decentralized identity solution running + end-to-end on the Internet Computer blockchain. +

+
+ +
+
`; +}; diff --git a/src/frontend/src/styles/main.css b/src/frontend/src/styles/main.css index fc9f11048a..2a73671d1e 100644 --- a/src/frontend/src/styles/main.css +++ b/src/frontend/src/styles/main.css @@ -131,6 +131,7 @@ --vc-brand-alt: rgba(215, 205, 235, 1); --vc-grey: grey; --vc-light-grey: #d4d8e5; + --vc-brand-gradient: linear-gradient(90deg, #4b19d6 0%, #890eed 100%); /** * value tokens: sizes (--vs => valueSize) @@ -203,6 +204,9 @@ --rc-button--disabled: var(--vc-shadow); + --rc-landing-page-background: var(--vc-brand-gradient); + --rc-landing-page-background-text: var(--vc-snow); + /* color used to elevate something from its background secondary button, card, icon button @@ -254,6 +258,8 @@ --rg-brand-bruised: var(--vc-brand-blue) 50%, var(--vc-brand-purple) 90%; /* reference tokens: sizes */ + --rs-main-content-width: 40rem; + --rs-inline-grid-gap: var(--vs-inline); --rs-inline-icon-gap: var(--vs-inline); @@ -313,6 +319,12 @@ --rs-line--thick: calc(var(--rs-line) * 4); --rs-footer-height: 4rem; + + --rs-landing-page-left-pane-padding: calc(var(--vs-gutter) * 8); + --rs-landing-page-left-pane-min-height--mobile: 40rem; + --rs-landing-page-right-pane-padding--desktop: 10vmax; + --rs-landing-page-right-pane-padding--mobile: calc(var(--vs-stack) * 2); + --rs-landing-page-stack: calc(var(--vs-stack) * 4); } /* II) Optional Theme Settings: DarkMode, LightMode, Product Specific stuff */ @@ -755,8 +767,8 @@ a:hover, .l-container { position: relative; font-size: 1.6rem; - min-width: 40rem; - max-width: 40rem; + min-width: var(--rs-main-content-width); + max-width: var(--rs-main-content-width); /* centers the container and adds a bit of space to make sure the footer does not stick to it */ margin: 0 auto 2rem; } @@ -949,6 +961,161 @@ a:hover, color: rgba(0, 0, 0, 0.5); } +/** + * LandingPage component + */ + +.c-landingPage { + display: grid; + grid-template-columns: 1fr minmax(var(--rs-main-content-width), 1fr); + grid-template-areas: "left right"; + + height: 100vh; +} + +.c-landingPage__logo { + position: absolute; + left: var(--rs-landing-page-left-pane-padding); + top: var(--rs-landing-page-left-pane-padding); + + color: var(--rc-landing-page-background-text); +} + +.c-landingPage__logo .c-logo { + padding: 0; +} + +.c-landingPage__left { + background: var(--rc-landing-page-background); + color: var(--rc-landing-page-background-text); + + grid-area: left; + + display: flex; + flex-direction: column; + align-items: flex-start; + + padding: var(--rs-landing-page-left-pane-padding); +} + +.c-landingPage__left__content { + flex: 1; + + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + padding: 0 20%; + + /* To compensate for the IC logo that is outisde the normal flow with position absolute */ + --logo-height: 3rem; + margin-top: var(--logo-height); +} + +.c-landingPage__logo--mobile { + display: none; +} + +.c-landingPage__logo--desktop { + display: block; +} + +.c-landingPage__right { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + grid-area: right; + + overflow-y: scroll; +} + +.c-landingPage__right__content { + min-width: var(--rs-main-content-width); + max-width: var(--rs-main-content-width); + /* This is necessary in case the content is bigger than the parent. */ + /* It keeps the start of the box at the top of the container. */ + max-height: 90%; + + display: flex; + flex-direction: column; + align-items: center; +} + +.c-landingPage__right__content--full-width { + width: 100%; + padding-bottom: var(--rs-landing-page-stack); +} + +.c-landingPage .c-footer__link { + padding: 0; +} + +.c-landingPage__left__footer { + display: flex; + gap: var(--rs-inline-grid-gap); +} + +@media (max-width: 512px) { + .c-landingPage { + display: block; + + padding: 0 5vmax; + + background: var(--rc-landing-page-background); + + height: auto; + min-height: 100vh; + } + + .c-landingPage__logo { + display: flex; + position: static; + justify-content: center; + + order: 1; + color: var(--rc-landing-page-background-text); + + padding: var(--rs-landing-page-stack) 0; + } + + .c-landingPage__left { + background: none; + order: 2; + + padding: 0; + margin-top: var(--rs-landing-page-stack); + padding-bottom: var(--rs-landing-page-stack); + + gap: var(--rs-landing-page-stack); + } + + .c-landingPage__left__content { + padding: 0; + /* We don't need to account for the logo with absolute position */ + margin-top: 0; + } + + .c-landingPage__right { + order: 1; + + background: var(--rc-light); + border-radius: var(--rs-card-border-radius); + padding: var(--rs-landing-page-right-pane-padding--mobile); + + overflow: auto; + + min-height: var(--rs-landing-page-left-pane-min-height--mobile); + } + + .c-landingPage__right__content { + min-width: auto; + max-width: auto; + } +} + /** * Card components */ diff --git a/src/showcase/src/pages/manageNewLanding.astro b/src/showcase/src/pages/manageNewLanding.astro new file mode 100644 index 0000000000..fc339c48da --- /dev/null +++ b/src/showcase/src/pages/manageNewLanding.astro @@ -0,0 +1,15 @@ +--- +import Screen from "../layouts/Screen.astro"; +--- + + + + diff --git a/src/showcase/src/pages/managePickManyNewLanding.astro b/src/showcase/src/pages/managePickManyNewLanding.astro new file mode 100644 index 0000000000..dd3c0995e2 --- /dev/null +++ b/src/showcase/src/pages/managePickManyNewLanding.astro @@ -0,0 +1,17 @@ +--- +import Screen from "../layouts/Screen.astro"; +--- + + + + diff --git a/src/showcase/src/pages/managePickNewLanding.astro b/src/showcase/src/pages/managePickNewLanding.astro new file mode 100644 index 0000000000..9b8218c838 --- /dev/null +++ b/src/showcase/src/pages/managePickNewLanding.astro @@ -0,0 +1,17 @@ +--- +import Screen from "../layouts/Screen.astro"; +--- + + + +