Skip to content

Commit 7b223bd

Browse files
committed
fix: prevent users from being able to select disabled dropdown items
1 parent 0aac828 commit 7b223bd

2 files changed

Lines changed: 30 additions & 7 deletions

File tree

static/css/v3/forms.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@
401401
.dropdown__item--disabled:hover,
402402
.dropdown__item--disabled:focus {
403403
background-color: transparent;
404+
color: var(--color-text-secondary);
404405
}
405406

406407
.field--error .dropdown__trigger {

templates/v3/includes/_field_dropdown.html

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,28 @@
5959
this.selected = this.defaultValue;
6060
this.selectedLabel = label;
6161
this.$dispatch('field-change', { name: '{{ name }}', value: this.defaultValue, label });
62+
},
63+
focusNextEnabled(el) {
64+
let n = el.nextElementSibling;
65+
while (n && n.hasAttribute('data-value') && this.disabledValues.includes(n.dataset.value)) {
66+
n = n.nextElementSibling;
67+
}
68+
if (n && n.hasAttribute('data-value')) n.focus();
69+
},
70+
focusPrevEnabled(el) {
71+
let p = el.previousElementSibling;
72+
while (p && p.hasAttribute('data-value') && this.disabledValues.includes(p.dataset.value)) {
73+
p = p.previousElementSibling;
74+
}
75+
if (p && p.hasAttribute('data-value')) p.focus();
76+
else this.$refs.trigger.focus();
77+
},
78+
firstEnabledOption() {
79+
const opts = this.$refs.list.querySelectorAll('[data-value]');
80+
for (const el of opts) {
81+
if (!this.disabledValues.includes(el.dataset.value)) return el;
82+
}
83+
return null;
6284
}
6385
}">
6486
{# djlint:on #}
@@ -85,7 +107,7 @@
85107
@keydown.enter.prevent="open = !open"
86108
@keydown.space.prevent="open = !open"
87109
@keydown.escape.prevent="open = false"
88-
@keydown.arrow-down.prevent="open = true; $nextTick(() => $refs.list.querySelector('[role=option]')?.focus())"
110+
@keydown.arrow-down.prevent="open = true; $nextTick(() => firstEnabledOption()?.focus())"
89111
:aria-expanded="open"
90112
aria-haspopup="listbox"
91113
{% if label %}aria-labelledby="field-{{ name }}-label"{% endif %}
@@ -131,12 +153,12 @@
131153
:aria-disabled="disabledValues.includes('{{ value }}')"
132154
data-value="{{ value }}"
133155
data-label="{{ label }}"
134-
@click="choose('{{ value }}', '{{ label }}')"
135-
@keydown.enter.prevent="choose('{{ value }}', '{{ label }}')"
136-
@keydown.space.prevent="choose('{{ value }}', '{{ label }}')"
137-
@keydown.arrow-down.prevent="$el.nextElementSibling?.focus()"
138-
@keydown.arrow-up.prevent="$el.previousElementSibling?.hasAttribute('data-value') ? $el.previousElementSibling.focus() : $refs.trigger.focus()"
139-
tabindex="0">{{ label }}</div>
156+
@click="if (!disabledValues.includes('{{ value }}')) choose('{{ value }}', '{{ label }}')"
157+
@keydown.enter.prevent="if (!disabledValues.includes('{{ value }}')) choose('{{ value }}', '{{ label }}')"
158+
@keydown.space.prevent="if (!disabledValues.includes('{{ value }}')) choose('{{ value }}', '{{ label }}')"
159+
@keydown.arrow-down.prevent="focusNextEnabled($el)"
160+
@keydown.arrow-up.prevent="focusPrevEnabled($el)"
161+
:tabindex="disabledValues.includes('{{ value }}') ? -1 : 0">{{ label }}</div>
140162
{% endfor %}
141163
</div>
142164
</div>

0 commit comments

Comments
 (0)