Place the Data Layers group label outside the panel and soften the finder's focus

The group label is drawn on the page just outside the panel's edge instead
of over the rows; the panel clips what leaves it, so the label is teleported
to the body and placed from the tick. The finder shows focus as a soft ring
on the field's frame in place of the hard outline round the bare input.

Co-authored-by: Sameh Khamis <[email protected]>
This commit is contained in:
Manjunath PaparajuandSameh Khamis authored and Sameh Khamis committed 2026-11-14 16:12:59 -08:00
1 parent 584e77dc4f
commit 0550f7c2d2
3 files changed
+53 -20

No files matched your search

+13
View File
@@ -111,6 +111,19 @@
outline: none; 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 { .layer-finder__chip {
display: inline-flex; display: inline-flex;
flex: none; flex: none;
+21 -17
View File
@@ -60,12 +60,11 @@
outline: none; outline: none;
} }
/* The group's name, shown to the left (inside the panel) on hover or /* The group's name, drawn on the page just outside the panel's edge while a
focus. Hidden labels take no room, so nothing reaches past the panel. */ tick is pointed at or focused, so it covers none of the rows. */
.layer-section-index__label { .layer-section-index__label {
position: absolute; position: fixed;
top: 50%; z-index: 30;
right: 14px;
padding: 0.25rem 0.5rem; padding: 0.25rem 0.5rem;
color: rgba(236, 244, 248, 0.92); color: rgba(236, 244, 248, 0.92);
font-family: var(--font-mono); font-family: var(--font-mono);
@@ -76,21 +75,26 @@
background: rgba(12, 12, 20, 0.88); background: rgba(12, 12, 20, 0.88);
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 6px; border-radius: 6px;
display: none; transform: translateY(-50%);
opacity: 0;
transform: translate(4px, -50%);
pointer-events: none; pointer-events: none;
z-index: 3; animation: layer-section-index-label 120ms ease both;
transition:
opacity 120ms ease,
transform 120ms ease;
} }
.layer-section-index__tick:hover .layer-section-index__label, @keyframes layer-section-index-label {
.layer-section-index__tick:focus-visible .layer-section-index__label { from {
display: block; opacity: 0;
opacity: 1; translate: -4px 0;
transform: translate(0, -50%); }
to {
opacity: 1;
translate: 0 0;
}
}
@media (prefers-reduced-motion: reduce) {
.layer-section-index__label {
animation: none;
}
} }
body.mobile-shell .layer-section-index { body.mobile-shell .layer-section-index {
+19 -3
View File
@@ -32,6 +32,17 @@ function syncCurrent() {
if (scrolls && list.scrollTop + list.clientHeight >= list.scrollHeight - 2) index = sections.value.length - 1; if (scrolls && list.scrollTop + list.clientHeight >= list.scrollHeight - 2) index = sections.value.length - 1;
current.value = Math.max(0, index); 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) { function jump(i) {
const h = headings()[i]; const h = headings()[i];
if (!h || !list) return; if (!h || !list) return;
@@ -67,8 +78,13 @@ onBeforeUnmount(() => {
:aria-label="t('Jump to {name}', { name: section.label })" :aria-label="t('Jump to {name}', { name: section.label })"
:aria-current="section.i === current ? 'true' : undefined" :aria-current="section.i === current ? 'true' : undefined"
@click="jump(section.i)" @click="jump(section.i)"
> @mouseenter="showTip($event, section)"
<span class="layer-section-index__label" aria-hidden="true">{{ section.label }}</span> @mouseleave="hideTip"
</button> @focus="showTip($event, section)"
@blur="hideTip"
></button>
<Teleport to="body">
<span v-if="tip" class="layer-section-index__label" :style="{ left: tip.left, top: tip.top }" aria-hidden="true">{{ tip.label }}</span>
</Teleport>
</nav> </nav>
</template> </template>