# Inputs >> Select Rich >> Features ||20
```js script
import { LitElement, html } from '@lion/core';
import '@lion/listbox/define';
import '@lion/listbox/define';
import '@lion/select-rich/define';
```
## Model value
You can set the full `modelValue` for each option, which includes the checked property for whether it is checked or not.
```html
Red
```
## Options with HTML
The main feature of this rich select that makes it rich, is that your options can contain HTML.
```js preview-story
export const optionsWithHTML = () => html`
`;
};
```
## Interaction Mode
You can set the interaction mode to either `mac` or `windows/linux`.
By default, it will choose based on the user Operating System, but it can be forced.
This changes the keyboard interaction.
```js preview-story
export const interactionMode = () => html`
RedHotpinkTealRedHotpinkTeal
`;
```
## Checked index & value
You can get/set the checkedIndex and checkedValue.
```js preview-story
export const checkedIndexAndValue = ({ shadowRoot }) => html`
RedHotpinkTeal
`;
```
## No default selection
If you want to set a placeholder option with something like 'Please select', you can of course do this, the same way you would do it in a native select.
Simply put an option with a modelValue that is `null`.
```html
select a color
```
However, this allows the user to explicitly select this option.
Often, you may want a placeholder that appears initially, but cannot be selected explicitly by the user.
For this you can use `has-no-default-selected` attribute.
```js preview-story
export const noDefaultSelection = () => html`
RedHotpinkTeal
`;
```
> By default, the placeholder is completely empty in the `LionSelectInvoker`,
> but subclassers can easily override this in their extension, by the overriding `_noSelectionTemplate()` method.
## Single Option
If there is a single option rendered, then `singleOption` property is set to `true` on `lion-select-rich` and invoker as well. Invoker also gets `single-option` which can be used to having desired templating and styling. As in here the arrow is not displayed for single option
```js preview-story
export const singleOption = () => html`
Red
`;
```
When adding/removing options the `singleOption` will only be `true` when there is exactly one option.
```js preview-story
class SingleOptionRemoveAdd extends LitElement {
static get properties() {
return {
options: { type: Array },
};
}
constructor() {
super();
this.options = ['Option 1', 'Option 2'];
}
render() {
return html`
${this.options.map(
option => html` ${option} `,
)}
`;
}
addOption() {
this.options.push(`Option ${this.options.length + 1} with a long title`);
this.options = [...this.options];
this.requestUpdate();
}
removeOption() {
if (this.options.length >= 2) {
this.options.pop();
this.options = [...this.options];
this.requestUpdate();
}
}
}
customElements.define('single-option-remove-add', SingleOptionRemoveAdd);
export const singleOptionRemoveAdd = () => {
return html``;
};
```
## Custom Invoker
You can provide a custom invoker using the invoker slot.
This means it will get the selected value(s) as an input property `.selectedElement`.
You can use this `selectedElement` to then render the content to your own invoker.
```html
...
```
An example of how such a custom invoker class could look like:
```js
class MyInvokerButton extends LitElement() {
static get properties() {
return {
selectedElement: {
type: Object,
};
}
}
_contentTemplate() {
if (this.selectedElement) {
const labelNodes = Array.from(this.selectedElement.childNodes);
// Nested html in the selected option
if (labelNodes.length > 0) {
// Cloning is important if you plan on passing nodes straight to a lit template
return labelNodes.map(node => node.cloneNode(true));
}
// Or if it is just text inside the selected option, no html
return this.selectedElement.textContent;
}
return ``;
}
render() {
return html`
${this._contentTemplate()}
`;
}
}
```
> This example only works if your option elements don't have ShadowDOM boundaries themselves.
> Cloning deeply only works up until the first shadow boundary.