diff --git a/docs/pages/components/select.md b/docs/pages/components/select.md
index 6fd05cbe1..872563817 100644
--- a/docs/pages/components/select.md
+++ b/docs/pages/components/select.md
@@ -454,3 +454,58 @@ const App = () => (
>
);
```
+
+### Custom Tags
+
+When multiple options can be selected, you can provide custom tags by passing a function to the `getTag` property.
+Your `getTag(option, index)` function can return a string, a Lit Template,
+or an HTMLElement.
+
+```html:preview
+
+
+
+ Email
+
+
+
+
+
+ Phone
+
+
+
+
+
+ Chat
+
+
+ Option 4
+ Option 5
+
+
+
+
+```
diff --git a/src/components/select/select.component.ts b/src/components/select/select.component.ts
index 54d809854..9bc5a0cd3 100644
--- a/src/components/select/select.component.ts
+++ b/src/components/select/select.component.ts
@@ -8,6 +8,7 @@ import { html } from 'lit';
import { LocalizeController } from '../../utilities/localize.js';
import { property, query, state } from 'lit/decorators.js';
import { scrollIntoView } from '../../internal/scroll.js';
+import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { waitForEvent } from '../../internal/event.js';
import { watch } from '../../internal/watch.js';
import ShoelaceElement from '../../internal/shoelace-element.js';
@@ -15,7 +16,7 @@ import SlIcon from '../icon/icon.component.js';
import SlPopup from '../popup/popup.component.js';
import SlTag from '../tag/tag.component.js';
import styles from './select.styles.js';
-import type { CSSResultGroup } from 'lit';
+import type { CSSResultGroup, TemplateResult } from 'lit';
import type { ShoelaceFormControl } from '../../internal/shoelace-element.js';
import type SlOption from '../option/option.component.js';
import type SlRemoveEvent from '../../events/sl-remove.js';
@@ -172,6 +173,31 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon
/** The select's required attribute. */
@property({ type: Boolean, reflect: true }) required = false;
+ /**
+ * A function that customizes the tags to be rendered when multiple=true. The first argument is the option, the second
+ * is the current tag's index. The function should return either a Lit TemplateResult or a string containing trusted HTML of the symbol to render at
+ * the specified value.
+ */
+ @property() getTag: (option: SlOption, index: number) => TemplateResult | string | HTMLElement = option => {
+ return html`
+ this.handleTagRemove(event, option)}
+ >
+ ${option.getTextLabel()}
+
+ `;
+ };
+
/** Gets the validity state object */
get validity() {
return this.valueInput.validity;
@@ -547,6 +573,21 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon
this.formControlController.updateValidity();
});
}
+ protected get tags() {
+ return this.selectedOptions.map((option, index) => {
+ if (index < this.maxOptionsVisible || this.maxOptionsVisible <= 0) {
+ const tag = this.getTag(option, index);
+ // Wrap so we can handle the remove
+ return html`