Kanban pipeline
Move products through typed workflow states.
What you will build
Build a status board with persisted card moves and reusable saved arrangements.
Start with the React setup or Vue setup. Use the complete files below with the shared recipe modules. The browser-memory store resets on reload; an API integration must preserve the same contracts.
Required files: shared/products.ts, shared/store.ts, product-config.ts, list-records.ts, view-actions.ts, editable-actions.ts, product-form.ts, get-form-config.ts, pipeline-config.ts, recipe-pipeline.
Copy the shared mutation store and adapter, plus the product form catalog. The status options define the lanes and the update action validates the new value.
pipeline-config.ts
import { defineTableConfig } from "@/components/ui/yayaw-table/config/helpers";
import { productConfig } from "./product-config";
export const pipelineConfig = defineTableConfig({
...productConfig,
table: {
...productConfig.table,
displayModes: ["table", "kanban"],
defaultDisplayMode: "kanban",
allowEdit: true,
enableColumnFilters: true,
enableAdvancedFilters: true,
enableViews: true,
allowViewSave: true,
allowInlineEdit: true,
enableGrouping: true,
kanban: {
groupBy: "status",
titleColumn: "name",
cardColumnIds: ["price", "stock"],
showCardLabels: true,
},
},
});import { defineTableConfig } from "@/components/ui/yayaw-table-vue/config";
import { productConfig } from "./product-config";
export const pipelineConfig = defineTableConfig({
...productConfig,
table: {
...productConfig.table,
displayModes: ["table", "kanban"],
defaultDisplayMode: "kanban",
allowEdit: true,
enableColumnFilters: true,
enableAdvancedFilters: true,
enableViews: true,
allowViewSave: true,
allowInlineEdit: true,
enableGrouping: true,
kanban: {
groupBy: "status",
titleColumn: "name",
cardColumnIds: ["price", "stock"],
showCardLabels: true,
},
},
});Entry component
Sample data. Changes stay in this preview.
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { NuqsAdapter } from "nuqs/adapters/react";
import { useState } from "react";
import { Toaster } from "sonner";
import { DataTable } from "@/components/ui/yayaw-table";
import { getEditableActions } from "./editable-actions";
import { getFormConfig } from "./get-form-config";
import { pipelineConfig } from "./pipeline-config";
import type { ExamplePresentation } from "./presentation";
const getConfig = () => pipelineConfig;
export default function PipelineRecipe(presentation: ExamplePresentation = {}) {
const [queryClient] = useState(() => new QueryClient());
return (
<QueryClientProvider client={queryClient}>
<NuqsAdapter>
<DataTable
{...presentation}
getFormConfig={getFormConfig}
getRowId={(row) => String(row.id)}
getTableActions={getEditableActions}
getTableConfig={getConfig}
tableId="recipe-pipeline"
tableType="products"
title={presentation.title ?? "Pipeline"}
/>
<Toaster />
</NuqsAdapter>
</QueryClientProvider>
);
}Sample data. Changes stay in this preview.
<script setup lang="ts">
import type { ExamplePresentation } from "./presentation";
defineProps<ExamplePresentation>();
import { YayawDataTable } from "@/components/ui/yayaw-table-vue";
import { getEditableActions } from "./editable-actions";
import { getFormConfig } from "./get-form-config";
import { pipelineConfig } from "./pipeline-config";
const getRowId = (row: Record<string, unknown>) => String(row.id);
</script>
<template>
<YayawDataTable v-bind="$props" table-type="products" table-id="recipe-pipeline" :title="title ?? 'Pipeline'"
:config="pipelineConfig" :get-table-actions="getEditableActions" :get-row-id="getRowId"
:get-form-config="getFormConfig" />
</template>Verify the result
Open the board: Desk lamp starts in Draft.
Move Desk lamp to Active.
Switch to Table and check its status is Active.
Filter to Draft and confirm it is absent.
In a real backend, test a refused transition and confirm the card returns to its confirmed state.
Use the existing playground to explore the library’s controls.
Walk through the result
| Action | Expected result |
|---|---|
| Move Desk lamp from Draft to Active. | The status changes in the store, not only on screen. |
| Switch to Table. | Desk lamp still has Active status. |
| Save the current arrangement from the view menu. | Reopening the saved view starts without a modified indicator. |
| Change a card property, then reset the view. | The saved presentation returns; product data is not rolled back. |
On mobile, use View settings for presentation, the Data menu for export, and the search button in the toolbar. Resetting a view does not undo writes. Try the keyboard as well as pointer input.