fix(gui-v2): WorkspaceSwitcher review nits (Tailwind grid, scoped-CSS trim, a11y button, initials guard)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -52,9 +52,9 @@ function buildDisplay(org: Organisation): WorkspaceDisplay {
|
|||||||
const words = org.name.trim().split(/\s+/)
|
const words = org.name.trim().split(/\s+/)
|
||||||
|
|
||||||
const initials
|
const initials
|
||||||
= words.length >= 2
|
= (words.length >= 2
|
||||||
? (words[0][0] + words[1][0]).toUpperCase()
|
? (words[0][0] + words[1][0]).toUpperCase()
|
||||||
: org.name.slice(0, 2).toUpperCase()
|
: org.name.slice(0, 2).toUpperCase()) || '?'
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: org.id,
|
id: org.id,
|
||||||
@@ -123,7 +123,7 @@ function selectOrg(ws: WorkspaceDisplay): void {
|
|||||||
<!-- Logo square (gradient background is bespoke: dynamic hex pair cannot be a static Tailwind class — RFC §7.4 justified inline-style) -->
|
<!-- Logo square (gradient background is bespoke: dynamic hex pair cannot be a static Tailwind class — RFC §7.4 justified inline-style) -->
|
||||||
<span
|
<span
|
||||||
v-if="current"
|
v-if="current"
|
||||||
class="ws-logo-square flex-shrink-0 rounded-[var(--p-border-radius)] inline-flex items-center justify-center text-white font-bold text-[12px]"
|
class="ws-logo-square w-8 h-8 flex-shrink-0 rounded-[var(--p-border-radius)] inline-flex items-center justify-center text-white font-bold text-[12px]"
|
||||||
:style="{ background: `linear-gradient(135deg, ${current.gradient[0]}, ${current.gradient[1]})` }"
|
:style="{ background: `linear-gradient(135deg, ${current.gradient[0]}, ${current.gradient[1]})` }"
|
||||||
>
|
>
|
||||||
{{ current.initials }}
|
{{ current.initials }}
|
||||||
@@ -167,19 +167,21 @@ function selectOrg(ws: WorkspaceDisplay): void {
|
|||||||
<!-- .pop-ws .list: p-[6px] -->
|
<!-- .pop-ws .list: p-[6px] -->
|
||||||
<div class="min-w-[280px] p-[6px]">
|
<div class="min-w-[280px] p-[6px]">
|
||||||
<!-- .pop-ws .opt: grid 3-col, gap, p, rounded, cursor-pointer -->
|
<!-- .pop-ws .opt: grid 3-col, gap, p, rounded, cursor-pointer -->
|
||||||
<div
|
<!-- TODO TECH-WS-GUI-REDESIGN: full listbox/menu ARIA (role, roving tabindex, arrow-key nav) — tracked -->
|
||||||
|
<button
|
||||||
v-for="ws in allOrgs"
|
v-for="ws in allOrgs"
|
||||||
:key="ws.id"
|
:key="ws.id"
|
||||||
class="grid cursor-pointer items-center gap-[12px] rounded-[var(--p-border-radius)] p-[10px] hover:bg-[var(--p-content-hover-background)]"
|
type="button"
|
||||||
|
class="grid w-full grid-cols-[36px_1fr_auto] cursor-pointer items-center gap-[12px] rounded-[var(--p-border-radius)] border-0 bg-transparent p-[10px] text-start hover:bg-[var(--p-content-hover-background)]"
|
||||||
:class="[
|
:class="[
|
||||||
ws.id === current?.id ? 'bg-[var(--p-primary-50)]' : '',
|
ws.id === current?.id ? 'bg-[var(--p-primary-50)]' : '',
|
||||||
]"
|
]"
|
||||||
style="grid-template-columns: 36px 1fr auto;"
|
:aria-current="current?.id === ws.id ? 'true' : undefined"
|
||||||
@click="selectOrg(ws)"
|
@click="selectOrg(ws)"
|
||||||
>
|
>
|
||||||
<!-- Org logo — larger variant (36px) with dynamic gradient (same inline-style justification as trigger) -->
|
<!-- Org logo — larger variant (36px) with dynamic gradient (same inline-style justification as trigger) -->
|
||||||
<span
|
<span
|
||||||
class="ws-logo-square-lg flex-shrink-0 rounded-[var(--p-border-radius)] inline-flex items-center justify-center text-white font-bold text-[13px]"
|
class="ws-logo-square-lg w-9 h-9 flex-shrink-0 rounded-[var(--p-border-radius)] inline-flex items-center justify-center text-white font-bold text-[13px]"
|
||||||
:style="{ background: `linear-gradient(135deg, ${ws.gradient[0]}, ${ws.gradient[1]})` }"
|
:style="{ background: `linear-gradient(135deg, ${ws.gradient[0]}, ${ws.gradient[1]})` }"
|
||||||
>{{ ws.initials }}</span>
|
>{{ ws.initials }}</span>
|
||||||
|
|
||||||
@@ -203,7 +205,7 @@ function selectOrg(ws: WorkspaceDisplay): void {
|
|||||||
v-else
|
v-else
|
||||||
class="w-[18px]"
|
class="w-[18px]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Footer (.pop-ws .foot: p-[8px], border-top, flex, gap-[4px]) -->
|
<!-- Footer (.pop-ws .foot: p-[8px], border-top, flex, gap-[4px]) -->
|
||||||
@@ -231,26 +233,20 @@ function selectOrg(ws: WorkspaceDisplay): void {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/**
|
/**
|
||||||
* Two layout exceptions that Tailwind cannot express as static utilities:
|
* FIX 2: ws-logo-square — width/height moved to Tailwind (w-8 h-8 on the element).
|
||||||
*
|
* Tailwind has no inset directional box-shadow utility at this granularity →
|
||||||
* 1. ws-logo-square: fixed 32×32px with inset box-shadow.
|
* scoped CSS last resort per RFC §7.4.
|
||||||
* Tailwind has w-8/h-8 but no built-in `box-shadow: inset 0 -2px 0 rgba(0,0,0,0.10)`.
|
|
||||||
* The background gradient is already handled via inline :style (dynamic hex pair).
|
|
||||||
*/
|
*/
|
||||||
.ws-logo-square {
|
.ws-logo-square {
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
box-shadow: inset 0 -2px 0 rgb(0 0 0 / 10%);
|
box-shadow: inset 0 -2px 0 rgb(0 0 0 / 10%);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 2. ws-logo-square-lg: larger 36×36px variant used in the dropdown list.
|
* FIX 2: ws-logo-square-lg — width/height moved to Tailwind (w-9 h-9 on the element).
|
||||||
* Same box-shadow exception as above (inset shadow has no Tailwind equivalent).
|
* Same box-shadow exception as above (inset shadow has no Tailwind equivalent).
|
||||||
* Background gradient set via inline :style on the element (dynamic hex pair).
|
* Background gradient set via inline :style on the element (dynamic hex pair).
|
||||||
*/
|
*/
|
||||||
.ws-logo-square-lg {
|
.ws-logo-square-lg {
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
box-shadow: inset 0 -2px 0 rgb(0 0 0 / 10%);
|
box-shadow: inset 0 -2px 0 rgb(0 0 0 / 10%);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user