-
Notifications
You must be signed in to change notification settings - Fork 336
feat(file-upload, input, numeric, search, switch): Add accessibility information #3974
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -173,7 +173,7 @@ export default defineComponent({ | |
| const getTriggerContent = (t: any, disabled: boolean) => { | ||
| return ( | ||
| <div class="trigger-btn"> | ||
| <tiny-button disabled={disabled} onClick={handleTriggerClick}> | ||
| <tiny-button disabled={disabled} aria-label={t('ui.fileUpload.uploadFile')} onClick={handleTriggerClick}> | ||
| <TinyIconPlus /> | ||
| <span>{t('ui.fileUpload.uploadFile')}</span> | ||
| </tiny-button> | ||
|
|
@@ -225,17 +225,36 @@ export default defineComponent({ | |
|
|
||
| const getThumIcon = (file) => [ | ||
| showDownload && ( | ||
| <span class="thumb-icon" title={t('ui.fileUpload.downloadFile')} onClick={() => execDownload(file)}> | ||
| <span | ||
| class="thumb-icon" | ||
| role="button" | ||
| tabindex="0" | ||
| aria-label={t('ui.fileUpload.downloadFile')} | ||
| title={t('ui.fileUpload.downloadFile')} | ||
| onClick={() => execDownload(file)}> | ||
| <TinyIconDownload class="download-icon" /> | ||
| </span> | ||
|
Comment on lines
+228
to
236
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add keyboard event handler for accessibility. The download icon has ♻️ Proposed fix <span
class="thumb-icon"
role="button"
tabindex="0"
aria-label={t('ui.fileUpload.downloadFile')}
title={t('ui.fileUpload.downloadFile')}
+ onKeydown={(event) => handleEnter(event, () => execDownload(file))}
onClick={() => execDownload(file)}>
<TinyIconDownload class="download-icon" />
</span>
🤖 Prompt for AI Agents |
||
| ), | ||
| isEdm && !isFolder && showUpdate && ( | ||
| <span class="thumb-icon" title={t('ui.fileUpload.updateFile')} onClick={() => updateFile(file)}> | ||
| <span | ||
| class="thumb-icon" | ||
| role="button" | ||
| tabindex="0" | ||
| aria-label={t('ui.fileUpload.updateFile')} | ||
| title={t('ui.fileUpload.updateFile')} | ||
| onClick={() => updateFile(file)}> | ||
| <TinyIconFileCloudupload class="refres-icon" /> | ||
| </span> | ||
|
Comment on lines
+239
to
247
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add keyboard event handler for accessibility. The update icon has ♻️ Proposed fix <span
class="thumb-icon"
role="button"
tabindex="0"
aria-label={t('ui.fileUpload.updateFile')}
title={t('ui.fileUpload.updateFile')}
+ onKeydown={(event) => handleEnter(event, () => updateFile(file))}
onClick={() => updateFile(file)}>
<TinyIconFileCloudupload class="refres-icon" />
</span>
🤖 Prompt for AI Agents |
||
| ), | ||
| showDel && ( | ||
| <span class="thumb-icon" title={t('ui.fileUpload.deleteFile')} onClick={() => handleRemove(file)}> | ||
| <span | ||
| class="thumb-icon" | ||
| role="button" | ||
| tabindex="0" | ||
| aria-label={t('ui.fileUpload.deleteFile')} | ||
| title={t('ui.fileUpload.deleteFile')} | ||
| onClick={() => handleRemove(file)} | ||
| onKeydown={(event) => handleEnter(event, () => handleRemove(file))}> | ||
| <TinyIconClose class="close-icon" /> | ||
| </span> | ||
| ) | ||
|
Comment on lines
+250
to
260
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Undefined function Line 257 references the 🐛 Proposed fixAdd the const getThumIcon = (file) => [
+ // Helper to handle Enter key press
+ const handleEnter = (event, callback) => {
+ if (event.key === 'Enter' || event.key === ' ') {
+ event.preventDefault()
+ callback()
+ }
+ }
+
showDownload && (Alternatively, if this pattern is used elsewhere in the codebase, consider extracting it to a shared utility module.
🤖 Prompt for AI Agents |
||
|
|
@@ -508,7 +527,7 @@ export default defineComponent({ | |
| const attrs = a($attrs, ['^on[A-Z]']) | ||
|
|
||
| return ( | ||
| <div class="tiny-file-upload" {...attrs}> | ||
| <div class="tiny-file-upload" role="group" aria-label={title} {...attrs}> | ||
| {isSaasType ? getDefaultTitle(title, this.showTitle) : ''} | ||
| {notice} | ||
| {isPictureCard ? uploadList : ''} | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,6 +24,8 @@ | |||||||||||||||||||||
| " | ||||||||||||||||||||||
| v-if="controls" | ||||||||||||||||||||||
| role="button" | ||||||||||||||||||||||
| :aria-disabled="state.minDisabled || state.inputDisabled" | ||||||||||||||||||||||
| aria-label="decrease" | ||||||||||||||||||||||
|
Comment on lines
+27
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Internationalize the aria-label value. The 🌐 Proposed fix to use i18n :aria-disabled="state.minDisabled || state.inputDisabled"
- aria-label="decrease"
+ :aria-label="t('ui.numeric.decrease')"
v-repeat-click="decrease"
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| v-repeat-click="decrease" | ||||||||||||||||||||||
| @keydown.enter="decrease" | ||||||||||||||||||||||
| > | ||||||||||||||||||||||
|
|
@@ -51,6 +53,8 @@ | |||||||||||||||||||||
| " | ||||||||||||||||||||||
| v-if="controls" | ||||||||||||||||||||||
| role="button" | ||||||||||||||||||||||
| :aria-disabled="state.maxDisabled || state.inputDisabled" | ||||||||||||||||||||||
| aria-label="increase" | ||||||||||||||||||||||
|
Comment on lines
+56
to
+57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Internationalize the aria-label value. The 🌐 Proposed fix to use i18n :aria-disabled="state.maxDisabled || state.inputDisabled"
- aria-label="increase"
+ :aria-label="t('ui.numeric.increase')"
v-repeat-click="increase"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| v-repeat-click="increase" | ||||||||||||||||||||||
| @keydown.enter="increase" | ||||||||||||||||||||||
| > | ||||||||||||||||||||||
|
|
@@ -74,6 +78,11 @@ | |||||||||||||||||||||
| > | ||||||||||||||||||||||
| <input | ||||||||||||||||||||||
| :tabindex="tabindex" | ||||||||||||||||||||||
| role="numeric" | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. role=“numeric” 不是有效的 ARIA 角色。对于带有增减控制的数字输入,请使用 role=“spinbutton”。aria-valuemin、aria-valuemax 和 aria-valuenow 属性专为 spinbutton 角色设计。 |
||||||||||||||||||||||
| :aria-valuemin="min" | ||||||||||||||||||||||
| :aria-valuemax="max" | ||||||||||||||||||||||
| :aria-valuenow="state.currentValue" | ||||||||||||||||||||||
| :aria-disabled="state.inputDisabled" | ||||||||||||||||||||||
|
Comment on lines
+81
to
+85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Replace invalid ARIA role with "spinbutton".
🔧 Proposed fix- role="numeric"
+ role="spinbutton"
:aria-valuemin="min"
:aria-valuemax="max"
:aria-valuenow="state.currentValue"
:aria-disabled="state.inputDisabled"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| :class=" | ||||||||||||||||||||||
| m( | ||||||||||||||||||||||
| gcls('numeric_input_inner'), | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -62,6 +62,8 @@ | |||||||||||||||||||||
| <span | ||||||||||||||||||||||
| class="tiny-numeric__decrease" | ||||||||||||||||||||||
| role="button" | ||||||||||||||||||||||
| aria-label="decrease" | ||||||||||||||||||||||
| :aria-disabled="state.minDisabled" | ||||||||||||||||||||||
|
Comment on lines
+65
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Internationalize the aria-label values. The 🌐 Proposed fix to use i18n- aria-label="decrease"
+ :aria-label="t('ui.numeric.decrease')"
:aria-disabled="state.minDisabled"- aria-label="increase"
+ :aria-label="t('ui.numeric.increase')"
:aria-disabled="state.maxDisabled"Also applies to: 77-78 🤖 Prompt for AI Agents |
||||||||||||||||||||||
| v-if="state.controls && !unit" | ||||||||||||||||||||||
| v-repeat-click="decrease" | ||||||||||||||||||||||
| :class="{ 'is-disabled': state.minDisabled }" | ||||||||||||||||||||||
|
|
@@ -72,6 +74,8 @@ | |||||||||||||||||||||
| <span | ||||||||||||||||||||||
| class="tiny-numeric__increase" | ||||||||||||||||||||||
| role="button" | ||||||||||||||||||||||
| aria-label="increase" | ||||||||||||||||||||||
| :aria-disabled="state.maxDisabled" | ||||||||||||||||||||||
| v-if="state.controls && !unit" | ||||||||||||||||||||||
| v-repeat-click="increase" | ||||||||||||||||||||||
| :class="{ 'is-disabled': state.maxDisabled }" | ||||||||||||||||||||||
|
|
@@ -103,6 +107,11 @@ | |||||||||||||||||||||
| </span> | ||||||||||||||||||||||
| <input | ||||||||||||||||||||||
| :tabindex="tabindex" | ||||||||||||||||||||||
| role="numeric" | ||||||||||||||||||||||
| :aria-valuemin="min" | ||||||||||||||||||||||
| :aria-valuemax="max" | ||||||||||||||||||||||
| :aria-valuenow="state.currentValue" | ||||||||||||||||||||||
| :aria-disabled="state.inputDisabled" | ||||||||||||||||||||||
|
Comment on lines
+110
to
+114
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Replace invalid ARIA role with "spinbutton".
🔧 Proposed fix- role="numeric"
+ role="spinbutton"
:aria-valuemin="min"
:aria-valuemax="max"
:aria-valuenow="state.currentValue"
:aria-disabled="state.inputDisabled"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| :class="[ | ||||||||||||||||||||||
| 'tiny-numeric__input-inner', | ||||||||||||||||||||||
| { 'tiny-numeric__show-left': !state.controls && (showLeft || shape === 'filter') } | ||||||||||||||||||||||
|
|
@@ -130,6 +139,8 @@ | |||||||||||||||||||||
| <span | ||||||||||||||||||||||
| class="tiny-numeric__decrease" | ||||||||||||||||||||||
| role="button" | ||||||||||||||||||||||
| aria-label="decrease" | ||||||||||||||||||||||
| :aria-disabled="state.minDisabled" | ||||||||||||||||||||||
|
Comment on lines
+142
to
+143
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Internationalize the aria-label values. Same issue as in the filter variant: 🌐 Proposed fix to use i18n- aria-label="decrease"
+ :aria-label="t('ui.numeric.decrease')"
:aria-disabled="state.minDisabled"- aria-label="increase"
+ :aria-label="t('ui.numeric.increase')"
:aria-disabled="state.maxDisabled"Also applies to: 154-155 |
||||||||||||||||||||||
| v-if="controls && !unit" | ||||||||||||||||||||||
| v-repeat-click="decrease" | ||||||||||||||||||||||
| :class="{ 'is-disabled': state.minDisabled }" | ||||||||||||||||||||||
|
|
@@ -140,6 +151,8 @@ | |||||||||||||||||||||
| <span | ||||||||||||||||||||||
| class="tiny-numeric__increase" | ||||||||||||||||||||||
| role="button" | ||||||||||||||||||||||
| aria-label="increase" | ||||||||||||||||||||||
| :aria-disabled="state.maxDisabled" | ||||||||||||||||||||||
| v-if="controls && !unit" | ||||||||||||||||||||||
| v-repeat-click="increase" | ||||||||||||||||||||||
| :class="{ 'is-disabled': state.maxDisabled }" | ||||||||||||||||||||||
|
|
@@ -171,6 +184,11 @@ | |||||||||||||||||||||
| </span> | ||||||||||||||||||||||
| <input | ||||||||||||||||||||||
| :tabindex="tabindex" | ||||||||||||||||||||||
| role="numeric" | ||||||||||||||||||||||
| :aria-valuemin="min" | ||||||||||||||||||||||
| :aria-valuemax="max" | ||||||||||||||||||||||
| :aria-valuenow="state.currentValue" | ||||||||||||||||||||||
| :aria-disabled="state.inputDisabled" | ||||||||||||||||||||||
|
Comment on lines
+187
to
+191
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Replace invalid ARIA role with "spinbutton". Same critical issue as in the filter variant: 🔧 Proposed fix- role="numeric"
+ role="spinbutton"
:aria-valuemin="min"
:aria-valuemax="max"
:aria-valuenow="state.currentValue"
:aria-disabled="state.inputDisabled"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| :class="['tiny-numeric__input-inner', { 'tiny-numeric__show-left': !controls && showLeft }]" | ||||||||||||||||||||||
| ref="input" | ||||||||||||||||||||||
| :value="state.displayValue" | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,6 +2,8 @@ | |||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||
| :class="m(gcls('search-default'))" | ||||||||||||||||||||||||||||||||||
| data-tag="tiny-search" | ||||||||||||||||||||||||||||||||||
| role="search" | ||||||||||||||||||||||||||||||||||
| :aria-label="placeholder || 'search'" | ||||||||||||||||||||||||||||||||||
| @mouseenter="state.hovering = true" | ||||||||||||||||||||||||||||||||||
| @mouseleave="state.hovering = false" | ||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||
|
|
@@ -30,6 +32,10 @@ | |||||||||||||||||||||||||||||||||
| gcls({ 'pc-search-present-unbig': size === 'small' && !big }) | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| " | ||||||||||||||||||||||||||||||||||
| role="button" | ||||||||||||||||||||||||||||||||||
| tabindex="0" | ||||||||||||||||||||||||||||||||||
| aria-haspopup="listbox" | ||||||||||||||||||||||||||||||||||
| :aria-expanded="state.show" | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+35
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add keyboard event handler to the selector trigger. The trigger div has ♻️ Proposed fix <div
v-show="!state.collapse && state.types.length"
data-tag="tiny-search__present"
:class="..."
role="button"
tabindex="0"
aria-haspopup="listbox"
:aria-expanded="state.show"
+ @keydown.enter="showSelector"
+ @keydown.space.prevent="showSelector"
@click="showSelector"
>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| @click="showSelector" | ||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||
| <slot name="text" :slot-scope="state.searchValue"> | ||||||||||||||||||||||||||||||||||
|
|
@@ -70,6 +76,10 @@ | |||||||||||||||||||||||||||||||||
| :placeholder="placeholder" | ||||||||||||||||||||||||||||||||||
| type="text" | ||||||||||||||||||||||||||||||||||
| data-tag="tiny-search__input" | ||||||||||||||||||||||||||||||||||
| role="searchbox" | ||||||||||||||||||||||||||||||||||
| :aria-label="placeholder || 'search input'" | ||||||||||||||||||||||||||||||||||
| :aria-expanded="state.show" | ||||||||||||||||||||||||||||||||||
| aria-haspopup="listbox" | ||||||||||||||||||||||||||||||||||
| @keyup.enter="searchEnterKey" | ||||||||||||||||||||||||||||||||||
| @input="handleInput" | ||||||||||||||||||||||||||||||||||
| @change="handleChange" | ||||||||||||||||||||||||||||||||||
|
|
@@ -91,7 +101,13 @@ | |||||||||||||||||||||||||||||||||
| " | ||||||||||||||||||||||||||||||||||
| v-if="state.showClear && !state.collapse" | ||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||
| <a :class="m(gcls('pc-search-input-btn-transtion-a'))" @click="clear"> | ||||||||||||||||||||||||||||||||||
| <a | ||||||||||||||||||||||||||||||||||
| :class="m(gcls('pc-search-input-btn-transtion-a'))" | ||||||||||||||||||||||||||||||||||
| role="button" | ||||||||||||||||||||||||||||||||||
| tabindex="0" | ||||||||||||||||||||||||||||||||||
| aria-label="clear search" | ||||||||||||||||||||||||||||||||||
| @click="clear" | ||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+104
to
+110
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add keyboard event handlers to button-like anchors. The clear (lines 104-110) and search (lines 130-136) anchors have ♻️ Proposed fix for clear button <a
:class="m(gcls('pc-search-input-btn-transtion-a'))"
role="button"
tabindex="0"
aria-label="clear search"
+ @keydown.enter="clear"
+ @keydown.space.prevent="clear"
@click="clear"
>Apply similar changes to the search button (lines 130-136). Also applies to: 130-136 |
||||||||||||||||||||||||||||||||||
| <icon-close | ||||||||||||||||||||||||||||||||||
| @mousedown.prevent | ||||||||||||||||||||||||||||||||||
| data-tag="tiny-svg-size" | ||||||||||||||||||||||||||||||||||
|
|
@@ -111,7 +127,13 @@ | |||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| " | ||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||
| <a :class="m(gcls('pc-search-input-btn-a'))" @click="searchClick"> | ||||||||||||||||||||||||||||||||||
| <a | ||||||||||||||||||||||||||||||||||
| :class="m(gcls('pc-search-input-btn-a'))" | ||||||||||||||||||||||||||||||||||
| role="button" | ||||||||||||||||||||||||||||||||||
| tabindex="0" | ||||||||||||||||||||||||||||||||||
| aria-label="submit search" | ||||||||||||||||||||||||||||||||||
| @click="searchClick" | ||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||
| <icon-search | ||||||||||||||||||||||||||||||||||
| :class=" | ||||||||||||||||||||||||||||||||||
| m( | ||||||||||||||||||||||||||||||||||
|
|
@@ -130,13 +152,19 @@ | |||||||||||||||||||||||||||||||||
| ref="selector" | ||||||||||||||||||||||||||||||||||
| data-tag="tiny-search__selector" | ||||||||||||||||||||||||||||||||||
| :class="m(gcls('search-selector'))" | ||||||||||||||||||||||||||||||||||
| role="listbox" | ||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||
| <div data-tag="tiny-search__selector-body" :class="m(gcls('search-selector-body'))"> | ||||||||||||||||||||||||||||||||||
| <ul data-tag="tiny-search__poplist"> | ||||||||||||||||||||||||||||||||||
| <li | ||||||||||||||||||||||||||||||||||
| v-for="(item, index) in state.types" | ||||||||||||||||||||||||||||||||||
| :key="index" | ||||||||||||||||||||||||||||||||||
| data-tag="tiny-search__poplist-item" | ||||||||||||||||||||||||||||||||||
| role="option" | ||||||||||||||||||||||||||||||||||
| :aria-label="item.text || item.label" | ||||||||||||||||||||||||||||||||||
| :aria-selected="item === state.searchValue" | ||||||||||||||||||||||||||||||||||
| :id="`tiny-search__option-${index}`" | ||||||||||||||||||||||||||||||||||
| tabindex="-1" | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+155
to
+167
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# First, let's understand the full structure of the mobile-first.vue file
wc -l packages/vue/src/search/src/mobile-first.vueRepository: opentiny/tiny-vue Length of output: 109 🏁 Script executed: #!/bin/bash
# Read the file to understand the context around lines 155-167
sed -n '1,50p' packages/vue/src/search/src/mobile-first.vueRepository: opentiny/tiny-vue Length of output: 1811 🏁 Script executed: #!/bin/bash
# Read around the lines in question (155-167)
sed -n '140,180p' packages/vue/src/search/src/mobile-first.vueRepository: opentiny/tiny-vue Length of output: 1624 🏁 Script executed: #!/bin/bash
# Search for keyboard event handlers in the search component
rg -n 'onKeydown|onKeyup|keypress|@keydown|@keyup|ArrowDown|ArrowUp|handleKey' packages/vue/src/search/src/ --type=ts --type=vueRepository: opentiny/tiny-vue Length of output: 88 🏁 Script executed: #!/bin/bash
# Search for click handlers and interaction handlers in the listbox section
rg -n '@click|click|handleClick' packages/vue/src/search/src/mobile-first.vue -A 2 -B 2Repository: opentiny/tiny-vue Length of output: 1191 🏁 Script executed: #!/bin/bash
# Search for keyboard patterns without file type restriction
rg -n 'keydown|keyup|keypress|ArrowDown|ArrowUp|Escape|handleKey' packages/vue/src/search/src/mobile-first.vueRepository: opentiny/tiny-vue Length of output: 101 🏁 Script executed: #!/bin/bash
# Read the script section of the file to see if keyboard handlers are defined there
tail -n +180 packages/vue/src/search/src/mobile-first.vue | head -n 85Repository: opentiny/tiny-vue Length of output: 2574 🏁 Script executed: #!/bin/bash
# Let's look at the entire script logic section
sed -n '220,265p' packages/vue/src/search/src/mobile-first.vueRepository: opentiny/tiny-vue Length of output: 1291 🏁 Script executed: #!/bin/bash
# Search for the showSelector and changeKey function implementations
rg -n 'showSelector|changeKey' packages/vue/src/search/src/mobile-first.vue -A 5Repository: opentiny/tiny-vue Length of output: 543 🏁 Script executed: #!/bin/bash
# Check parent components or renderless logic for search component
find packages/vue/src/search -name '*.ts' -o -name '*.js' -o -name '*.vue' | head -20Repository: opentiny/tiny-vue Length of output: 247 🏁 Script executed: #!/bin/bash
# Find the renderless search implementation
find . -path '*/vue-renderless/search*' -name '*.ts' -o -name '*.js' | grep -v node_modules | head -20Repository: opentiny/tiny-vue Length of output: 827 🏁 Script executed: #!/bin/bash
# Try to find renderless search in node_modules since it's an external dependency
find packages -name '*renderless*' -type dRepository: opentiny/tiny-vue Length of output: 80 🏁 Script executed: #!/bin/bash
# Check if renderless is in package.json as dependency
cat packages/vue/package.json | grep -A 5 -B 5 renderlessRepository: opentiny/tiny-vue Length of output: 278 🏁 Script executed: #!/bin/bash
# Search for keyboard navigation patterns specifically for listbox options in the entire search directory
rg -n 'listbox|option.*key|keyboard.*listbox' packages/vue/src/search/ --type=ts --type=vueRepository: opentiny/tiny-vue Length of output: 88 🏁 Script executed: #!/bin/bash
# More specific search for keyboard event bindings on options or listbox elements
rg -n '@key|keydown|keyup|key.*handler|ArrowDown|ArrowUp' packages/vue/src/search/src/Repository: opentiny/tiny-vue Length of output: 389 🏁 Script executed: #!/bin/bash
# List files in renderless search directory
find packages/renderless -name '*search*' -type fRepository: opentiny/tiny-vue Length of output: 101 🏁 Script executed: #!/bin/bash
# Read the search renderless implementation
ls -la packages/renderless/src/search/ 2>/dev/null || ls -la packages/renderless/search/ 2>/dev/null || find packages/renderless -path '*search*' -type fRepository: opentiny/tiny-vue Length of output: 294 🏁 Script executed: #!/bin/bash
# Find search.vue.ts or similar in renderless
find packages/renderless -name '*search*.ts' -o -name '*search*.js'Repository: opentiny/tiny-vue Length of output: 101 🏁 Script executed: #!/bin/bash
# Read the renderless Vue search implementation
cat -n packages/renderless/src/search/vue.tsRepository: opentiny/tiny-vue Length of output: 4008 🏁 Script executed: #!/bin/bash
# Also read the index.ts for context
cat -n packages/renderless/src/search/index.tsRepository: opentiny/tiny-vue Length of output: 5812 🏁 Script executed: #!/bin/bash
# Search for keyboard-related logic in renderless search
rg -n 'keydown|keyup|keypress|Arrow|Escape' packages/renderless/src/search/Repository: opentiny/tiny-vue Length of output: 43 Implement keyboard navigation for the ARIA listbox pattern. The listbox has proper ARIA attributes (role="listbox", role="option", aria-label, aria-selected) but lacks keyboard support. The WAI-ARIA listbox pattern requires:
Currently, options have Consider implementing the complete keyboard navigation as described in the WAI-ARIA Authoring Practices Guide. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| :class=" | ||||||||||||||||||||||||||||||||||
| m( | ||||||||||||||||||||||||||||||||||
| gcls('search-selector-poplist-item'), | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -18,6 +18,8 @@ | |||||||||||||||||||||||||||||||||||||||||
| state.searchSize ? 'tiny-search--' + state.searchSize : '', | ||||||||||||||||||||||||||||||||||||||||||
| { 'is-disabled': disabled } | ||||||||||||||||||||||||||||||||||||||||||
| ]" | ||||||||||||||||||||||||||||||||||||||||||
| role="search" | ||||||||||||||||||||||||||||||||||||||||||
| :aria-label="placeholder || 'search'" | ||||||||||||||||||||||||||||||||||||||||||
| @mouseenter="state.hovering = true" | ||||||||||||||||||||||||||||||||||||||||||
| @mouseleave="state.hovering = false" | ||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -26,7 +28,15 @@ | |||||||||||||||||||||||||||||||||||||||||
| <slot name="prefix"></slot> | ||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||
| <transition name="tiny-transition-search-line-fade" mode="out-in"> | ||||||||||||||||||||||||||||||||||||||||||
| <div v-show="!state.collapse && state.types.length" class="tiny-search__present" @click="showSelector"> | ||||||||||||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||||||||||
| v-show="!state.collapse && state.types.length" | ||||||||||||||||||||||||||||||||||||||||||
| class="tiny-search__present" | ||||||||||||||||||||||||||||||||||||||||||
| role="button" | ||||||||||||||||||||||||||||||||||||||||||
| tabindex="0" | ||||||||||||||||||||||||||||||||||||||||||
| aria-haspopup="listbox" | ||||||||||||||||||||||||||||||||||||||||||
| :aria-expanded="state.show" | ||||||||||||||||||||||||||||||||||||||||||
| @click="showSelector" | ||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+31
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Button role requires keyboard activation. The dropdown trigger has ⌨️ Proposed fix to add keyboard support <div
v-show="!state.collapse && state.types.length"
class="tiny-search__present"
role="button"
tabindex="0"
aria-haspopup="listbox"
:aria-expanded="state.show"
@click="showSelector"
+ @keydown.enter="showSelector"
+ @keydown.space.prevent="showSelector"
>📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
| <slot name="text" :slot-scope="state.searchValue"> | ||||||||||||||||||||||||||||||||||||||||||
| <span class="tiny-search__text">{{ state.searchValue.text }}</span> | ||||||||||||||||||||||||||||||||||||||||||
| </slot> | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -37,6 +47,10 @@ | |||||||||||||||||||||||||||||||||||||||||
| </transition> | ||||||||||||||||||||||||||||||||||||||||||
| <input | ||||||||||||||||||||||||||||||||||||||||||
| ref="input" | ||||||||||||||||||||||||||||||||||||||||||
| role="searchbox" | ||||||||||||||||||||||||||||||||||||||||||
| :aria-label="placeholder || 'search'" | ||||||||||||||||||||||||||||||||||||||||||
| :aria-expanded="state.show" | ||||||||||||||||||||||||||||||||||||||||||
| :aria-controls="state.show ? 'tiny-search__selector' : undefined" | ||||||||||||||||||||||||||||||||||||||||||
| v-bind="a($attrs, ['type', 'class', 'style', '^on[A-Z]', 'id', 'clearable'])" | ||||||||||||||||||||||||||||||||||||||||||
| v-model="state.currentValue" | ||||||||||||||||||||||||||||||||||||||||||
| :disabled="disabled" | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -51,6 +65,7 @@ | |||||||||||||||||||||||||||||||||||||||||
| :placeholder="placeholder" | ||||||||||||||||||||||||||||||||||||||||||
| type="text" | ||||||||||||||||||||||||||||||||||||||||||
| class="tiny-search__input" | ||||||||||||||||||||||||||||||||||||||||||
| aria-haspopup="listbox" | ||||||||||||||||||||||||||||||||||||||||||
| @keyup.enter="searchEnterKey($event)" | ||||||||||||||||||||||||||||||||||||||||||
| @change="handleChange" | ||||||||||||||||||||||||||||||||||||||||||
| @input="handleInput" | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -61,26 +76,37 @@ | |||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||
| <transition name="tiny-transition-icon-scale-in"> | ||||||||||||||||||||||||||||||||||||||||||
| <div class="tiny-search__input-btn tiny-icon-close" v-if="state.showClear && !state.collapse && !disabled"> | ||||||||||||||||||||||||||||||||||||||||||
| <a @click="clear($event)"> | ||||||||||||||||||||||||||||||||||||||||||
| <a role="button" tabindex="0" aria-label="clear search" @click="clear($event)" @keydown.enter="clear($event)"> | ||||||||||||||||||||||||||||||||||||||||||
| <icon-close @mousedown.prevent class="tiny-svg-size" /> | ||||||||||||||||||||||||||||||||||||||||||
| </a> | ||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||
| </transition> | ||||||||||||||||||||||||||||||||||||||||||
| <slot v-if="slots.suffix" name="suffix"></slot> | ||||||||||||||||||||||||||||||||||||||||||
| <div v-else-if="!slots.prefix && !slots.suffix" class="tiny-search__input-btn"> | ||||||||||||||||||||||||||||||||||||||||||
| <a @click="searchClick($event)"> | ||||||||||||||||||||||||||||||||||||||||||
| <a role="button" tabindex="0" aria-label="submit search" @click="searchClick($event)"> | ||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Submit button missing keyboard activation. Similar to the dropdown trigger, this button has ⌨️ Proposed fix to add keyboard support- <a role="button" tabindex="0" aria-label="submit search" @click="searchClick($event)">
+ <a role="button" tabindex="0" aria-label="submit search" @click="searchClick($event)" @keydown.enter="searchClick($event)" @keydown.space.prevent="searchClick($event)">📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
| <icon-search :style="{ fill: state.collapse && transparent ? '#fff' : '' }" class="tiny-svg-size" /> | ||||||||||||||||||||||||||||||||||||||||||
| </a> | ||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||
| <transition name="tiny-transition-zoom-in-top" mode="out-in"> | ||||||||||||||||||||||||||||||||||||||||||
| <div v-show="state.show && state.types.length" ref="selector" class="tiny-search__selector"> | ||||||||||||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||||||||||
| v-show="state.show && state.types.length" | ||||||||||||||||||||||||||||||||||||||||||
| ref="selector" | ||||||||||||||||||||||||||||||||||||||||||
| id="tiny-search__selector" | ||||||||||||||||||||||||||||||||||||||||||
| class="tiny-search__selector" | ||||||||||||||||||||||||||||||||||||||||||
| role="listbox" | ||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||
| <div class="tiny-search__selector-body"> | ||||||||||||||||||||||||||||||||||||||||||
| <ul class="tiny-search__poplist"> | ||||||||||||||||||||||||||||||||||||||||||
| <li | ||||||||||||||||||||||||||||||||||||||||||
| v-for="(item, index) in state.types" | ||||||||||||||||||||||||||||||||||||||||||
| :key="index" | ||||||||||||||||||||||||||||||||||||||||||
| class="tiny-search__poplist-item" | ||||||||||||||||||||||||||||||||||||||||||
| role="option" | ||||||||||||||||||||||||||||||||||||||||||
| :aria-label="item.text || item.label" | ||||||||||||||||||||||||||||||||||||||||||
| :aria-selected="item === state.searchValue" | ||||||||||||||||||||||||||||||||||||||||||
| :id="`tiny-search__option-${index}`" | ||||||||||||||||||||||||||||||||||||||||||
| tabindex="-1" | ||||||||||||||||||||||||||||||||||||||||||
| @click="changeKey(item)" | ||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||
| <slot name="poplist" :slot-scope="item"> | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,9 +12,14 @@ | |||||||||||||||||
| ) | ||||||||||||||||||
| " | ||||||||||||||||||
| data-tag="tiny-switch" | ||||||||||||||||||
| role="switch" | ||||||||||||||||||
| :aria-checked="state.currentValue === trueValue" | ||||||||||||||||||
| :aria-disabled="state.disabled || types === 'loading'" | ||||||||||||||||||
| :aria-label="types === 'word' ? undefined : state.currentValue === trueValue ? 'on' : 'off'" | ||||||||||||||||||
|
Comment on lines
+15
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # List files in the switch directory to understand the structure
find packages/vue/src/switch/src -type f -name "*.vue" | head -20Repository: opentiny/tiny-vue Length of output: 140 🏁 Script executed: # Read the mobile-first.vue file to see the actual code
wc -l packages/vue/src/switch/src/mobile-first.vueRepository: opentiny/tiny-vue Length of output: 109 🏁 Script executed: # Read the relevant sections of mobile-first.vue
cat -n packages/vue/src/switch/src/mobile-first.vue | head -80Repository: opentiny/tiny-vue Length of output: 3472 🏁 Script executed: cat -n packages/vue/src/switch/src/pc.vue | head -80Repository: opentiny/tiny-vue Length of output: 3328 🏁 Script executed: # Search for 'on' and 'off' i18n keys in the switch or locale files
find . -type f \( -name "*.ts" -o -name "*.js" -o -name "*.json" \) -path "*/locale/*" | head -20Repository: opentiny/tiny-vue Length of output: 43 🏁 Script executed: # Search for usage of t('on') or t('off') in the codebase
rg "t\(['\"]on['\"]" --type ts --type js | head -20Repository: opentiny/tiny-vue Length of output: 43 🏁 Script executed: # Search for 'yes' and 'no' to understand the pattern
rg "t\(['\"]yes['\"]|t\(['\"]no['\"]" --type ts --type js --type vue | head -30Repository: opentiny/tiny-vue Length of output: 88 🏁 Script executed: # Find locale-related files
fd -e json -e ts -e js | grep -i locale | head -20Repository: opentiny/tiny-vue Length of output: 821 🏁 Script executed: # Search for where 'yes' and 'no' are used in the codebase
rg "yes|no" packages/vue/src/switch --type-add vue:*.vue -t vue | grep -E "(yes|no)" | head -30Repository: opentiny/tiny-vue Length of output: 926 🏁 Script executed: # Check the renderless switch implementation to understand i18n
cat -n packages/renderless/src/switch/vue.ts | head -100Repository: opentiny/tiny-vue Length of output: 3509 🏁 Script executed: # Check the English locale file
cat -n packages/vue-locale/src/lang/en.ts | grep -A 5 -B 5 "yes\|no\|on\|off" | head -50Repository: opentiny/tiny-vue Length of output: 1719 🏁 Script executed: # Check the Chinese locale file
cat -n packages/vue-locale/src/lang/zh-CN.ts | grep -A 5 -B 5 "yes\|no\|on\|off" | head -50Repository: opentiny/tiny-vue Length of output: 1587 Internationalize aria-label to match visible text translations. The aria-label on line 18 uses hardcoded English strings For other switch types (icon/default), the aria-label should be internationalized to be consistent with the rest of the component's translation strategy. 🌐 Suggested fix- :aria-label="types === 'word' ? undefined : state.currentValue === trueValue ? 'on' : 'off'"
+ :aria-label="types === 'word' ? undefined : state.currentValue === trueValue ? t('yes') : t('no')"This uses the existing i18n keys that are already employed for visible text, ensuring accessibility labels are translated for all users. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| :tabindex="tabindex" | ||||||||||||||||||
| @click="toggle" | ||||||||||||||||||
| @keydown.space="toggle" | ||||||||||||||||||
| @keydown.enter="toggle" | ||||||||||||||||||
| > | ||||||||||||||||||
| <span | ||||||||||||||||||
| data-tag="tiny-switch-handle" | ||||||||||||||||||
|
|
||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,6 +12,10 @@ | |||||||||||||||||
| <template> | ||||||||||||||||||
| <span | ||||||||||||||||||
| v-if="!state.isDisplayOnly" | ||||||||||||||||||
| role="switch" | ||||||||||||||||||
| :aria-checked="state.currentValue === trueValue" | ||||||||||||||||||
| :aria-disabled="disabled" | ||||||||||||||||||
| :aria-label="state.showText ? (state.currentValue === trueValue ? 'on' : 'off') : undefined" | ||||||||||||||||||
|
Comment on lines
+15
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's check if the file exists and read the relevant sections
fd "pc.vue" -p "*switch*"Repository: opentiny/tiny-vue Length of output: 156 🏁 Script executed: # Read the file to verify the code snippet and context
cat -n packages/vue/src/switch/src/pc.vue | head -60Repository: opentiny/tiny-vue Length of output: 2844 🏁 Script executed: # Search for i18n function usage in the component
rg -t vue "t\(" packages/vue/src/switch/src/pc.vue -B 2 -A 2Repository: opentiny/tiny-vue Length of output: 88 🏁 Script executed: # Search for i18n resources to check if 'on'/'off', 'yes'/'no' keys exist
fd -t f -e "json" -e "ts" -e "js" | xargs rg -l "\"yes\"|\"no\"|\"on\"|\"off\"" | head -20Repository: opentiny/tiny-vue Length of output: 43 🏁 Script executed: # Check what i18n keys are actually available for switch component
fd "switch" -p "*lang*" -o "*i18n*" -o "*locale*"Repository: opentiny/tiny-vue Length of output: 192 🏁 Script executed: # Look for i18n configuration and translation files
find . -type f -name "*switch*" -path "*/lang/*" -o -type f -name "*switch*" -path "*/locale/*"Repository: opentiny/tiny-vue Length of output: 43 🏁 Script executed: # Search for where switch i18n strings are defined
rg -i "yes|no|on|off" --type json | grep -i switchRepository: opentiny/tiny-vue Length of output: 1210 🏁 Script executed: # Check the import statement to understand where t() comes from
cat -n packages/vue/src/switch/src/pc.vue | grep -A 5 "import"Repository: opentiny/tiny-vue Length of output: 549 🏁 Script executed: # Look for locale/lang files in the switch component directory
fd . packages/vue/src/switch/ -type fRepository: opentiny/tiny-vue Length of output: 231 🏁 Script executed: # Check if there are i18n keys specifically for 'on'/'off'
rg "on.*off|off.*on" --type jsonRepository: opentiny/tiny-vue Length of output: 401 🏁 Script executed: # Look for locale or translation files
find . -type f -name "*.json" -path "*locale*" -o -type f -name "*.ts" -path "*locale*"Repository: opentiny/tiny-vue Length of output: 963 🏁 Script executed: # Check vue-common for the t() function implementation to understand i18n usage
find . -path "*vue-common*" -type f | head -20Repository: opentiny/tiny-vue Length of output: 919 🏁 Script executed: # Search for where 'on'/'off' might be defined as i18n keys
rg "\"on\"|\"off\"" --type json | head -30Repository: opentiny/tiny-vue Length of output: 43 🏁 Script executed: # Check if there's a switch-specific locale file
find . -type d -name "switch" | xargs -I {} find {} -name "*.json" -o -name "*.ts"Repository: opentiny/tiny-vue Length of output: 976 🏁 Script executed: # Search for accessible.on or accessible.off patterns in the codebase
rg "accessible|aria" --type jsonRepository: opentiny/tiny-vue Length of output: 169 🏁 Script executed: # Check the English locale file for switch-related keys
cat packages/vue-locale/src/lang/en.ts | grep -i "switch\|yes\|no\|on\|off" -A 2 -B 2Repository: opentiny/tiny-vue Length of output: 19428 🏁 Script executed: # Check the full English locale structure
head -100 packages/vue-locale/src/lang/en.tsRepository: opentiny/tiny-vue Length of output: 2497 🏁 Script executed: # Search for 'yes' and 'no' in locale files
rg "yes|no" packages/vue-locale/src/lang/ -A 1 -B 1Repository: opentiny/tiny-vue Length of output: 50373 🏁 Script executed: # Check if 'on'/'off' keys exist in locale files
rg "on|off" packages/vue-locale/src/lang/ -A 1 -B 1 | head -50Repository: opentiny/tiny-vue Length of output: 2575 🏁 Script executed: # Look at the renderless locale index to understand available keys
cat packages/renderless/src/locales/index.tsRepository: opentiny/tiny-vue Length of output: 3642 Internationalize aria-label values and remove conditional logic. The accessibility attributes are a great addition, but there are two actionable concerns:
🌐 Suggested fix for internationalization- :aria-label="state.showText ? (state.currentValue === trueValue ? 'on' : 'off') : undefined"
+ :aria-label="state.currentValue === trueValue ? t('yes') : t('no')"This uses the existing i18n function and provides labels unconditionally. Consider whether 'yes'/'no' semantics are appropriate for your use case, or add dedicated 'on'/'off' keys to locale files for better semantic alignment. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| :class="[state.wrapClasses, state.showText ? 'tiny-switch__text' : '']" | ||||||||||||||||||
| :tabindex="tabindex" | ||||||||||||||||||
| :style="state.switchStyle" | ||||||||||||||||||
|
|
||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 1251
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 88
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 1040
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 4250
🏁 Script executed:
# Look for icon component imports in the file head -100 packages/vue/src/file-upload/src/mobile-first.vueRepository: opentiny/tiny-vue
Length of output: 2215
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 43
🏁 Script executed:
# Find the IconPlusCircle implementation cat packages/vue-icon/src/plus-circle.tsRepository: opentiny/tiny-vue
Length of output: 277
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 43
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 50373
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 3688
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 291
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 513
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 2791
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 3008
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 2112
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 1180
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 137
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 3460
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 1327
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 456
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 1040
🏁 Script executed:
Repository: opentiny/tiny-vue
Length of output: 1548
The ARIA attributes on IconPlusCircle are not applied to the underlying DOM element.
The
IconPlusCirclecomponent receivesrole="button",tabindex="0", andaria-labelattributes, but they are not forwarded to the rendered SVG. The component's setup function only extractsfill,width,height, andcustom-classfrom context attributes—ARIA attributes are excluded. Additionally, the icon lacks click and keyboard handlers.To fix this:
<button>element, orOn mobile, the icon is shown alone (
sm:hidden) without a button wrapper, making it inaccessible to keyboard users.🤖 Prompt for AI Agents