Skip to content

Interactive components with no focus styling fall back to the browser's default outline #459

Description

@mathewtaylor

Follow-up to #457 / #458, found while reviewing that fix.

The problem

#457 covered components that remove the focus outline and draw nothing in its place — focus is invisible, a WCAG 2.4.7 failure. This issue is the neighbouring case: components that never style focus at all, so the browser paints its own outline.

That is a different, milder problem. Focus is visible, so it passes WCAG. But it is the user agent's outline, not the theme's — Chrome's blue rectangle sitting next to the themed ring-ring used everywhere else. On a page mixing both, focus appears to change style as you tab.

Spotted on BbCollapsibleTrigger: the docs site's "View Code" toggle renders a blue browser outline while the input above it shows the themed ring.

browser default outline on a collapsible trigger

Neither the Components nor the Primitives layer sets any focus class on it — verified across both.

Affected

25 confirmed, checking Components and Primitives together (a component styled in one layer is not listed):

Disclosure BbCollapsibleTrigger, BbAccordionTrigger
Overlay triggers BbDialogTrigger, BbSheetTrigger, BbPopoverTrigger, BbAlertDialogTrigger, BbDrawerTrigger, BbDrawerClose
Navigation BbBreadcrumbLink, BbCarouselNext, BbCarouselPrevious, BbResponsiveNavItems, BbTablePagination
Inputs / pickers BbColorPicker, BbDateTimePicker, BbRating, BbFileUpload, BbInputGroupAddon
Other BbCopyText, BbThemeSwitcher, BbSidebarRail, BbMarker, BbFormWizard, BbDataTableToolbar, BbDashboardGrid

Suggested fix

Apply the library's ring, matching the split #458 settled on:

  • Standalone controls (triggers, buttons, links) → focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2
  • Controls in tight vertical rhythm (anything with a label directly above) → the same without ring-offset-2, since the form rows leave only a 3px label gap and an offset ring extends 4px

Not a mechanical sweep

Several of these need a judgement call rather than the default treatment, which is why this is separate from #458 rather than folded into it:

  • BbSidebarRail is a thin drag strip — a 2px ring may be most of the control
  • BbCarouselNext/Previous overlay slide content, so ring contrast depends on the image behind them
  • BbMarker and BbRating are small repeated elements where an offset ring will collide with neighbours
  • BbDashboardGrid and BbDataTableToolbar are containers; the focusable thing inside them may be what needs the ring, not the wrapper

Worth doing a few at a time with a visual check, rather than one find-and-replace.

Also worth fixing alongside

demos/BlazorBlueprint.Demo.Shared/Shared/CodeBlock.razor is what shows the outline in the screenshot above. It uses BbCollapsibleTrigger, so fixing the component fixes the docs site for free — no demo-side change needed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggood first issueGood for newcomers

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions