Skip to content

Commit 5b78e96

Browse files
committed
2 parents bccd6a0 + 6d33099 commit 5b78e96

2 files changed

Lines changed: 35 additions & 27 deletions

File tree

frontend/src/lib/pickers/BasePicker.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@
577577
{#if loading}
578578
<div class="p-4 text-center" style="color: var(--ds-text-subtle);">{t('common.loading')}</div>
579579
{:else if options.length > 0}
580-
<div role="listbox" class="max-h-60 overflow-y-auto">
580+
<div role="listbox" data-testid="picker-option-list" class="max-h-60 overflow-y-auto">
581581
{#each options as opt, index (opt.value ?? 'unassigned')}
582582
{@const itemSelected = multiple ? isItemSelected(opt.value) : $isSelected(opt)}
583583
{@const isHighlighted = highlightedIndex === index}

frontend/src/lib/settings/CustomFields.svelte

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,11 @@
8888
{ value: 'linking', label: 'Linking', icon: Link2, iconColor: '#3B82F6' }
8989
];
9090
91-
const selectedFieldType = $derived(fieldTypes.find(ft => ft.value === formData.field_type));
91+
const fieldTypePickerPositioning = {
92+
strategy: 'fixed',
93+
placement: 'bottom-start',
94+
sameWidth: true
95+
};
9296
9397
// Asset field configuration
9498
let assetSetId = $state(null);
@@ -275,6 +279,15 @@
275279
linkingMirrorAllowedItemTypeIds = [];
276280
}
277281
282+
function selectFieldType(type) {
283+
if (!type) return;
284+
if (isBooleanCustomFieldType(type.value)) {
285+
optionItems = [];
286+
nextOptionId = 1;
287+
}
288+
formData.field_type = type.value;
289+
}
290+
278291
// Board-configuration routes this page may return to. External, protocol-
279292
// relative, and unrelated paths are rejected rather than trusted.
280293
function validateReturnTo(raw) {
@@ -661,6 +674,14 @@
661674
]);
662675
</script>
663676
677+
{#snippet fieldTypeOption({ item: fieldType })}
678+
{@const FieldTypeIcon = fieldType.icon}
679+
<div class="flex items-center gap-3 min-w-0">
680+
<FieldTypeIcon class="w-4 h-4 flex-shrink-0" style="color: {fieldType.iconColor};" />
681+
<span class="truncate">{fieldType.label}</span>
682+
</div>
683+
{/snippet}
684+
664685
<PageHeader
665686
icon={Database}
666687
title={t('fields.title')}
@@ -734,32 +755,19 @@
734755
735756
<div>
736757
<Label for="field-type" required class="mb-2">{t('fields.fieldType')}</Label>
737-
<DropdownMenu
738-
triggerTestid="custom-field-type-trigger"
739-
triggerIcon={selectedFieldType?.icon}
740-
triggerIconBgColor={selectedFieldType?.iconColor}
741-
triggerText={selectedFieldType?.label || 'Select type...'}
742-
triggerClass="w-full h-[38px] rounded-lg border px-3 text-sm"
743-
triggerStyle="border-color: var(--ds-border); background: var(--ds-surface); color: var(--ds-text);"
744-
triggerAlignment="between"
745-
showChevron={true}
758+
<BasePicker
759+
id="field-type"
760+
value={formData.field_type}
761+
items={fieldTypes}
762+
placeholder="Select type..."
763+
ariaLabel={t('fields.fieldType')}
746764
disabled={!!editingField}
747-
maxWidth="max-w-72"
748-
items={fieldTypes.map(type => ({
749-
id: type.value,
750-
type: 'regular',
751-
icon: type.icon,
752-
iconColor: type.iconColor,
753-
title: type.label,
754-
testid: `custom-field-type-${type.value}`,
755-
onClick: () => {
756-
if (isBooleanCustomFieldType(type.value)) {
757-
optionItems = [];
758-
nextOptionId = 1;
759-
}
760-
formData.field_type = type.value;
761-
}
762-
}))}
765+
getValue={(type) => type.value}
766+
getLabel={(type) => type.label}
767+
itemSnippet={fieldTypeOption}
768+
optionTestid={(option) => `custom-field-type-${option.value}`}
769+
positioning={fieldTypePickerPositioning}
770+
onSelect={selectFieldType}
763771
/>
764772
{#if editingField}
765773
<p class="mt-2 text-xs" style="color: var(--ds-text-subtle);">

0 commit comments

Comments
 (0)