-
Notifications
You must be signed in to change notification settings - Fork 0
fix: give the token gate some CSS, since it shipped with none #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
35a343a
b2c10c3
c2a82f2
e857541
9a9d8a6
e0ca6df
82238ba
b5d1d9b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -547,3 +547,161 @@ | |
| .hw-nav-item.hw-nav-unavailable:hover { | ||
| opacity: 0.6; | ||
| } | ||
|
|
||
| /* === AUTH GATE === */ | ||
|
|
||
| /* The token prompt is the first thing a v2 install shows anyone, and it | ||
| shipped with no rules at all: a bare heading, an unstyled input and a | ||
| default browser button, rendered in page flow underneath the sidebar and | ||
| clipped off the viewport. It is a gate, not a panel, so it covers the app | ||
| instead of sitting inside it. */ | ||
| .hw-auth-prompt { | ||
| position: fixed; | ||
| inset: 0; | ||
|
Comment on lines
+559
to
+560
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a signed-out keyboard user tabs past the token input and Retry button, focus proceeds to the sidebar or mobile navigation even though this fixed overlay visually covers those controls. The user is then operating concealed links, and activating one can invoke the already-bound hash router while authentication is still pending; make the rest of the app inert or trap focus within the prompt until it closes. Useful? React with 👍 / 👎.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The gate's siblings (sidebar, content, mobile nav) now go inert while the prompt is visible and recover on close, and auth.js gets a new cache key. Verified in the running app: a simulated tab walk from the token input cycles only between the input and Retry. Fixed in HEAD. |
||
| /* Above every layout layer: the sidebar and mobile nav both sit at 100, | ||
| and the mobile nav follows the gate in the DOM, so an equal level would | ||
| paint tappable navigation on top of a signed-out screen. */ | ||
| z-index: 200; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| padding: var(--hw-space-md); | ||
| background: var(--hw-bg-primary); | ||
| background: color-mix(in srgb, var(--hw-bg-primary) 92%, transparent); | ||
| } | ||
|
|
||
| /* display:flex above beats the hidden attribute's UA display:none, so without | ||
| this the gate is drawn permanently and nothing behind it is reachable. */ | ||
| .hw-auth-prompt[hidden] { | ||
| display: none; | ||
| } | ||
|
|
||
| .hw-auth-prompt form { | ||
| width: 100%; | ||
| max-width: 24rem; | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: var(--hw-space-md); | ||
| padding: var(--hw-space-lg); | ||
| /* bg-card only exists in the light and terminal themes. Without the | ||
| fallback the default theme resolves it to nothing and the card loses its | ||
| background entirely against the overlay behind it. */ | ||
| background: var(--hw-bg-card, var(--hw-bg-secondary)); | ||
| border: 1px solid var(--hw-border-color); | ||
| border-radius: var(--hw-border-radius-md); | ||
| box-shadow: var(--hw-shadow-card); | ||
| } | ||
|
|
||
| .hw-auth-prompt h2 { | ||
| margin: 0; | ||
| font-family: var(--hw-font-display); | ||
| font-size: var(--hw-font-size-lg); | ||
| font-weight: 500; | ||
| /* 19.2px at weight 500 is not WCAG large text, and the light theme's | ||
| accent blue only reaches 3.7:1 there, so themes may override. */ | ||
| color: var(--hw-auth-heading, var(--hw-accent-primary)); | ||
| } | ||
|
|
||
| .hw-auth-prompt label { | ||
| font-family: var(--hw-font-display); | ||
| font-size: var(--hw-font-size-xs); | ||
| letter-spacing: 0.08em; | ||
| text-transform: uppercase; | ||
| /* Small uppercase text needs 4.5:1, and the tertiary tone misses that in | ||
| every theme. The credential field's name is not decoration. */ | ||
| color: var(--hw-text-secondary); | ||
| margin-bottom: calc(-1 * var(--hw-space-sm)); | ||
| } | ||
|
|
||
| .hw-auth-prompt input { | ||
| width: 100%; | ||
| box-sizing: border-box; | ||
| font-family: var(--hw-font-display); | ||
| font-size: var(--hw-font-size-md); | ||
| padding: var(--hw-space-sm) var(--hw-space-md); | ||
| background: var(--hw-bg-primary); | ||
| /* The stock border tone sits under 1.7:1 on the input fill in every | ||
| theme, and a control a signed-out user cannot find is a locked door. | ||
| The secondary text tone clears the 3:1 non-text floor everywhere. */ | ||
| border: 1px solid var(--hw-auth-input-border, var(--hw-text-secondary)); | ||
| border-radius: var(--hw-border-radius-sm); | ||
| color: var(--hw-text-primary); | ||
| transition: border-color var(--hw-transition-fast); | ||
| } | ||
|
|
||
| .hw-auth-prompt input:focus { | ||
| outline: none; | ||
| border-color: var(--hw-accent-primary); | ||
| } | ||
|
|
||
| /* Outlined rather than filled, and measured rather than assumed. A filled | ||
| accent button is unreadable in the light theme: accent #3b82f6 behind | ||
| bg-primary #f5f3ef is 3.32:1, under the 4.5:1 AA floor. --hw-accent-primary-dim | ||
| is worse, since neither alternate theme redefines it and both inherit the | ||
| base theme's dark olive. Body text on the card is the one pairing every | ||
| theme has to keep readable, and it measures 14.94 / 13.82 / 14.50 across | ||
| default, light and terminal. The accent carries the emphasis as a border, | ||
| where contrast against text does not matter. */ | ||
| .hw-auth-prompt button { | ||
| font-family: var(--hw-font-display); | ||
| font-size: var(--hw-font-size-sm); | ||
| padding: var(--hw-space-sm) var(--hw-space-md); | ||
| background: transparent; | ||
| border: 1px solid var(--hw-accent-primary); | ||
| border-radius: var(--hw-border-radius-sm); | ||
| color: var(--hw-text-primary); | ||
| cursor: pointer; | ||
| transition: background-color var(--hw-transition-fast); | ||
| } | ||
|
|
||
| .hw-auth-prompt button:hover { | ||
| background: var(--hw-bg-hover); | ||
| } | ||
|
|
||
| .hw-auth-prompt button:focus-visible { | ||
| outline: 2px solid var(--hw-accent-primary); | ||
| outline-offset: 2px; | ||
| } | ||
|
|
||
| /* role="alert" with no styling reads as body copy, which is the one thing an | ||
| error must not do. */ | ||
| .hw-auth-prompt #auth-error { | ||
| margin: 0; | ||
| font-size: var(--hw-font-size-sm); | ||
| color: var(--hw-auth-error, var(--hw-status-critical)); | ||
| } | ||
|
|
||
| .hw-auth-prompt #auth-error[hidden] { | ||
| display: none; | ||
| } | ||
|
|
||
| /* === AUTH STATUS (sidebar) === */ | ||
|
|
||
| .hw-auth-status { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| gap: var(--hw-space-sm); | ||
| padding: var(--hw-space-sm) var(--hw-space-md); | ||
| font-size: var(--hw-font-size-xs); | ||
| /* Status and logout are meaningful labels, and the tertiary tone fails | ||
| 4.5:1 on every sidebar. */ | ||
| color: var(--hw-text-secondary); | ||
| } | ||
|
|
||
| .hw-auth-status button { | ||
| font-family: var(--hw-font-display); | ||
| font-size: var(--hw-font-size-xs); | ||
| padding: var(--hw-space-xs) var(--hw-space-sm); | ||
| background: transparent; | ||
| border: 1px solid var(--hw-border-color); | ||
| border-radius: var(--hw-border-radius-sm); | ||
| color: var(--hw-text-secondary); | ||
| cursor: pointer; | ||
| transition: all var(--hw-transition-fast); | ||
| } | ||
|
|
||
| .hw-auth-status button:hover { | ||
| border-color: var(--hw-accent-primary); | ||
| color: var(--hw-text-primary); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -89,10 +89,34 @@ HumWatch.auth._setState = function(label) { | |
| if (state) state.textContent = label; | ||
| }; | ||
|
|
||
| // Every path that starts the dashboard goes through this, because a gate left | ||
| // visible after authentication succeeds now takes the inert app down with it. | ||
| HumWatch.auth.closePrompt = function() { | ||
| HumWatch.auth._promptOpen = false; | ||
| HumWatch.auth._cancelRetry(); | ||
| HumWatch.auth._setPromptVisible(false); | ||
| }; | ||
|
Comment on lines
+94
to
+98
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an automatic retry succeeds after Useful? React with 👍 / 👎.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. _setPromptVisible now resets the error text and hidden state whenever the prompt shows. Both writers (the rate-limit notice and the submit failure) run after that reset, verified live: rate-limit message shows, gate closes on success, and the reopened prompt is clean. Fixed in HEAD. |
||
|
|
||
| HumWatch.auth._setPromptVisible = function(visible) { | ||
| var prompt = document.getElementById('auth-prompt'); | ||
| if (prompt) prompt.hidden = !visible; | ||
| if (prompt) { | ||
| prompt.hidden = !visible; | ||
| // The gate paints above the app, but tab order ignores paint order: | ||
| // without this, focus walks into the concealed sidebar and nav, where | ||
| // Enter drives the hash router while authentication is still pending. | ||
| var siblings = prompt.parentElement ? prompt.parentElement.children : []; | ||
| for (var i = 0; i < siblings.length; i++) { | ||
| if (siblings[i] !== prompt) siblings[i].inert = visible; | ||
| } | ||
|
Comment on lines
+107
to
+110
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the startup probe hits the authentication-failure 429 limit, Useful? React with 👍 / 👎.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. _startProtectedDashboard now runs HumWatch.auth.closePrompt(), which hides the gate, clears the inert siblings, and cancels any pending retry. Verified live: handleRateLimited then a successful start leaves the gate hidden and all three siblings interactive. Fixed in HEAD. |
||
| } | ||
| if (visible) { | ||
| // A reopened prompt starts clean. handleRateLimited sets its message | ||
| // after this call, so the retry notice still shows when it applies. | ||
| var error = document.getElementById('auth-error'); | ||
| if (error) { | ||
| error.textContent = ''; | ||
| error.hidden = true; | ||
| } | ||
| var input = document.getElementById('auth-token'); | ||
| if (input) { | ||
| input.value = ''; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On upgrades where a browser has cached
/css/components.css?v=1.0.0or/js/app.js?v=1.0.0, this commit keeps those same URLs instatic/index.html, so the browser can reuse the previous files. That leaves the token gate unstyled—the regression this patch is intended to fix—and can leave the newly emptied version label blank because the cached app script lacksshowAgentVersion; change the query versions for both modified assets.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both changed assets now load as ?v=2.0.3 and the pinned components.css digest is updated. Fixed in b2c10c3.