Skip to content

feat(button): add neutral variant to the button directive - #3853

Open
florent-leborgne wants to merge 1 commit into
mainfrom
flb/neutral-button-variant
Open

feat(button): add neutral variant to the button directive#3853
florent-leborgne wants to merge 1 commit into
mainfrom
flb/neutral-button-variant

Conversation

@florent-leborgne

@florent-leborgne florent-leborgne commented Aug 13, 2026

Copy link
Copy Markdown
Member

Follow-up to the hub pages thread. Martijn asked for a third button type exposed on the button directive, and Fabri described it as a monochrome secondary button.

Problem

The {button} directive offers two variants and both are blue. primary is a filled Elastic blue, secondary is an Elastic blue outline.

When the two sit next to each other, the secondary button competes with the primary for attention. A cluster of peer links has no correct option at all, because every button claims to be a call to action. That is what blocks the hub hero, where several buttons need equal rank.

What this adds

:type: neutral. It keeps the geometry of the existing variants and changes only the color and the weight.

Property Value Token
Border color #868e9a grey-70
Border width 1px border
Text color #1c1e23 ink-dark
Background transparent none
Font weight 500 font-medium
Hover border #1c1e23 ink-dark
Hover background #f6f9fc grey-10
Focus ring #85b7ff blue-elastic-50

Every value comes from theme.css. The change introduces no new tokens.

Height, padding, radius, and font size match primary and secondary exactly, so a neutral button lines up with its neighbors inside a button-group. The focus ring stays Elastic blue, so keyboard focus reads the same across all three variants.

Two deliberate divergences, please review

These are the parts I'd most like a second opinion on, because they depart from _LandingPage.cshtml, which is where the existing two styles came from.

  1. Border width is 1px, against 2px on secondary. A 2px grey border carried too much visual weight for a variant whose job is to recede.
  2. Font weight is 500, against 600 on both existing variants. Same reasoning.

Both keep box-sizing: border-box, so the outer geometry does not change and mixed-variant groups still align.

Accessibility

WCAG 1.4.11 asks for 3:1 contrast on the boundary that identifies a control. grey-70 measures 3.31:1 against white and is the lightest grey token that clears it. grey-60 fails at 2.67:1. Text contrast measures 16.68:1.

Worth flagging for the hub pages stack: the current proof of concept uses grey-20 (1.32:1) and grey-30 (1.63:1) borders. Both fail that threshold and need lifting when they adopt this variant.

Out of scope

  • A second monochrome level, such as an ink-dark bordered lead action. The hero can pair one primary with several neutral buttons instead. Worth revisiting if the all-monochrome hero wins.
  • An orthogonal :tone: property. It doubles the style surface for combinations nobody has asked for yet.
  • Migrating the hub pages CSS onto this class. That belongs in the hub pages stack.
  • Arrow and chevron behavior, which is a separate thread of feedback.

Testing

  • Four new test classes in ButtonTests.cs covering the type, the :variant: alias, rendering inside a button-group, and no diagnostics. dotnet test tests/Elastic.Markdown.Tests/ --filter "FullyQualifiedName~Button" passes 72 tests.
  • npm run build in src/Elastic.Documentation.Site confirms every Tailwind utility resolves to a real token.
  • docs/syntax/buttons.md documents the variant, so the rendered preview of /syntax/buttons exercises it.

🤖 Generated with Claude Code

The button directive offered two variants and both were blue. A
`secondary` button next to a `primary` one competes for attention. A
cluster of peer links had no correct option, because every button
claimed to be a call to action.

Add `:type: neutral`. It keeps the geometry of the existing variants and
changes only the color and the weight. All values come from theme.css,
so the change introduces no new tokens.

The border uses `grey-70`. That is the lightest grey token that clears
the 3:1 non-text contrast ratio in WCAG 1.4.11, at 3.31:1 against white.
`grey-60` fails at 2.67:1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants