Skip to content

Item

An item is a flexible list entry used to display structured content such as a media element, text, and actions. It is composed of several sub-components that each handle a specific area of the item.

Bas MiliusEngineer
Jane DoeDesigner
John DoeProduct manager

Props

is-control?: boolean
Renders the item as a label so that clicking anywhere in the row toggles the single form control (toggle, checkbox or radio) it contains.

Slots

default
The content of the item, typically composed of item sub-components.

Examples

Clickable

Wrap an item in a clickable pane to turn it into an interactive list entry. The whole row highlights on hover.

<template>
    <div style="display: flex; flex-flow: column; gap: 9px; width: min(100%, 420px)">
        <FluxClickablePane
            v-for="project in projects"
            :key="project.name"
            type="button">
            <FluxItem>
                <FluxItemMedia
                    is-center
                    :size="40">
                    <FluxBoxedIcon
                        :color="project.color"
                        :name="project.icon"
                        :size="40"/>
                </FluxItemMedia>

                <FluxItemContent is-center>
                    <strong>{{ project.name }}</strong>
                    <span style="font-size: .875rem; opacity: .6">{{ project.description }}</span>
                </FluxItemContent>

                <FluxItemMedia is-center>
                    <FluxIcon
                        name="angle-right"
                        style="opacity: .4"/>
                </FluxItemMedia>
            </FluxItem>
        </FluxClickablePane>
    </div>
</template>

<script
    setup
    lang="ts">
    import type { FluxColor, FluxIconName } from '@flux-ui/types';
    import { FluxBoxedIcon, FluxClickablePane, FluxIcon, FluxItem, FluxItemContent, FluxItemMedia } from '@flux-ui/components';

    const projects: { name: string; description: string; icon: FluxIconName; color: FluxColor }[] = [
        {name: 'Aurora', description: 'Design system', icon: 'palette', color: 'primary'},
        {name: 'Nebula', description: 'Marketing site', icon: 'rocket', color: 'info'},
        {name: 'Orbit', description: 'Analytics dashboard', icon: 'chart-line', color: 'success'}
    ];
</script>

Complete

An item composed of media, content and actions stacked together.

Bas MiliusEngineer
Jane DoeDesigner
John DoeProduct manager

<template>
    <FluxPane style="width: min(100%, 480px)">
        <FluxItemStack>
            <FluxItem
                v-for="member in members"
                :key="member.name">
                <FluxItemMedia
                    is-center
                    :size="40">
                    <FluxAvatar
                        :alt="member.name"
                        fallback-icon="user"
                        :size="40"/>
                </FluxItemMedia>

                <FluxItemContent is-center>
                    <strong>{{ member.name }}</strong>
                    <span style="font-size: .875rem; opacity: .6">{{ member.role }}</span>
                </FluxItemContent>

                <FluxItemActions is-center>
                    <FluxAction
                        icon="pen"
                        aria-label="Edit"/>
                    <FluxAction
                        is-destructive
                        icon="trash"
                        aria-label="Remove"/>
                </FluxItemActions>
            </FluxItem>
        </FluxItemStack>
    </FluxPane>
</template>

<script
    setup
    lang="ts">
    import { FluxAction, FluxAvatar, FluxItem, FluxItemActions, FluxItemContent, FluxItemMedia, FluxItemStack, FluxPane } from '@flux-ui/components';

    const members = [
        {name: 'Bas Milius', role: 'Engineer'},
        {name: 'Jane Doe', role: 'Designer'},
        {name: 'John Doe', role: 'Product manager'}
    ];
</script>

Notifications

A notification feed with a leading icon, message, timestamp and a dismiss action.

Jane Doe started following you2 minutes ago
John Doe liked your post1 hour ago
New comment on Release notes3 hours ago

<template>
    <FluxPane style="width: min(100%, 480px)">
        <FluxItemStack>
            <FluxItem
                v-for="notification in notifications"
                :key="notification.title">
                <FluxItemMedia
                    is-center
                    :size="40">
                    <FluxBoxedIcon
                        :color="notification.color"
                        :name="notification.icon"
                        :size="40"/>
                </FluxItemMedia>

                <FluxItemContent is-center>
                    <strong>{{ notification.title }}</strong>
                    <span style="font-size: .875rem; opacity: .6">{{ notification.time }}</span>
                </FluxItemContent>

                <FluxItemActions is-center>
                    <FluxAction
                        icon="xmark"
                        aria-label="Dismiss"/>
                </FluxItemActions>
            </FluxItem>
        </FluxItemStack>
    </FluxPane>
</template>

<script
    setup
    lang="ts">
    import type { FluxColor, FluxIconName } from '@flux-ui/types';
    import { FluxAction, FluxBoxedIcon, FluxItem, FluxItemActions, FluxItemContent, FluxItemMedia, FluxItemStack, FluxPane } from '@flux-ui/components';

    const notifications: { title: string; time: string; icon: FluxIconName; color: FluxColor }[] = [
        {title: 'Jane Doe started following you', time: '2 minutes ago', icon: 'user-plus', color: 'info'},
        {title: 'John Doe liked your post', time: '1 hour ago', icon: 'heart', color: 'danger'},
        {title: 'New comment on Release notes', time: '3 hours ago', icon: 'message', color: 'primary'}
    ];
</script>

Settings

A settings list where each row pairs a description with a switch.

Push notificationsReceive alerts on your devices.
Email digestA weekly summary in your inbox.
Two-factor authenticationAdd an extra layer of security.

<template>
    <FluxPane style="width: min(100%, 480px)">
        <FluxItemStack>
            <FluxItem
                v-for="setting in items"
                :key="setting.key">
                <FluxItemContent>
                    <strong>{{ setting.label }}</strong>
                    <span style="font-size: .875rem; opacity: .6">{{ setting.description }}</span>
                </FluxItemContent>

                <FluxItemActions is-center>
                    <FluxToggle v-model="settings[setting.key]"/>
                </FluxItemActions>
            </FluxItem>
        </FluxItemStack>
    </FluxPane>
</template>

<script
    setup
    lang="ts">
    import { reactive } from 'vue';
    import { FluxItem, FluxItemActions, FluxItemContent, FluxItemStack, FluxPane, FluxToggle } from '@flux-ui/components';

    const settings = reactive<Record<string, boolean>>({
        push: true,
        email: false,
        twoFactor: true
    });

    const items = [
        {key: 'push', label: 'Push notifications', description: 'Receive alerts on your devices.'},
        {key: 'email', label: 'Email digest', description: 'A weekly summary in your inbox.'},
        {key: 'twoFactor', label: 'Two-factor authentication', description: 'Add an extra layer of security.'}
    ];
</script>

Control

With is-control the whole row becomes the label for its form control. Click anywhere to toggle.

<template>
    <FluxPane style="width: min(100%, 480px)">
        <FluxItemStack>
            <FluxItem
                v-for="option in options"
                :key="option.key"
                is-control>
                <FluxItemContent is-center>
                    <strong>{{ option.label }}</strong>
                    <span style="font-size: .875rem; opacity: .6">{{ option.description }}</span>
                </FluxItemContent>

                <FluxItemActions is-center>
                    <FluxToggle v-model="enabled[option.key]"/>
                </FluxItemActions>
            </FluxItem>
        </FluxItemStack>
    </FluxPane>
</template>

<script
    setup
    lang="ts">
    import { reactive } from 'vue';
    import { FluxItem, FluxItemActions, FluxItemContent, FluxItemStack, FluxPane, FluxToggle } from '@flux-ui/components';

    const enabled = reactive<Record<string, boolean>>({
        marketing: true,
        product: false,
        security: true
    });

    const options = [
        {key: 'marketing', label: 'Marketing emails', description: 'News, offers and product announcements.'},
        {key: 'product', label: 'Product updates', description: 'Release notes and changelogs.'},
        {key: 'security', label: 'Security alerts', description: 'Important notices about your account.'}
    ];
</script>

Selectable

A multi-select list where the whole row toggles the checkbox, thanks to is-control.

<template>
    <FluxPane style="width: min(100%, 480px)">
        <FluxItemStack>
            <FluxItem
                v-for="member in members"
                :key="member.key"
                is-control>
                <FluxItemMedia is-center>
                    <FluxFormCheckbox v-model="selected[member.key]"/>
                </FluxItemMedia>

                <FluxItemMedia
                    is-center
                    :size="40">
                    <FluxAvatar
                        :alt="member.name"
                        fallback-icon="user"
                        :size="40"/>
                </FluxItemMedia>

                <FluxItemContent is-center>
                    <strong>{{ member.name }}</strong>
                    <span style="font-size: .875rem; opacity: .6">{{ member.email }}</span>
                </FluxItemContent>
            </FluxItem>
        </FluxItemStack>
    </FluxPane>
</template>

<script
    setup
    lang="ts">
    import { reactive } from 'vue';
    import { FluxAvatar, FluxFormCheckbox, FluxItem, FluxItemContent, FluxItemMedia, FluxItemStack, FluxPane } from '@flux-ui/components';

    const selected = reactive<Record<string, boolean>>({
        bas: true,
        jane: false,
        john: true
    });

    const members = [
        {key: 'bas', name: 'Bas Milius', email: 'bas@example.com'},
        {key: 'jane', name: 'Jane Doe', email: 'jane@example.com'},
        {key: 'john', name: 'John Doe', email: 'john@example.com'}
    ];
</script>

Integrations

Connected services with a status badge and a toggle to connect or disconnect.

<template>
    <FluxPane style="width: min(100%, 520px)">
        <FluxItemStack>
            <FluxItem
                v-for="app in apps"
                :key="app.key"
                is-control>
                <FluxItemMedia
                    is-center
                    :size="40">
                    <FluxBoxedIcon
                        :color="app.color"
                        :name="app.icon"
                        :size="40"/>
                </FluxItemMedia>

                <FluxItemContent is-center>
                    <strong>{{ app.name }}</strong>
                    <span style="font-size: .875rem; opacity: .6">{{ app.description }}</span>
                </FluxItemContent>

                <FluxItemActions is-center>
                    <FluxBadge
                        :color="connected[app.key] ? 'success' : 'gray'"
                        :label="connected[app.key] ? 'Connected' : 'Disconnected'"/>

                    <FluxToggle v-model="connected[app.key]"/>
                </FluxItemActions>
            </FluxItem>
        </FluxItemStack>
    </FluxPane>
</template>

<script
    setup
    lang="ts">
    import type { FluxColor, FluxIconName } from '@flux-ui/types';
    import { reactive } from 'vue';
    import { FluxBadge, FluxBoxedIcon, FluxItem, FluxItemActions, FluxItemContent, FluxItemMedia, FluxItemStack, FluxPane, FluxToggle } from '@flux-ui/components';

    const connected = reactive<Record<string, boolean>>({
        github: true,
        slack: true,
        drive: false
    });

    const apps: { key: string; name: string; description: string; icon: FluxIconName; color: FluxColor }[] = [
        {key: 'github', name: 'GitHub', description: 'Sync issues and pull requests.', icon: 'code-branch', color: 'gray'},
        {key: 'slack', name: 'Slack', description: 'Send updates to your channels.', icon: 'message', color: 'primary'},
        {key: 'drive', name: 'Cloud Storage', description: 'Attach files from the cloud.', icon: 'cloud', color: 'info'}
    ];
</script>

Transactions

A transaction list with a directional icon and a trailing amount.

Acme Inc.June 14, 2026
+€2,400.00
Coffee RoastersJune 13, 2026
-€4.80
Cloud HostingJune 12, 2026
-€19.99

<template>
    <FluxPane style="width: min(100%, 480px)">
        <FluxItemStack>
            <FluxItem
                v-for="transaction in transactions"
                :key="transaction.merchant">
                <FluxItemMedia
                    is-center
                    :size="40">
                    <FluxBoxedIcon
                        :color="transaction.isIncome ? 'success' : 'gray'"
                        :name="transaction.isIncome ? 'arrow-trend-up' : 'arrow-trend-down'"
                        :size="40"/>
                </FluxItemMedia>

                <FluxItemContent is-center>
                    <strong>{{ transaction.merchant }}</strong>
                    <span style="font-size: .875rem; opacity: .6">{{ transaction.date }}</span>
                </FluxItemContent>

                <FluxItemContent
                    is-center
                    style="flex-grow: 0; text-align: right">
                    <strong :style="{color: transaction.isIncome ? 'var(--success-600)' : undefined}">{{ transaction.amount }}</strong>
                </FluxItemContent>
            </FluxItem>
        </FluxItemStack>
    </FluxPane>
</template>

<script
    setup
    lang="ts">
    import { FluxBoxedIcon, FluxItem, FluxItemContent, FluxItemMedia, FluxItemStack, FluxPane } from '@flux-ui/components';

    const transactions = [
        {merchant: 'Acme Inc.', date: 'June 14, 2026', amount: '+€2,400.00', isIncome: true},
        {merchant: 'Coffee Roasters', date: 'June 13, 2026', amount: '-€4.80', isIncome: false},
        {merchant: 'Cloud Hosting', date: 'June 12, 2026', amount: '-€19.99', isIncome: false}
    ];
</script>

Downloads

Active downloads with an inline progress bar and a cancel action.

annual-report.pdf
72% of 8.2 MB
design-assets.zip
35% of 254 MB

<template>
    <FluxPane style="width: min(100%, 520px)">
        <FluxItemStack>
            <FluxItem
                v-for="download in downloads"
                :key="download.name">
                <FluxItemMedia
                    is-center
                    :size="40">
                    <FluxBoxedIcon
                        color="primary"
                        name="file-lines"
                        :size="40"/>
                </FluxItemMedia>

                <FluxItemContent is-center>
                    <strong>{{ download.name }}</strong>
                    <FluxProgressBar
                        :value="download.progress"
                        :max="100"/>
                    <span style="font-size: .875rem; opacity: .6">{{ download.progress }}% of {{ download.size }}</span>
                </FluxItemContent>

                <FluxItemActions is-center>
                    <FluxAction
                        icon="xmark"
                        aria-label="Cancel"/>
                </FluxItemActions>
            </FluxItem>
        </FluxItemStack>
    </FluxPane>
</template>

<script
    setup
    lang="ts">
    import { FluxAction, FluxBoxedIcon, FluxItem, FluxItemActions, FluxItemContent, FluxItemMedia, FluxItemStack, FluxPane, FluxProgressBar } from '@flux-ui/components';

    const downloads = [
        {name: 'annual-report.pdf', size: '8.2 MB', progress: 72},
        {name: 'design-assets.zip', size: '254 MB', progress: 35}
    ];
</script>

Snippet

vue
<template>
    <Preview>
        <FluxPane style="width: min(100%, 420px)">
            <FluxItemStack>
                <FluxItem
                    v-for="person in people"
                    :key="person.name">
                    <FluxItemMedia
                        is-center
                        :size="40">
                        <FluxAvatar
                            :alt="person.name"
                            :fallback-icon="person.avatar ? undefined : 'user'"
                            :src="person.avatar"
                            :size="40"/>
                    </FluxItemMedia>

                    <FluxItemContent is-center>
                        <strong>{{ person.name }}</strong>
                        <span style="font-size: .875rem; opacity: .6">{{ person.role }}</span>
                    </FluxItemContent>
                </FluxItem>
            </FluxItemStack>
        </FluxPane>
    </Preview>
</template>

<script
    setup
    lang="ts">
    import { FluxAvatar, FluxItem, FluxItemContent, FluxItemMedia, FluxItemStack, FluxPane } from '@flux-ui/components';

    const people = [
        {name: 'Bas Milius', role: 'Engineer', avatar: 'https://avatars.githubusercontent.com/u/978257?v=4'},
        {name: 'Jane Doe', role: 'Designer', avatar: null},
        {name: 'John Doe', role: 'Product manager', avatar: null}
    ];
</script>

Available sub-components

Used components