From af58306db51c00ebcff54acb2b06d6abbb6ff68d Mon Sep 17 00:00:00 2001 From: "Z. Charles Dziura" Date: Wed, 9 Jul 2025 06:52:55 -0400 Subject: [PATCH] Experimenting with card design --- webapp/package-lock.json | 24 ++++++------- webapp/src/app/app.html | 2 +- webapp/src/app/app.scss | 6 +++- webapp/src/app/app.ts | 22 +++++++----- webapp/src/app/components/card/card.scss | 11 +++--- .../src/app/components/nav-rail/nav-rail.scss | 8 ++--- webapp/src/app/routes/login/login.html | 7 +++- webapp/src/app/routes/login/login.scss | 2 -- webapp/src/app/routes/login/login.ts | 13 ++++--- webapp/src/app/routes/plan/plan.scss | 4 +-- webapp/src/styles.scss | 25 ++++--------- webapp/src/styles/components/button.scss | 6 ++-- webapp/src/styles/fonts.scss | 36 ------------------- webapp/src/styles/typography.scss | 18 ++++++++++ 14 files changed, 83 insertions(+), 101 deletions(-) delete mode 100644 webapp/src/styles/fonts.scss create mode 100644 webapp/src/styles/typography.scss diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 2761c20..d3a3556 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -260,7 +260,7 @@ "node_modules/@angular/compiler": { "version": "20.0.2", "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.0.2.tgz", - "integrity": "sha512-BJYXGUZaY9awYvgt0w9TDq73A1+m8W5eMRn/krWeQcfWakwTgs27BSxmhfJhD45KrMrky5yxAvGgqSfMKrLeng==", + "integrity": "sha512-BJYXGUZaY9awYvgt0w9TDq73A1+m8W5remRn/krWeQcfWakwTgs27BSxmhfJhD45KrMrky5yxAvGgqSfMKrLeng==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1336,7 +1336,7 @@ "node_modules/@inquirer/figures": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.12.tgz", - "integrity": "sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2emWYIn0jQ==", + "integrity": "sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2remWYIn0jQ==", "dev": true, "license": "MIT", "engines": { @@ -1558,7 +1558,7 @@ "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7remiVqA==", "dev": true, "license": "MIT", "dependencies": { @@ -2332,7 +2332,7 @@ "node_modules/@npmcli/package-json/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "integrity": "sha512-XnAIvQ8rem+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", "dependencies": { @@ -3223,7 +3223,7 @@ "node_modules/@tufjs/models/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "integrity": "sha512-XnAIvQ8rem+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", "dependencies": { @@ -3648,7 +3648,7 @@ "node_modules/cacache/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "integrity": "sha512-XnAIvQ8rem+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", "dependencies": { @@ -5207,7 +5207,7 @@ "node_modules/ignore-walk/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "integrity": "sha512-XnAIvQ8rem+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", "dependencies": { @@ -6410,7 +6410,7 @@ "node_modules/minipass-flush/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2remQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "license": "ISC" }, @@ -6443,7 +6443,7 @@ "node_modules/minipass-pipeline/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2remQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "license": "ISC" }, @@ -6476,7 +6476,7 @@ "node_modules/minipass-sized/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2remQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "license": "ISC" }, @@ -8201,7 +8201,7 @@ "node_modules/tar/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2remQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "license": "ISC" }, @@ -8403,7 +8403,7 @@ "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0remRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { diff --git a/webapp/src/app/app.html b/webapp/src/app/app.html index 852a964..f0fe9ab 100644 --- a/webapp/src/app/app.html +++ b/webapp/src/app/app.html @@ -1,4 +1,4 @@ -@if ($showNavRail()) { +@if ($showNavRail | async) { }
diff --git a/webapp/src/app/app.scss b/webapp/src/app/app.scss index 6677532..f298451 100644 --- a/webapp/src/app/app.scss +++ b/webapp/src/app/app.scss @@ -1,10 +1,14 @@ :host { display: grid; - grid-template-areas: 'nav' 'main'; + grid-template-areas: 'nav main'; grid-template-columns: min-content auto; min-height: 100vh; } main { + align-items: center; + display: grid; grid-area: main; + grid-template-rows: 0 auto; // Handle the mangling the layout + justify-items: center; } diff --git a/webapp/src/app/app.ts b/webapp/src/app/app.ts index 210acd0..dd841dc 100644 --- a/webapp/src/app/app.ts +++ b/webapp/src/app/app.ts @@ -1,19 +1,25 @@ -import { Component, computed, signal } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; +import { AsyncPipe } from '@angular/common'; +import { Component, inject } from '@angular/core'; +import { NavigationEnd, Router, RouterOutlet } from '@angular/router'; +import { filter, map } from 'rxjs'; import { NavRail } from './components/nav-rail/nav-rail'; const ROUTES_THAT_HIDE_NAV_RAIL = /^\/login$/; @Component({ selector: 'app-root', - imports: [RouterOutlet, NavRail], + imports: [AsyncPipe, RouterOutlet, NavRail], styleUrl: './app.scss', templateUrl: './app.html', }) export class App { - private readonly $_pathname = signal(location.pathname); - readonly $showNavRail = computed(() => { - const pathname = this.$_pathname(); - return pathname.length > 0 && !ROUTES_THAT_HIDE_NAV_RAIL.test(pathname); - }); + private readonly router = inject(Router); + + readonly $showNavRail = this.router.events.pipe( + filter(event => event instanceof NavigationEnd), + map( + ({ urlAfterRedirects }: NavigationEnd) => + urlAfterRedirects.length > 0 && !ROUTES_THAT_HIDE_NAV_RAIL.test(urlAfterRedirects) + ) + ); } diff --git a/webapp/src/app/components/card/card.scss b/webapp/src/app/components/card/card.scss index d9fce72..7649468 100644 --- a/webapp/src/app/components/card/card.scss +++ b/webapp/src/app/components/card/card.scss @@ -1,23 +1,22 @@ :host { - background-color: var(--color-surface-container); border: 1px solid var(--color-outline); - border-radius: 0.2em; + border-radius: 1.2rem; color: var(--color-on-surface); display: inline-grid; - font-size: 1.8em; + font-size: 1.8rem; grid-template-areas: 'head' 'body' 'foot'; grid-template-rows: min-content auto min-content; - padding: 0.4em; + padding: 1.6rem; } header { - margin-top: 0.4em; + margin-top: 0.4rem; } footer { justify-content: flex-end; display: flex; flex-direction: row; - margin-top: 1.2em; + margin-top: 1.2rem; } diff --git a/webapp/src/app/components/nav-rail/nav-rail.scss b/webapp/src/app/components/nav-rail/nav-rail.scss index fc911a1..52aa106 100644 --- a/webapp/src/app/components/nav-rail/nav-rail.scss +++ b/webapp/src/app/components/nav-rail/nav-rail.scss @@ -1,7 +1,7 @@ nav { background-color: var(--color-surface-container); - box-shadow: rgba(0, 0, 0, 0.02) 0px 1px 3px 0px, rgba(27, 31, 35, 0.15) 0px 0px 0px 1px; - font-size: 1.6em; + box-shadow: var(--box-shadow); + font-size: 1.6rem; height: 100%; .nav-list { @@ -9,7 +9,7 @@ nav { display: flex; flex-direction: column; list-style: none; - padding: 1.8em 1.2em; + padding: 1.8rem 1.2rem; .nav-list__item { align-items: center; @@ -18,7 +18,7 @@ nav { inline-size: min-content; &:not(:last-of-type) { - margin-bottom: 1.8em; + margin-bottom: 1.8rem; } .nav-list__item-label { diff --git a/webapp/src/app/routes/login/login.html b/webapp/src/app/routes/login/login.html index 147cfc4..9de9b31 100644 --- a/webapp/src/app/routes/login/login.html +++ b/webapp/src/app/routes/login/login.html @@ -1 +1,6 @@ -

login works!

+ +

Login

+
+ I'm the body! +
+
diff --git a/webapp/src/app/routes/login/login.scss b/webapp/src/app/routes/login/login.scss index b5a1c47..b01a4ba 100644 --- a/webapp/src/app/routes/login/login.scss +++ b/webapp/src/app/routes/login/login.scss @@ -1,5 +1,3 @@ :host { display: grid; - height: 100%; - width: 100%; } diff --git a/webapp/src/app/routes/login/login.ts b/webapp/src/app/routes/login/login.ts index a9e4eee..244e85d 100644 --- a/webapp/src/app/routes/login/login.ts +++ b/webapp/src/app/routes/login/login.ts @@ -1,11 +1,10 @@ import { Component } from '@angular/core'; +import { Card } from 'components/card/card'; @Component({ - selector: 'app-login', - imports: [], - templateUrl: './login.html', - styleUrl: './login.scss' + selector: 'app-login', + templateUrl: './login.html', + styleUrl: './login.scss', + imports: [Card], }) -export class Login { - -} +export class Login {} diff --git a/webapp/src/app/routes/plan/plan.scss b/webapp/src/app/routes/plan/plan.scss index 7d8abf6..bf0cb3c 100644 --- a/webapp/src/app/routes/plan/plan.scss +++ b/webapp/src/app/routes/plan/plan.scss @@ -15,9 +15,9 @@ header { display: flex; flex-direction: column; grid-area: body; - padding-left: 1.8em; + padding-left: 1.8rem; & > *:not(:last-child) { - margin-bottom: 1.6em; + margin-bottom: 1.6rem; } } diff --git a/webapp/src/styles.scss b/webapp/src/styles.scss index f4c9a13..0991b86 100644 --- a/webapp/src/styles.scss +++ b/webapp/src/styles.scss @@ -1,5 +1,5 @@ @import url('./styles/reset.scss'); -@import url('./styles/fonts.scss'); +@import url('./styles/typography.scss'); @import url('./styles/components/button.scss'); :root { @@ -33,25 +33,14 @@ --color-shadow: oklch(0.3396 0.0743 281.7 / 25%); --color-shadow-variant: oklch(0 0 0 / 30%); + + --box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 3px, rgba(0, 0, 0, 0.24) 0px 1px 2px; + + font-family: system-ui, sans-serif; + font-size: 62.5%; + font-weight: 400; } body { - font-family: 'Quicksand', sans-serif; - font-size: 62.5%; - font-weight: 400; margin: 0; } - -h1, -h3, -h5 { - font-family: 'Limelight', serif; - font-weight: 400; -} - -h2, -h4, -h6 { - font-family: 'Quicksand', sans-serif; - font-weight: 500; -} diff --git a/webapp/src/styles/components/button.scss b/webapp/src/styles/components/button.scss index ef1a0e4..9e2e8e4 100644 --- a/webapp/src/styles/components/button.scss +++ b/webapp/src/styles/components/button.scss @@ -1,11 +1,11 @@ button { background-color: var(--color-surface-container); border: 1px solid var(--color-outline); - border-radius: 0.4em; + border-radius: 0.4rem; color: var(--color-on-surface-container); cursor: pointer; - font-size: 0.8em; - padding: 0.2em 0.6em; + font-size: 0.8rem; + padding: 0.2rem 0.6rem; &:hover { box-shadow: var(--color-shadow) 0px 3px 8px; diff --git a/webapp/src/styles/fonts.scss b/webapp/src/styles/fonts.scss deleted file mode 100644 index f88a4c1..0000000 --- a/webapp/src/styles/fonts.scss +++ /dev/null @@ -1,36 +0,0 @@ -/* latin-ext */ -@font-face { - font-family: 'Limelight'; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(https://fonts.gstatic.com/s/limelight/v20/XLYkIZL7aopJVbZJHDuoNOlHnnY.woff2) format('woff2'); - unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'Limelight'; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(https://fonts.gstatic.com/s/limelight/v20/XLYkIZL7aopJVbZJHDuoOulH.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} -/* latin-ext */ -@font-face { - font-family: 'Quicksand'; - font-style: normal; - font-weight: 300 700; - font-display: swap; - src: url(https://fonts.gstatic.com/s/quicksand/v36/6xKtdSZaM9iE8KbpRA_hJVQNcOM.woff2) format('woff2'); - unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'Quicksand'; - font-style: normal; - font-weight: 300 700; - font-display: swap; - src: url(https://fonts.gstatic.com/s/quicksand/v36/6xKtdSZaM9iE8KbpRA_hK1QN.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} diff --git a/webapp/src/styles/typography.scss b/webapp/src/styles/typography.scss new file mode 100644 index 0000000..b415606 --- /dev/null +++ b/webapp/src/styles/typography.scss @@ -0,0 +1,18 @@ +h1, +h2, +h3 { + font-family: Avenir, Montserrat, Corbel, 'URW Gothic', source-sans-pro, sans-serif; + font-weight: 500; +} + +h1 { + font-size: 5.7rem; +} + +h2 { + font-size: 4.5rem; +} + +h3 { + font-size: 3.6rem; +}