mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
Give the shared-record banner the inline-action row shape
The strip is new this release and had not been checked against the design standards. It carried the shape §11 names as the anti-pattern: a centred flex-wrap row whose gap-y drops the action onto its own line once the name is long enough. The maintainership strip is the sibling that already had an action and already had the right shape, so the two now read the same — sentence on min-w-0 flex-1, way out on shrink-0, beside it rather than under it. The exit control was a 32px tap target. Leaving somebody else's record on a phone is the one interaction in the whole banner stack, and it now carries the standard's floor (min-h-11 sm:min-h-9). The three strips also spell their icon size three ways for identical CSS; they all use size-3.5 now. Text tiers are unchanged and were already right: the person's name is foreground because it is content, the read-only qualifier is muted because it is meta.
This commit is contained in:
1 parent
c12a6873b3
commit
81529a3910
4 files changed
+34
-18
No files matched your search
@@ -97,7 +97,7 @@ export function MaintainershipBanner() {
|
||||
data-testid="maintainership-banner"
|
||||
className="border-border bg-muted/40 text-muted-foreground flex items-start gap-2 border-b px-4 py-2 text-xs sm:items-center"
|
||||
>
|
||||
<Languages className="mt-0.5 h-3.5 w-3.5 shrink-0 sm:mt-0" aria-hidden />
|
||||
<Languages className="mt-0.5 size-3.5 shrink-0 sm:mt-0" aria-hidden />
|
||||
<p className="flex-1 leading-snug">
|
||||
{t("i18n.maintainershipBanner.notice")}{" "}
|
||||
<a
|
||||
@@ -118,7 +118,7 @@ export function MaintainershipBanner() {
|
||||
// the surrounding hit area is what the user actually taps.
|
||||
className="hover:text-foreground focus-visible:ring-ring/50 -mr-2 inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-sm transition-colors focus-visible:ring-2 focus-visible:outline-none"
|
||||
>
|
||||
<X className="h-3.5 w-3.5" aria-hidden />
|
||||
<X className="size-3.5" aria-hidden />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -31,7 +31,7 @@ export function DemoBanner() {
|
||||
data-slot="demo-banner"
|
||||
className="bg-primary/10 border-primary/30 text-foreground flex items-center justify-center gap-2 border-b px-3 py-2 text-xs"
|
||||
>
|
||||
<FlaskConical className="h-3.5 w-3.5 shrink-0" aria-hidden="true" />
|
||||
<FlaskConical className="size-3.5 shrink-0" aria-hidden="true" />
|
||||
<span className="text-center">{t("demoBanner.message")}</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -83,7 +83,7 @@ export function OfflineBanner() {
|
||||
data-slot="offline-banner"
|
||||
className="bg-warning/15 border-warning/40 text-foreground flex items-center justify-center gap-2 border-b px-3 py-2 text-xs"
|
||||
>
|
||||
<WifiOff className="h-3.5 w-3.5 shrink-0" aria-hidden="true" />
|
||||
<WifiOff className="size-3.5 shrink-0" aria-hidden="true" />
|
||||
<span className="text-center">
|
||||
{t("offlineBanner.message")}
|
||||
{hasCachedData ? ` ${t("offlineBanner.showingCached")}` : ""}
|
||||
|
||||
@@ -30,7 +30,18 @@ import { accountLabel } from "@/lib/sharing/account-access-view";
|
||||
*
|
||||
* The name is `text-foreground` and the qualifier `text-muted-foreground`, per
|
||||
* the two-tier text rule — the person's name is content, the read-only note is
|
||||
* meta. Mounted for every authenticated route inside `<AuthShell>` (the
|
||||
* meta.
|
||||
*
|
||||
* The row is the inline-action shape from UI-STANDARDS §11 rather than a
|
||||
* centred wrapping stack: sentence `min-w-0 flex-1`, action `shrink-0`, so the
|
||||
* way out stays beside the sentence instead of dropping onto its own line once
|
||||
* the name is long. `<MaintainershipBanner>` is the sibling that already had an
|
||||
* action and already had this shape; the two now read the same. The tap target
|
||||
* carries the standard's floor (`min-h-11 sm:min-h-9`) — a person leaving
|
||||
* somebody else's record on a phone is the one interaction in the stack, and it
|
||||
* was a 32px target.
|
||||
*
|
||||
* Mounted for every authenticated route inside `<AuthShell>` (the
|
||||
* `<DemoBanner>` pattern) so no page can forget it, and rendered from
|
||||
* `accountAccess.active`, which the server resolves: the banner appears exactly
|
||||
* when the server says the session is inside a record, never on a client guess.
|
||||
@@ -54,25 +65,30 @@ export function SharedRecordBanner() {
|
||||
role="status"
|
||||
data-slot="shared-record-banner"
|
||||
data-account-id={active.accountId}
|
||||
className="bg-warning/15 border-warning/40 flex flex-wrap items-center justify-center gap-x-3 gap-y-1 border-b px-3 py-2 text-xs"
|
||||
className="bg-warning/15 border-warning/40 flex items-start gap-3 border-b px-3 py-2 text-xs sm:items-center"
|
||||
>
|
||||
<Eye className="text-foreground size-3.5 shrink-0" aria-hidden="true" />
|
||||
<span className="text-foreground text-center font-medium">
|
||||
{t("recordSharing.banner.viewing", { name })}
|
||||
</span>
|
||||
{/* Resolved server-side. `canWrite` is false for every grant in v1, and
|
||||
the day it is not, this line stops claiming otherwise on its own. */}
|
||||
{!active.canWrite && (
|
||||
<span className="text-muted-foreground text-center">
|
||||
{t("recordSharing.banner.readOnly")}
|
||||
</span>
|
||||
)}
|
||||
<Eye
|
||||
className="text-foreground mt-0.5 size-3.5 shrink-0 sm:mt-0"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<p className="min-w-0 flex-1 leading-snug">
|
||||
<span className="text-foreground font-medium">
|
||||
{t("recordSharing.banner.viewing", { name })}
|
||||
</span>{" "}
|
||||
{/* Resolved server-side. `canWrite` is false for every grant in v1, and
|
||||
the day it is not, this line stops claiming otherwise on its own. */}
|
||||
{!active.canWrite && (
|
||||
<span className="text-muted-foreground">
|
||||
{t("recordSharing.banner.readOnly")}
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
data-slot="shared-record-banner-exit"
|
||||
onClick={() => switchAccount.mutate(null)}
|
||||
disabled={switchAccount.isPending}
|
||||
className="text-foreground hover:bg-warning/25 focus-visible:ring-ring inline-flex min-h-8 shrink-0 items-center gap-1.5 rounded-md px-2 py-1 font-medium underline underline-offset-2 focus-visible:ring-2 focus-visible:outline-none disabled:opacity-50"
|
||||
className="text-foreground hover:bg-warning/25 focus-visible:ring-ring inline-flex min-h-11 shrink-0 items-center gap-1.5 rounded-md px-2 py-1 font-medium underline underline-offset-2 focus-visible:ring-2 focus-visible:outline-none disabled:opacity-50 sm:min-h-9"
|
||||
>
|
||||
{switchAccount.isPending ? (
|
||||
<Loader2
|
||||
|
||||
Reference in new issue
Block a user