Skip to content

Card

FluxFlowCard is the node surface: a header carrying the type icon and title, a body and an optional footer. It is a plain element, so it renders inside a Node or on its own.

A card always shows an icon, so every node on the canvas reads as a type at a glance. Each variant brings its own icon, tint and type name; icon, color and label override them.

Analyze Market
Collects competitor insights and analyzes market trends.
Opus 4.8
394 tokens

Required icons

bolt
circle-dot
code-branch
play

Props

title?: string
The title shown in the header of the card. Without one the card falls back to the name of its type.

subtitle?: string
A secondary line shown under the title.

label?: string
The name of the card's type, used as the header text when no title is given.

icon?: FluxIconName
The icon shown in the header. A card always renders one; each variant brings its own default.

color?: FluxColor
The tint of the header icon.

active?: boolean
Highlights the card with an accent border, for example while it runs.

isLoading?: boolean
Replaces the header icon with a spinner in the same tinted tile, for a step that is currently running.

Slots

default
The body of the card. Place plain text or any Flux component here, for example a FluxDescriptionList for compact key/value data.

footer
The footer of the card, typically a row of FluxTag and FluxBadge chips.

header
The trailing end of the header, beside the title. Meant for one small thing that qualifies the node, such as a status badge or a counter.

Variants

FluxFlowTriggerCard, FluxFlowConditionCard and FluxFlowActionCard are thin wrappers around FluxFlowCard that preset the three common automation node types. Each default is overridable with the label, icon and color props.

  • FluxFlowTriggerCard — type "Trigger", icon bolt, color info.
  • FluxFlowConditionCard — type "Condition", icon code-branch, color warning.
  • FluxFlowActionCard — type "Action", icon play, color primary.

Variants

The three node variants. Override label, icon and color to fit your own node types.

Webhook Received
Fires whenever a request hits the endpoint.
Amount over €100
Routes high-value orders for manual review.
Send Invoice
Emails the generated invoice to the customer.

<template>
    <FluxFlex
        :gap="48"
        style="flex-wrap: wrap; align-items: flex-start; justify-content: center; padding: 12px 0">
        <FluxFlowTriggerCard title="Webhook Received">
            Fires whenever a request hits the endpoint.
        </FluxFlowTriggerCard>

        <FluxFlowConditionCard title="Amount over €100">
            Routes high-value orders for manual review.
        </FluxFlowConditionCard>

        <FluxFlowActionCard title="Send Invoice">
            Emails the generated invoice to the customer.
        </FluxFlowActionCard>
    </FluxFlex>
</template>

<script
    setup
    lang="ts">
    import { FluxFlex } from '@flux-ui/components';
    import { FluxFlowActionCard, FluxFlowConditionCard, FluxFlowTriggerCard } from '@flux-ui/flow';
</script>

Colors

The badge accepts any FluxColor, so you can style a card for any kind of node.

Primary
An agent step.
Info
A trigger step.
Success
A completed step.
Warning
A step needing review.
Danger
A failed step.

<template>
    <FluxFlex
        :gap="48"
        style="flex-wrap: wrap; align-items: flex-start; justify-content: center; padding: 12px 0">
        <FluxFlowCard title="Primary" icon="robot" color="primary">
            An agent step.
        </FluxFlowCard>

        <FluxFlowCard title="Info" icon="bolt" color="info">
            A trigger step.
        </FluxFlowCard>

        <FluxFlowCard title="Success" icon="circle-check" color="success">
            A completed step.
        </FluxFlowCard>

        <FluxFlowCard title="Warning" icon="gauge" color="warning">
            A step needing review.
        </FluxFlowCard>

        <FluxFlowCard title="Danger" icon="stopwatch" color="danger">
            A failed step.
        </FluxFlowCard>
    </FluxFlex>
</template>

<script
    setup
    lang="ts">
    import { FluxFlex } from '@flux-ui/components';
    import { FluxFlowCard } from '@flux-ui/flow';
</script>

Rich content

The card body is a plain vertical stack, so you are not limited to text. Drop in any component from Flux or Flux Statistics: a FluxDescriptionList for compact key/value data, a FluxStatisticsLegend for a color coded breakdown, a chart, badges, anything you need.

Rich content

A card mixing plain text, a FluxDescriptionList and a FluxStatisticsLegend.

Generate Report
Summarizes the quarter's numbers into an executive brief.
Model
Opus 4.8
Tokens
394
Duration
0.43s

<template>
    <div style="display: flex; justify-content: center; padding: 12px 0">
        <FluxFlowActionCard title="Generate Report" icon="brain" color="primary">
            Summarizes the quarter's numbers into an executive brief.

            <FluxDescriptionList>
                <FluxDescriptionItem label="Model">Opus 4.8</FluxDescriptionItem>
                <FluxDescriptionItem label="Tokens">394</FluxDescriptionItem>
                <FluxDescriptionItem label="Duration">0.43s</FluxDescriptionItem>
            </FluxDescriptionList>

            <FluxStatisticsLegend direction="vertical">
                <FluxStatisticsLegendItem color="primary" label="Revenue" value="+12%"/>
                <FluxStatisticsLegendItem color="warning" label="Churn" value="-3%"/>
                <FluxStatisticsLegendItem color="success" label="Retention" value="94%"/>
            </FluxStatisticsLegend>
        </FluxFlowActionCard>
    </div>
</template>

<script
    setup
    lang="ts">
    import { FluxDescriptionItem, FluxDescriptionList } from '@flux-ui/components';
    import { FluxFlowActionCard } from '@flux-ui/flow';
    import { FluxStatisticsLegend, FluxStatisticsLegendItem } from '@flux-ui/statistics';
</script>

The header slot fills the trailing end of the header, beside the title. Keep it to one small thing that qualifies the node; anything larger belongs in the body or the footer.

Send the invoiceOnce per order
Live
Delivers the invoice to the billing address on file.

<template>
    <FluxFlowActionCard title="Send the invoice" subtitle="Once per order" icon="paper-plane">
        <template #header>
            <FluxBadge color="success" label="Live"/>
        </template>

        Delivers the invoice to the billing address on file.
    </FluxFlowActionCard>
</template>

<script
    setup
    lang="ts">
    import { FluxBadge } from '@flux-ui/components';
    import { FluxFlowActionCard } from '@flux-ui/flow';
</script>

Interactive content

Nothing about the body is read only. Because it is plain markup, interactive controls, buttons and animated values work exactly as they would anywhere else, so a card can double as a small control surface for its node.

Toggle

A FluxToggle drives the node's state; the badge and accent border follow it.

New order receivedShopify webhook
Enabled
Channel
Storefront
Live

<template>
    <div style="display: flex; justify-content: center; padding: 12px 0">
        <FluxFlowTriggerCard
            title="New order received"
            subtitle="Shopify webhook"
            :color="enabled ? 'info' : 'gray'"
            :active="enabled">
            <FluxDescriptionList>
                <FluxDescriptionItem label="Enabled">
                    <FluxToggle v-model="enabled"/>
                </FluxDescriptionItem>
                <FluxDescriptionItem label="Channel">Storefront</FluxDescriptionItem>
            </FluxDescriptionList>

            <template #footer>
                <FluxBadge
                    :color="enabled ? 'info' : 'gray'"
                    :label="enabled ? 'Live' : 'Paused'"/>
            </template>
        </FluxFlowTriggerCard>
    </div>
</template>

<script
    setup
    lang="ts">
    import { FluxBadge, FluxDescriptionItem, FluxDescriptionList, FluxToggle } from '@flux-ui/components';
    import { FluxFlowTriggerCard } from '@flux-ui/flow';
    import { ref } from 'vue';

    const enabled = ref(true);
</script>

Approval

A FluxAvatar identifies the reviewer and a FluxSecondaryButton in the footer resolves the step.

Manager approvalExpense over € 500
Reviewer
Jane Doe
SLA
4 hours

<template>
    <div style="display: flex; justify-content: center; padding: 12px 0">
        <FluxFlowCard
            title="Manager approval"
            subtitle="Expense over € 500"
            :icon="approved ? 'circle-check' : 'hourglass-clock'"
            :color="approved ? 'success' : 'warning'"
            :active="!approved">
            <FluxDescriptionList>
                <FluxDescriptionItem label="Reviewer">
                    <span style="display: flex; align-items: center; gap: 9px">
                        <FluxAvatar :size="24" fallback="colorized" fallback-initials="JD"/>
                        Jane Doe
                    </span>
                </FluxDescriptionItem>
                <FluxDescriptionItem label="SLA">4 hours</FluxDescriptionItem>
            </FluxDescriptionList>

            <template #footer>
                <FluxSecondaryButton
                    v-if="!approved"
                    icon-leading="circle-check"
                    label="Approve"
                    @click="approved = true"/>
                <FluxBadge
                    v-else
                    icon="circle-check"
                    label="Approved"
                    color="success"/>
            </template>
        </FluxFlowCard>
    </div>
</template>

<script
    setup
    lang="ts">
    import { FluxAvatar, FluxBadge, FluxDescriptionItem, FluxDescriptionList, FluxSecondaryButton } from '@flux-ui/components';
    import { FluxFlowCard } from '@flux-ui/flow';
    import { ref } from 'vue';

    const approved = ref(false);
</script>

Live progress

A FluxStatisticsMeter reflects a running job by animating its value while the card stays active.

Build image
Progress0%

<template>
    <div style="display: flex; justify-content: center; padding: 12px 0">
        <FluxFlowActionCard title="Build image" icon="server" color="primary" active>
            <FluxStatisticsMeter
                color="primary"
                icon="gauge-high"
                title="Progress"
                :value="progress"/>
        </FluxFlowActionCard>
    </div>
</template>

<script
    setup
    lang="ts">
    import { FluxFlowActionCard } from '@flux-ui/flow';
    import { FluxStatisticsMeter } from '@flux-ui/statistics';
    import { onBeforeUnmount, onMounted, ref } from 'vue';

    const progress = ref(0);

    let frame = 0;

    onMounted(() => {
        const start = performance.now();

        const tick = (now: number) => {
            progress.value = ((now - start) / 3200) % 1;
            frame = requestAnimationFrame(tick);
        };

        frame = requestAnimationFrame(tick);
    });

    onBeforeUnmount(() => cancelAnimationFrame(frame));
</script>

Loading

Set isLoading to swap the type icon for a spinner in the same tinted tile, so a running step reads as busy without moving anything on the canvas.

Sync inventoryWarehouse API
Products
1.284
Batch size
250

<template>
    <div style="display: flex; justify-content: center; padding: 12px 0">
        <FluxFlowActionCard
            title="Sync inventory"
            subtitle="Warehouse API"
            :active="isRunning"
            :is-loading="isRunning">
            <FluxDescriptionList>
                <FluxDescriptionItem label="Products">1.284</FluxDescriptionItem>
                <FluxDescriptionItem label="Batch size">250</FluxDescriptionItem>
            </FluxDescriptionList>

            <template #footer>
                <FluxSecondaryButton
                    icon-leading="rotate"
                    label="Run step"
                    :disabled="isRunning"
                    @click="run"/>

                <FluxBadge
                    v-if="isFinished"
                    color="success"
                    icon="circle-check"
                    label="Synced"/>
            </template>
        </FluxFlowActionCard>
    </div>
</template>

<script
    setup
    lang="ts">
    import { FluxBadge, FluxDescriptionItem, FluxDescriptionList, FluxSecondaryButton } from '@flux-ui/components';
    import { FluxFlowActionCard } from '@flux-ui/flow';
    import { onBeforeUnmount, ref } from 'vue';

    const isFinished = ref(false);
    const isRunning = ref(false);

    let timeout = 0;

    onBeforeUnmount(() => clearTimeout(timeout));

    function run(): void {
        isFinished.value = false;
        isRunning.value = true;

        timeout = setTimeout(() => {
            isFinished.value = true;
            isRunning.value = false;
        }, 2400);
    }
</script>

Used components