From 288602253c872e68423ed8d533b36986b36708e9 Mon Sep 17 00:00:00 2001 From: Thalida Noel Date: Sat, 8 Aug 2026 22:35:44 -0400 Subject: [PATCH 1/3] Say what codecity is on the page that covers everything else The landing is fixed over the whole viewport, so it hides the header and footer: on a cold boot nobody saw the version, the repo link or the credit until they had already loaded a repo. The three now sit under the wordmark, where attribution belongs on a landing page, in both landing modes since the switcher covers the chrome either way. That made a third surface showing the same three things, so they move to components/AppMeta as one definition each and the wording, URLs and link targets can no longer drift. Colour stays with each surface: the header holds its link at icon weight, the footer lifts it above the prose, the landing sits it between the two. Co-Authored-By: Claude Opus 5 (1M context) --- app/src/components/AppMeta/AppMeta.css | 32 +++++++++ app/src/components/AppMeta/AppMeta.tsx | 65 +++++++++++++++++++ app/src/layout/AppFooter/AppFooter.css | 20 ++---- app/src/layout/AppFooter/AppFooter.tsx | 6 +- app/src/layout/AppFooter/FooterMeta.tsx | 30 --------- app/src/layout/AppHeader/AppHeader.css | 11 +--- app/src/layout/AppHeader/AppHeader.tsx | 12 +--- app/src/views/ProjectsView/ProjectsView.css | 21 +++++- app/src/views/ProjectsView/ProjectsView.tsx | 8 ++- .../views/ProjectsView/ProjectsView.test.tsx | 46 +++++++++++++ 10 files changed, 185 insertions(+), 66 deletions(-) create mode 100644 app/src/components/AppMeta/AppMeta.css create mode 100644 app/src/components/AppMeta/AppMeta.tsx delete mode 100644 app/src/layout/AppFooter/FooterMeta.tsx diff --git a/app/src/components/AppMeta/AppMeta.css b/app/src/components/AppMeta/AppMeta.css new file mode 100644 index 00000000..22331ecd --- /dev/null +++ b/app/src/components/AppMeta/AppMeta.css @@ -0,0 +1,32 @@ +/* Shared shape for the version / about / credit atoms. Each surface sets its + own colours, since the same link reads differently among header icons than it + does against footer prose. */ + +.meta-line { + display: inline-flex; + align-items: center; + gap: var(--cc-space-3); + flex-wrap: wrap; + min-width: 0; +} + +.meta-version, +.meta-credit { + white-space: nowrap; +} + +.meta-link { + text-decoration: none; +} +.meta-link:hover, +.meta-link:focus-visible { + color: var(--cc-text-strong); + text-decoration: underline; +} + +/* Pointer-events off so a stray click between items can't land on the dot. */ +.meta-sep { + flex: 0 0 auto; + color: var(--cc-text-faint); + pointer-events: none; +} diff --git a/app/src/components/AppMeta/AppMeta.tsx b/app/src/components/AppMeta/AppMeta.tsx new file mode 100644 index 00000000..993cb914 --- /dev/null +++ b/app/src/components/AppMeta/AppMeta.tsx @@ -0,0 +1,65 @@ +// components/AppMeta/AppMeta.tsx โ€” What codecity says about itself: which build +// is running, where the source is, and who made it. +// +// Three surfaces show these, in different arrangements: the app header carries +// about, the app footer splits version and credit across its two ends, and the +// project switcher runs all three under the wordmark. One definition each, so +// the wording, the URLs and the link targets cannot drift apart. +// +// Colour is left to the surface (see each one's CSS): the header keeps its link +// at icon weight, the footer lifts it above the prose around it. + +import './AppMeta.css'; +import { SERVER_CONFIG } from '@/state/stores/serverConfig'; +import { REPO_URL, CREATOR_URL } from '@/constants/ui'; + +/** The running build's version, as reported by the server. */ +export function MetaVersion() { + return v{SERVER_CONFIG.value.version}; +} + +/** Outward link to the repo. */ +export function MetaAbout() { + return ( + + about + + ); +} + +/** Authorship, linked to the author's site. */ +export function MetaCredit() { + return ( + + made by ๐Ÿฆ„{' '} + + thalida. + + + ); +} + +/** All three on one line, separated. Used where there's room for the full set. */ +export function MetaLine() { + return ( + + + ยท + + ยท + + + ); +} diff --git a/app/src/layout/AppFooter/AppFooter.css b/app/src/layout/AppFooter/AppFooter.css index 11adb21a..5653b6d8 100644 --- a/app/src/layout/AppFooter/AppFooter.css +++ b/app/src/layout/AppFooter/AppFooter.css @@ -119,21 +119,15 @@ /* โ”€โ”€ Version + credit โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ /* Version sits with the status dot on the left; the credit holds the right. - Both stay a step below the status text so the live state reads first, and - the link brightens like any other. */ -.app-footer-version, -.app-footer-credit { + Both stay a step below the status text so the live state reads first, and the + link sits above the prose around it so it reads as one. Shape comes from + components/AppMeta. */ +#app-footer .meta-version, +#app-footer .meta-credit { color: var(--cc-text-muted); - white-space: nowrap; } -.app-footer-link { +#app-footer .meta-link { color: var(--cc-text-primary); - text-decoration: none; -} -.app-footer-link:hover, -.app-footer-link:focus-visible { - color: var(--cc-text-strong); - text-decoration: underline; } /* โ”€โ”€ Footer responsive narrowing โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ @@ -147,7 +141,7 @@ .app-footer-status-detail { display: none; } - .app-footer-credit { + .meta-credit { display: none; } } diff --git a/app/src/layout/AppFooter/AppFooter.tsx b/app/src/layout/AppFooter/AppFooter.tsx index e0644320..85b311cf 100644 --- a/app/src/layout/AppFooter/AppFooter.tsx +++ b/app/src/layout/AppFooter/AppFooter.tsx @@ -31,7 +31,7 @@ import { import { openDebug } from '@/state/stores/ui'; import { isDebugMode } from '@/utils/debugMode'; import { FooterSep } from './FooterSep'; -import { FooterVersion, FooterCredit } from './FooterMeta'; +import { MetaVersion, MetaCredit } from '@/components/AppMeta/AppMeta'; export interface FooterStatus { /** True when live-poll is active; renders as `live`. False renders as `paused`. */ @@ -156,7 +156,7 @@ export function AppFooter() {

Turn any git repo into a 3D city