mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
fix: preserve keyboard focus and separate Space activation from voice
Keep focus visible across controls and stable during Contacts, Cockpit and mission roster updates. Preserve native short Space activation, and claim push-to-talk only after a 500 ms hold. Add panel Escape handling and keyboard-accessible attribution controls. Retains the Map Source foundation contributed in https://github.com/bilawalsidhu/gods-eye-view/pull/171.
This commit is contained in:
1 parent
c82fdd7478
commit
5228ab9e40
22 files changed
+3500
-157
No files matched your search
@@ -36,6 +36,39 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Keyboard focus is an app-wide state and must survive selected/active button
|
||||
skins. Individual controls can choose an inset/outset offset, but no local
|
||||
`outline: none` rule may erase the ring. */
|
||||
:where(
|
||||
button,
|
||||
a[href],
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
summary,
|
||||
[tabindex],
|
||||
[role='button'],
|
||||
[role='checkbox'],
|
||||
[role='combobox'],
|
||||
[role='link'],
|
||||
[role='listbox'],
|
||||
[role='menuitem'],
|
||||
[role='menuitemcheckbox'],
|
||||
[role='menuitemradio'],
|
||||
[role='option'],
|
||||
[role='radio'],
|
||||
[role='searchbox'],
|
||||
[role='slider'],
|
||||
[role='spinbutton'],
|
||||
[role='switch'],
|
||||
[role='tab'],
|
||||
[role='textbox'],
|
||||
[role='treeitem']
|
||||
):focus-visible {
|
||||
outline: 2px solid var(--text-primary) !important;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -703,7 +736,10 @@ body.cockpit-mode #cockpit-cloud-effects.active {
|
||||
font-size: 13px;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
transition:
|
||||
background-color var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
color var(--transition-fast);
|
||||
}
|
||||
|
||||
.panel-collapse-btn:hover {
|
||||
@@ -739,11 +775,23 @@ body.cockpit-mode #cockpit-cloud-effects.active {
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
border-radius: var(--btn-radius);
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
/* Keep the keyboard focus outline immediate. */
|
||||
transition:
|
||||
background-color var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
box-shadow var(--transition-fast),
|
||||
color var(--transition-fast),
|
||||
transform var(--transition-fast);
|
||||
overflow: hidden;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Keep keyboard focus visible inside the scrolling preset row. */
|
||||
.style-btn:focus-visible {
|
||||
outline: 2px solid var(--text-primary);
|
||||
outline-offset: -3px;
|
||||
}
|
||||
|
||||
.style-btn::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
@@ -788,7 +836,9 @@ body.cockpit-mode #cockpit-cloud-effects.active {
|
||||
font-size: 20px;
|
||||
line-height: 1;
|
||||
color: var(--text-secondary);
|
||||
transition: all var(--transition-fast);
|
||||
transition:
|
||||
color var(--transition-fast),
|
||||
text-shadow var(--transition-fast);
|
||||
}
|
||||
|
||||
.btn-label {
|
||||
@@ -915,7 +965,12 @@ body.cockpit-mode #cockpit-cloud-effects.active {
|
||||
backdrop-filter: blur(16px);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
transition:
|
||||
background-color var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
box-shadow var(--transition-fast),
|
||||
color var(--transition-fast),
|
||||
border-radius var(--transition-fast);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@@ -1056,10 +1111,6 @@ body.cockpit-mode #cockpit-cloud-effects.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.pp-toggle-group .pp-toggle-btn {
|
||||
transition: all var(--transition-fast), border-radius var(--transition-fast);
|
||||
}
|
||||
|
||||
.pp-toggle-group .pp-slider-row.visible ~ .pp-toggle-btn,
|
||||
.pp-toggle-group:has(.pp-slider-row.visible) .pp-toggle-btn {
|
||||
border-radius: 8px 8px 0 0;
|
||||
@@ -1372,12 +1423,31 @@ body.cockpit-mode #cockpit-cloud-effects.active {
|
||||
letter-spacing: 0.6px;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
transition: background-color var(--transition-fast), color var(--transition-fast);
|
||||
}
|
||||
.pp-mode-btn + .pp-mode-btn { border-left: 1px solid rgba(255, 255, 255, 0.14); }
|
||||
.pp-mode-btn:hover { background: rgba(255, 255, 255, 0.08); color: var(--text-primary); }
|
||||
.pp-mode-btn.active { background: var(--accent); color: #000; }
|
||||
|
||||
/* These controls also move into Cockpit Display; keep focus on the control
|
||||
itself and inside clipped button groups, independent of selection color. */
|
||||
.pp-toggle-btn:focus-visible,
|
||||
.pp-select:focus-visible,
|
||||
.pp-mode-btn:focus-visible {
|
||||
outline: 2px solid var(--text-primary);
|
||||
outline-offset: -3px;
|
||||
}
|
||||
|
||||
.pp-mode-btn:focus-visible {
|
||||
box-shadow: inset 0 0 0 4px #061014;
|
||||
}
|
||||
|
||||
.pp-slider:focus-visible,
|
||||
.param-slider:focus-visible {
|
||||
outline: 2px solid var(--text-primary);
|
||||
outline-offset: 4px;
|
||||
}
|
||||
|
||||
#clean-view-toggle {
|
||||
width: var(--pp-expanded-width);
|
||||
}
|
||||
@@ -1695,7 +1765,12 @@ body.ui-clean-view #scene-runtime.active {
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
transition:
|
||||
background-color var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
box-shadow var(--transition-fast),
|
||||
color var(--transition-fast),
|
||||
transform var(--transition-fast);
|
||||
outline: none;
|
||||
white-space: nowrap;
|
||||
font-family: var(--font-sans);
|
||||
@@ -1705,6 +1780,14 @@ body.ui-clean-view #scene-runtime.active {
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.location-pill:focus-visible,
|
||||
.poi-pill:focus-visible,
|
||||
.search-toggle-btn:focus-visible,
|
||||
#location-search:focus-visible {
|
||||
outline: 2px solid var(--text-primary);
|
||||
outline-offset: -3px;
|
||||
}
|
||||
|
||||
.location-pill:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border-color: var(--glass-border-hover);
|
||||
@@ -1767,7 +1850,12 @@ body.ui-clean-view #scene-runtime.active {
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
transition:
|
||||
background-color var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
box-shadow var(--transition-fast),
|
||||
color var(--transition-fast),
|
||||
transform var(--transition-fast);
|
||||
outline: none;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
@@ -1831,7 +1919,11 @@ body.ui-clean-view #scene-runtime.active {
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
transition:
|
||||
background-color var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
box-shadow var(--transition-fast),
|
||||
color var(--transition-fast);
|
||||
outline: none;
|
||||
font-size: 14px;
|
||||
flex-shrink: 0;
|
||||
@@ -1895,7 +1987,12 @@ body.ui-clean-view #scene-runtime.active {
|
||||
backdrop-filter: blur(16px);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
transition:
|
||||
background-color var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
color var(--transition-fast),
|
||||
opacity var(--transition-fast),
|
||||
transform var(--transition-fast);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@@ -3389,7 +3486,8 @@ body.cockpit-mode #view-switcher button {
|
||||
.cockpit-utility-glyph:focus-visible {
|
||||
border-color: var(--glass-border-hover);
|
||||
color: var(--text-primary);
|
||||
outline: none;
|
||||
outline: 2px solid var(--text-primary);
|
||||
outline-offset: -3px;
|
||||
}
|
||||
.cockpit-utility-popover {
|
||||
position: static;
|
||||
@@ -4766,6 +4864,14 @@ body.cockpit-mode #intel-hud .hud-right-edge { right: 22px; }
|
||||
letter-spacing: .09em;
|
||||
text-align: center;
|
||||
}
|
||||
#space-mission-panel-host .space-mission-roster-focus-continuation {
|
||||
margin: 0;
|
||||
padding: 3px;
|
||||
color: rgba(190, 230, 230, .58);
|
||||
font: 7px/1.4 'JetBrains Mono', monospace;
|
||||
letter-spacing: .08em;
|
||||
text-align: center;
|
||||
}
|
||||
#space-mission-panel .space-mission-view-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -5351,6 +5457,12 @@ body.cockpit-mode #intel-hud .hud-right-edge { right: 22px; }
|
||||
color: #fff;
|
||||
outline: none;
|
||||
}
|
||||
/* Keep focus distinct when the selected tab owns the accent colors. */
|
||||
.context-mode-button:focus-visible {
|
||||
outline: 2px solid var(--text-primary);
|
||||
outline-offset: -3px;
|
||||
}
|
||||
|
||||
.context-mode-button.active {
|
||||
border-color: rgba(0, 212, 255, .75);
|
||||
color: #eaffff;
|
||||
@@ -5849,12 +5961,24 @@ body.cockpit-mode #intel-hud .hud-right-edge { right: 22px; }
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
transition:
|
||||
background-color var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
box-shadow var(--transition-fast),
|
||||
color var(--transition-fast),
|
||||
min-width var(--transition-fast),
|
||||
letter-spacing var(--transition-fast);
|
||||
outline: none;
|
||||
min-width: 38px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* An inset ring stays visible inside the scrolling layer list. */
|
||||
.data-toggle-btn:focus-visible {
|
||||
outline: 2px solid var(--text-primary);
|
||||
outline-offset: -3px;
|
||||
}
|
||||
|
||||
.data-toggle-btn.feed-loading,
|
||||
.data-toggle-btn.feed-degraded,
|
||||
.data-toggle-btn.feed-stale,
|
||||
@@ -5933,7 +6057,11 @@ body.cockpit-mode #intel-hud .hud-right-edge { right: 22px; }
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
transition:
|
||||
background-color var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
color var(--transition-fast),
|
||||
opacity var(--transition-fast);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@@ -6141,6 +6269,11 @@ body.cockpit-mode #intel-hud .hud-right-edge { right: 22px; }
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#cctv-camera-select:focus-visible {
|
||||
outline: 2px solid var(--text-primary);
|
||||
outline-offset: -3px;
|
||||
}
|
||||
|
||||
#cctv-camera-select:disabled {
|
||||
opacity: 0.45;
|
||||
}
|
||||
@@ -6480,7 +6613,11 @@ body.cockpit-mode #intel-hud .hud-right-edge { right: 22px; }
|
||||
letter-spacing: 1.2px;
|
||||
padding: 6px 9px;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
transition:
|
||||
background-color var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
color var(--transition-fast),
|
||||
opacity var(--transition-fast);
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
min-width: 72px;
|
||||
@@ -6574,7 +6711,10 @@ body.cockpit-mode #intel-hud .hud-right-edge { right: 22px; }
|
||||
letter-spacing: 0.8px;
|
||||
padding: 4px 6px;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
transition:
|
||||
background-color var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
color var(--transition-fast);
|
||||
}
|
||||
|
||||
.scene-shot-btn:hover {
|
||||
@@ -7746,6 +7886,26 @@ body:not(.ui-clean-view):not(.recording-mode) #cesium-credits {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#command-dock #location-bar .dock-tray-toggle {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
color: inherit;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
font: inherit;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#command-dock #location-bar .dock-tray-toggle:focus-visible {
|
||||
outline: 2px solid var(--text-primary);
|
||||
outline-offset: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#command-dock #control-panel .dock-tray-toggle {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
@@ -8193,7 +8353,7 @@ body:not(.ui-clean-view):not(.recording-mode):has(#intel-hud[data-variant='minim
|
||||
transform-origin: bottom left;
|
||||
transition:
|
||||
opacity 180ms ease,
|
||||
visibility 180ms ease,
|
||||
visibility 0s linear 180ms,
|
||||
transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
|
||||
}
|
||||
|
||||
@@ -8215,6 +8375,9 @@ body:not(.ui-clean-view):not(.recording-mode):has(#intel-hud[data-variant='minim
|
||||
pointer-events: auto;
|
||||
transform: translateY(0) scale(1);
|
||||
margin-bottom: 10px;
|
||||
/* Make newly revealed controls enter the Tab order immediately. The base
|
||||
rule still delays visibility on close so its opacity fade can finish. */
|
||||
transition-delay: 0s;
|
||||
}
|
||||
|
||||
#command-dock #location-bar.collapsed .dock-popover-content,
|
||||
|
||||
Reference in new issue
Block a user