v0.3 Phase 4i: counterlines as interaction-affordance identity
Round-7 redirect (Option D): move counterlines from notices (where
they're invisible) to interactive controls (where they add identity).
Three-level model:
Level 0 no counterline panels, notices (default), content, disabled
Level 1 quiet controls, chips, active nav
1 px, 48% opacity dark / 34% light
Level 2 focus / strong keyboard focus, recording state
2 px, 85% opacity
Notices retire from default counterline rendering. Notice already
carries enough semantic language: bar + icon + border + bg + label.
A complementary inset on top was adding nothing. Notice can opt in
via <LumotiaNotice counterline ... /> when it deliberately mimics
control identity.
Token deltas vs Phase 4h.
--counterline-width: 1px unchanged
--counterline-width-focus: 2px new (Level-2 width)
--counterline-opacity-dark: 0.48 was 0.32 (raised so Level-1
actually reads on controls)
--counterline-opacity-light: 0.34 was 0.22
--counterline-opacity-focus: 0.85 new
--role-brand-counterline: #3A6BFF new (blue counter for the
orange brand accent so
primary buttons get an
identity edge like the
other roles)
--button-{role}-counterline new (per-role component tokens
subscribing to role-counterline
via color-mix)
--focus-ring-color new (defaults to brand accent;
HC overrides to #005FCC)
LumotiaButton applies counterlines to primary + destructive variants
only. Secondary + tertiary stay clean. All variants get a Level-2
focus-visible ring at --focus-ring-color * opacity-focus, with the
existing ring-offset-2 ring-offset-bg pattern.
LumotiaNotice gains a `counterline` boolean prop, default false. When
set, the previous Phase 4h inset shadow re-applies.
HC contract: counterline-width 0 + all -counterline tokens transparent.
Focus width stays 2 px because the HC focus ring IS the tactile
detail in that mode. focus-ring-color forces to #005FCC.
Honest evaluation of the visible result.
Notices: visibly cleaner without the default inset shadow. Reads
with more confidence. Good change.
Buttons: counterline applied at 1 px / 48% dark / 34% light is
perceptible at standard viewing but screenshot-zoom subtle. Focus
state implemented but not visible in static screenshots; requires
manual tab-test in the dev server.
Recommend keeping the architecture even if the visual is restrained,
because the focus-state work is genuinely valuable accessibility
scaffolding regardless of how the Level-1 reads.
Verified.
- npm run check: 0 errors, 0 warnings across 5707 files.
Phase 5c (Dictation layout migration) still queued for a focused
fresh sitting. This commit does not block it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,11 @@
|
||||
/** Slim variant collapses to a single line with no title block.
|
||||
For ambient page-level notices (eg. "You're in browser preview"). */
|
||||
slim?: boolean;
|
||||
/** v0.3 Phase 4i opt-in: render the tactile counterline as an
|
||||
inset shadow. Off by default — notices already carry enough
|
||||
semantic language without the extra decoration. Reserve for
|
||||
cases where the notice deliberately mimics control identity. */
|
||||
counterline?: boolean;
|
||||
children?: Snippet;
|
||||
classes?: string;
|
||||
}
|
||||
@@ -45,6 +50,7 @@
|
||||
dismissible = false,
|
||||
onDismiss,
|
||||
slim = false,
|
||||
counterline = false,
|
||||
children,
|
||||
classes = "",
|
||||
}: Props = $props();
|
||||
@@ -112,7 +118,7 @@
|
||||
role={ariaRole}
|
||||
class="rounded-r-lg rounded-l-sm border border-l-4 text-[13px] flex gap-2.5
|
||||
{slim ? 'px-3 py-2 items-center' : 'px-4 py-3 items-start'}
|
||||
{tonePal.bar} {tonePal.border} {tonePal.bg} {tonePal.shadow} {classes}"
|
||||
{tonePal.bar} {tonePal.border} {tonePal.bg} {counterline ? tonePal.shadow : ''} {classes}"
|
||||
>
|
||||
<ToneIcon size={slim ? 14 : 16} class="shrink-0 {slim ? '' : 'mt-0.5'} {tonePal.iconColor}" aria-hidden="true" />
|
||||
<div class="flex-1 min-w-0 leading-relaxed text-text">
|
||||
|
||||
Reference in New Issue
Block a user