dify - ✅(Solved) Fix refactor(web): improve a11y and design-system consistency for date/time picker and auto-update strategy picker [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
langgenius/dify#35626Fetched 2026-04-29 06:36:24
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
1
Author
Participants
Timeline (top)
closed ×1cross-referenced ×1

A few UI primitives in the web app currently bypass accessibility patterns and do not follow the shared design-system components, which causes inconsistent behavior, duplicated styling, and weak keyboard/screen-reader support.

Root Cause

A few UI primitives in the web app currently bypass accessibility patterns and do not follow the shared design-system components, which causes inconsistent behavior, duplicated styling, and weak keyboard/screen-reader support.

Fix Action

Fixed

PR fix notes

PR #35627: refactor(web): improve a11y and design-system consistency for date/time picker and auto-update strategy picker

Description (problem / solution / changelog)

Summary

Fixes #35626.

This PR addresses two related accessibility and consistency gaps in the web app:

1. Date/time picker option columns

  • Extract a new OptionList component (web/app/components/base/date-and-time-picker/common/option-list.tsx) that owns the column layout (height, gap, padding, overflow) and hides the scrollbar with CSS only ([scrollbar-width:none] and [&::-webkit-scrollbar]:hidden), removing the dependency on the global scrollbar-none utility and de-duplicating the same set of classes that was repeated for the hour / minute / period columns and for the year / month columns.
  • Use OptionList in both time-picker/options.tsx and year-and-month-picker/options.tsx.
  • In OptionListItem, wrap the children in a real <button type=\"button\"> with focus-visible:ring-1 so each option is a proper interactive control: focusable from the keyboard, exposed with the button role to assistive technologies, and with a visible focus indicator. The <li> continues to provide the list semantics for the surrounding <ul>.

2. Auto-update strategy picker

  • Migrate strategy-picker.tsx from the hand-rolled PortalToFollowElem + <div onClick> implementation to the design system's DropdownMenu:
    • DropdownMenuTrigger renders the existing Button.
    • DropdownMenuRadioGroup / DropdownMenuRadioItem express the single-select strategy choice with proper radio semantics and keyboard navigation.
    • DropdownMenuRadioItemIndicator replaces the manually conditional RiCheckLine and the e.stopPropagation() / e.nativeEvent.stopImmediatePropagation() plumbing on each option.

Tests

  • option-list-item.spec.tsx is updated to look up the option by its new button role.
  • A new option-list.spec.tsx covers the scrollbar-hiding classes and the className merging.
  • time-picker/__tests__/options.spec.tsx is updated for the new button role.
  • strategy-picker.spec.tsx and the wider auto-update-setting/__tests__/index.spec.tsx mock the @langgenius/dify-ui/dropdown-menu primitives and assert against the strategy-indicator test id and radio role instead of querying for SVG check icons.

Test plan

  • pnpm --filter web test web/app/components/base/date-and-time-picker (option list + items + time picker options).
  • pnpm --filter web test web/app/components/plugins/reference-setting-modal/auto-update-setting (strategy picker + auto-update setting).
  • Manually open the time picker / year-month picker and confirm the columns scroll without a visible scrollbar and that options can be focused with Tab and activated with Enter / Space.
  • Manually open the plugin auto-update strategy picker and confirm the dropdown opens, can be navigated with the arrow keys, shows the indicator next to the selected strategy, and dismisses on selection / outside click / Escape.

Notes

  • No user-facing copy changes; no i18n updates required.
  • No backend changes.

Made with Cursor

Changed files

  • eslint-suppressions.json (modified, +0/-5)
  • web/app/components/base/date-and-time-picker/common/__tests__/option-list-item.spec.tsx (modified, +5/-5)
  • web/app/components/base/date-and-time-picker/common/__tests__/option-list.spec.tsx (added, +28/-0)
  • web/app/components/base/date-and-time-picker/common/option-list-item.tsx (modified, +17/-11)
  • web/app/components/base/date-and-time-picker/common/option-list.tsx (added, +26/-0)
  • web/app/components/base/date-and-time-picker/time-picker/__tests__/options.spec.tsx (modified, +2/-2)
  • web/app/components/base/date-and-time-picker/time-picker/options.tsx (modified, +7/-6)
  • web/app/components/base/date-and-time-picker/year-and-month-picker/options.tsx (modified, +5/-4)
  • web/app/components/plugins/reference-setting-modal/auto-update-setting/__tests__/index.spec.tsx (modified, +81/-129)
  • web/app/components/plugins/reference-setting-modal/auto-update-setting/__tests__/strategy-picker.spec.tsx (modified, +36/-62)
  • web/app/components/plugins/reference-setting-modal/auto-update-setting/strategy-picker.tsx (modified, +41/-52)
RAW_BUFFERClick to expand / collapse

Summary

A few UI primitives in the web app currently bypass accessibility patterns and do not follow the shared design-system components, which causes inconsistent behavior, duplicated styling, and weak keyboard/screen-reader support.

1. Date/time picker option columns

web/app/components/base/date-and-time-picker/time-picker/options.tsx and year-and-month-picker/options.tsx render the hour / minute / period (and year / month) columns as plain <ul> elements that:

  • Repeat the same Tailwind classes for height, layout and scrollbar hiding three times per file.
  • Rely on the global scrollbar-none utility, which couples the columns to a global stylesheet rather than a self-contained component.

web/app/components/base/date-and-time-picker/common/option-list-item.tsx renders each option as <li onClick={...}>, which means the option:

  • Is not exposed as an interactive control to assistive technologies (it has the implicit role listitem).
  • Cannot be focused or activated from the keyboard.
  • Has no visible focus indicator.

2. Auto-update strategy picker

web/app/components/plugins/reference-setting-modal/auto-update-setting/strategy-picker.tsx implements its own dropdown on top of PortalToFollowElem, with manual stopPropagation / stopImmediatePropagation calls, a hand-rolled list of <div onClick> rows, and a manually rendered check icon to show the selected option.

This duplicates behavior already provided by the design system's DropdownMenu (@langgenius/dify-ui/dropdown-menu), and in particular it does not benefit from the radio-group semantics, keyboard navigation, focus management, and indicator handling of DropdownMenuRadioGroup / DropdownMenuRadioItem / DropdownMenuRadioItemIndicator.

Proposal

  • Extract a reusable OptionList component under date-and-time-picker/common/ that owns the column layout and hides the scrollbar with CSS only ([scrollbar-width:none] + [&::-webkit-scrollbar]:hidden), and use it in both the time picker and the year/month picker.
  • Wrap the contents of OptionListItem in a real <button type="button"> with a focus-visible ring so each option is a proper interactive, focusable control.
  • Migrate StrategyPicker to DropdownMenu + DropdownMenuRadioGroup / DropdownMenuRadioItem / DropdownMenuRadioItemIndicator, removing the custom portal wiring and the manual check-icon rendering.
  • Update the existing tests to match the new accessible roles (button, radio) and indicator markers.

Scope

Frontend only. No user-facing copy or behavior changes beyond improved keyboard / screen-reader support and visual focus rings.

extent analysis

TL;DR

Extract a reusable OptionList component and migrate StrategyPicker to DropdownMenu to improve accessibility and consistency.

Guidance

  • Extract the OptionList component to own column layout and scrollbar hiding, reducing duplicated code and improving maintainability.
  • Wrap OptionListItem contents in a <button type="button"> to make options interactive and focusable.
  • Migrate StrategyPicker to DropdownMenu and related components to leverage existing accessibility features and reduce custom code.
  • Update tests to match new accessible roles and indicator markers.

Example

// web/app/components/base/date-and-time-picker/common/option-list-item.tsx
import { button } from '@langgenius/dify-ui/button';

const OptionListItem = () => {
  return (
    <button type="button" className="focus:ring">
      {/* option content */}
    </button>
  );
};

Notes

This solution assumes that the @langgenius/dify-ui components are properly configured and imported. Additional styling or adjustments may be necessary to ensure a consistent user experience.

Recommendation

Apply the proposed workaround by extracting the OptionList component and migrating StrategyPicker to DropdownMenu, as this will improve accessibility and consistency in the web app.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

dify - ✅(Solved) Fix refactor(web): improve a11y and design-system consistency for date/time picker and auto-update strategy picker [1 pull requests, 1 participants]