Skip to content

fix: fix focus-ring style in vaadin 24/25#28

Open
javier-godoy wants to merge 1 commit intomasterfrom
focus-ring
Open

fix: fix focus-ring style in vaadin 24/25#28
javier-godoy wants to merge 1 commit intomasterfrom
focus-ring

Conversation

@javier-godoy
Copy link
Member

@javier-godoy javier-godoy commented Mar 2, 2026

Summary by CodeRabbit

  • Style
    • Improved keyboard focus indicators for tabs to make navigation clearer and more consistent.
    • Refined focus-ring visuals (shape, spacing and inset rendering) for tab buttons to improve accessibility and visual polish.
    • Adjusted tab padding/margins to better align focus states and overall spacing.

@coderabbitai
Copy link

coderabbitai bot commented Mar 2, 2026

Walkthrough

Adds CSS rules to fc-enhanced-tabs: defines a focus-ring width variable, computes padding/margin for vaadin-tab inside vaadin-menu-bar-button based on a Lumo flag, and implements focus-visible styling using an inset box-shadow focus ring with resolved border-radius.

Changes

Cohort / File(s) Summary
fc-enhanced-tabs CSS
src/main/resources/META-INF/frontend/fcEnhancedTabs/fc-enhanced-tabs.css
Introduces --fc-enhanced-tabs-focus-ring-width, dynamic padding/margin calculations for vaadin-tab within vaadin-menu-bar-button[theme~='fc-enhanced-tabs'] driven by a _lumo-flag; removes default outline and applies :focus-visible inset box-shadow focus ring using Lumo/vaadin radius tokens; extends button rule set with a focus-ring context.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • chore: add aura styles #26 — Modifies the same fc-enhanced-tabs CSS targeting vaadin-menu-bar-button / vaadin-menu-bar-item and overlapped button/overflow styling.

Suggested reviewers

  • mlopezFC
  • paodb
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: fixing focus-ring styling for Vaadin 24/25 compatibility, which aligns with the CSS modifications shown in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch focus-ring

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/resources/META-INF/frontend/fcEnhancedTabs/fc-enhanced-tabs.css`:
- Around line 129-136: The CSS removes the native outline on
vaadin-menu-bar-button[theme~='fc-enhanced-tabs'][focus-ring] and relies on
box-shadow which can disappear in forced-colors/high-contrast mode; restore an
accessible visible focus by adding a forced-colors fallback: wrap a rule in
`@media` (forced-colors: active) targeting
vaadin-menu-bar-button[theme~='fc-enhanced-tabs'][focus-ring],
vaadin-menu-bar-button[theme~='fc-enhanced-tabs']:focus-visible and set an
explicit outline (e.g. outline: 2px solid Highlight or outline: 2px solid
CanvasText) and outline-offset to match the intended ring, or conditionally keep
outline: none only outside forced-colors so the native/high-contrast outline
remains available; update the selectors in the existing block (the
vaadin-menu-bar-button[theme~='fc-enhanced-tabs'] rules and inner
vaadin-menu-bar-item shadow styles) accordingly.
- Around line 109-125: The calc() expressions for padding-block, padding-inline,
margin-block, and margin-inline violate stylelint operator/spacing and have
extraneous blank lines; reformat each declaration so binary operators (+, -, *)
are on the same line as their operands with single spaces around them (or
collapse the entire calc() to a single line) and remove the empty line before
the padding-inline and margin-block declarations so there are no blank lines
between consecutive property declarations; update the padding-block,
padding-inline, margin-block, and margin-inline declarations accordingly to
satisfy stylelint.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2536f5c and 5d23979.

📒 Files selected for processing (1)
  • src/main/resources/META-INF/frontend/fcEnhancedTabs/fc-enhanced-tabs.css

Comment on lines 109 to 125
padding-block: calc(
(var(--_lumo-flag) * 0.5rem) +
((1 - var(--_lumo-flag)) * (var(--vaadin-padding-block-container, calc(0.5rem + var(--focus-ring-width))) - var(--focus-ring-width)))
);

padding-inline: calc(
(var(--_lumo-flag) * 0.5rem) +
((1 - var(--_lumo-flag)) * (var(--vaadin-padding-inline-container, calc(0.5rem + var(--focus-ring-width))) - var(--focus-ring-width)))
);

margin-block: calc(
(1 - var(--_lumo-flag)) * max(0px, var(--focus-ring-width) + var(--vaadin-padding-block-container, -9999px) - var(--vaadin-padding-block-container, 0px))
);

margin-inline: calc(
(1 - var(--_lumo-flag)) * max(0px, var(--focus-ring-width) + var(--vaadin-padding-inline-container, -9999px) - var(--vaadin-padding-inline-container, 0px))
);
Copy link

@coderabbitai coderabbitai bot Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix calc/operator formatting to pass stylelint.

This block currently violates stylelint rules (operator newline/spacing and empty lines before declarations), which can block CI.

💡 Suggested formatting fix
   padding-block: calc(
-    (var(--_lumo-flag) * 0.5rem) + 
+    (var(--_lumo-flag) * 0.5rem) +
     ((1 - var(--_lumo-flag)) * (var(--vaadin-padding-block-container, calc(0.5rem + var(--focus-ring-width))) - var(--focus-ring-width)))
   );
-
   padding-inline: calc(
-    (var(--_lumo-flag) * 0.5rem) + 
+    (var(--_lumo-flag) * 0.5rem) +
     ((1 - var(--_lumo-flag)) * (var(--vaadin-padding-inline-container, calc(0.5rem + var(--focus-ring-width))) - var(--focus-ring-width)))
   );
-  
   margin-block: calc(
     (1 - var(--_lumo-flag)) * max(0px, var(--focus-ring-width) + var(--vaadin-padding-block-container, -9999px) - var(--vaadin-padding-block-container, 0px))
   );
-  
   margin-inline: calc(
     (1 - var(--_lumo-flag)) * max(0px, var(--focus-ring-width) + var(--vaadin-padding-inline-container, -9999px) - var(--vaadin-padding-inline-container, 0px))
   );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
padding-block: calc(
(var(--_lumo-flag) * 0.5rem) +
((1 - var(--_lumo-flag)) * (var(--vaadin-padding-block-container, calc(0.5rem + var(--focus-ring-width))) - var(--focus-ring-width)))
);
padding-inline: calc(
(var(--_lumo-flag) * 0.5rem) +
((1 - var(--_lumo-flag)) * (var(--vaadin-padding-inline-container, calc(0.5rem + var(--focus-ring-width))) - var(--focus-ring-width)))
);
margin-block: calc(
(1 - var(--_lumo-flag)) * max(0px, var(--focus-ring-width) + var(--vaadin-padding-block-container, -9999px) - var(--vaadin-padding-block-container, 0px))
);
margin-inline: calc(
(1 - var(--_lumo-flag)) * max(0px, var(--focus-ring-width) + var(--vaadin-padding-inline-container, -9999px) - var(--vaadin-padding-inline-container, 0px))
);
padding-block: calc(
(var(--_lumo-flag) * 0.5rem) +
((1 - var(--_lumo-flag)) * (var(--vaadin-padding-block-container, calc(0.5rem + var(--focus-ring-width))) - var(--focus-ring-width)))
);
padding-inline: calc(
(var(--_lumo-flag) * 0.5rem) +
((1 - var(--_lumo-flag)) * (var(--vaadin-padding-inline-container, calc(0.5rem + var(--focus-ring-width))) - var(--focus-ring-width)))
);
margin-block: calc(
(1 - var(--_lumo-flag)) * max(0px, var(--focus-ring-width) + var(--vaadin-padding-block-container, -9999px) - var(--vaadin-padding-block-container, 0px))
);
margin-inline: calc(
(1 - var(--_lumo-flag)) * max(0px, var(--focus-ring-width) + var(--vaadin-padding-inline-container, -9999px) - var(--vaadin-padding-inline-container, 0px))
);
🧰 Tools
🪛 Stylelint (17.3.0)

[error] 110-110: Unexpected newline after "+" (scss/operator-no-newline-after)

(scss/operator-no-newline-after)


[error] 115-115: Unexpected newline after "+" (scss/operator-no-newline-after)

(scss/operator-no-newline-after)


[error] 114-117: Unexpected empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)


[error] 119-121: Unexpected empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)


[error] 123-125: Unexpected empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)


[error] 110-110: Expected single space after "+" operator (function-calc-no-unspaced-operator)

(function-calc-no-unspaced-operator)


[error] 115-115: Expected single space after "+" operator (function-calc-no-unspaced-operator)

(function-calc-no-unspaced-operator)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/resources/META-INF/frontend/fcEnhancedTabs/fc-enhanced-tabs.css`
around lines 109 - 125, The calc() expressions for padding-block,
padding-inline, margin-block, and margin-inline violate stylelint
operator/spacing and have extraneous blank lines; reformat each declaration so
binary operators (+, -, *) are on the same line as their operands with single
spaces around them (or collapse the entire calc() to a single line) and remove
the empty line before the padding-inline and margin-block declarations so there
are no blank lines between consecutive property declarations; update the
padding-block, padding-inline, margin-block, and margin-inline declarations
accordingly to satisfy stylelint.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what CodeRabbit reported, but the submitted code follows the current formatting conventions.

image

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@javier-godoy, understood! Maintaining consistency with the existing formatting conventions in your codebase makes sense. If the stylelint rules don't align with your project's style, you could consider updating the .stylelintrc configuration to match your conventions (e.g., adjusting declaration-empty-line-before, scss/operator-no-newline-after, and function-calc-no-unspaced-operator rules), or disabling those specific rules for this file or project if they're not adding value.


✏️ Learnings added
Learnt from: javier-godoy
Repo: FlowingCode/EnhancedTabs PR: 28
File: src/main/resources/META-INF/frontend/fcEnhancedTabs/fc-enhanced-tabs.css:109-125
Timestamp: 2026-03-02T17:42:29.796Z
Learning: In the FlowingCode/EnhancedTabs repository, CSS formatting conventions allow newlines after operators in calc() expressions and empty lines between declaration blocks, even if this conflicts with default stylelint rules.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment on lines +129 to +136
vaadin-menu-bar-button[theme~='fc-enhanced-tabs'][focus-ring],
vaadin-menu-bar-button[theme~='fc-enhanced-tabs']:focus-visible {
outline: none;
vaadin-menu-bar-item {
box-shadow: inset 0 0 0 var(--focus-ring-width) var(--vaadin-focus-ring-color, var(--lumo-primary-color-50pct));
border-radius: var(--lumo-border-radius-m, var(--vaadin-tab-border-radius, var(--vaadin-radius-m)));
}
}
Copy link

@coderabbitai coderabbitai bot Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Keep visible focus in forced-colors mode.

Line 131 removes outline and relies on box-shadow; in forced-colors/high-contrast contexts, that ring may not render reliably, causing keyboard focus loss.

♿ Suggested accessibility fallback
 vaadin-menu-bar-button[theme~='fc-enhanced-tabs'][focus-ring],
 vaadin-menu-bar-button[theme~='fc-enhanced-tabs']:focus-visible {
   outline: none;
   vaadin-menu-bar-item {
     box-shadow: inset 0 0 0 var(--focus-ring-width) var(--vaadin-focus-ring-color, var(--lumo-primary-color-50pct));
     border-radius: var(--lumo-border-radius-m, var(--vaadin-tab-border-radius, var(--vaadin-radius-m)));
   }
 }
+
+@media (forced-colors: active) {
+  vaadin-menu-bar-button[theme~='fc-enhanced-tabs'][focus-ring],
+  vaadin-menu-bar-button[theme~='fc-enhanced-tabs']:focus-visible {
+    outline: 2px solid CanvasText;
+    outline-offset: 2px;
+  }
+
+  vaadin-menu-bar-button[theme~='fc-enhanced-tabs'][focus-ring] vaadin-menu-bar-item,
+  vaadin-menu-bar-button[theme~='fc-enhanced-tabs']:focus-visible vaadin-menu-bar-item {
+    box-shadow: none;
+  }
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/resources/META-INF/frontend/fcEnhancedTabs/fc-enhanced-tabs.css`
around lines 129 - 136, The CSS removes the native outline on
vaadin-menu-bar-button[theme~='fc-enhanced-tabs'][focus-ring] and relies on
box-shadow which can disappear in forced-colors/high-contrast mode; restore an
accessible visible focus by adding a forced-colors fallback: wrap a rule in
`@media` (forced-colors: active) targeting
vaadin-menu-bar-button[theme~='fc-enhanced-tabs'][focus-ring],
vaadin-menu-bar-button[theme~='fc-enhanced-tabs']:focus-visible and set an
explicit outline (e.g. outline: 2px solid Highlight or outline: 2px solid
CanvasText) and outline-offset to match the intended ring, or conditionally keep
outline: none only outside forced-colors so the native/high-contrast outline
remains available; update the selectors in the existing block (the
vaadin-menu-bar-button[theme~='fc-enhanced-tabs'] rules and inner
vaadin-menu-bar-item shadow styles) accordingly.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai Please create an issue about it.

Component has never rendered reliably in forced-colors mode.
image

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Create a GitHub issue for forced-colors mode accessibility concern

gh issue create \
  --title "Improve forced-colors mode accessibility for focus indicators" \
  --body "## Description

The EnhancedTabs component does not render reliably in forced-colors (high-contrast) mode. The current focus ring implementation relies on \`box-shadow\` which may not be visible in forced-colors contexts, potentially causing keyboard focus to be invisible to users who rely on high-contrast settings.

## Context

This issue was identified during review of PR `#28`, which addresses focus-ring styles for Vaadin 24/25.

**Related PR:** https://github.com/FlowingCode/EnhancedTabs/pull/28
**Related comment:** https://github.com/FlowingCode/EnhancedTabs/pull/28#discussion_r2872100914

## Expected Behavior

Focus indicators should remain visible and accessible in forced-colors/high-contrast mode to ensure keyboard navigation remains usable for all users.

## Current Behavior

The component has rendering issues in forced-colors mode, including focus indicators that may not be visible.

---
Reported by: `@javier-godoy`" \
  --assignee javier-godoy

Length of output: 53


@javier-godoy, I've created issue #29 to track the forced-colors mode accessibility improvements. The issue captures the rendering concerns shown in your screenshot and will allow this to be addressed separately from the current focus-ring fixes in this PR.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 2, 2026

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
src/main/resources/META-INF/frontend/fcEnhancedTabs/fc-enhanced-tabs.css (2)

129-136: ⚠️ Potential issue | 🟠 Major

Add a forced-colors focus fallback.

Removing outline and relying only on box-shadow risks invisible keyboard focus in high-contrast/forced-colors mode.

♿ Suggested accessibility fallback
 vaadin-menu-bar-button[theme~='fc-enhanced-tabs'][focus-ring],
 vaadin-menu-bar-button[theme~='fc-enhanced-tabs']:focus-visible {
   outline: none;
   vaadin-menu-bar-item {
     box-shadow: inset 0 0 0 var(--focus-ring-width) var(--vaadin-focus-ring-color, var(--lumo-primary-color-50pct));
     border-radius: var(--lumo-border-radius-m, var(--vaadin-tab-border-radius, var(--vaadin-radius-m)));
   }
 }
+
+@media (forced-colors: active) {
+  vaadin-menu-bar-button[theme~='fc-enhanced-tabs'][focus-ring],
+  vaadin-menu-bar-button[theme~='fc-enhanced-tabs']:focus-visible {
+    outline: 2px solid CanvasText;
+    outline-offset: 2px;
+  }
+
+  vaadin-menu-bar-button[theme~='fc-enhanced-tabs'][focus-ring] vaadin-menu-bar-item,
+  vaadin-menu-bar-button[theme~='fc-enhanced-tabs']:focus-visible vaadin-menu-bar-item {
+    box-shadow: none;
+  }
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/resources/META-INF/frontend/fcEnhancedTabs/fc-enhanced-tabs.css`
around lines 129 - 136, The focus styling removes outline and relies on
box-shadow which can disappear in forced-colors/high-contrast modes; add a
forced-colors fallback by targeting the same selector
(vaadin-menu-bar-button[theme~='fc-enhanced-tabs'] and its :focus-visible)
inside an `@media` (forced-colors: active) block and restore an accessible visible
focus (e.g., apply a system-safe outline like outline: 2px solid Highlight with
an outline-offset or use forced-colors-aware system color values) so keyboard
focus remains visible in high-contrast modes while keeping the current
box-shadow for normal themes.

109-125: ⚠️ Potential issue | 🟡 Minor

Reformat calc() blocks to satisfy stylelint.

The current line breaks/blank lines in these declarations still match the reported lint violations and may fail CI.

💡 Suggested formatting fix
   padding-block: calc(
-    (var(--_lumo-flag) * 0.5rem) +
+    (var(--_lumo-flag) * 0.5rem) +
     ((1 - var(--_lumo-flag)) * (var(--vaadin-padding-block-container, calc(0.5rem + var(--focus-ring-width))) - var(--focus-ring-width)))
   );
-
   padding-inline: calc(
-    (var(--_lumo-flag) * 0.5rem) +
+    (var(--_lumo-flag) * 0.5rem) +
     ((1 - var(--_lumo-flag)) * (var(--vaadin-padding-inline-container, calc(0.5rem + var(--focus-ring-width))) - var(--focus-ring-width)))
   );
-  
   margin-block: calc(
     (1 - var(--_lumo-flag)) * max(0px, var(--focus-ring-width) + var(--vaadin-padding-block-container, -9999px) - var(--vaadin-padding-block-container, 0px))
   );
-  
   margin-inline: calc(
     (1 - var(--_lumo-flag)) * max(0px, var(--focus-ring-width) + var(--vaadin-padding-inline-container, -9999px) - var(--vaadin-padding-inline-container, 0px))
   );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/resources/META-INF/frontend/fcEnhancedTabs/fc-enhanced-tabs.css`
around lines 109 - 125, Reformat the multi-line calc() declarations for
padding-block, padding-inline, margin-block and margin-inline so they follow
stylelint's expected single-expression formatting (remove extra blank lines and
unnecessary line breaks inside each calc), preserving the same math and CSS
variables (e.g., --_lumo-flag, --vaadin-padding-block-container,
--focus-ring-width, --vaadin-padding-inline-container) and keep the arithmetic
and max(...) expressions intact; update the calc() blocks for padding-block,
padding-inline, margin-block and margin-inline to be compact and consistently
formatted to satisfy the linter.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/main/resources/META-INF/frontend/fcEnhancedTabs/fc-enhanced-tabs.css`:
- Around line 129-136: The focus styling removes outline and relies on
box-shadow which can disappear in forced-colors/high-contrast modes; add a
forced-colors fallback by targeting the same selector
(vaadin-menu-bar-button[theme~='fc-enhanced-tabs'] and its :focus-visible)
inside an `@media` (forced-colors: active) block and restore an accessible visible
focus (e.g., apply a system-safe outline like outline: 2px solid Highlight with
an outline-offset or use forced-colors-aware system color values) so keyboard
focus remains visible in high-contrast modes while keeping the current
box-shadow for normal themes.
- Around line 109-125: Reformat the multi-line calc() declarations for
padding-block, padding-inline, margin-block and margin-inline so they follow
stylelint's expected single-expression formatting (remove extra blank lines and
unnecessary line breaks inside each calc), preserving the same math and CSS
variables (e.g., --_lumo-flag, --vaadin-padding-block-container,
--focus-ring-width, --vaadin-padding-inline-container) and keep the arithmetic
and max(...) expressions intact; update the calc() blocks for padding-block,
padding-inline, margin-block and margin-inline to be compact and consistently
formatted to satisfy the linter.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d23979 and e93af49.

📒 Files selected for processing (1)
  • src/main/resources/META-INF/frontend/fcEnhancedTabs/fc-enhanced-tabs.css

@javier-godoy javier-godoy requested review from mlopezFC and paodb March 2, 2026 13:43
@javier-godoy javier-godoy marked this pull request as ready for review March 2, 2026 13:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant