What CTkKanBan gives you
A reusable board widget, default card rendering, live inline editing, built-in add/edit forms, per-card and per-column operations, and a large style surface.
Everything you need to build a database-backed Kanban workflow with CustomTkinter: installation, data modeling, forms, querying, CRUD integration, styling, callbacks, and the complete public API.
The package is built around one primary widget: CTkKanbanBoard. You give it an ordered set
of columns, an optional initial set of cards, and an optional field schema. From there, the board handles
rendering, selection, drag-and-drop movement, search, filters, sorting, inline field editing, built-in
forms, and context menus.
Two design choices define the project:
A reusable board widget, default card rendering, live inline editing, built-in add/edit forms, per-card and per-column operations, and a large style surface.
Deployment, authentication, application-level rules beyond field validators, and any backend-specific authorization policy.
The package metadata in pyproject.toml declares:
requires-python = ">=3.10"dependencies = ["customtkinter>=5.2.2,<7", "tzdata ..."]python -m venv .venv
# Windows PowerShell
.venv\Scripts\Activate.ps1
# macOS / Linux
source .venv/bin/activate
python -m pip install CTkKanBan
Verify the interpreter and installed package before debugging GUI code:
python -c "import CTkKanBan; print(CTkKanBan.__version__, CTkKanBan.__file__)"
The examples are included in the source repository and source distribution, not the installed wheel. From a source checkout, install the checkout and run:
python -m pip install -e .
python example_all_features.py
python example_sqlite.py
The demo exercises custom fields, built-in forms, callbacks, styling, drag-and-drop, search, filtering,
sorting, and a custom card renderer. example_sqlite.py is the runnable persistence example.
Together they are the best source-level tour of intended application usage.
pip check, and exercises the SQLite adapter before a release artifact can be attested or
published.
A minimal board needs three things:
CTk window that gives the board room to expand.import customtkinter as ctk
from ctk_kanban import CTkKanbanBoard
columns = [
{"id": "todo", "title": "To Do", "color": "#3B82F6"},
{"id": "doing", "title": "Doing", "color": "#F59E0B"},
{"id": "done", "title": "Done", "color": "#10B981"},
]
cards = [
{"id": 1, "column": "todo", "title": "Write docs", "sort_order": 1},
{"id": 2, "column": "doing", "title": "Review callbacks", "sort_order": 1},
]
app = ctk.CTk()
app.title("CTkKanBan Quick Start")
app.geometry("1100x700")
app.grid_rowconfigure(0, weight=1)
app.grid_columnconfigure(0, weight=1)
board = CTkKanbanBoard(app, columns=columns, cards=cards)
board.grid(row=0, column=0, sticky="nsew")
app.mainloop()
id, column, and
title. The value of card["column"] must exactly match an existing
column["id"].
add_card(), update_card(), move_card(), and
set_state() instead of mutating the original input lists. The board stores deep copies.
Start with the smallest persistence option that matches the application. You can change paths later because the board UI talks to storage through stable operation and result contracts.
Pass columns and cards directly. Best for UI work and local prototypes.
Use the transactional adapter for a local database with schema creation, revisions, and paging.
Use SQLite →Wrap four repository functions for SQL, NoSQL, an ORM, a cloud SDK, or an HTTP API.
Connect CRUD →Implement the full protocol for native queries, event feeds, conflict snapshots, or bulk writes.
Implement the protocol →data_source or the legacy
on_data_changed snapshot callback. The constructor rejects both together because two
persistence writers can diverge.
The board works with plain mappings rather than custom ORM or dataclass types. The typed definitions in
ctk_kanban.models document the expected shapes, but at runtime the widget accepts
dictionary-like mappings and normalizes them.
A column is an ordered board lane. The required keys are id and title. Column
IDs must be hashable and unique. Optional keys let you control appearance and behavior per column:
A card must include id, column, and title. Any additional keys
are preserved. The board uses sort_order only for manual ordering; all other values are
application-defined card data.
Fields describe how card keys should behave in the default renderer, built-in form, search, filtering,
and sorting. If you do not provide a field list, the package uses a default schema containing
title, description, priority, assignee,
due_date, and tags.
If you provide a custom field list and omit title, the validator inserts a default
title field at the front because the board always requires it.
get_data() returns only mutable board data: columns and cards. get_state()
goes further and includes the current search query, active filters, sort settings, per-column sorts, and
the selected card ID. Use set_data() when reloading from storage, and set_state()
when you want to restore both data and the current board view.
The simplest practical workflow is to build a board from local data, then mutate it through the public API. This lets you prototype UI behavior before introducing persistence.
import customtkinter as ctk
from ctk_kanban import CTkKanbanBoard
app = ctk.CTk()
app.geometry("1200x760")
app.grid_rowconfigure(0, weight=1)
app.grid_columnconfigure(0, weight=1)
board = CTkKanbanBoard(
app,
columns=[
{"id": "backlog", "title": "Backlog"},
{"id": "todo", "title": "To Do"},
{"id": "done", "title": "Done"},
],
cards=[
{"id": 1, "column": "backlog", "title": "Audit dark theme", "sort_order": 1},
{"id": 2, "column": "todo", "title": "Write tutorial", "sort_order": 1},
],
)
board.grid(row=0, column=0, sticky="nsew")
# Programmatic updates
board.add_card({"id": 3, "column": "todo", "title": "Review API docs"})
board.move_card(1, "todo", 0)
board.update_card(2, {"title": "Write getting started guide"})
app.mainloop()
A few behavior details are worth knowing immediately:
add_card() appends a new card to the end of its column when sort_order is
omitted.
move_card() and reorder_card() rewrite manual sort_order
values so the column remains sequential.
get_cards_by_column() returns the current display order, not the raw insertion order of
the internal card mapping.
The built-in form system is driven entirely by field definitions. If
enable_builtin_card_form=True, the board can open the add form automatically from the
toolbar and per-column add buttons. Existing cards use inline field editing by default.
Click any value in the default card renderer to edit it in place. Empty editable
show_on_card fields receive an add placeholder. Enter, focus loss, or the check button saves;
Escape cancels. Text areas use Ctrl+Enter to save. Set
enable_inline_card_editing=False to retain the earlier full-card edit flow.
fields = [
{
"key": "title",
"label": "Title",
"type": "text",
"required": True,
"show_on_card": True,
"show_in_form": True,
"searchable": True,
"sortable": True,
},
{
"key": "priority",
"label": "Priority",
"type": "select",
"options": ["Low", "Medium", "High"],
"default": "Medium",
"show_on_card": True,
"show_in_form": True,
"filterable": True,
"sortable": True,
},
{
"key": "description",
"label": "Description",
"type": "textarea",
"show_on_card": True,
"show_in_form": True,
"searchable": True,
},
]
board = CTkKanbanBoard(
app,
columns=[{"id": "todo", "title": "To Do"}],
cards=[],
fields=fields,
card_form_mode="sidepanel", # or "popup"
enable_inline_card_editing=True,
enable_builtin_card_form=True,
)
board.open_add_card_form("todo")
card_form_mode="popup"Uses CardFormDialog, a modal CTkToplevel wrapper around the form.
card_form_mode="sidepanel"Embeds the same form content in a panel beside the board instead of opening a top-level window.
enable_builtin_card_form=False, the board does not
create its own form. Instead it emits on_add_card_requested and
on_edit_card_requested so your application can open its own editor UI.
textarea, checkbox, select, and date. Other field
types, including datetime, tag, badge without options, and
multiselect, use compact text entry controls. For tags and
multiselect, comma-separated input is normalized to list[str].
Search, filter, and sort behavior is field-aware. The board only exposes fields in the built-in UI if the field definitions opt into that behavior.
fields = [
{"key": "title", "label": "Title", "type": "text", "required": True, "searchable": True, "sortable": True},
{"key": "assignee", "label": "Assignee", "type": "select", "options": ["Maya", "Owen"], "filterable": True, "searchable": True},
{"key": "priority", "label": "Priority", "type": "select", "options": ["Low", "Medium", "High"], "filterable": True, "sortable": True},
{"key": "due_date", "label": "Due date", "type": "date", "filterable": True, "sortable": True},
]
board = CTkKanbanBoard(
app,
columns=columns,
cards=cards,
fields=fields,
filter_mode="dim", # or "hide"
)
board.search("Maya")
board.apply_filters({"priority": "High", "overdue_only": True})
board.sort_cards("due_date")
board.sort_cards("manual", reverse=True, column_id="review")
searchable=True.title and
description.
filterable=True.apply_filters() also accepts list/set filters and callable predicates.filter_mode="hide" removes non-matching cards from view.filter_mode="dim" keeps non-matching cards visible but visually de-emphasized.manual, priority, due_date,
created_date, updated_date, title, and any field marked
sortable=True.
manual uses sort_order.priority has a fixed ranking of Critical, High,
Medium, then Low.
sort_cards(..., column_id=...) when
allow_column_sorting=True.
Database integration is operation-first. The board updates optimistically, sends a focused mutation to one background persistence worker, then merges canonical IDs, timestamps, versions, or defaults returned by storage. Choose one of the following integration levels.
| Option | Use it when | You implement |
|---|---|---|
SQLiteKanbanDataSource |
You need a complete local database with no external driver. | Only application setup and initial seed data. |
CRUDKanbanDataSource |
You already have repository, ORM, collection, SDK, or HTTP CRUD functions. | Read, create, update, and delete callbacks. |
KanbanDataSource |
You need native database queries, bulk writes, event history, or change streams. | The complete five-method protocol. |
on_data_changed |
You have a small file or legacy full-snapshot save function. | One synchronous snapshot callback. |
The included adapter owns its schema and uses a fresh thread-safe connection for each operation. It provides transactions, atomic batches, optimistic revisions, idempotent event replay, generated card IDs, timestamps, server-side adapter querying, paging, and change polling.
import customtkinter as ctk
from ctk_kanban import CTkKanbanBoard, SQLiteKanbanDataSource
app = ctk.CTk()
source = SQLiteKanbanDataSource("kanban.db")
source.seed_board(
"work",
[
{"id": "todo", "title": "To Do"},
{"id": "done", "title": "Done"},
],
cards=[],
replace=False,
)
board = CTkKanbanBoard(
app,
data_source=source,
board_id="work",
actor_id="desktop-user-17",
auto_load=True,
server_side_query=True,
page_size=100,
poll_interval_ms=2000,
completed_columns=["done"],
)
board.pack(fill="both", expand=True)
app.mainloop()
replace=False creates missing records without clearing an
existing board. Use replace=True for an intentional reset; it clears cards, columns, event
history, and the board revision.
CRUDKanbanDataSource is database-neutral: it does not guess a connection string, driver,
schema, query language, or authentication model. Your application keeps those decisions and supplies
four normal repository callbacks. This works for PostgreSQL, MySQL, SQL Server, Oracle, MongoDB,
DynamoDB, Redis, graph databases, cloud SDKs, ORMs, and remote APIs.
from contextlib import contextmanager
from ctk_kanban import CRUDKanbanDataSource
def read_board(board_id):
return {
"columns": repository.list_columns(board_id),
"cards": repository.list_cards(board_id),
"revision": repository.get_revision(board_id), # Optional
}
def create(resource, board_id, record, context):
# resource is exactly "card" or "column".
return repository.insert(
resource,
board_id,
record,
position=context.position,
transaction=context.transaction,
event_id=context.metadata.event_id,
)
def update(resource, board_id, record_id, record, context):
return repository.update(
resource,
board_id,
record_id,
record,
position=context.position,
transaction=context.transaction,
expected_revision=context.metadata.expected_revision,
)
def delete(resource, board_id, record_id, context):
repository.delete(
resource,
board_id,
record_id,
transaction=context.transaction,
)
@contextmanager
def transaction(events):
with repository.begin() as session:
yield session
source = CRUDKanbanDataSource(
read=read_board,
create=create,
update=update,
delete=delete,
transaction=transaction, # Optional but recommended for atomic batches
)
The bridge translates board operations into CRUD calls:
context.position.create returns the canonical stored record.read_board.transaction(events).| Return | Meaning |
|---|---|
| Record mapping | Accepted. The returned database values become the canonical card or column. |
None or True |
Accepted using the record submitted to the callback. |
False |
Rejected. The board restores the optimistic UI change. |
MutationResult |
Advanced response with conflicts, revisions, ID maps, changed records, or retryability. |
transaction(events).
Use a direct adapter when reading every record into the CRUD bridge would be inefficient or when the backend should own concurrency, queries, event history, and batching.
from ctk_kanban import (
BoardLoadResult,
CardPage,
CardQuery,
ChangePage,
MutationEvent,
MutationResult,
)
class MyDataSource:
def load_board(
self, board_id: str, query: CardQuery | None = None
) -> BoardLoadResult:
...
def apply_mutation(self, event: MutationEvent) -> MutationResult:
...
def apply_batch(self, events: list[MutationEvent]) -> MutationResult:
...
def query_cards(self, board_id: str, query: CardQuery) -> CardPage:
...
def get_changes(
self, board_id: str, since_revision: int | str | None
) -> ChangePage:
...
Adapter methods are intentionally blocking and thread-safe; PersistenceCoordinator owns
the worker. Treat event_id as an idempotency key, check expected_revision in
the same transaction as the write, and make apply_batch() all-or-nothing.
RetryPolicy defaults to three attempts with bounded exponential backoff. Connection,
timeout, and operating-system failures move the coordinator offline after retries. Pending operations
remain visible and queue in memory in FIFO order.
A custom adapter should raise ConnectionError, TimeoutError, or
OSError for retryable connectivity failures. Domain rejections should return
MutationResult(accepted=False, reason=...) instead.
Observe transitions with on_persistence_status or
get_persistence_status(). Call set_online(True) after connectivity returns,
or call retry_last_save() after resolving a rejected write.
Storage can return ConflictDetails when expected_revision is stale.
Configure conflict_strategy as:
"server_wins": replace local data with the server snapshot."local_wins": retry the local operation against the current server revision."callback": invoke on_conflict so the application decides.auto_load=True loads board_id after the widget is constructed.server_side_query=True delegates toolbar search, filters, sorting, and paging.page_size controls the requested page size; load_next_page() appends more.poll_interval_ms > 0 calls get_changes() and reloads after remote events.refresh_from_source() from the notification handler.
on_data_changed remains useful for JSON files and small local snapshots. It runs
synchronously and receives all columns and cards plus the focused action event.
def save_snapshot(event):
write_json({"columns": event["columns"], "cards": event["cards"]})
return True
board = CTkKanbanBoard(
app,
columns=columns,
cards=cards,
on_data_changed=save_snapshot,
)
Return False or {"cancel": True, "reason": "..."} to reject and restore an
action. Use on_action_cancelled to display or log the reason.
set_data(), set_cards(),
set_columns(), and set_state() replace local state without persistence
callbacks. They are intended for application-driven reloads. With a data source, prefer
refresh_from_source().
destroy() when disposing the board so pending Tk callbacks and the worker close.The standalone database integration guide contains the same persistence model in a compact format for teams that want a database-only handout.
The default renderer uses a modern adaptive light/dark system: layered board surfaces, colored column rails, priority-accented cards, compact metadata tiles, filter chips, persistence status pills, and matching form controls. These defaults work without a custom style and remain fully configurable.
The default card renderer is field-driven, but you can fully replace card content with a custom renderer while still using the built-in search, form, filter, and callback infrastructure.
import customtkinter as ctk
def render_card(card_frame, card_data, fields, theme):
card_frame.grid_columnconfigure(0, weight=1)
ctk.CTkLabel(
card_frame,
text=card_data["title"],
anchor="w",
font=ctk.CTkFont(size=14, weight="bold"),
text_color=theme["text_color"],
).grid(row=0, column=0, sticky="ew", padx=10, pady=(10, 4))
if card_data.get("description"):
ctk.CTkLabel(
card_frame,
text=str(card_data["description"]),
anchor="w",
justify="left",
wraplength=230,
text_color=theme["muted_text_color"],
).grid(row=1, column=0, sticky="ew", padx=10, pady=(0, 10))
style = {
"board_fg_color": ("#EEF2F7", "#09111F"),
"column_fg_color": ("#E2E8F0", "#152033"),
"card_fg_color": ("#FFFFFF", "#101827"),
"card_hover_color": ("#F8FAFC", "#17233A"),
"card_selected_color": ("#DBEAFE", "#1E3A5F"),
"drop_indicator_color": "#38BDF8",
}
board = CTkKanbanBoard(
app,
columns=columns,
cards=cards,
fields=fields,
style=style,
priority_colors={"Critical": "#B91C1C"},
tag_colors={"API": "#1D4ED8"},
card_renderer=render_card,
)
The renderer signature is:
CardRenderer = Callable[[Any, dict[str, Any], list[dict[str, Any]], dict[str, Any]], None]
The first argument is the card frame that you populate. The board does not add default content when a custom renderer is supplied.
The board supports both card dragging and column dragging. These features are enabled by default and are controlled by constructor flags rather than a separate drag manager.
enable_card_drag toggles card movement.enable_card_reorder allows reordering inside a column.enable_column_drag allows dragging column headers.enable_drag_preview shows a drag preview window during movement.show_drop_indicator displays insertion markers.enable_horizontal_autoscroll and enable_vertical_autoscroll keep drag targets
reachable near the edges.
Two column-level rules affect dragging:
locked column cannot receive moved cards.enforce_column_limits=True, a column with max_cards set refuses
additional cards once the limit is reached.
CTkKanBan keeps a single selected card ID. Programmatic selection is exposed through
select_card(), clear_selection(), and get_selected_card().
The built-in card context menu includes:
(copy) to the title.
You can append your own actions with card_context_menu_items. Each custom menu item can be
always enabled, always disabled, or conditionally enabled with a callable.
The board exposes a small but useful state API for serialization, persistence, and undo-like workflows.
| Method | What it captures or restores |
|---|---|
get_data() |
Columns and cards only. |
set_data(data) |
Replaces columns and cards without touching persistence callbacks. |
get_state() |
Columns, cards, search query, filters, sort, per-column sorts, and selected card. |
set_state(state) |
Restores a snapshot previously returned by get_state(). |
set_cards(cards) |
Replaces only the card collection. |
set_columns(columns) |
Replaces only the column collection after validating that existing cards still fit. |
This split is deliberate. Use get_data() for persistence formats that should not include UI
search/filter state. Use get_state() for restoring the board as the user left it.
End-user mutations record defensive before/after snapshots up to undo_limit.
undo() and redo() restore those snapshots; with a data source attached, the
board computes focused delta events so partially loaded server data is not overwritten.
Use apply_batch() for imports and multi-step edits. Supported operation names are
add_card, update_card, delete_card, move_card,
add_column, update_column, delete_column, and
move_column.
saved = board.apply_batch(
[
{
"operation": "update_card",
"card_id": 10,
"new_data": {"priority": "High"},
},
{
"operation": "move_card",
"card_id": 10,
"target_column": "review",
},
{
"operation": "add_card",
"card_data": {
"column": "todo",
"title": "Follow up",
},
},
],
source="bulk_edit",
)
apply_batch() in a full adapter or a transaction callback in the CRUD bridge.
The board has a broad, flat style dictionary. Colors can be passed directly through
theme or style, and the constructor merges nested
priority_colors, tag_colors, and font_config overrides from the
style mapping.
Visual details such as card_metadata_fg_color, card_accent_width,
column_control_fg_color, column_count_full_fg_color,
filter_chip_fg_color, and the success, warning, and danger surface colors can be changed
independently. Existing broad keys such as card_fg_color and button_fg_color
continue to work.
In practice:
style overrides theme when both set the same style key.font_config entry such as {"toolbar": font} becomes
toolbar_font internally.
get_style() returns the full merged style snapshot.drag_update_interval_ms and
cleanup_time_budget_ms.
Primary entry point:
The tables below cover the complete constructor surface for this release. Run
help(CTkKanbanBoard) against your installed version when you need its exact live signature.
| Parameter | Type / default | Meaning |
|---|---|---|
master |
Any parent widget | Parent passed to the underlying CTkFrame. |
columns |
None |
Ordered column definitions. Each column needs id and title. |
cards |
None |
Initial card definitions. Cards must reference existing column IDs. |
fields |
None |
Field schema for rendering, forms, search, filter, and sort. Defaults are used when omitted. |
enable_horizontal_scroll |
True |
Wraps the board area in a horizontal CTkScrollableFrame. |
enable_column_scroll |
True |
Wraps each column body in a vertical CTkScrollableFrame. |
column_width |
300 |
Column width in pixels. Validation requires at least 160. |
column_height |
600 |
Column height in pixels. Validation requires at least 180. |
column_gap |
12 |
Horizontal spacing between columns. Must be non-negative. |
board_padding |
None |
Outer padding. When omitted, the theme's board_padding value is used. |
| Parameter | Default | Meaning |
|---|---|---|
show_toolbar |
True |
Creates the built-in toolbar row above the board. |
show_search |
True |
Shows the search box when enable_search=True. |
show_filter_button |
True |
Shows the filter button when enable_filters=True. |
show_sort_button |
True |
Shows the sort button when enable_sorting=True. |
show_add_card_button |
True |
Shows the toolbar-level add-card button. |
show_clear_filters_button |
True |
Shows the toolbar clear button. |
| Parameter | Default | Meaning |
|---|---|---|
show_card_count |
True |
Shows per-column card counts unless a column overrides with show_count. |
show_column_add_button |
True |
Shows per-column add buttons unless a column overrides with show_add_button. |
show_column_menu |
True |
Shows each column's menu button unless a column overrides with show_menu. |
enforce_column_limits |
True |
Honors max_cards limits during add and move operations. |
enable_column_drag |
True |
Allows dragging columns by their headers. |
card_mode |
"detailed" |
"compact" truncates visible content; "detailed" shows more fields. |
enable_card_hover |
True |
Applies hover colors to cards. |
enable_card_selection |
True |
Selects cards on click and updates selection visuals. |
enable_card_context_menu |
True |
Shows the built-in right-click menu. |
enable_card_double_click |
True |
Double-click starts inline title editing unless you override it with a callback. |
enable_inline_card_editing |
True |
Lets users click default-rendered card fields and edit them inside the card. |
enable_builtin_card_form |
True |
Controls whether the board creates its own add/edit forms. |
card_form_mode |
"popup" |
Switches between a modal dialog and a side panel. |
confirm_delete |
True |
Asks for confirmation before request_delete_card() deletes a card. |
enable_card_drag |
True |
Allows dragging cards. |
enable_card_reorder |
True |
Allows reordering within a column. |
enable_drag_preview |
True |
Shows a preview window while dragging cards. |
drag_preview_opacity |
1.0 |
Clamped to the supported range 0.1 to 1.0. |
show_drop_indicator |
True |
Displays an insertion marker during drag operations. |
enable_horizontal_autoscroll |
True |
Autoscrolls the board horizontally during card drags. |
enable_vertical_autoscroll |
True |
Autoscrolls individual columns vertically during card drags. |
incremental_card_rendering |
True |
Reuses widgets for most card-level mutations instead of forcing a full refresh. |
incremental_column_rendering |
True |
Reuses widgets for many column-level mutations. |
drag_update_interval_ms |
16 |
Coalesces high-frequency drag motion updates. |
autoscroll_interval_ms |
45 |
Minimum interval between autoscroll updates. |
cleanup_time_budget_ms |
8 |
Time budget for deferred widget cleanup batches. Must be at least 1. |
| Parameter | Default | Meaning |
|---|---|---|
enable_search |
True |
Enables search APIs and toolbar search UI. |
enable_filters |
True |
Enables filter APIs and built-in filter dialog. |
enable_sorting |
True |
Enables sorting APIs and built-in sort menus. |
allow_column_sorting |
True |
Allows sort_cards(..., column_id=...) and the "Sort column..." menu entry. |
default_sort |
"manual" |
Initial global sort key. Must be an allowed sort key. |
filter_mode |
"hide" |
Either remove or dim cards that do not match the current view. |
show_no_results |
True |
Displays an empty-result message in columns with no visible cards. |
theme |
None |
Style override mapping merged into the default theme. |
style |
None |
Alias for theme-style overrides. Wins over theme on overlapping keys. |
priority_colors |
None |
Per-priority chip color overrides merged over DEFAULT_PRIORITY_COLORS. |
tag_colors |
None |
Per-tag chip color overrides. |
font_config |
None |
Mapping of font slots such as toolbar or card_title to font objects. |
card_renderer |
None |
Custom card rendering callback. Replaces the default card body builder. |
card_context_menu_items |
None |
Extra context-menu actions appended after the built-in items. |
| Parameter | Default | Meaning |
|---|---|---|
responsive_columns |
True |
Lets columns adapt between the configured minimum and maximum widths. |
min_column_width |
240 |
Smallest responsive column width; must be at least 160. |
max_column_width |
420 |
Largest responsive column width; must not be below the minimum. |
column_control_size |
30 |
Pixel size used by compact column controls; minimum 28. |
card_density |
"comfortable" |
Spacing preset: "compact", "comfortable", or "spacious". |
show_drag_handles |
True |
Shows the visual drag affordance on cards. |
max_visible_tags |
6 |
Maximum tags rendered on a card before remaining tags are summarized. |
tags_per_row |
3 |
Maximum tag chips placed on each rendered row. |
confirm_discard_changes |
True |
Prompts before replacing or closing a dirty built-in form. |
highlight_search_matches |
True |
Highlights matching text in visible card content. |
| Parameter | Default | Meaning |
|---|---|---|
data_source |
None |
SQLite, CRUD, or custom KanbanDataSource used for durable state. |
board_id |
"default" |
Durable board namespace passed to every data-source operation. |
actor_id |
None |
User, process, or device identity included with mutation metadata. |
auto_load |
False |
Loads the board from data_source after construction. |
server_side_query |
False |
Delegates search, filters, sorting, and paging to the data source. |
page_size |
100 |
Requested card page size; must be at least 1. |
poll_interval_ms |
0 |
Change polling interval. Zero disables polling. |
retry_policy |
None |
Optional RetryPolicy; defaults are used when omitted. |
disable_while_saving |
True |
Rejects overlapping user mutations while a write is pending. |
id_factory |
None |
Callable that creates local card IDs; UUID strings are used by default. |
use_temporary_ids |
True |
Marks new IDs as temporary so storage may replace them canonically. |
immutable_card_ids |
True |
Prevents ordinary updates from changing a card ID. |
immutable_column_ids |
True |
Prevents ordinary updates from changing a column ID. |
conflict_strategy |
"server_wins" |
"server_wins", "local_wins", or "callback". |
undo_limit |
50 |
Maximum in-memory undo entries. Zero disables history. |
completion_field |
"completed" |
Boolean card key used by overdue and completion behavior. |
completed_columns |
None |
Column IDs whose cards count as completed for overdue behavior. |
timezone_name |
"UTC" |
IANA timezone used for date comparison and display. |
locale_name |
None |
Optional locale name used when formatting stored timestamps. |
normalize_empty_values |
True |
Normalizes empty optional form values using each field's empty-value rule. |
logger |
None |
Optional logger for persistence errors and operational diagnostics. |
Callbacks receive an event mapping. Mutation callbacks may cancel before persistence; status and conflict callbacks observe the asynchronous data-source lifecycle.
| Parameter | Default | When it runs |
|---|---|---|
on_card_clicked | None | After a card click and selection update. |
on_card_double_clicked | None | After a card double-click. |
on_card_right_clicked | None | When opening the card context flow. |
on_card_moved | None | Before committing a cross-column move. |
on_card_reordered | None | Before committing same-column order changes. |
on_card_created | None | Before a created card is persisted. |
on_card_updated | None | Before a card update is persisted. |
on_card_deleted | None | Before a card deletion is persisted. |
on_column_created | None | Before a column creation is persisted. |
on_column_updated | None | Before a column update is persisted. |
on_column_deleted | None | Before a column deletion is persisted. |
on_column_reordered | None | Before column order is committed. |
on_data_changed | None | Legacy full-snapshot persistence path. |
on_filter_changed | None | Before active filters change. |
on_search_changed | None | Before the search query changes. |
on_sort_changed | None | Before global or column sort changes. |
on_action_cancelled | None | After an optimistic action is restored. |
on_error | None | When callback, load, query, or persistence work fails. |
on_add_card_requested | None | Overrides the built-in add-card form request. |
on_edit_card_requested | None | Overrides the built-in edit-card form request. |
on_persistence_status | None | On loading, saving, saved, retrying, offline, conflict, or error states. |
on_conflict | None | When storage reports a conflict; may return "server_wins" or "local_wins". |
| Method | Returns | Notes |
|---|---|---|
| add_card(card_data, *, source="api") | Card copy or None |
Validates, assigns a new trailing sort_order when needed, and can be cancelled. |
| update_card(card_id, new_data, *, source="api") | Card copy or None |
Merges new data into the current card, revalidates it, and can rename the card ID. |
| delete_card(card_id, *, source="api") | bool |
Deletes and reindexes manual order in the source column. Returns False on cancellation. |
| duplicate_card(card_id, *, source="api") | Card copy or None |
Copies the card, generates a new ID, appends (copy) to the title, and adds it. |
| move_card(card_id, target_column, target_index=None, *, source="api") | bool |
Moves or reorders a card and rewrites manual sort_order values. |
| reorder_card(card_id, target_index, *, source="api") | bool |
Convenience wrapper for same-column reordering. |
| add_column(column_data, *, source="api") | Column copy or None |
Appends a column to the end of the board order and can be cancelled. |
| update_column(column_id, new_data, *, source="api") | Column copy or None |
Updates metadata and can atomically rename the column ID across existing cards. |
| delete_column(column_id, *, source="api") | bool |
Deletes only empty columns. Raises if any card still belongs to the column. |
| move_column(column_id, target_index, *, source="api") | bool |
Moves a column in the ordered column list. |
| apply_batch(operations, *, source="batch") | bool |
Applies supported card and column operations as one UI change and one adapter batch. |
| Method | Returns | Notes |
|---|---|---|
| get_card(card_id) | Card copy or None |
Raises if the ID is unhashable, but returns None for a missing hashable ID. |
| get_all_cards() | list[dict[str, Any]] |
Returns the owned insertion order of the internal card mapping. |
| get_cards_by_column(column_id) | list[dict[str, Any]] |
Returns the current display order for that column, including active sorting. |
| get_column(column_id) | Column copy or None |
Returns one column by ID. |
| get_columns() | list[dict[str, Any]] |
Returns the current board column order. |
| get_style() | dict[str, Any] |
Returns the merged theme plus priority_colors, tag_colors, and font_config. |
| get_data() | BoardData |
Returns only columns and cards. |
| load_data(data) | None |
Alias for set_data(). |
| set_data(data) | None |
Replaces columns and cards while preserving current view state unless you overwrite it. |
| load_cards(cards) | None |
Alias for set_cards(). |
| set_cards(cards) | None |
Replaces the complete card collection without firing persistence callbacks. |
| set_columns(columns) | None |
Replaces columns after checking that existing cards do not reference removed columns. |
| clear_board() | None |
Removes all cards while preserving columns and clearing selection. |
| get_state() | dict[str, Any] |
Returns data plus search, filters, global sort, per-column sorts, and selected card ID. |
| set_state(state) | None |
Restores a previously captured board state snapshot. |
| Method | Returns | Notes |
|---|---|---|
| can_undo() | bool |
Reports whether an undo snapshot is available. |
| undo() | bool |
Restores the previous state and persists the focused delta when a data source is attached. |
| can_redo() | bool |
Reports whether a redo snapshot is available. |
| redo() | bool |
Reapplies the latest undone state and persists its focused delta. |
| refresh_from_source() | bool |
Starts an asynchronous board load; returns False without a data source. |
| query_source(query, *, append=False) | bool |
Runs a CardQuery asynchronously and replaces or appends the visible page. |
| load_next_page(column_id=None) | bool |
Requests the next page globally or for one column using current query state. |
| get_persistence_status() | dict[str, Any] |
Returns state, message, board revision, and queued mutation count. |
| retry_last_save() | bool |
Retries the last rejected or failed pending write. |
| set_online(online) | None |
Marks persistence online/offline; going online starts FIFO queue replay. |
| remap_card_id(old_id, new_id, *, persist=False) | Card copy | Replaces a temporary card ID and updates selection/widgets without duplication. |
| set_column_width(width, column_id=None) | None |
Sets the shared width or one adjustable column width within configured bounds. |
| destroy() | None |
Cancels polling/cleanup callbacks, closes forms, and shuts down the persistence worker. |
| Method | Returns | Notes |
|---|---|---|
| refresh() | None |
Fully rebuilds the visible board from the owned data and current view state. |
| search(query) | bool |
Updates the current query and can be cancelled by on_search_changed. |
| clear_search() | None |
Convenience wrapper that resets the query to an empty string. |
| apply_filters(filters) | bool |
Replaces the active filter mapping and can be cancelled by on_filter_changed. |
| clear_filters() | None |
Equivalent to apply_filters({}). |
| sort_cards(sort_key, reverse=False, column_id=None) | bool |
Applies a global or per-column display sort without mutating card content except manual move order APIs. |
| select_card(card_id) | Card copy | Updates the single-card selection state and card visuals. |
| clear_selection() | None |
Clears the current selection. |
| get_selected_card() | Card copy or None |
Returns the selected card if one is currently selected. |
| start_inline_card_edit(card_id, field_key="title") | bool |
Starts editing one visible writable field inside a default-rendered card. |
| open_add_card_form(column_id=None) | None |
Opens the add flow for a column or the first unlocked column when omitted. |
| open_edit_card_form(card_id) | None |
Explicitly opens the configured full-card popup or side-panel form. |
| request_delete_card(card_id) | bool |
Runs the configured confirmation flow, then deletes through the normal delete API. |
These public exports form the database-neutral boundary. Application code usually constructs one data
source and passes it to CTkKanbanBoard; adapter authors use the typed contracts directly.
| Export | Purpose |
|---|---|
KanbanDataSource |
Runtime-checkable five-method protocol accepted by the board. |
SQLiteKanbanDataSource |
Included transactional SQLite implementation. |
CRUDKanbanDataSource |
Four-callback bridge for an application-owned repository. |
PersistenceCoordinator |
Single-worker ordering, retries, offline replay, loads, queries, and callback scheduling. |
RetryPolicy |
Retry configuration: attempts, initial delay, multiplier, and maximum delay. |
CRUDResource |
Type alias for the literal resource names "card" and "column". |
CRUDWriteResult |
Type alias for record mappings, MutationResult, booleans, or None. |
CRUDKanbanDataSource| Callback | Signature | Responsibility |
|---|---|---|
read |
(board_id) |
Return BoardLoadResult or a mapping with columns, cards, and optional revision. |
create |
(resource, board_id, record, context) |
Insert a card or column and preferably return its canonical stored record. |
update |
(resource, board_id, record_id, record, context) |
Replace/update one stored record. The ID is the previous ID during a rename. |
delete |
(resource, board_id, record_id, context) |
Delete one stored card or column. |
transaction |
(events) -> context manager |
Optional atomic scope. The yielded value becomes context.transaction. |
changes |
(board_id, since_revision) |
Optional optimized change feed returning ChangePage or an equivalent mapping. |
CRUDContext| Attribute | Meaning |
|---|---|
event | The complete focused MutationEvent. |
metadata | Convenience property exposing event.metadata. |
transaction | Object yielded by the transaction context manager, or None. |
position | Ordered column position for column create/reorder operations. |
previous_id | Stored identifier targeted by update or delete. |
SQLiteKanbanDataSource| Method | Purpose |
|---|---|
seed_board(board_id, columns, cards, *, replace=False) | Creates/imports an initial board. |
load_board(board_id, query=None) | Loads columns and a card page. |
query_cards(board_id, query) | Searches, filters, sorts, and pages cards. |
apply_mutation(event) | Applies one event transactionally and idempotently. |
apply_batch(events) | Applies one-board events atomically with temporary-ID rebasing. |
get_changes(board_id, since_revision) | Returns persisted events after a revision. |
| Contract | Important fields |
|---|---|
EventMetadata |
board_id, actor_id, event_id,
transaction_id, expected_revision, source,
timestamp. |
MutationEvent |
type, focused payload, and metadata.
to_dict() and from_mapping() cross serialization boundaries. |
MutationResult |
accepted, reason, canonical card/column,
changed records, id_map, board_revision, conflict,
and retryable. |
ConflictDetails |
expected_revision, actual_revision,
optional server_data, and a user-facing message. |
PersistenceState |
Literal status values used by persistence status callbacks. |
| Contract | Fields |
|---|---|
CardQuery |
column_id, search, filters, sort_key,
reverse, offset, limit, completion settings, and timezone. |
CardPage |
cards, total, offset, limit,
column_totals, board_revision, and derived has_more. |
BoardLoadResult |
columns, initial cards, column_totals,
board_revision, and has_more. |
ChangePage |
Mutation events after a revision and the latest board_revision. |
RetryPolicy defaults| Field | Default | Meaning |
|---|---|---|
attempts | 3 | Total attempts including the first call. |
initial_delay | 0.25 | Seconds before the first retry. |
multiplier | 2.0 | Delay multiplier after each failure. |
max_delay | 3.0 | Maximum delay between attempts. |
ColumnDefinition| Key | Required | Meaning |
|---|---|---|
id |
Yes | Hashable, non-empty identifier used by cards and public APIs. |
title |
Yes | Display name shown in the column header. |
color |
No | Header accent color for the column's vertical color bar. |
max_cards |
No | Non-negative card limit. Enforced only when enforce_column_limits=True. |
locked |
No | Blocks card additions and moves into the column. |
show_count |
No | Per-column override for the count badge. |
show_add_button |
No | Per-column override for the header add button. |
show_menu |
No | Per-column override for the header menu button. |
CardDefinition| Key | Required | Meaning |
|---|---|---|
id |
Yes | Hashable, non-empty card identifier. |
column |
Yes | The column ID that currently owns the card. |
title |
Yes | Card title. Cannot be empty. |
sort_order |
No | Numeric manual order value used by the manual sort mode. |
| Any other key | No | Preserved as card data for rendering, searching, filtering, sorting, and callbacks. |
FieldDefinition| Key | Meaning |
|---|---|
key |
Unique field name stored in card dictionaries. |
label |
User-facing label used on cards, forms, and dialogs. |
type |
One of text, textarea, number, select,
multiselect, date, datetime, checkbox,
tag, tags, badge, or hidden.
|
required |
Marks the field as required during validation. title is always required. |
default |
Default value used by the built-in add form. |
placeholder |
Entry placeholder text for the built-in form. |
options |
Allowed options for select and multiselect. |
show_on_card |
Includes the field in the default card renderer and makes it an inline-edit target. |
show_in_form |
Includes the field in the built-in form. |
searchable |
Includes the field in board search. |
filterable |
Includes the field in the built-in filter dialog. |
sortable |
Allows the field key to be used as a sort key. |
read_only |
Disables editing in both the inline editor and built-in form while preserving the value. |
validator |
Custom callable (value, card_copy) -> bool | str | None. |
| Field type | Built-in form control | Default card rendering behavior |
|---|---|---|
text |
Single-line entry | Label: value text. |
textarea |
Textbox | Wrapped body text. |
number |
Single-line entry, converted to int or float |
Label: value text. |
select |
Option menu | Label: value text unless the field key is priority. |
multiselect |
Comma-separated entry parsed to list[str] |
Label: value text. |
date / datetime |
Single-line entry | Label: value text. |
checkbox |
Checkbox | Yes / No text. |
tag, tags, badge |
Single-line entry, except tags parses comma-separated values |
Rendered as chips. |
hidden |
Not shown by default | Not shown by default. |
ContextMenuItem and related aliases| Type | Definition |
|---|---|
ContextMenuItem |
Requires label and callback. Optional
enabled accepts a boolean or callable, and separator_before inserts a
menu separator.
|
BoardData |
{"columns": [...], "cards": [...]} |
KanbanEvent |
dict[str, Any] |
KanbanCallback |
Callable[[KanbanEvent], Any] |
CardRenderer |
Callable[[Any, dict[str, Any], list[dict[str, Any]], dict[str, Any]], None] |
Every event dictionary created by the board includes type, timestamp, and
source. The rest of the payload depends on the callback.
Cancellable callbacks may reject an operation by returning False or a mapping with
{"cancel": True}. Non-cancellable callbacks are purely observational.
| Callback | Event type | Cancellable | Key payload fields |
|---|---|---|---|
on_card_clicked |
card_clicked |
No | card_id, card_data, x_root, y_root |
on_card_double_clicked |
card_double_clicked |
No | card_id, card_data, pointer coordinates when triggered by mouse |
on_card_right_clicked |
card_right_clicked |
No | card_id, card_data, pointer coordinates |
on_card_created |
card_created |
Yes | card_id, card_data, column_data |
on_card_updated |
card_updated |
Yes |
card_id, old_card_id, card_data,
old_card_data, changed_fields, changed_cards,
column_data
|
on_card_deleted |
card_deleted |
Yes | card_id, card_data, old_card_data, changed_cards |
on_card_moved |
card_moved |
Yes |
card_id, old_column, new_column, old_index,
new_index, old_sort_order, new_sort_order,
changed_cards
|
on_card_reordered |
card_reordered |
Yes | Same payload shape as on_card_moved for same-column order changes. |
on_column_created |
column_created |
Yes | column_id, column_data, index |
on_column_updated |
column_updated |
Yes |
column_id, old_column_id, column_data,
old_column_data, changed_fields, affected_cards
|
on_column_deleted |
column_deleted |
Yes | column_id, column_data, old_index |
on_column_reordered |
column_reordered |
Yes | column_id, old_index, new_index, columns |
on_data_changed |
data_changed |
Yes | action_type, action_event, columns, cards |
on_filter_changed |
filter_changed |
Yes | filters, old_filters |
on_search_changed |
search_changed |
Yes | query, old_query |
on_sort_changed |
sort_changed |
Yes | sort_key, reverse, column_id, old_sort |
on_action_cancelled |
action_cancelled |
No | action_type, reason, action_event |
on_error |
error |
No | error, message, optional action_event |
on_add_card_requested |
add_card_requested |
No | column_id, column_data |
on_edit_card_requested |
edit_card_requested |
No | card_id, card_data |
on_persistence_status |
persistence_status |
No | board_id, state, message, queued_count |
on_conflict |
conflict |
Decision |
mutation and conflict. Return "server_wins" or
"local_wins"; another return keeps the configured strategy.
|
A ContextMenuItem.callback receives a single event with
type="card_context_action", source="context_menu", card_id, and
card_data.
The package exports DEFAULT_THEME, DEFAULT_STYLE,
DEFAULT_PRIORITY_COLORS, merge_theme(), and merge_style(). The
following keys exist in DEFAULT_THEME.
| Keys | Used by |
|---|---|
board_fg_color, board_corner_radius, board_padding
|
Board container background, shape, and outer padding. |
toolbar_fg_color, toolbar_border_color,
toolbar_border_width, toolbar_corner_radius,
toolbar_text_color, toolbar_button_text_color,
toolbar_primary_button_text_color
|
Toolbar surface and button text styling. |
column_fg_color, column_header_fg_color,
column_border_color, column_border_width,
column_corner_radius, column_header_corner_radius,
column_title_text_color, column_count_fg_color,
column_count_text_color, column_control_hover_color,
column_no_results_text_color
|
Column frame, header, count badge, controls, and no-results text. |
| Keys | Used by |
|---|---|
card_fg_color, card_hover_color, card_selected_color,
card_border_color, card_selected_border_color,
card_border_width, card_corner_radius,
card_title_text_color, card_body_text_color,
card_metadata_text_color, card_min_height, card_gap
|
Default card background, border, typography, and spacing. |
tag_fg_color, tag_text_color, badge_text_color,
priority_colors, tag_colors
|
Chip rendering for tag, tags, badge, and priority values. |
drop_indicator_color, drag_preview_fg_color, drag_preview_text_color |
Drag indicator and drag preview window styling. |
| Keys | Used by |
|---|---|
button_fg_color, button_hover_color, button_text_color,
button_text_color_disabled, button_corner_radius,
button_border_width
|
Primary action buttons, including the toolbar add button and form save button. |
secondary_button_fg_color, secondary_button_hover_color,
secondary_button_text_color, secondary_button_text_color_disabled,
secondary_button_corner_radius, secondary_button_border_width
|
Secondary action buttons such as toolbar filter/sort/clear and form cancel. |
search_fg_color, search_border_color, search_text_color,
search_placeholder_text_color
|
Toolbar search entry. |
input_fg_color, input_border_color, input_text_color,
input_placeholder_text_color, input_corner_radius,
input_border_width
|
Single-line form controls. |
textbox_fg_color, textbox_border_color, textbox_text_color,
textbox_corner_radius, textbox_border_width
|
Textarea controls in forms. |
checkbox_fg_color, checkbox_hover_color,
checkbox_border_color, checkbox_checkmark_color,
checkbox_text_color, checkbox_text_color_disabled,
checkbox_corner_radius, checkbox_border_width
|
Checkbox form controls and filter dialog checkbox. |
optionmenu_fg_color, optionmenu_button_color,
optionmenu_button_hover_color, optionmenu_text_color,
optionmenu_text_color_disabled, optionmenu_dropdown_fg_color,
optionmenu_dropdown_hover_color, optionmenu_dropdown_text_color,
optionmenu_corner_radius
|
Select controls and filter dialog option menus. |
dialog_fg_color, dialog_border_color,
dialog_border_width, dialog_corner_radius,
dialog_title_text_color, dialog_text_color
|
Popup dialogs. |
panel_fg_color, panel_border_color, panel_border_width,
panel_corner_radius, panel_title_text_color
|
Side-panel form mode. |
menu_fg_color, menu_hover_color, menu_text_color,
menu_hover_text_color, menu_disabled_text_color,
menu_border_width
|
Tk menus created for sort, move, and card actions. |
scrollbar_button_color, scrollbar_button_hover_color |
Scrollable column bodies and dialogs. |
danger_color, muted_text_color, text_color,
overlay_text_color, corner_radius, border_width
|
Shared text, alert, and fallback geometry values across the widget tree. |
The constructor accepts a font_config mapping. Each entry is stored internally as
{name}_font. The current widgets read these font slots:
Most applications only instantiate CTkKanbanBoard. The package also exports lower-level
widgets that the board itself uses. These are most useful when you want to extend or embed parts of the
board behavior in a custom composition.
| Class | Primary purpose | Public methods |
|---|---|---|
CTkKanbanCard |
Renders one card and forwards pointer gestures to the board. | set_selected(), set_dimmed(), set_dragging() |
CTkKanbanColumn |
Owns a column header, scrollable card layout, no-results label, and drop indicator. |
update_column_data(), add_card_widget(),
place_card_widget(), set_card_widget_order(),
remove_card_widget(), update_card_count(),
show_drop_indicator(), clear_drop_indicator(),
prepare_drag_geometry(), clear_drag_geometry(),
card_index_at(), contains_point(), autoscroll(),
show_no_results(), clear_no_results()
|
CTkKanbanToolbar |
Optional toolbar used by the board. | set_search_query(), set_filter_active(), destroy() |
| Class | Signature | Use case |
|---|---|---|
ctk_kanban.dialogs.CardFormFrame |
CardFormFrame(master, fields, theme, *, title, initial_data=None, on_submit, on_close=None, **kwargs) | Reusable embedded form widget. Exposes focus_first_control(). |
ctk_kanban.dialogs.CardFormDialog |
CardFormDialog(master, fields, theme, *, title, initial_data=None, on_submit, on_close=None) | Modal popup wrapper around CardFormFrame. |
ctk_kanban.dialogs.FilterDialog |
FilterDialog(master, fields, cards, theme, *, current_filters=None, on_apply) | Exact-match filter editor generated from filterable fields. |
These functions are available from submodules and are useful when you want to integrate more tightly with the package's data model or UI helpers.
ctk_kanban.themes| Function or constant | Purpose |
|---|---|
DEFAULT_THEME / DEFAULT_STYLE |
Default style dictionary. |
DEFAULT_PRIORITY_COLORS |
Default priority chip colors for Critical, High, Medium, and Low. |
| merge_theme(theme=None) | Returns a defensive copy of the default theme updated by the supplied mapping. |
| merge_style(style=None) | Alias for merge_theme(). |
ctk_kanban.events| Function | Purpose |
|---|---|
| create_event(event_type, source="api", **payload) | Creates a standard event dictionary with a UTC ISO timestamp and source tag. |
| cancellation_reason(result) | Interprets the return value of a callback and extracts a cancellation reason when present. |
ctk_kanban.validators| Function | Purpose |
|---|---|
| validate_column(column) | Validates and normalizes one column definition. |
| validate_columns(columns) | Validates an ordered column collection and rejects duplicate IDs. |
| validate_card(card, column_ids) | Validates one card while preserving custom fields. |
| validate_cards(cards, column_ids) | Validates a card collection and rejects duplicate IDs. |
| validate_field(field) | Validates one field definition and fills default values. |
| validate_fields(fields) | Validates the field list or returns the package defaults when None. |
| validate_card_values(card, fields) | Applies required, option, type, and custom validation rules to card values. |
| validate_context_menu_items(items) | Validates custom context-menu action definitions. |
ctk_kanban.utils| Function | Purpose |
|---|---|
| clone(value) | Deep-copies public data before storing it or returning it. |
| display_value(value) | Converts values into concise text for default rendering and form population. |
| searchable_text(value) | Creates case-folded search text from a value. |
| parse_temporal(value) | Best-effort conversion of dates and ISO strings into timezone-aware datetime values. |
| comparable_value(value) | Builds a stable sort value across temporal, numeric, string, boolean, and other types. |
| parse_list_value(value) | Normalizes comma-separated or iterable list-like form input to list[str]. |
| generate_card_id(existing_ids) | Generates the next integer ID when all current IDs are integers, otherwise a UUID string. |
| iter_widget_tree(widget) | Yields a widget and all descendants. |
| Exception | Meaning |
|---|---|
KanbanError |
Base class for all package-specific exceptions. |
KanbanValidationError |
Raised when board options or public data shapes are invalid. |
KanbanDuplicateIDError |
Raised when a card ID, column ID, or field key is duplicated. |
KanbanUnknownColumnError |
Raised when a card references a missing column or a column API targets an unknown ID. |
KanbanMoveCancelledError |
Exported for callers that want to treat a cancelled move as an error condition. |
KanbanPersistenceError |
Raised for board-level persistence constraints, such as mutating while saves are locked. |
KanbanConflictError |
Exported persistence subtype for applications that represent concurrency conflicts as exceptions. |
Check the current search query, active filters, and filter_mode. In
"hide" mode, non-matching cards are removed from the visible column contents. In
"dim" mode they remain visible but muted.
add_card() or update_card() return None?
A cancellable callback rejected the change. Check on_card_created,
on_card_updated, or on_data_changed, and listen to
on_action_cancelled for the reason.
delete_card(), move_card(), or move_column() return False?The operation was cancelled by a callback or, for delete, the user rejected a confirmation prompt.
The public API only allows deleting empty columns. Move or delete the column's cards first.
The built-in overdue check reads the configured due-date and completion fields. Completed columns and the display timezone are configurable, and database timestamps can be rendered for the chosen locale.
Wrap your repository's four CRUD functions with CRUDKanbanDataSource. Implement
KanbanDataSource directly only when you need native server-side queries, bulk writes,
conflict snapshots, or change streams. Start at
Database and Persistence.
Inspect get_persistence_status() and your application logs. Transient connection failures
retry and then queue offline; call set_online(True) when connectivity returns. Rejected
writes and conflicts require resolution before retry_last_save().
get_changes() reports that durable state advanced, then the board calls
refresh_from_source() to obtain a consistent page. Set poll_interval_ms=0 to
disable polling or call refresh from your own push notification handler.
Return the complete canonical stored card from a CRUD create callback, or set
MutationResult.card/id_map in a custom adapter. The board will replace its
temporary ID and update selection and widgets.
UI callbacks run on Tk's thread, but data-source and CRUD methods run on the persistence worker. Keep Tk access out of storage code; return typed results and let the coordinator schedule board updates.
KanbanDataSource protocol directly.
read result in the worker. For very large
datasets, implement native query_cards() in a full data source.
created_at, updated_at, and
version fields. Legacy created_date and updated_date sort keys remain
available for existing schemas.
column and status as aliases for the
card's current column ID, but the built-in filter UI generates only the fields marked
filterable=True plus overdue_only.