UI corrections, and the test page that had served its purpose - #68
Merged
Conversation
… it proved stays The Globe was a destination and it was also the test bed. The question it was built to answer was whether a map library could draw a planet from XYZ tiles, and the answer arrived: MapSurface and DrawMap now open on the same adaptive `globe` projection, so the sphere is on every surface that draws a map rather than on one screen beside them. What the screen kept after that was a fifth place to go, and it is retired. WHAT IS REMOVED IS THE DESTINATION, NOT THE GLOBE. `pages/GlobeScreen.tsx` goes, and with it the `"globe"` member of `AppScreen`, `goGlobe` on the auth context, the `NavGroup` in `lib/navigation.ts`, the `NavItem` in the navigation column, and in App the lazy import, the `screen === "globe"` branch, the `globe` arm of `navigateTo` and the `openFromGlobe` handoff that flew the map to an area pressed on the planet. `components/globe/` STAYS, because it has a second consumer. BoardSurface mounts `GlobeSurface` as the studio's globe editor, registered in `lib/studioEditors.ts`, and that editor is not part of what is being retired. The chunk is still built and is still lazy; the whiteboard is now the only thing that pulls it. `cameraNavigation.tsx` and `SpaceBackdrop.tsx` also stay. Both were written for the globe and both were moved to `components/map/` when the work map took the same projection, which is the move that made this screen redundant in the first place. Nothing was persisted that now names a screen that is gone: `screen` is component state seeded to "map", not a stored preference, so no saved value can point at the removed destination. 263 lines removed across five files, two added. tsc reports no errors, the 289 frontend tests pass, and the production build completes -- the GlobeSurface chunk is 4.74 kB and is now reached only from BoardSurface.
…es the traffic lights Two corrections to the same bar. THE LAYOUT SWITCH WAS INERT UNDER THE STUDIO, not merely redundant. The board draws its own 15rem column and the shell's navigation column fights it for the left edge, so MapScreen pins the layout to workspace for as long as the board is up and restores the previous mode on close. A press on the switch set docked, that effect set workspace back on the same beat, and the outcome was an icon that flickered over a layout that did not move. A control whose only result is to be undone is one to withhold, so it is now gated on `!boardOpen` -- a prop the bar already received and already read for the map telemetry. The way out of the mode is unaffected: closing the board restores the layout by itself, and the board's own toggle stays in the bar through `boardSlotRef`. THE MARK KEEPS A CENTIMETRE CLEAR OF THE WINDOW CONTROLS. The bar reserved `pl-[4.5rem]` for them, which is 72 px, and macOS puts the last of the three traffic lights at almost exactly that -- so the logotype started where the green button ended and read as a fourth control. Now `calc(4.5rem+1cm)`. The unit is deliberate on both halves. The 4.5rem stays a rem because it is the space the platform's own controls occupy, which is theirs to scale. The gap is `1cm` because what is being asked for is a physical distance between two marks a reader sees side by side, and CSS anchors that unit to the reference pixel, so it does not drift if the root size is ever changed. Both values stay unconditional. `onMac` is resolved from the runtime after mount and starts false, so gating either on it would slide the wordmark leftward on every launch. The consequence is unchanged from before this commit: on Windows and Linux, where this bar draws the window controls at its other end, the reserved strip is empty. tsc reports no errors and the 289 frontend tests pass.
…s the icon Two images, and the project has been careful about which is which since the brand landed: the icon is the wordless circle, generated into the .icns and the .ico and drawn by the title bar and the splash, because it is what the operating system shows when it has 32 px to show it in. The mark is the hexagonal badge carrying TERRA and EARTH OBSERVATION, which is what the README opens with and what the LaTeX manual references. The paragraph at the foot of settings is the project speaking about itself as a project, to a reader who might go and look at the repository. That is the mark's job, so the mark goes there, at 40 px, top-aligned so it does not centre itself against a sentence that reflows to two lines and back. COPIED TO public/ RATHER THAN REACHED FOR ACROSS THE REPOSITORY. docs/ is not under the Vite root and serving from it would mean widening server.fs.allow for one image. The icon is already carried twice for exactly this reason -- build/appicon.png and public/terra-logo.png are one file in two places -- so this follows a path the project already takes rather than opening a new one. The copy is byte for byte identical to docs/img/v4/TERRA_EO_Logo.png. alt="" because the badge says TERRA and the sentence beside it says TERRA. A screen reader announcing the name twice reads as two things rather than one: the text carries the meaning and the image is the signature on it.
A year of runs is mostly days without one, so the empty square is what draws the shape of the year. It was drawing nothing at all, and so was the first swatch of the legend under it -- five steps rendering as four. THE VALUE WAS NEVER THE PROBLEM. `bg-line/55` compiled to `background-color: rgb(var(--p-line) / <alpha-value>)`, with the placeholder still in it. That placeholder is Tailwind v3, where the engine substituted it per utility; v4 copies the declared value through and wraps opacity around it with color-mix, so the literal string reached the stylesheet and the parser dropped the rule. An invalid background-color is not a wrong colour, it is no declaration at all, which is why the cells kept the page behind them and why nothing reported it. Fixed here by reaching past the `line` scale to the channels it is built from: `bg-[rgb(var(--p-line))]`, which is the narrow way around the defect. The wide way is to drop <alpha-value> from the ten tokens in index.css that carry it, and that is deliberately NOT this commit: it revives thirteen further utilities across roughly thirty files -- bg-surface and bg-surface-raised among them -- repainting the navigation column, the buttons and the cards in tones that were declared but never once rendered. That is a design pass over the app's surfaces, to be taken on its own terms rather than smuggled in behind a heatmap. The comment on LEVEL_CLASS records both, so the arbitrary value is not mistaken for one that wants simplifying back into a dead utility. TWO VALUES FOR THE IDLE STEP, because the headroom under the first filled step is not the same in both themes. The filled steps are the accent and the accent is already darkened for light, so one alpha lands both; the idle step is the neutral line against the page, and the accent at 45 per cent reaches 2.32 on the dark background but only 2.01 on the light one. A single alpha bright enough to be worth looking at in the dark rises to 94 per cent of the first filled step in the light, which is an idle day reading as busy as a working one. Full line in dark and 75 per cent in light hold it at 79 per cent of the first filled step in both. Contrast against --background, dark then light: idle 1.85 / 1.59 1 run 2.32 / 2.01 2-3 3.24 / 2.69 4-6 4.49 / 3.67 7+ 6.25 / 5.02 Verified in the compiled stylesheet rather than by eye: the two rules are rgb(var(--p-line)) under [data-theme=dark] and color-mix(in oklab, rgb(var(--p-line)) 75%, transparent) at the base.
The field accepted keystrokes and reverted to the stored name. Nothing failed and nothing was reported, because nothing had gone wrong on the way to the database -- the value never got that far. THE LOOP. ProfilePage held one effect doing three jobs, with `goAuth` in its dependency list. `goAuth` was an arrow literal written inside the context value's useMemo in lib/auth.tsx, so it was a different function every time that memo recomputed -- and it recomputes on `runs`, on `projects`, on `prefs`, on `screen`. The effect called `refreshRuns`, which brings a fresh array back across the Wails bridge; `setRuns` therefore always changed identity, the memo recomputed, `goAuth` was new, and the effect ran again. Each pass re-seeded the field from `user.display_name`. The revert was not occasional, it was continuous. TWO REPAIRS, AND NEITHER IS SUFFICIENT ALONE. The plain destinations get one identity for the life of the provider. goMap, goAuth, goAnalysis, goEnergy and goFlood move out of the memo into useCallback with empty dependency lists -- setScreen is a state setter and React guarantees its identity. A consumer is entitled to put a context callback in a dependency array; these could not be put in one. goProfile does not join them: it reads `user` and `screen` to decide where to land and what to record, so its identity properly follows those. The effect becomes three. Redirect when signed out, seed the field, refresh the run list. The seeding one keys on `user?.display_name` -- the string -- rather than on `user`, which is a fresh object after every save. Keyed on the object, uploading an avatar mid-edit would still have discarded a half-typed name, with no loop needed. A stable callback with the three jobs still fused leaves that avatar case standing. Split effects with an unstable callback still spin. Both. The loop was also hammering the database: `refreshRuns` ran continuously for as long as settings was open and now runs once, on mount. The Go side was not at fault and is untouched. UpdateProfile in app_session.go validates nothing that could reject an ordinary name.
The bottom entry of the navigation column read "Settings" beside the user's avatar. The avatar already said whose account it was; the word said what the row did, which the position and the separator above it were saying too. It now carries the display name. Every other entry in the column names a destination and this one names a person, which is the shape the account control takes in the applications this column is modelled on: the row reads as "you", and settings is what you get when you press yourself. Signed out it stays "Sign in", because there is no name to show and the row is an invitation rather than an identity. TRIMMED, AND FALLING BACK TO THE DESTINATION. The name is only guarded at the point of save, not in the database, so a blank one can reach this row -- and a row rendering an empty string beside an avatar is a row with no label at all. NavItem grows an optional `title`, set here to the whole name. The column is 13.5rem and the label span already truncated; a truncated name is a name you cannot read, and the other entries are unaffected because the prop is optional and they do not pass it. The trade is that the word "Settings" is no longer in the column for someone hunting for it. It remains on the title bar's equivalent control, which carries it as a title for the same reason this row now carries a name.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Six corrections to the interface, and the removal of a screen that existed to prove a library.
GlobeSurface— stays and is now the studio's own map.The one that was not what it looked like
The idle squares turned out not to be a colour choice. Chasing it into the compiled stylesheet found
<alpha-value>— Tailwind v3 syntax — reaching the output literally under v4, which does not substitute it. Fourteen utilities across the application were producing invalid CSS the parser dropped in silence.The full correction repainted parts of the interface that had been living with the defect and looked deliberate, so it was reverted in favour of a contained fix that reaches the palette channels directly. The token defect is still there, now documented at the site, and is worth its own change with the visual diff in front of a reader.
Testing
gofmt,go vet, the Go suite under-race,tsc, the frontend suite andcheck:typesall pass. Exercised in the window.golangci-lintis not installed on the machine this was written on, so that part of the repository's gate has not run.