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.
Required icons
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", iconbolt, colorinfo.FluxFlowConditionCard— type "Condition", iconcode-branch, colorwarning.FluxFlowActionCard— type "Action", iconplay, colorprimary.
Variants
The three node variants. Override label, icon and color to fit your own node types.
<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.
<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.
- 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>Header
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.
<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.
- Enabled
- Channel
- Storefront
<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.
- Reviewer
- Jane DoeJD
- 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.
<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.
- 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>