diff --git a/src/ui/styles/layer-finder.css b/src/ui/styles/layer-finder.css
index 865e6b9c4..32a09092f 100644
--- a/src/ui/styles/layer-finder.css
+++ b/src/ui/styles/layer-finder.css
@@ -111,6 +111,19 @@
outline: none;
}
+/* Focus shows on the field's frame, as a soft ring, in place of the hard
+ keyboard outline round the bare input. */
+.layer-finder__field input:focus,
+.layer-finder__field input:focus-visible {
+ outline: none !important;
+ box-shadow: none;
+}
+
+.layer-finder__field:focus-within {
+ border-color: rgba(54, 220, 255, 0.7);
+ box-shadow: 0 0 0 3px rgba(54, 220, 255, 0.1);
+}
+
.layer-finder__chip {
display: inline-flex;
flex: none;
diff --git a/src/ui/styles/layer-section-index.css b/src/ui/styles/layer-section-index.css
index a2695e019..1046f153e 100644
--- a/src/ui/styles/layer-section-index.css
+++ b/src/ui/styles/layer-section-index.css
@@ -60,12 +60,11 @@
outline: none;
}
-/* The group's name, shown to the left (inside the panel) on hover or
- focus. Hidden labels take no room, so nothing reaches past the panel. */
+/* The group's name, drawn on the page just outside the panel's edge while a
+ tick is pointed at or focused, so it covers none of the rows. */
.layer-section-index__label {
- position: absolute;
- top: 50%;
- right: 14px;
+ position: fixed;
+ z-index: 30;
padding: 0.25rem 0.5rem;
color: rgba(236, 244, 248, 0.92);
font-family: var(--font-mono);
@@ -76,21 +75,26 @@
background: rgba(12, 12, 20, 0.88);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 6px;
- display: none;
- opacity: 0;
- transform: translate(4px, -50%);
+ transform: translateY(-50%);
pointer-events: none;
- z-index: 3;
- transition:
- opacity 120ms ease,
- transform 120ms ease;
+ animation: layer-section-index-label 120ms ease both;
}
-.layer-section-index__tick:hover .layer-section-index__label,
-.layer-section-index__tick:focus-visible .layer-section-index__label {
- display: block;
- opacity: 1;
- transform: translate(0, -50%);
+@keyframes layer-section-index-label {
+ from {
+ opacity: 0;
+ translate: -4px 0;
+ }
+ to {
+ opacity: 1;
+ translate: 0 0;
+ }
+}
+
+@media (prefers-reduced-motion: reduce) {
+ .layer-section-index__label {
+ animation: none;
+ }
}
body.mobile-shell .layer-section-index {
diff --git a/src/ui/views/panels/LayerSectionIndex.vue b/src/ui/views/panels/LayerSectionIndex.vue
index 5bf6e394d..79f5b6262 100644
--- a/src/ui/views/panels/LayerSectionIndex.vue
+++ b/src/ui/views/panels/LayerSectionIndex.vue
@@ -32,6 +32,17 @@ function syncCurrent() {
if (scrolls && list.scrollTop + list.clientHeight >= list.scrollHeight - 2) index = sections.value.length - 1;
current.value = Math.max(0, index);
}
+// The name of the tick being pointed at or focused. It is drawn on the page
+// itself, just outside the panel's edge: the panel clips what leaves it, and a
+// label inside would cover the rows.
+const tip = ref(null);
+function showTip(event, section) {
+ const box = event.currentTarget.getBoundingClientRect();
+ tip.value = { label: section.label, left: `${Math.round(box.right + 10)}px`, top: `${Math.round(box.top + box.height / 2)}px` };
+}
+const hideTip = () => {
+ tip.value = null;
+};
function jump(i) {
const h = headings()[i];
if (!h || !list) return;
@@ -67,8 +78,13 @@ onBeforeUnmount(() => {
:aria-label="t('Jump to {name}', { name: section.label })"
:aria-current="section.i === current ? 'true' : undefined"
@click="jump(section.i)"
- >
- {{ section.label }}
-
+ @mouseenter="showTip($event, section)"
+ @mouseleave="hideTip"
+ @focus="showTip($event, section)"
+ @blur="hideTip"
+ >
+
+ {{ tip.label }}
+