|
88 | 88 | { value: 'linking', label: 'Linking', icon: Link2, iconColor: '#3B82F6' } |
89 | 89 | ]; |
90 | 90 |
|
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 | + }; |
92 | 96 |
|
93 | 97 | // Asset field configuration |
94 | 98 | let assetSetId = $state(null); |
|
275 | 279 | linkingMirrorAllowedItemTypeIds = []; |
276 | 280 | } |
277 | 281 |
|
| 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 | +
|
278 | 291 | // Board-configuration routes this page may return to. External, protocol- |
279 | 292 | // relative, and unrelated paths are rejected rather than trusted. |
280 | 293 | function validateReturnTo(raw) { |
|
661 | 674 | ]); |
662 | 675 | </script> |
663 | 676 |
|
| 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 | +
|
664 | 685 | <PageHeader |
665 | 686 | icon={Database} |
666 | 687 | title={t('fields.title')} |
|
734 | 755 |
|
735 | 756 | <div> |
736 | 757 | <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')} |
746 | 764 | 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} |
763 | 771 | /> |
764 | 772 | {#if editingField} |
765 | 773 | <p class="mt-2 text-xs" style="color: var(--ds-text-subtle);"> |
|
0 commit comments