Skip to content

Item ​

Items are the rows of a list: each one holds text plus optional icons, avatars, thumbnails, notes, badges, buttons, or a form control, and can be made tappable or swipeable.

IonItem is the row. IonItemGroup and IonItemDivider split rows into titled sections. IonItemSliding, IonItemOptions, and IonItemOption add swipe-to-reveal actions. Rows usually sit in an IonList; their text goes in an IonLabel.

Basic usage ​

Put the text in an IonLabel. A label in the default slot grows to fill the row, so anything after it is pushed to the trailing edge.

razor
<IonList>
    <IonItem>
        <IonLabel>Inbox</IonLabel>
    </IonItem>
    <IonItem>
        <IonLabel>Drafts</IonLabel>
    </IonItem>
    <IonItem>
        <IonLabel>Archive</IonLabel>
    </IonItem>
</IonList>

Slots ​

Start holds leading content (icons, avatars, thumbnails), End holds trailing content (notes, badges, buttons). Icons placed directly in Start/End get a 24px box and Ionic's slot margins; an avatar shrinks to 40px (md) / 36px (ios) and a thumbnail grows to 56px. Once you use a named slot, put the label in <ChildContent>.

razor
@* Once a named slot (Start / End) is used, the label goes in <ChildContent>. *@
<IonList>
    <IonItem>
        <Start>
            <IonIcon Icon="@Ionicons.Wifi" />
        </Start>
        <ChildContent>
            <IonLabel>Wi-Fi</IonLabel>
        </ChildContent>
        <End>
            <IonNote>Home</IonNote>
        </End>
    </IonItem>
    <IonItem>
        <Start>
            <IonAvatar>
                <img src="https://ionicframework.com/docs/img/demos/avatar.svg" />
            </IonAvatar>
        </Start>
        <ChildContent>
            <IonLabel>Ada Lovelace</IonLabel>
        </ChildContent>
        <End>
            <IonBadge>3</IonBadge>
        </End>
    </IonItem>
</IonList>

Clickable items ​

An item becomes clickable when Button or Href is set: the row surface is rendered as a button (or an a for Href), gets a pointer cursor and a hover wash, and raises OnClick on tap. With Href, the item then navigates through the app's NavigationManager: a forward push with the mode's page transition by default, RouterDirection="back" for a pop transition, or "root" to clear the history stack without a transition. Disabled dims the row and blocks input; neither OnClick nor navigation runs.

razor
<IonList>
    @* Href: tapping navigates to the route (forward push with the mode's page transition). *@
    <IonItem Href="/settings">
        <IonLabel>Settings</IonLabel>
    </IonItem>

    @* Button: a tappable row; handle the tap in OnClick. *@
    <IonItem Button="true" OnClick="Refresh">
        <IonLabel>Refreshed @_refreshes times</IonLabel>
    </IonItem>

    <IonItem Button="true" Disabled="true">
        <IonLabel>Delete account</IonLabel>
    </IonItem>
</IonList>

@code {
    private int _refreshes;

    private void Refresh() => _refreshes++;
}

Detail arrow ​

The trailing chevron follows Detail. When it is unset, the chevron appears only in ios mode and only on clickable items. Detail="true" / "false" forces it on or off in both modes; DetailIcon replaces the icon.

razor
<IonList>
    @* Detail unset: a clickable item shows the chevron in ios mode only. *@
    <IonItem Button="true">
        <IonLabel>Default</IonLabel>
    </IonItem>
    <IonItem Detail="true">
        <IonLabel>Always shown</IonLabel>
    </IonItem>
    <IonItem Button="true" Detail="false">
        <IonLabel>Never shown</IonLabel>
    </IonItem>
    <IonItem Button="true" Detail="true" DetailIcon="@Ionicons.CaretForwardOutline">
        <IonLabel>Custom icon</IonLabel>
    </IonItem>
</IonList>

Lines ​

By default an item draws a hairline under its content that starts after the Start slot and the leading padding (the inset look). Lines="full" draws it across the whole row and Lines="none" removes it. Lines="inset" looks like the default, but it also opts the item out of the list's Lines (see List lines): an item's own value always wins.

razor
<IonList>
    @* Default: the divider starts after the Start slot and the leading padding. *@
    <IonItem>
        <Start>
            <IonIcon Icon="@Ionicons.Star" />
        </Start>
        <ChildContent>
            <IonLabel>Default</IonLabel>
        </ChildContent>
    </IonItem>
    <IonItem Lines="full">
        <Start>
            <IonIcon Icon="@Ionicons.Star" />
        </Start>
        <ChildContent>
            <IonLabel>Full</IonLabel>
        </ChildContent>
    </IonItem>
    <IonItem Lines="none">
        <Start>
            <IonIcon Icon="@Ionicons.Star" />
        </Start>
        <ChildContent>
            <IonLabel>None</IonLabel>
        </ChildContent>
    </IonItem>
</IonList>

Buttons in items ​

An IonButton inside an item or item divider that has no Size is rendered small, as in Ionic. Set any Size, including "default", to keep the button's own size.

razor
<IonList>
    @* A button in an item defaults to Size="small". *@
    <IonItem>
        <ChildContent>
            <IonLabel>Backup codes</IonLabel>
        </ChildContent>
        <End>
            <IonButton Fill="outline">Show</IonButton>
        </End>
    </IonItem>

    @* Any explicit Size (including "default") keeps the button's own size. *@
    <IonItem>
        <ChildContent>
            <IonLabel>Storage</IonLabel>
        </ChildContent>
        <End>
            <IonButton Size="default">Upgrade</IonButton>
        </End>
    </IonItem>
</IonList>

Inputs in items ​

Put a form control in the default slot; it renders its own label (Label on IonInput and IonSelect, the child content of IonToggle and IonCheckbox). The item cascades a marker the controls react to: IonInput and IonSelect drop their highlight bar because the item already draws a divider, and toggles, checkboxes, and radios stretch across the row.

razor
@* Form controls go in the default slot and bring their own label. *@
<IonList>
    <IonItem>
        <IonInput Label="Name" Placeholder="Your name" @bind-Value="_name" />
    </IonItem>
    <IonItem>
        <IonInput Label="Email" LabelPlacement="stacked" @bind-Value="_email" />
    </IonItem>
    <IonItem>
        <IonToggle @bind-Checked="_notifications">Notifications</IonToggle>
    </IonItem>
    <IonItem>
        <IonCheckbox @bind-Checked="_terms">I agree to the terms</IonCheckbox>
    </IonItem>
</IonList>

@code {
    private string? _name;
    private string? _email;
    private bool _notifications = true;
    private bool _terms;
}

Color ​

Color takes a palette name: the row is filled with the color and its text — including IonLabels without their own Color — switches to the color's contrast color, as in Ionic. Ionic also darkens the row's divider to the color's shade; here the divider keeps the theme's border color.

razor
@* The row is filled with the palette color; the label takes the contrast color. *@
<IonList>
    <IonItem Button="true" Color="danger">
        <IonLabel>Delete account</IonLabel>
    </IonItem>
</IonList>

Item groups and dividers ​

IonItemGroup is a plain block that groups one section's rows. IonItemDivider is the section header: a tinted row with its own minimum height, Start/End slots, and a bottom hairline. Color fills the divider with the palette color. Ionic's sticky is not ported (Miko has no position: sticky), so the divider scrolls with the content.

razor
<IonList>
    <IonItemGroup>
        <IonItemDivider>
            <IonLabel>Fruits</IonLabel>
        </IonItemDivider>
        <IonItem>
            <IonLabel>Apple</IonLabel>
        </IonItem>
        <IonItem>
            <IonLabel>Banana</IonLabel>
        </IonItem>
    </IonItemGroup>

    <IonItemGroup>
        <IonItemDivider>
            <IonLabel>Vegetables</IonLabel>
        </IonItemDivider>
        <IonItem>
            <IonLabel>Carrot</IonLabel>
        </IonItem>
        <IonItem>
            <IonLabel>Spinach</IonLabel>
        </IonItem>
    </IonItemGroup>
</IonList>

Sliding items ​

IonItemSliding wraps one IonItem and up to two IonItemOptions, one per Side ("end" by default, or "start"). A horizontal swipe of at least 32px to the left opens the end options and a swipe to the right opens the start options; a swipe in the other direction closes the row again. A drag that is mostly vertical is left to scrolling. The options slide in over the row's edge when the swipe is released; the row does not follow the finger and the item itself does not move.

Keep the open state in your component. Bind Open with @bind-Open, pass OpenSide, and update the side from OnSwipe. A row keeps a swipe's open state when the parent re-renders, but the OpenSide you pass decides which options an open row shows: with only @bind-Open, a start swipe reveals the end options. To close the row from code, for example after an option was tapped, set the bound value to false.

Unlike Ionic, tapping the row does not close it, opening one row does not close the others, and Expandable does not add a full-swipe action. Disabled on IonItemSliding turns the swipe off.

razor
@* Swipe left reveals the end options, swipe right the start options. Keep Open and the side in
   your own state: an open row shows the options of the OpenSide you pass. *@
<IonList>
    @foreach (var message in _messages)
    {
        <IonItemSliding @bind-Open="message.Open" OpenSide="@message.Side" OnSwipe="side => message.Side = side">
            <IonItem>
                <IonLabel>@message.Subject</IonLabel>
            </IonItem>
            <IonItemOptions Side="start">
                <IonItemOption OnClick="() => message.Open = false">Unread</IonItemOption>
            </IonItemOptions>
            <IonItemOptions Side="end">
                <IonItemOption Color="danger" OnClick="() => _messages.Remove(message)">Delete</IonItemOption>
            </IonItemOptions>
        </IonItemSliding>
    }
</IonList>

@code {
    private readonly List<Message> _messages =
    [
        new("Lunch on Friday?"),
        new("Quarterly report"),
        new("Your order has shipped"),
    ];

    private sealed class Message(string subject)
    {
        public string Subject { get; } = subject;
        public bool Open { get; set; }
        public string Side { get; set; } = "end";
    }
}

API ​

Every component also accepts Class (extra CSS classes), Style (an inline Style object) and Id (the root element's id) — see Conventions.

IonItem ​

ParameterTypeDefaultDescription
ButtonboolfalseWhen true, the item renders a clickable button native surface and becomes activatable (Ionic button).
Colorstring?nullNamed palette color (Ionic color): "primary", "danger", …. Fills the row with the palette color and switches its text — including IonLabels without their own color — to the color's contrast color, as in Ionic.
Detailbool?nullWhen set, forces the detail chevron on (true) or off (false). When null, Ionic shows it only on iOS for a clickable item. Mirrors Ionic detail.
DetailIconstring"chevron-forward"Icon used for the detail chevron (Ionic detailIcon). Defaults to chevron-forward.
DisabledboolfalseWhen true, the item is dimmed and non-interactive (Ionic disabled).
Hrefstring?nullLink target (Ionic href). When set, the native surface is an a and the item is clickable; the default click behavior navigates to the target through the injected NavigationManager with a mode page transition (iOS push / MD fade-up).
Linesstring?nullHow the bottom border is displayed (Ionic lines): "full", "inset", or "none". Null uses the theme default hairline.
RouterDirectionstring?nullNavigation direction when Href is clicked (mirrors Ionic's routerDirection): "forward" (default — push with transition), "back" (pop-style reverse transition), or "root" (clear the history stack, no transition).
EventTypeDescription
OnClickEventCallbackRaised when a clickable item is tapped (skipped when disabled).
SlotTypeDescription
ChildContentRenderFragment?Content placed between the component's tags.
EndRenderFragment?Content for Ionic's end slot — placed after the label (right in LTR). Typically a trailing note or control.
StartRenderFragment?Content for Ionic's start slot — placed before the label (left in LTR). Typically a leading icon or avatar.

IonItemDivider ​

ParameterTypeDefaultDescription
Colorstring?nullNamed palette color (Ionic color): "primary", "danger", …. Fills the divider with the palette color and switches its text to the color's contrast color, as in Ionic.
SlotTypeDescription
ChildContentRenderFragment?Content placed between the component's tags.
EndRenderFragment?Content for Ionic's end slot — placed after the label (right in LTR).
StartRenderFragment?Content for Ionic's start slot — placed before the label (left in LTR).

IonItemGroup ​

SlotTypeDescription
ChildContentRenderFragment?Content placed between the component's tags.

IonItemSliding ​

ParameterTypeDefaultDescription
DisabledboolfalseWhen true, the row cannot be slid (Ionic disabled disables the swipe gesture).
OpenboolfalseWhen true the row is slid open, revealing the options on OpenSide. Bind it (@bind-Open) to open or close the row from code. Unbound, the row keeps a swipe's open state across re-renders of the parent until the value passed here changes.
OpenSidestring"end"Which side's options are revealed when Open is true: "end" (default) or "start". A swipe does not write this back — update it from OnSwipe when the row has start options.
EventTypeDescription
OnSwipeEventCallback<string>Raised after a recognized horizontal swipe (at least 32px), before OpenChanged, with the side it points to: "end" for a swipe to the left, "start" for a swipe to the right.
OpenChangedEventCallback<bool>Raised when a swipe opens or closes the row.
SlotTypeDescription
ChildContentRenderFragment?Content placed between the component's tags.

IonItemOptions ​

ParameterTypeDefaultDescription
Sidestring"end"Edge these options are anchored to: "end" (default) or "start". Mirrors Ionic's side attribute on ion-item-options.
SlotTypeDescription
ChildContentRenderFragment?Content placed between the component's tags.

IonItemOption ​

ParameterTypeDefaultDescription
Colorstring?nullNamed palette color for the fill (e.g. "primary", "danger", "success"). Null uses the default option fill. Mirrors Ionic's color.
DisabledboolfalseWhen true the option is dimmed and non-interactive (Ionic disabled).
ExpandableboolfalseIonic expandable. Stamps item-option-expandable (flex-grow: 1 within its IonItemOptions); Ionic's full-swipe expansion that covers the other options and triggers this one is not implemented.
Hrefstring?nullRoute to navigate to (Ionic href). When set, the native surface is an a, and a tap raises OnClick and then navigates through the app's NavigationManager with the mode's page transition, like IonItem.
RouterDirectionstring?nullNavigation direction for Href (Ionic routerDirection): "forward" (default — push with the mode's transition), "back" (pop-style transition), or "root" (clear the history, no transition).
EventTypeDescription
OnClickEventCallbackRaised when the option is tapped (skipped when disabled).
SlotTypeDescription
ChildContentRenderFragment?Content placed between the component's tags.

Styling ​

Theme tokens ​

Theme token IonicTheme.Item (ItemToken). Assign only the values you want to change — the rest keep the mode defaults below. App-wide: builder.AddIonic(o => o.Theme.Item = new ItemToken { … }); for one subtree: a ConfigProvider. See Theming.

TokenTypemdios
AvatarEndSlotMarginStartfloat168
AvatarSizefloat4036
AvatarSlotMarginVerticalfloat82
AvatarStartSlotMarginEndfloat1616
BorderColorColorrgba(0, 0, 0, 0.07)rgba(0, 0, 0, 0.2)
ColorColor#000000#000000
DividerBackgroundColor#f2f2f2#f7f7f7
DividerColorColor#404040#000000
DividerMinHeightfloat3028
IconEndSlotMarginStartfloat160
IconSlotMarginVerticalfloat127
IconStartSlotMarginEndfloat3216
LabelMarginEndfloat08
LabelMarginVerticalfloat1010
MinHeightfloat4844
OptionBackgroundColor#0054e9#0054e9
OptionColorColor#ffffff#ffffff
PaddingEndfloat1616
PaddingStartfloat1616
ThumbnailSizefloat5656

The divider's font size is the HeaderFontSize token of the List theme. Standalone avatar and thumbnail sizes are on the Avatar and Thumbnail pages.

CSS classes ​

App stylesheet rules always win over Ionic's own rules (see Theming), so these classes can be targeted directly from GlobalStyles.cs.

SelectorElement
.ion-itemThe item host. Also carries the mode (md / ios) and the state classes below.
.ion-item .item-nativeThe row surface (div, button for Button, a for Href): flex row, minimum height, leading padding, hover wash.
.ion-item .item-innerEverything after the Start slot. Carries the trailing padding and the default divider.
.ion-item .input-wrapperWraps the default slot.
.ion-item .item-native > .ion-slot-start, .ion-item .item-inner > .ion-slot-endThe Start / End slot wrappers. The ion-slot-* classes are shared with other components, so anchor them like this.
.ion-item .item-detail-iconThe detail chevron.
.item-lines-default, .item-lines-full, .item-lines-inset, .item-lines-noneThe resolved Lines (default when unset).
.ion-activatable, .item-disabledClickable (Button / Href), Disabled.
.ion-color, .ion-color-{name}Color (e.g. .ion-color-danger).
.item-last-in-listThe last item of an inset list (stamped by IonList).
.ion-item-divider, .item-divider-inner, .item-divider-wrapperThe divider host, its inner row, and the default-slot wrapper.
.ion-item-groupThe group.
.ion-item-sliding, .item-sliding-open, .item-sliding-open-start, .item-sliding-open-end, .item-sliding-disabledThe sliding host and its open / disabled state.
.ion-item-options, .item-options-start, .item-options-endAn options container and its Side.
.ion-item-option, .ion-item-option .button-nativeAn option host (carries the fill) and its clickable surface.
.item-option-expandable, .item-option-disabledExpandable, Disabled on an option.
csharp
// GlobalStyles.cs — roomier rows in one list: <IonList Class="roomy">…</IonList>
[".roomy .ion-item .item-native"] = new()
{
    MinHeight = Length.Px(64),
},

Released under the MIT License.