Skip to content

Commit c380398

Browse files
duncanmccleanclaudejasonvarga
authored
[6.x] Combobox 2.0 (#13843)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Jason Varga <jason@pixelfear.com>
1 parent 2a2966f commit c380398

File tree

18 files changed

+1501
-457
lines changed

18 files changed

+1501
-457
lines changed

.storybook/preview.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {router} from '@inertiajs/vue3';
55
import {action} from 'storybook/actions';
66
import './storybook.css';
77
import './theme.css';
8-
import {translate} from '@/translations/translator';
8+
import {translate, translateChoice} from '@/translations/translator';
99
import registerUiComponents from '@/bootstrap/ui';
1010
import DateFormatter from '@/components/DateFormatter';
1111
import NumberFormatter from '@/components/NumberFormatter';
@@ -25,6 +25,7 @@ router.on('before', (event) => {
2525

2626
setup(async (app) => {
2727
window.__ = translate;
28+
window.__n = translateChoice;
2829

2930
window.Statamic = {
3031
$config: {
@@ -63,6 +64,7 @@ setup(async (app) => {
6364
};
6465

6566
app.config.globalProperties.__ = translate;
67+
app.config.globalProperties.__n = translateChoice;
6668
app.config.globalProperties.$date = new DateFormatter;
6769
app.config.globalProperties.$number = new NumberFormatter;
6870
app.config.globalProperties.cp_url = (url) => url;

.storybook/storybook.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
@custom-variant dark (&:where(.dark, .dark *));
1010

1111
:root {
12+
--focus-outline-color: var(--color-blue-400);
13+
1214
/* GROUP VARIABLES -- DECORATION -- COLOURS
1315
=================================================== */
1416
--color-code-background: hsl(287deg 80% 93.5%);

resources/js/components/SiteSelector.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ defineEmits(['update:modelValue']);
1515
:options="sites"
1616
option-label="name"
1717
option-value="handle"
18+
align="end"
19+
:adaptive-width="true"
1820
:model-value="modelValue"
1921
@update:model-value="$emit('update:modelValue', $event)"
2022
/>

resources/js/components/field-conditions/Condition.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
<template #no-options><div class="hidden" /></template>
1616
<template #option="option">
1717
<div class="flex items-center">
18-
<span v-text="option.label" />
18+
<span class="flex-shrink-0 truncate" v-text="option.label" />
1919
<span
2020
v-text="option.value"
21-
class="font-mono text-2xs text-gray-500 dark:text-gray-300"
21+
class="font-mono text-2xs text-gray-500 dark:text-gray-300 truncate"
2222
:class="{ 'ml-2': option.label }"
2323
/>
2424
</div>
@@ -29,7 +29,7 @@
2929
</Combobox>
3030
</div>
3131

32-
<div class="w-auto min-w-32">
32+
<div class="w-auto min-w-40">
3333
<Select
3434
class="w-full"
3535
:model-value="condition.operator"

resources/js/components/field-validation/Builder.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
<button
7777
type="button"
7878
class="opacity-75 hover:opacity-100 cursor-pointer"
79-
:aria-label="__('Deselect option')"
79+
:aria-label="__('Remove :label', { label: rule })"
8080
@click="remove(rule)"
8181
>
8282
&times;
@@ -236,6 +236,8 @@ export default {
236236
if (!this.rules.includes(rule)) {
237237
this.rules.push(rule);
238238
}
239+
240+
this.$nextTick(() => this.$refs.rulesSelect.focus());
239241
},
240242
241243
add(rule) {
@@ -258,8 +260,6 @@ export default {
258260
if (this.searchNotFound(rulesSelect) || this.hasUnfinishedParameters(rule)) return;
259261
260262
this.add(rule);
261-
262-
this.$nextTick(() => this.$refs.searchInput.blur());
263263
},
264264
265265
remove(rule) {

resources/js/components/fieldtypes/DictionaryFieldtype.vue

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
<div
3434
v-for="option in selectedOptions"
3535
:key="getOptionValue(option)"
36-
class="sortable-item cursor-grab"
36+
class="sortable-item cursor-grab active:cursor-grabbing"
3737
>
3838
<Badge size="lg" color="white">
3939
<div v-if="labelHtml" v-html="getOptionLabel(option)"></div>
@@ -43,18 +43,14 @@
4343
v-if="!disabled && !readOnly"
4444
type="button"
4545
class="-mx-3 cursor-pointer px-3 text-gray-400 hover:text-gray-700"
46-
:aria-label="__('Deselect option')"
47-
@click="deselect(option.value)"
46+
:aria-label="__('Remove :label', { label: getOptionLabel(option) })"
47+
@click="deselect(getOptionValue(option))"
4848
>
4949
<span>&times;</span>
5050
</button>
51-
<button
52-
v-else
53-
type="button"
54-
class="-mx-3 cursor-pointer px-3 text-gray-400 hover:text-gray-700"
55-
>
51+
<span v-else class="-mx-3 cursor-pointer px-3 text-gray-400 hover:text-gray-700">
5652
<span>&times;</span>
57-
</button>
53+
</span>
5854
</Badge>
5955
</div>
6056
</div>

resources/js/components/fieldtypes/SelectFieldtype.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<template>
22
<Combobox
3+
:id="id"
34
:clearable="config.clearable"
45
:disabled="config.disabled"
56
:label-html="config.label_html"
@@ -11,7 +12,7 @@
1112
:read-only="isReadOnly"
1213
:searchable="config.searchable || config.taggable"
1314
:taggable="config.taggable"
14-
:id="id"
15+
:close-on-select="(config.taggable && !options.length) || !config.multiple"
1516
@update:modelValue="comboboxUpdated"
1617
/>
1718
</template>

resources/js/components/fieldtypes/TagsFieldtype.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
:placeholder="__(config.placeholder)"
99
:read-only="isReadOnly"
1010
:taggable="true"
11+
:should-open-dropdown="(open) => open && options.length > 0"
1112
@update:modelValue="update"
1213
/>
1314
</template>

resources/js/components/global-header/SiteSelector.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
size="sm"
1111
variant="ghost"
1212
icon="globe-arrow"
13+
align="end"
14+
:adaptive-width="true"
1315
class="[&_[data-ui-combobox-trigger]]:text-white/85"
1416
/>
1517
</div>

resources/js/components/inputs/relationship/SelectField.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
:placeholder="__(config.placeholder) || __('Choose...')"
1212
:read-only="readOnly"
1313
:taggable="isTaggable"
14+
:close-on-select="isTaggable"
1415
option-label="title"
1516
option-value="id"
1617
@update:modelValue="itemsSelected"
@@ -27,7 +28,7 @@
2728
<div v-text="noOptionsText" />
2829
</template>
2930
<template #selected-option>
30-
<span v-if="items.length === 1" v-text="items[0].title"></span>
31+
<span v-if="items.length === 1" v-text="items[0].title" class="truncate"></span>
3132
</template>
3233
<template #selected-options>
3334
<!-- We don't want to display the selected options here. The RelationshipInput component does that for us. -->

0 commit comments

Comments
 (0)