Skip to content

Conversation

@shenjunjian
Copy link
Collaborator

@shenjunjian shenjunjian commented Dec 4, 2025

PR

为select 添加 aria-* 的一些属性,方便ai识别读取

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Improved accessibility across Select and Option components: added ARIA roles, labels, owned list linkage and a stable list identifier to enhance screen-reader semantics.
  • Tests

    • Updated UI tests to use more specific element selectors, aligning test queries with the updated markup and ensuring stable interactions.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions github-actions bot added the bug Something isn't working label Dec 4, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 4, 2025

Walkthrough

Adds ARIA attributes to select and option Vue components and introduces a new ariaListId state property initialized from crypto.randomUUID() to link listbox ownership for accessibility; also updates several tests to use .tiny-option selectors.

Changes

Cohort / File(s) Summary
Renderless select state
packages/renderless/src/select/vue.ts
Adds ariaListId state property initialized with 'tiny-select-' + crypto.randomUUID().slice(-8)
Option components
packages/vue/src/option/src/mobile-first.vue, packages/vue/src/option/src/pc.vue
Adds role="option", :aria-label="state.currentLabel", and :aria-selected="state.itemSelected" on option root elements
Select components
packages/vue/src/select/src/mobile-first.vue, packages/vue/src/select/src/pc.vue
Adds ARIA attributes to inputs (role="combobox", aria-haspopup="listbox", aria-autocomplete="list", :aria-owns/:aria-controls bound to state) and to dropdown containers (role="listbox", :id="state.ariaListId")
Tests — selector updates
examples/sites/demos/pc/app/select/*.spec.ts (multiple files)
Replaces role-based queries (getByRole('listitem')) with CSS-class locators (locator('.tiny-option')) and scopes some locators with .nth(0)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–25 minutes

  • Review packages/renderless/src/select/vue.ts for correct UUID usage and SSR safety (crypto availability).
  • Verify all :aria-owns/:aria-controls bindings reference state.ariaListId consistently.
  • Confirm test selector changes still assert the intended elements and timing (flakiness risk).
  • Check templates for any accidental attribute binding typos in mobile/pc variants.

Poem

🐰
I found a tiny id beneath the pine,
I stitched it to listboxes, snug and fine.
Options now chatter in ARIA tongue,
Screen readers listen — the victory's sung.
Hop, click, select — accessibility done! 🥕

Pre-merge checks and finishing touches

✅ 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 describes the main change: adding ARIA properties to the select component for AI accessibility, which is accurately reflected in all file changes across the select components.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch shen/aria-select

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bfc7549 and 7747a87.

📒 Files selected for processing (6)
  • examples/sites/demos/pc/app/select/allow-create.spec.ts (2 hunks)
  • examples/sites/demos/pc/app/select/automatic-dropdown.spec.ts (1 hunks)
  • examples/sites/demos/pc/app/select/basic-usage.spec.ts (2 hunks)
  • examples/sites/demos/pc/app/select/binding-obj.spec.ts (1 hunks)
  • examples/sites/demos/pc/app/select/cache-usage.spec.ts (1 hunks)
  • examples/sites/demos/pc/app/select/clearable.spec.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
examples/sites/demos/pc/app/select/cache-usage.spec.ts (1)
examples/sites/demos/pc/app/grid/editor/inner-editor.spec.js (1)
  • input (8-8)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: PR E2E Test (pnpm test:e2e3)
🔇 Additional comments (2)
examples/sites/demos/pc/app/select/basic-usage.spec.ts (1)

9-9: LGTM: Improved dropdown scoping.

Adding .nth(0) appropriately scopes the dropdown locator to the first instance, which improves test specificity when multiple dropdowns may be present.

examples/sites/demos/pc/app/select/cache-usage.spec.ts (1)

13-13: Incorrect premise: Component uses role="option", not role="listitem".

The option elements correctly implement role="option" with aria-label and aria-selected attributes, fully compliant with WCAG/ARIA specifications for listbox options. The test selector change from (presumably) getByRole('listitem') is not applicable since the component never used that role. Using .tiny-option class selectors as alternatives to role-based queries is acceptable, though role-based selectors would be more resilient to CSS changes.

Likely an incorrect or invalid review comment.


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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dba45e3 and bfc7549.

📒 Files selected for processing (5)
  • packages/renderless/src/select/vue.ts (1 hunks)
  • packages/vue/src/option/src/mobile-first.vue (1 hunks)
  • packages/vue/src/option/src/pc.vue (1 hunks)
  • packages/vue/src/select/src/mobile-first.vue (4 hunks)
  • packages/vue/src/select/src/pc.vue (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: PR E2E Test (pnpm test:e2e3)
🔇 Additional comments (8)
packages/vue/src/option/src/mobile-first.vue (1)

24-26: ARIA attributes correctly implemented.

The role and ARIA attributes are properly added for accessibility. The aria-selected attribute will be converted to a string by Vue's binding system.

packages/vue/src/option/src/pc.vue (1)

20-22: ARIA attributes correctly implemented.

The role and ARIA attributes are properly added, aligning with WCAG guidelines for option elements within a listbox.

packages/vue/src/select/src/pc.vue (2)

297-301: ARIA combobox pattern correctly implemented.

The role and ARIA attributes properly establish the combobox pattern with correct ownership and control relationships to the listbox.


362-363: Listbox role and ID correctly linked.

The listbox role and ID binding complete the ARIA ownership relationship, enabling proper screen reader navigation.

packages/vue/src/select/src/mobile-first.vue (4)

248-252: ARIA combobox pattern correctly implemented on filterable input.

The ARIA attributes properly establish combobox semantics with ownership linkage to the listbox.


285-289: ARIA combobox pattern correctly implemented on main input.

The ARIA attributes align with the combobox pattern. Note that both this input and the filterable input (line 215) reference the same ariaListId, which is acceptable since their visibility is controlled by mutually exclusive conditions (filterable and !shape).


353-354: Listbox role and ID correctly linked.

The listbox role and ID binding complete the ARIA relationship with the combobox inputs.


466-469: Code formatting updated.

The class binding has been reformatted to consistently use the m() helper function. No functional change.

Comment on lines +299 to +300
})),
ariaListId: 'tiny-select-' + crypto.randomUUID().slice(-8)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check for browserslist and browser support configuration
fd -t f "browserslist|.browserslistrc" || echo "No browserslist found"
# Also check package.json for engine constraints and browser field
cat package.json | head -50

Repository: opentiny/tiny-vue

Length of output: 1731


🏁 Script executed:

# Search for crypto.randomUUID usage in the codebase
rg "crypto\.randomUUID|crypto\.getRandomValues" -A 2 -B 2

Repository: opentiny/tiny-vue

Length of output: 4224


🏁 Script executed:

# Check if there are any polyfills or UUID libraries already in use
rg "uuid|polyfill|fillRandom|getRandomValues" -l | head -20

Repository: opentiny/tiny-vue

Length of output: 385


🏁 Script executed:

# Look for browserslist configuration in various locations
find . -maxdepth 2 -type f \( -name ".browserslistrc" -o -name "browserslist" \) -o -path "*/package.json" | head -10

Repository: opentiny/tiny-vue

Length of output: 75


🏁 Script executed:

# Check if there's a browserslist config in root or package.json
cat package.json | grep -A 10 "browserslist"

Repository: opentiny/tiny-vue

Length of output: 120


🏁 Script executed:

# Check the nanoid utility since it has IE polyfills
head -80 packages/utils/src/nanoid/index.ts

Repository: opentiny/tiny-vue

Length of output: 1674


🏁 Script executed:

# Check how generateID is implemented in the codebase
cat packages/vue/src/query-builder/src/utils/generateID.ts

Repository: opentiny/tiny-vue

Length of output: 2040


Replace direct crypto.randomUUID() with the project's existing generateID() utility.

The codebase uses crypto.randomUUID() without fallback, which is inconsistent with the established pattern. The project's generateID() utility in packages/vue/src/query-builder/src/utils/generateID.ts provides proper browser compatibility handling with fallbacks for environments where randomUUID() is unavailable.

-    ariaListId: 'tiny-select-' + crypto.randomUUID().slice(-8)
+    ariaListId: 'tiny-select-' + generateID().slice(-8)

Import generateID from @opentiny/utils at the top of the file.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/renderless/src/select/vue.ts around lines 299-300, replace the
direct use of crypto.randomUUID() for ariaListId with the project's generateID()
utility to ensure browser compatibility; add an import for generateID from
'@opentiny/utils' at the top of the file and use generateID().slice(-8) (or
otherwise adapt to generateID() return format) when constructing 'tiny-select-'
+ ... so it mirrors the existing pattern and fallback handling.

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants