From 7e7410a40657203a2468d9cedf05d9214a047f84 Mon Sep 17 00:00:00 2001 From: Adrian Wannenmacher Date: Tue, 3 Mar 2026 01:40:45 +0100 Subject: [PATCH] improve design of session view This improves the design of the session view a lot. However, several things still need to be done: 1. The rules section is not styled. 2. The session list is not styled. 3. The design is not responsive yet. This will take longer, as the base view will need to be overhauled substantially to take advantage of wider screens. 4. A light mode needs to be added. --- index.js | 6 +- style.css | 176 +++++++++++++++++++++++++++++++++++++++------ ui/layout.js | 10 ++- ui/session.js | 30 +++++--- ui/session_head.js | 6 +- ui/session_list.js | 6 +- 6 files changed, 194 insertions(+), 40 deletions(-) diff --git a/index.js b/index.js index 52a3411..262c804 100644 --- a/index.js +++ b/index.js @@ -11,7 +11,11 @@ m.route(document.body, "/", { let session = newSession ? null : parseInt(vnode.attrs.session); session = isNaN(session) ? null : session; - return m(Layout, m(BaseView, { newSession, session })); + return m( + Layout, + { backHref: session ? "/" : null }, + m(BaseView, { newSession, session }) + ); }, }, }); diff --git a/style.css b/style.css index 65dc509..a56b4ca 100644 --- a/style.css +++ b/style.css @@ -1,36 +1,148 @@ html { height: 100%; + font-family: sans-serif; + + --color-regular-text: white; + --color-regular-background: lch(from black calc(l + 10) c h); + --color-alter-text: white; + --color-alter-background: black; + --color-primary-text: black; + --color-primary-background: lch(from orange calc(l + 10) c h); + + color: var(--color-regular-text); + background-color: var(--color-regular-background); } body { min-height: 100%; height: 1px; + display: flex; + flex-direction: column; } -main { - display: contents; +h1 { + font-size: 2em; + margin: 0; +} + +h2 { + font-size: 1.75em; + margin: 0; +} + +h3 { + font-size: 1.5em; + margin: 0; +} + +h4 { + font-size: 1.35em; + margin: 0; +} + +h5 { + font-size: 1.25em; + margin: 0; +} + +h6 { + font-size: 1.1em; + margin: 0; +} + +button { + border: none; + border-radius: 5px; + color: var(--color-primary-text); + background: var(--color-primary-background); + padding: 1em 1em; + margin: 1em; + + &:disabled { + color: hsl(from var(--color-primary-text) h s calc(l + 25)); + background-color: + hsl(from var(--color-primary-background) h s calc(l + 25)); + } +} + +header.layout { + display: flex; + align-items: center; + + background-color: var(--color-alter-background); + color: var(--color-alter-text); + + >* { + padding: 0.5em 0.25em; + font-size: 2em; + color: inherit; + text-decoration: none; + margin: 0; + + &:first-child { + padding-left: 0.5em; + padding-right: 0.5em; + } + + &:nth-child(2) { + padding-left: 0; + } + + &:last-child { + padding-right: 0.5em; + } + } + +} + +main.layout { + flex-grow: 1; } .session-view { - min-height: 100%; display: flex; flex-direction: column; + min-height: 100%; gap: 1em; + >* { + padding-left: 1rem; + padding-right: 1rem; + } + + >:first-child { + padding-top: 1rem; + } + + >:last-child { + padding-bottom: 1rem; + } + + .session-view-header { + display: flex; + justify-content: space-between; + align-items: center; + + * { + margin: 0; + } + } + >.spacer { flex-grow: 1; } table { - border-collapse: collapse; + font-size: 1.5em; table-layout: fixed; width: 100%; text-align: center; + border-spacing: 0; } th, td { - border-right: 1px solid black; + border-right: 1px solid var(--color-regular-text); &:last-child { border-right: none; @@ -38,31 +150,36 @@ main { } thead { - border-bottom: 1px solid black; + border-bottom: 1px solid var(--color-regular-text); position: sticky; top: 0; - background: white; + background: var(--color-regular-background); + + th { + border-bottom: 3px double var(--color-regular-text); + padding: 0.5em 0; + } } tbody { - border-bottom: 1px solid black; + tr:last-child { + td { + border-bottom: 1px solid var(--color-regular-text); + } + } &:last-of-type { - border-bottom: none; + tr:last-child { + td { + border-bottom: none; + } + } } min-height: 5px; } } -button { - border: none; - border-radius: 5px; - background: light-grey; - padding: 0.5em 1em; - margin: 0.5em; -} - .current-round { display: grid; grid-template-areas: @@ -70,19 +187,30 @@ button { "they-raise current-points current-points we-raise" "they-win they-win we-win we-win"; grid-template-columns: 1fr auto auto 1fr; + gap: 1em; - background: white; + background: var(--color-regular-background); position: sticky; bottom: 0; + padding: 1em; + + color: var(--color-alter-text); + background-color: var(--color-alter-background); + + button { + margin: 0; + } + >h3 { grid-area: title; + margin: 0; } >.current-points { grid-area: current-points; align-content: center; - margin: 0 1em; + font-size: 2em; } >.they-raise { @@ -105,10 +233,12 @@ button { .continue { position: sticky; bottom: 0; - width: 100%; - background: white; + color: var(--color-alter-text); + background-color: var(--color-alter-background); + padding: 1em; - >* { - width: calc(100% - 1em); + button { + margin: 0; + width: 100%; } } \ No newline at end of file diff --git a/ui/layout.js b/ui/layout.js index 7b49490..2cb1ce9 100644 --- a/ui/layout.js +++ b/ui/layout.js @@ -25,7 +25,7 @@ export default class Layout { console.error("database error", error); } - view(vnode) { + view({ children, attrs: { backHref }}) { if (this.#db.failed) return m.fragment([ m("h1", "Watterblock kann nicht geöffnet werden"), @@ -45,6 +45,12 @@ export default class Layout { if (!this.#db.open) return m("p", "Öffne Datenbank, bitte warten…"); - return m("main", vnode.children); + return m.fragment([ + m("header.layout", [ + backHref ? m(m.route.Link, { href: backHref }, "←") : null, + m("h1", "Watterblock"), + ]), + m("main.layout", children), + ]); } } diff --git a/ui/session.js b/ui/session.js index 7fe1505..6c9bce6 100644 --- a/ui/session.js +++ b/ui/session.js @@ -6,27 +6,41 @@ import RoundView from "/ui/round.js"; import SessionHead from "/ui/session_head.js"; export default class SessionView { + #headOpen = false; + /** @param {{ attrs: { model: Session } }} param The session model to use. */ view({ attrs: { model } }) { let res = model.result; return m("article.session-view", [ - m(m.route.Link, { href: "/", selector: "button" }, "Zruck"), + m(".session-view-header", [ + m("h2", "Satz"), + m( + "button", + { onclick: () => this.#headOpen = !this.#headOpen }, + "Regln" + ), + ]), ( model.games.length === 0 && model.currentGame === null) ? m(SessionHead, { model }) : m.fragment([ - m("details", [ - m("summary", "Einstellungen"), - m(SessionHead, { model }), - ]), + this.#headOpen ? m(SessionHead, { model }) : null, m("section.record", [ - m("h3", "Mitschrift"), + this.#headOpen ? m("h3", "Mitschrift") : null, m("table", [ m("thead", [ m("tr", [ - m("th", ["se", " ", "•".repeat(res.theirPoints)]), - m("th", ["mia", " ", "•".repeat(res.ourPoints)]), + m("th", [ + model.theirTeam ? model.theirTeam : "Se", + " ", + "•".repeat(res.theirPoints), + ]), + m("th", [ + model.ourTeam ? model.ourTeam : "Mia", + " ", + "•".repeat(res.ourPoints), + ]), ]), ]), model.games.map((g) => m(GameView, { model: g })), diff --git a/ui/session_head.js b/ui/session_head.js index f3c743f..f8dafca 100644 --- a/ui/session_head.js +++ b/ui/session_head.js @@ -8,7 +8,7 @@ export default class SessionHead { view({ attrs: { model } }) { return m("section.session_head", [ m("h3", "Satzeinstellungen"), - m("section.session_head_names", [ + m("section.session-head-names", [ m("h4", "Teamnamen"), m("label", [ "Nam von eana", @@ -27,7 +27,7 @@ export default class SessionHead { }), ]), ]), - m("section.session_head_base", [ + m("section.session-head-base", [ m("h4", "Grundregln"), m("label", [ "Punkte zum gwinna", @@ -45,7 +45,7 @@ export default class SessionHead { }), ]), ]), - m("section.session_head_raising", [ + m("section.session-head-raising", [ m("h4", "Erhöhn"), m("label", [ m("input", { diff --git a/ui/session_list.js b/ui/session_list.js index 6736107..893703b 100644 --- a/ui/session_list.js +++ b/ui/session_list.js @@ -24,10 +24,10 @@ export default class SessionList { onclick: () => onSelect(s), }, [ - m("p", s.ourTeam !== "" ? s.ourTeam : "Unbnannts Team"), - m("p", s.theirTeam !== "" ? s.theirTeam : "Unbnannts Team"), - m("p", "•".repeat(s.result.ourPoints)), m("p", "•".repeat(s.result.theirPoints)), + m("p", s.theirTeam !== "" ? s.theirTeam : "Se"), + m("p", s.ourTeam !== "" ? s.ourTeam : "Mia"), + m("p", "•".repeat(s.result.ourPoints)), ], ), ]))