NewPower Apps · canvas componentData display✓ Tested in StudioMIT License
Kanban board
Columns and cards from two tables, each card moved left or right with a button or the keyboard. Work-in-progress limits stop a full column taking more, and OnMove tells your app what moved where.
- Name in Studio
- lcsKanban
- Version
- 0.1.0
- Properties
- 17 inputs · 4 outputs · 2 events · 1 action
Variations
As it is when you paste it, with every input at its default.
To do
2
- MarketingDraft the onboarding emailDue Friday
- EventsBook the venue for the launchTwo quotes in
In progress
2 of 3
- AutomationBuild the approval flowWaiting on the finance list
- Power AppsFix the gallery that stops at 500 rowsDelegation warning on Filter
In review
2 of 2 · Full
- Power BICheck the sales report totalsTwo regions differ
- DataverseRead the security roles planComments by Tuesday
Done
1
- GovernanceTurn on the data policySigned off
Full: review
Formulas on this screen
Set the same ones in Studio to try it the same way; there, each Notify shows its event in a banner, which this preview leaves out so nothing covers the component. The instance names are the ones Studio gives the first copy on a screen.
Screen1.OnVisible = ClearCollect(colCards, {Key: "c1", Column: "todo", Title: "Draft the onboarding email", Detail: "Due Friday", Tag: "Marketing"}, {Key: "c2", Column: "todo", Title: "Book the venue for the launch", Detail: "Two quotes in", Tag: "Events"}, {Key: "c3", Column: "doing", Title: "Build the approval flow", Detail: "Waiting on the finance list", Tag: "Automation"}, {Key: "c4", Column: "doing", Title: "Fix the gallery that stops at 500 rows", Detail: "Delegation warning on Filter", Tag: "Power Apps"}, {Key: "c5", Column: "review", Title: "Check the sales report totals", Detail: "Two regions differ", Tag: "Power BI"}, {Key: "c6", Column: "review", Title: "Read the security roles plan", Detail: "Comments by Tuesday", Tag: "Dataverse"}, {Key: "c7", Column: "done", Title: "Turn on the data policy", Detail: "Signed off", Tag: "Governance"})
lcsKanban_1.Cards = colCards
lcsKanban_1.OnMove = UpdateIf(colCards, Key = CardKey, {Column: ToColumn})
lcsKanban_1.OnCardSelect = Notify("Open " & LookUp(colCards, Key = CardKey).Title)
Label1.Text = "Full: " & lcsKanban_1.FullColumns
A web replica that behaves as the component does in Power Apps. In Studio it uses Microsoft's controls, which can look slightly different.
Add it in five steps
- In Power Apps Studio, open Settings > Updates and check that Modern controls and themes and Enhanced component properties are on.
- Open the Components tab in the tree view and select New component.
- Select an empty part of Studio, so the new component isn't selected.
- Copy the YAML on this page and press Ctrl+V.
lcsKanbanappears with all its properties. - On a screen, insert it from Insert > Custom >
lcsKanban.
What it needs
- No premium licence: standard controls, no connectors
- Modern controls and themes: on
- Enhanced component properties: on
- Tested in Power Apps Studio 3.26094.9 on October 17, 2026
- Version 0.1.0
Properties (24)
Read from the component's own YAML, so they always match what you paste.
| Property | Kind | Type | Default |
|---|---|---|---|
ColumnsThe board's columns, left to right: Key, Title and Limit (the most cards the column may hold; 0 for no limit). | Input | Table | Table(
{Key: "todo", Title: "To do", Limit: 0},
{Key: "doing", Title: "In progress", Limit: 3},
{Key: "review", Title: "In review", Limit: 2},
{Key: "done", Title: "Done", Limit: 0}
) |
CardsEvery card: Key, Column (the Key of its column), Title, Detail and Tag. Cards show in the order of this table. | Input | Table | Table(
{Key: "c1", Column: "todo", Title: "Draft the onboarding email", Detail: "Due Friday", Tag: "Marketing"},
{Key: "c2", Column: "todo", Title: "Book the venue for the launch", Detail: "Two quotes in", Tag: "Events"},
{Key: "c3", Column: "doing", Title: "Build the approval flow", Detail: "Waiting on the finance list", Tag: "Automation"},
{Key: "c4", Column: "doing", Title: "Fix the gallery that stops at 500 rows", Detail: "Delegation warning on Filter", Tag: "Power Apps"},
{Key: "c5", Column: "review", Title: "Check the sales report totals", Detail: "Two regions differ", Tag: "Power BI"},
{Key: "c6", Column: "review", Title: "Read the security roles plan", Detail: "Comments by Tuesday", Tag: "Dataverse"},
{Key: "c7", Column: "done", Title: "Turn on the data policy", Detail: "Signed off", Tag: "Governance"}
) |
CurrentKeyThe Key of the card to mark as selected, from your app. Leave it blank and the board marks the card last selected. | Input | Text | "" |
BlockWhenFullWhen true, a card can't be moved into a column that has reached its Limit: the button to move it there is turned off. | Input | Boolean | true |
ShowDetailShows each card's Detail line. | Input | Boolean | true |
ShowTagsShows each card's Tag above its title, in your colour. | Input | Boolean | true |
CardHeightThe height of every card, in pixels. Make it taller for long titles. | Input | Number | 96 |
BoardLabelWhat screen readers call the board. | Input | Text | "Board" |
CardsTextThe word screen readers say after a column's count, such as In progress, 2 cards. | Input | Text | "cards" |
OfTextThe word between a column's count and its limit, such as 2 of 3. | Input | Text | "of" |
FullTextWhat a column says when it has reached its limit. | Input | Text | "Full" |
MoveTextThe start of a move button's name, read out and shown on hover, such as Move Fix login to Done. | Input | Text | "Move" |
ToTextThe word between the card and the column in a move button's name. | Input | Text | "to" |
EmptyTextWhat an empty column says. | Input | Text | "No cards" |
AccentColorYour brand colour, for tags, the selected card and the focus ring. | Input | Color | RGBA(15, 108, 189, 1) |
ThemeLight, or Dark for a dark screen. | Input | Text | "Light" |
MotionPlays short animations: a card that moves glows, a selected card's outline draws itself, a column that fills up pulses. They never play for people who've asked their device for reduced motion. | Input | Boolean | true |
| Property | Kind | Type | Default |
|---|---|---|---|
SelectedKeyThe Key of the selected card, or blank. | Output | Text | — |
SelectedCardThe selected card's row from Cards. | Output | Record | — |
CardCountHow many cards the board has. | Output | Number | — |
FullColumnsKeys of the columns that have reached their limit, separated by commas. | Output | Text | — |
| Property | Kind | Type | Default |
|---|---|---|---|
OnMove(CardKey, ToColumn, FromColumn)Runs when the user moves a card. Change the card's Column in your data here; the board shows it there when Cards changes.
| Event | — | false |
OnCardSelect(CardKey)Runs when the user selects a card. Open its details here.
| Event | — | false |
| Property | Kind | Type | Default |
|---|---|---|---|
ClearSelection()Unmarks the selected card, such as after you close its details. | Action | — | — |
Guide
Use lcsKanban for work that moves through stages: tasks, requests, applications, support tickets, content waiting for review. Canvas apps have no Kanban control, and their galleries have no drag-and-drop events, so the usual answers are a code component your admin has to approve or a custom page. This component works in any canvas app:
- Columns and cards from two tables:
Columns(Key, Title, Limit) andCards(Key, Column, Title, Detail, Tag). Your data stays yours: the board shows what you give it. - Moves with buttons, not dragging: each card has a ← and → button that moves it to the column beside it. They're real buttons, so they work with a mouse, a finger, Tab and Enter, and a screen reader.
- Work-in-progress limits: give a column a
Limitand its header shows "2 of 3". At the limit the header says "Full", the column gets an amber edge, and withBlockWhenFullon, nothing can be moved into it. - Tells your app what happened:
OnMove(CardKey, ToColumn, FromColumn)runs when a card moves, andOnCardSelect(CardKey)when one is selected. You save the change; the board shows it as soon asCardschanges. - Reads at a glance: a tag in your colour, a bold title, one detail line, and the selected card outlined in your colour.
- Motion that feels premium: a card that has just moved glows in your colour, a selected card's outline draws itself around it, a column that fills up pulses in amber, and an empty column shows a tray that rises into place. Turn it off with
Motion; it never plays for people who've asked their device for reduced motion. AccentColor, aDarktheme, and every word it shows or reads out as an input, for your language.
The examples call it kbTasks on your screen, with your tasks in a collection, colTasks, that has a text column Stage.
Set the columns, with a limit on the middle one:
// kbTasks.Columns
Table(
{Key: "New", Title: "New", Limit: 0},
{Key: "Active", Title: "In progress", Limit: 5},
{Key: "Closed", Title: "Done", Limit: 0}
)
Turn your rows into cards. Each card's Column is the Key of the column it sits in:
// kbTasks.Cards
ForAll(
colTasks,
{
Key: Text(ID),
Column: Stage,
Title: Title,
Detail: "Due " & Text(DueDate, "mmm d"),
Tag: AssignedTo
}
)
Save a move. Change the collection, so the board updates at once, and then your data source:
// kbTasks.OnMove
UpdateIf(colTasks, Text(ID) = CardKey, {Stage: ToColumn});
Patch(Tasks, LookUp(Tasks, Text(ID) = CardKey), {Stage: ToColumn})
Open a card's details:
// kbTasks.OnCardSelect
Set(gblTask, LookUp(colTasks, Text(ID) = CardKey));
Navigate(scrTask)
Allow a move into a full column, but warn about it: set BlockWhenFull to false and check FullColumns in OnMove:
// kbTasks.OnMove, with BlockWhenFull set to false
If(
("," & ToColumn & ",") in ("," & kbTasks.FullColumns & ","),
Notify("That column was already at its limit.", NotificationType.Warning)
);
UpdateIf(colTasks, Text(ID) = CardKey, {Stage: ToColumn})
Columns usually come from a Dataverse choice column, such as Stage. Use the choice's labels as the columns' Keys, show the label with Text, and save the move with the choice's own value:
// kbTasks.Columns
Table(
{Key: "New", Title: "New", Limit: 0},
{Key: "Active", Title: "In progress", Limit: 5},
{Key: "Closed", Title: "Done", Limit: 0}
)
// kbTasks.Cards
ForAll(
colTasks,
{
Key: Text(Task),
Column: Text(Stage),
Title: Name,
Detail: "Due " & Text('Due Date', "mmm d"),
Tag: 'Assigned To'.'Full Name'
}
)
// kbTasks.OnMove
With(
{ stage: Switch(ToColumn, "New", 'Stage (Tasks)'.New, "Active", 'Stage (Tasks)'.Active, 'Stage (Tasks)'.Closed) },
UpdateIf(colTasks, Text(Task) = CardKey, { Stage: stage });
Patch(Tasks, LookUp(Tasks, Task = GUID(CardKey)), { Stage: stage })
)
Taskis the row's unique identifier, the column named after the table;GUIDturns the card's key back into it.'Stage (Tasks)'.Newis how Power Apps names a Dataverse choice's values; a global choice uses its own name.- A Users lookup, such as Assigned To, shows a person with
'Full Name'.
- Each card is a button named by its title, tag, detail and column ("Build the approval flow, Automation, Waiting on the finance list, In progress").
- Each move button says exactly what it does ("Move Build the approval flow to In review"), and adds "Full" when the column it would move to is full and the button is off.
- A full column says "Full" in its header as well as turning amber, so colour is never the only signal. The selected card has a thicker outline in your colour.
- The animations are short and play once (the longest, a full column's pulse, two rounds of under a second); none loops, and none plays for people who've asked their device for reduced motion.
- Each column is a list that screen readers announce with its count ("In progress, 2 cards"). All of these words are inputs:
BoardLabel,CardsText,OfText,FullText,MoveText,ToTextandEmptyText.
- No dragging. Canvas galleries have no drag-and-drop events, so cards move one column at a time with their buttons.
- The arrow keys don't move cards. Canvas components can't read key presses, so Tab moves from button to button and Enter or Space presses one.
- Columns share the board's width. Keep to about six columns, or make the component wider; columns don't scroll sideways.
- Each column is a gallery inside the board's gallery, the most nesting Power Apps allows. Microsoft's gallery guidance notes nested galleries can be slow, so keep a board to a few hundred cards and filter the rest out in
Cards. - Cards show in the order of
Cards. Sort your table to change the order. - The board doesn't change your data. It only reports a move in
OnMove; until your app changes the card'sColumn, the card stays where it was. - Every card is the same height (
CardHeight). A long title wraps and is cut off if it doesn't fit: make the cards taller, or keep titles short.
- 0.1.0: first version: columns and cards from two tables, move buttons with
OnMove, work-in-progress limits withBlockWhenFullandFullColumns, selection withOnCardSelect,SelectedCardandClearSelection(), and motion (Motion).
Did it work for you?
No ratings yet.Nobody has said it worked in their app yet.
Sign in to rate it or to say it worked in your app.
Comments
No comments yet. Share how you used it, or ask something.
Sign in to comment or reply. Comments show under a display name you choose, never your email.