Skip to content

Commit ead4d54

Browse files
Fix SelectField's icon/styles for field/option.
1 parent 3d425c2 commit ead4d54

File tree

5 files changed

+64
-12
lines changed

5 files changed

+64
-12
lines changed

.changeset/bright-donuts-appear.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte-ux': patch
3+
---
4+
5+
Fix SelectField MenuOption icons no longer being passed to MenuItems. Fix SelectField `classes: { field: ... }` not being incorporated into the inner `TextField` properly. Same with `classes: { option: ... }` not being incorporated into each inner `MenuItem` option. Update SelectField docs page with colored example that differentiates icon & input color, both in the field and the menu items.

packages/svelte-ux/src/lib/components/SelectField.svelte

+38-5
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,41 @@
6767
root?: string;
6868
field?: string | ComponentProps<TextField>['classes'];
6969
options?: string;
70-
option?: string;
70+
option?: string | ComponentProps<MenuItem>['classes'];
7171
selected?: string;
7272
group?: string;
7373
empty?: string;
7474
} = {};
7575
7676
let fieldClasses: ComponentProps<TextField>['classes'];
77-
$: fieldClasses = typeof classes.field === 'string' ? { root: classes.field } : classes.field;
77+
$: {
78+
let v: {root?: any} = {};
79+
if (typeof settingsClasses?.field === 'string') {
80+
v = { root: settingsClasses.field };
81+
} else {
82+
v = settingsClasses?.field ?? {};
83+
}
84+
if (typeof classes?.field === 'string') {
85+
fieldClasses = { ...v, root: cls(v.root, classes.field)};
86+
} else {
87+
fieldClasses = { ...v, ...classes?.field ?? {} };
88+
}
89+
}
90+
91+
let optionClasses: ComponentProps<MenuItem>['classes'];
92+
$: {
93+
let v: {root?: any} = {};
94+
if (typeof settingsClasses?.option === 'string') {
95+
v = { root: settingsClasses.option };
96+
} else {
97+
v = settingsClasses?.option ?? {};
98+
}
99+
if (typeof classes?.option === 'string') {
100+
optionClasses = { ...v, root: cls(v.root, classes.option)};
101+
} else {
102+
optionClasses = { ...v, ...classes?.option ?? {} };
103+
}
104+
}
78105
79106
// Menu props
80107
export let placement: Placement = 'bottom-start';
@@ -425,11 +452,13 @@
425452
on:keypress={onKeyPress}
426453
actions={fieldActions}
427454
classes={{
455+
...fieldClasses,
428456
container: inlineOptions
429-
? 'border-none shadow-none hover:shadow-none group-focus-within:shadow-none'
430-
: undefined,
457+
? cls('border-none shadow-none hover:shadow-none group-focus-within:shadow-none', fieldClasses?.container)
458+
: fieldClasses?.container,
459+
431460
}}
432-
class={cls('h-full', settingsClasses.field, fieldClasses)}
461+
class={cls('h-full')}
433462
role="combobox"
434463
aria-expanded={open ? 'true' : 'false'}
435464
aria-autocomplete={!inlineOptions ? 'list' : undefined}
@@ -534,6 +563,7 @@
534563
<svelte:fragment slot="option" let:option let:index>
535564
<slot name="option" {option} {index} {selected} {value} {highlightIndex}>
536565
<MenuItem
566+
classes={optionClasses}
537567
class={cls(
538568
index === highlightIndex && '[:not(.group:hover)>&]:bg-surface-content/5',
539569
option === selected && (classes.selected || 'font-semibold'),
@@ -549,6 +579,7 @@
549579
role="option"
550580
aria-selected={option === selected ? 'true' : 'false'}
551581
aria-disabled={option?.disabled ? 'true' : 'false'}
582+
icon={option.icon}
552583
>
553584
{optionText(option)}
554585
</MenuItem>
@@ -594,6 +625,7 @@
594625
<svelte:fragment slot="option" let:option let:index>
595626
<slot name="option" {option} {index} {selected} {value} {highlightIndex}>
596627
<MenuItem
628+
classes={optionClasses}
597629
class={cls(
598630
index === highlightIndex && '[:not(.group:hover)>&]:bg-surface-content/5',
599631
option === selected && (classes.selected || 'font-semibold'),
@@ -609,6 +641,7 @@
609641
role="option"
610642
aria-selected={option === selected ? 'true' : 'false'}
611643
aria-disabled={option?.disabled ? 'true' : 'false'}
644+
icon={option.icon}
612645
>
613646
{optionText(option)}
614647
</MenuItem>

packages/svelte-ux/src/lib/components/TextField.svelte

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
error?: string;
7171
prepend?: string;
7272
append?: string;
73+
icon?: string;
7374
} = {};
7475
7576
// Input props
@@ -259,7 +260,7 @@
259260
<slot name="prepend" />
260261
{#if icon}
261262
<span class="mr-3">
262-
<Icon data={asIconData(icon)} class="text-surface-content/50" />
263+
<Icon data={asIconData(icon)} class={cls("text-surface-content/50", classes.icon)} />
263264
</span>
264265
{/if}
265266
</div>

packages/svelte-ux/src/lib/components/_SelectListOptions.svelte

-3
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@
2424
2525
export let classes: {
2626
root?: string;
27-
option?: string;
28-
selected?: string;
2927
group?: string;
30-
empty?: string;
3128
} = {};
3229
3330
const settingsClasses = getComponentClasses('SelectField');

packages/svelte-ux/src/routes/docs/components/SelectField/+page.svelte

+19-3
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@
1515
import { cls } from '$lib/utils/styles';
1616
import type { MenuOption } from '$lib/types';
1717
18-
let options: MenuOption[] = [
18+
let graphicOptions: MenuOption[] = [
1919
{ label: 'One', value: 1, icon: mdiMagnify },
2020
{ label: 'Two', value: 2, icon: mdiPlus },
2121
{ label: 'Three', value: 3, icon: mdiPencil },
2222
{ label: 'Four', value: 4, icon: mdiAccount },
2323
];
2424
25+
let options: MenuOption[] = graphicOptions.map(o => { return { ...o, icon: undefined }; });
26+
2527
const optionsWithGroup: MenuOption[] = [
2628
{ label: 'One', value: 1, group: 'First' },
2729
{ label: 'Two', value: 2, group: 'First' },
@@ -185,7 +187,7 @@
185187
<h2>option slot with icon (field icon updates based on selected option)</h2>
186188

187189
<Preview>
188-
<SelectField {options} bind:value activeOptionIcon={true}>
190+
<SelectField options={graphicOptions} bind:value activeOptionIcon={true}>
189191
<div slot="option" let:option let:index let:selected let:highlightIndex>
190192
<MenuItem
191193
class={cls(
@@ -194,7 +196,6 @@
194196
option.group ? 'px-4' : 'px-2'
195197
)}
196198
scrollIntoView={index === highlightIndex}
197-
icon={{ data: option.icon, style: 'color: #0000FF;' }}
198199
>
199200
{option.label}
200201
</MenuItem>
@@ -371,6 +372,21 @@
371372
<SelectField {options} icon={mdiMagnify} />
372373
</Preview>
373374

375+
<h2>Icon and options with icons (field icon updates based on selected option)</h2>
376+
377+
<Preview>
378+
<SelectField
379+
options={graphicOptions}
380+
bind:value
381+
activeOptionIcon={true}
382+
classes={{
383+
field: { input: 'text-blue-600', icon: 'text-pink-300' },
384+
option: { root: 'text-blue-600', icon: 'text-pink-300' },
385+
}}
386+
on:change={(e) => console.log('on:change', e.detail)}
387+
/>
388+
</Preview>
389+
374390
<h2>Rounded</h2>
375391

376392
<Preview>

0 commit comments

Comments
 (0)