% \iffalse meta-comment % Copyright (C) 2026 Andreas Willibald Weber % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3c of this license or (at your % option) any later version. The latest version of the license is available at % https://www.latex-project.org/lppl.txt. % % This work has the LPPL maintenance status `maintained'. The Current % Maintainer of this work is Andreas Willibald Weber. % % This work consists of the source files kanban-board.dtx, % kanban-board-registry.dtx, kanban-board-dates.dtx, % kanban-board-config.dtx, kanban-board-render.dtx, % kanban-board-lifecycle.dtx, and kanban-board.ins. It also includes % build.lua, README.md, CHANGELOG.md, DEPENDS.txt, and LICENSE, the example % files kanban-board-example.tex, kanban-board-modes-example.tex, % kanban-board-deadlines-example.tex, kanban-board-date-formats-example.tex, % kanban-board-palette-example.tex, kanban-board-columnsep-example.tex, % kanban-board-break-example.tex, and kanban-board-landscape-example.tex, % the files in the testfiles directory, and the derived files % kanban-board.sty and kanban-board.pdf. % \fi % % \iffalse %<*driver> \documentclass[a4paper,11pt]{ltxdoc} \makeatletter \let\kanban@docverbatim\verbatim \let\kanban@enddocverbatim\endverbatim \let\kanban@doc@verbatim\@verbatim \let\kanban@doc@xverbatim\@xverbatim \makeatother \usepackage[T1]{fontenc} \usepackage{lmodern} \usepackage[ left=44mm, right=28mm, top=34mm, bottom=33mm, headheight=15pt, marginparwidth=34mm, marginparsep=4mm ]{geometry} \usepackage{microtype} \usepackage{ragged2e} \usepackage{enumitem} \usepackage{fancyhdr} \usepackage{titlesec} \usepackage{needspace} \usepackage{listings} \usepackage{pdflscape} \usepackage{kanban-board} \tcbuselibrary{breakable} \newcommand{\kanbanManualBreakCard}[4][]{% \kanbantask[author=#3,#1]{#2}{#4. Document the assumptions, record the outcome, and retain the evidence required for the next project review.}} \newcommand{\kanbanManualBreakDeadlineCard}[4]{% \kanbantask[author=#2,#3]{#1}{#4. Document the assumptions, record the outcome, and retain the evidence required for the next project review.}} % Diagnostic texts are quoted in typewriter type with ragged lines, so a % long message wraps without an overfull box. \newenvironment{kanbanManualMessage} {\begin{quote}\ttfamily\frenchspacing\raggedright} {\end{quote}} \newcommand{\kanbanManualDateFormatBoard}[2]{% \begin{minipage}[t]{0.48\linewidth} \textit{#2}\par\smallskip \begin{kanban}[columns={Upcoming},date-format=#1] \kanbantask[due=2099-07-18]{Upcoming}{Prepare the scheduled release} \end{kanban} \end{minipage}} \definecolor{kanbanManualRule}{HTML}{D7DEE2} \definecolor{kanbanManualCodeBack}{HTML}{F3F4F5} \definecolor{kanbanManualCodeRule}{HTML}{D8DDE1} \lstdefinestyle{kanbanmanual}{ language={[LaTeX]TeX}, basicstyle=\fontsize{9pt}{11pt}\selectfont\ttfamily\color{kanbanInk}, keywordstyle=\color{kanbanBlue!85!black}, commentstyle=\itshape\color{kanbanSage!75!black}, backgroundcolor=\color{kanbanManualCodeBack}, frame=single, rulecolor=\color{kanbanManualCodeRule}, framerule=0.35pt, framesep=0pt, framexleftmargin=2.5mm, framexrightmargin=2.5mm, framextopmargin=1.2mm, framexbottommargin=1.2mm, aboveskip=0.8\baselineskip, belowskip=0.8\baselineskip, columns=fullflexible, keepspaces=true, gobble=2, breaklines=true, showstringspaces=false, tabsize=2 } \lstset{style=kanbanmanual} \BeforeBeginEnvironment{lstlisting}{\Needspace{7\baselineskip}} \tcolorboxenvironment{macrocode}{ enhanced, breakable, sharp corners, colback=kanbanManualCodeBack, frame hidden, boxrule=0pt, boxsep=0pt, left=0pt, right=0pt, top=1mm, bottom=1mm, before skip=0.8\baselineskip, after skip=0.8\baselineskip } \tcolorboxenvironment{macrocode*}{ enhanced, breakable, sharp corners, colback=kanbanManualCodeBack, frame hidden, boxrule=0pt, boxsep=0pt, left=0pt, right=0pt, top=1mm, bottom=1mm, before skip=0.8\baselineskip, after skip=0.8\baselineskip } \setlength{\parindent}{0pt} \setlength{\parskip}{0.55em plus 0.1em minus 0.1em} \raggedbottom \setlength{\MacrocodeTopsep}{0.8\baselineskip} \setlist{itemsep=0.3em,topsep=0.45em,parsep=0pt} \makeatletter \let\@verbatim\kanban@doc@verbatim \let\@xverbatim\kanban@doc@xverbatim \let\verbatim\kanban@docverbatim \let\endverbatim\kanban@enddocverbatim \apptocmd{\@verbatim} {\advance\leftskip 2.5mm\advance\rightskip 2.5mm} {}{\PackageWarning{kanban-board-doc}{Could not adjust verbatim indentation}} % Index expl3 names as whole control sequences. The doc package collects a % name while the next character is a letter, so underscore and colon must be % letters inside macrocode. The l3doc class uses the same hook. \renewcommand*\MakePrivateLetters{% \makeatletter\catcode`\_=11 \catcode`\:=11 } % Two-digit subsection numbers need a wider number box in the contents. \renewcommand*\l@subsection{\@dottedtocline{2}{1.5em}{3em}} \renewcommand{\IndexParms}{% \raggedcolumns \parindent=0pt \columnsep=14pt \parskip=0pt plus 1pt \rightskip=0pt plus 2em \parfillskip=0pt \emergencystretch=1em \mathsurround=0pt \fontsize{7.8pt}{9.6pt}\selectfont \def\@idxitem{\par\hangindent 24pt}% \def\subitem{\@idxitem\hspace*{12pt}}% \def\subsubitem{\@idxitem\hspace*{20pt}}% \def\indexspace{\par\vspace{8pt plus 2pt minus 2pt}}} \makeatother \setcounter{tocdepth}{2} \titleformat{\section} {\Large\bfseries\sffamily\color{kanbanSlate}} {\thesection}{0.7em}{} \titleformat{\subsection} {\large\bfseries\sffamily\color{kanbanBlue}} {\thesubsection}{0.7em}{} \titlespacing*{\section}{0pt}{2.2em}{0.7em} \titlespacing*{\subsection}{0pt}{1.5em}{0.45em} \pagestyle{fancy} \fancyhf{} \fancyhead[L]{\small\sffamily\textbf{kanban-board}} \fancyhead[R]{\small\sffamily User manual} \fancyfoot[C]{\small\thepage} \renewcommand{\headrulewidth}{0.4pt} \renewcommand{\footrulewidth}{0pt} % Formats up to TeX Live 2020 do not preload hypdoc via ltxdoc. Newer doc % releases load hypdoc themselves, and this line is then a no-op. \usepackage{hypdoc} \AtBeginDocument{% \hypersetup{ linkcolor=kanbanBlue, urlcolor=kanbanTeal, citecolor=kanbanPlum, pdfauthor={Andreas Willibald Weber}, pdftitle={The kanban-board package}, pdfsubject={Kanban project boards in LaTeX} } % The doc package copies \MacroFont into \macro@font at the start of the % document, before this hook runs. Both names are therefore set here. \renewcommand{\MacroFont}{% \fontsize{8.8pt}{10.5pt}\selectfont\ttfamily\color{kanbanInk}}% \renewcommand{\AltMacroFont}{\MacroFont\itshape}% \expandafter\let\csname macro@font\endcsname\MacroFont} % Code inside the package guard is ordinary code and uses the upright font. \setcounter{StandardModuleDepth}{1} % Two index columns leave room for complete expl3 names. \setcounter{IndexColumns}{2} \EnableCrossrefs \CodelineIndex \RecordChanges \DoNotIndex{\NeedsTeXFormat,\ProvidesPackage,\RequirePackage} \DoNotIndex{\definecolor,\colorlet,\@ifundefinedcolor} \DoNotIndex{\newbool,\newcounter,\newlength,\setlength} \DoNotIndex{\def,\gdef,\edef,\let,\newcommand,\renewcommand} \DoNotIndex{\NewDocumentCommand,\NewDocumentEnvironment} \DoNotIndex{\DeclareOption,\ProcessOptions,\PackageError,\PackageWarning} \DoNotIndex{\par,\noindent,\ignorespaces,\relax} \DoNotIndex{\ifblank,\ifbool,\ifboolexpr,\ifdefempty,\ifdefstring} \DoNotIndex{\hfill,\hspace,\vspace} \DoNotIndex{\textcolor,\bfseries,\scriptsize,\raggedright} % Regular-expression escapes, TeX primitives and parameters, LaTeX kernel % commands, and commands of other packages are not package macros and are % therefore kept out of the index. The conditional primitives are produced % by name, because the typeset documentation skips the driver inside a % conditional, and a literal else or fi token in the driver would end that % conditional prematurely. \DoNotIndex{\A,\AM,\Z,\s,\.,\-,\,,\\} \ExplSyntaxOn \exp_args:Ne \DoNotIndex { \exp_not:c {ifnum} , \exp_not:c {ifdim} , \exp_not:c {else} , \exp_not:c {fi} } \ExplSyntaxOff \DoNotIndex{\begin,\end,\multiply,\csname,\endcsname} \DoNotIndex{\expandafter,\noexpand,\unexpanded,\global,\xdef,\numexpr} \DoNotIndex{\string,\space,\MessageBreak,\CurrentOption,\@ifundefined} \DoNotIndex{\year,\month,\day,\arabic,\stepcounter,\medskip} \DoNotIndex{\linewidth,\columnsep,\draw,\tikz,\switchcolumn} \DoNotIndex{\IfBooleanTF,\IfFormatAtLeastTF} \DoNotIndex{\boolfalse,\booltrue,\csdef,\csedef,\csgdef,\csuse,\csxappto} \DoNotIndex{\eappto,\ifnumequal,\ifstrequal,\notblank,\numdef,\numgdef} \DoNotIndex{\DeclareDefaultOption,\define@key,\ProcessKeyvalOptions} \DoNotIndex{\SetupKeyvalOptions} \DoNotIndex{\newtcolorbox,\tcbox,\tcbset,\tcbuselibrary} \DoNotIndex{\parindent,\mathsurround,\lineskiplimit,\hsize,\vsize,\maxdepth} \DoNotIndex{\splitmaxdepth,\boxmaxdepth,\hfuzz,\vfuzz,\delimitershortfall} \DoNotIndex{\nulldelimiterspace,\scriptspace,\predisplaysize,\displaywidth} \DoNotIndex{\displayindent,\overfullrule,\hangindent,\hoffset,\voffset} \DoNotIndex{\emergencystretch,\lineskip,\baselineskip,\parskip} \DoNotIndex{\abovedisplayskip,\abovedisplayshortskip,\belowdisplayskip} \DoNotIndex{\belowdisplayshortskip,\leftskip,\rightskip,\topskip} \DoNotIndex{\splittopskip,\tabskip,\spaceskip,\xspaceskip,\parfillskip} \DoNotIndex{\cs_new:Npn,\cs_new_protected:Npn,\cs_set:Npn,\cs_set:Npx} \DoNotIndex{\cs_new_eq:NN,\cs_if_exist:NTF,\cs_undefine:c} \DoNotIndex{\tl_new:N,\int_new:N,\bool_new:N,\seq_new:N,\clist_new:N} \DoNotIndex{\prop_new:N,\msg_new:nnnn,\prg_new_protected_conditional:Npnn} \DoNotIndex{\prg_return_true:,\prg_return_false:,\c_space_tl} \DoNotIndex{\exp_args:NV,\exp_args:NVV,\exp_args:NnV,\exp_args:NNo} \DoNotIndex{\ExplSyntaxOn,\ExplSyntaxOff} \begin{document} % Keep rendered deadline examples reproducible across rebuilds without % altering TeX's calendar primitives for the surrounding manual. \kbset{reference-date=2026-07-18} \DocInput{kanban-board.dtx} \DocInput{kanban-board-registry.dtx} \DocInput{kanban-board-dates.dtx} \DocInput{kanban-board-config.dtx} \DocInput{kanban-board-render.dtx} \DocInput{kanban-board-lifecycle.dtx} \end{document} % % \fi % % \GetFileInfo{kanban-board.sty} % \makeatletter % \def\kanban@manualversion v#1\relax{#1} % \edef\kanbanManualVersion{% % \expandafter\kanban@manualversion\fileversion\relax} % \makeatother % \changes{v1.0.0}{2026/11/15}{Initial public release.} % % \title{The \textsf{kanban-board} package\\ % \large Kanban project boards in LaTeX} % \author{Andreas Willibald Weber} % \date{Version \kanbanManualVersion\ (\filedate)} % % \hypersetup{pageanchor=false} % \newgeometry{left=32mm,right=37mm,top=34mm,bottom=33mm} % \begin{titlepage} % \centering % \vspace*{0.10\textheight} % {\color{kanbanBlue}\rule{0.84\textwidth}{1.2pt}\par} % \vspace{1.4em} % {\Huge\bfseries\sffamily\color{kanbanSlate} kanban-board\par} % \vspace{0.5em} % {\Large\sffamily\color{kanbanBlue} Kanban project boards in LaTeX\par} % \vspace{1.4em} % {\color{kanbanBlue}\rule{0.84\textwidth}{1.1pt}\par} % \vfill % \begin{minipage}{0.84\textwidth} % \centering % {\large\bfseries\sffamily Abstract\par} % \vspace{0.8em} % \small\justifying % The \textsf{kanban-board} package typesets compact project boards composed of % named columns and task cards. A card may carry a priority, an author, a % deadline, and a completion marker. Deadlines can be expressed either as % calendar dates or as months relative to a project start date. Two rendering % layouts are provided: a fixed horizontal board suited to short summaries and % a page-breakable layout for longer task lists. Named palettes and light or % dark board modes can be selected at package, document, or board level, and % a single card may carry a tinted background. Deadline chips distinguish % overdue, current, and future values. A reference % date can be fixed for reproducible output. Otherwise the compilation date is % used. Five common numeric date formats are available, with US notation as the % initial default. % This manual describes the public interface, gives complete usage examples, % and explains the date and configuration models. % \end{minipage} % \vfill % {\large Andreas Willibald Weber\par} % \vspace{0.4em} % {\sffamily Version \kanbanManualVersion\ (\filedate)\par} % \vspace{2em} % \end{titlepage} % \restoregeometry % \hypersetup{pageanchor=true} % \pagenumbering{roman} % % \tableofcontents % \clearpage % \pagenumbering{arabic} % % \section{Introduction} % % A Kanban board represents work by assigning cards to named stages such as % ``Backlog'', ``In progress'', and ``Done''. The package follows that model % directly. A board uses either the built-in columns, the current document % default, or a board-local list selected with the |columns| environment % option. The author then assigns each task to exactly one of those columns. % Columns are rendered in declaration order, and tasks retain their order % within each column. % % The package is intended for reports, project notes, teaching material, and % other documents in which a board should be generated from ordinary LaTeX % source. It is not an interactive project-management system: tasks are local % document data, and the package neither persists nor automatically moves them. % % \begin{tcolorbox}[ % enhanced, % title={At a glance}, % colback=kanbanSlate!4, % colframe=kanbanSlate!55, % colbacktitle=kanbanSlate, % coltitle=white, % fonttitle=\bfseries\sffamily, % boxrule=0.5pt, % arc=1mm, % left=4mm,right=4mm,top=3mm,bottom=3mm % ] % \begin{description} % \item[Core environment] |\begin{kanban}[options]|, with board-local columns % selected by the |columns={...}| option when required. % \item[Task command] |\kanbantask[options]{column}{text}|, with |\kbtask| % as a concise alias when that short name is available. % \item[Shared setup] |\kanbansetup{key=value,...}|, with |\kbset| as a % concise alias when that short name is available. % \item[Visual choices] Named palettes, light or dark mode, tinted card % backgrounds, and fixed or page-breakable layouts. % \item[Date choices] US, English, German, ISO, and slash-separated year-first % display formats, with validated Gregorian classification. % \item[Column geometry] Synchronized headings and transparent column bodies % in the fixed layout, with configurable separation. % \end{description} % \end{tcolorbox} % % \section{Requirements and installation} % % The package requires a LaTeX format dated 2020-10-01 or later and loads % \textsf{xcolor}, \textsf{etoolbox}, \textsf{tikz}, \textsf{tcolorbox}, and % \textsf{paracol}. On formats older than 2021-06-01, whose option processor % cannot parse brace groups in package option lists, \textsf{kvoptions} is % loaded additionally. These dependencies are included in the principal TeX % distributions. Continuous integration runs the regression and documentation % builds on both a current TeX Live installation and an actual TeX Live 2020 % installation. The declared format boundary is also exercised locally through % the official \textsf{latexrelease} compatibility mechanism. The regression % suite is run with pdfTeX, LuaTeX, and XeTeX. % % To install from the documented source, run % \begin{lstlisting} % latex kanban-board.ins % \end{lstlisting} % and copy |kanban-board.sty| to a directory searched by TeX. For a private % installation, that directory is normally a suitable location below % |TEXMFHOME|. No manual installation is necessary when the package is % installed through a TeX distribution. % % Load the package in the preamble. No options are required: % \begin{lstlisting} % \usepackage{kanban-board} % \end{lstlisting} % Initial document defaults may also be set while loading the package: % \begin{lstlisting} % \usepackage[ % columns={Planned,Active,Complete}, % palette=muted, % mode=light, % date-format=us, % startdate=07/01/2026, % reference-date=2026-07-18, % columnsep=2mm % ]{kanban-board} % \end{lstlisting} % These defaults can be changed later with |\kanbansetup| (or its concise % alias |\kbset|) or overridden by an individual board. The following sections % explain this hierarchy in detail. % % \section{The board environment} % % \DescribeEnv{kanban} % The environment has the syntax % \begin{quote} % |\begin{kanban}[|\meta{board options}|]|\\ % \hspace*{2em}\meta{task declarations}\\ % |\end{kanban}| % \end{quote} % If |columns| is omitted, or if |columns={}| is supplied, the board uses the % current document-wide column list. The package initially defines that list as % |Backlog,Doing,Done|. A non-empty comma-separated value replaces the default % for this board only. The additional braces around the value protect its % commas from the surrounding key list. Each name is trimmed. Its spelling and % its formatting are kept for the visible heading. Its lookup key is the % purified text of the name in uppercase. Ordinary macros are expanded, % formatting commands and braces are removed, and letter case is ignored. % Task targets undergo the same conversion, so |ColName|, |colname|, and % |COLNAME| all identify the same column. Likewise, |\emph{Soon}| and |Soon| % denote the same column, and so do |Q{1}| and |Q1|. Column names must be % unique after normalization and must not contain commas. % % Each board is independent. When a board begins, the package first resolves % the applicable column list. It then creates an empty task list and a zero % count for every resolved column before collecting task declarations. The % visible board is produced only when the environment ends. This deferred % construction is why tasks can be written in any cross-column order while % still appearing beneath the correct headings. % % \subsection{Board options} % % The optional argument accepts the following keys. % % \begin{description} % \item[|break|] % Selects the page-breakable layout. Each board column becomes a % \textsf{paracol} column with an independent colored header followed by its % cards. This layout is appropriate when task lists may continue onto a later % page. Headers are printed at the start of the board and are not repeated on % continuation pages. % \item[\texttt{columns=\{}\meta{column list}\texttt{\}}] % Replaces the current document-wide column list for this board only. The % value must be enclosed in braces because it contains commas. An empty value % retains the current document default. % \item[|columnsep=|\meta{length}] % Sets the horizontal distance between adjacent columns for this board. The % default is |2mm|. This value overrides the document default for the current % board only and is used by both the fixed and page-breakable layouts. The % accepted forms of the value are described in the subsection on column % geometry. % \item[|palette=|\meta{name}] % Selects a previously defined color palette for this board. The local % selection does not change the palette used by later boards. % \item[|date-format=us|, |english|, |german|, |iso|, or |ymd|] % Selects the numeric format used to print validated calendar dates on this % board. The initial default is |us|. This setting also resolves dates whose % slash-separated day and month are both at most 12. A local selection does % not change the format used by later boards. % \item[|startdate=|\meta{date}] % Sets the project start date for this board. It accepts any supported % calendar syntax and is used only when interpreting project-month deadlines % such as |M2|. This value overrides the document default for the current % board only. % \item[|reference-date=|\meta{date}] % Sets the date against which calendar and project-month deadlines are % classified for this board. Without this key, the package uses the TeX % compilation date. The exact alias |today| is also accepted. An explicit % reference date makes archival and automated builds reproducible. % \item[|mode=light| or |mode=dark|] % Selects the visual mode for this board. The default is |light|. A local % mode does not change the mode of subsequent boards. % \item[\texttt{labels=\{}\meta{label options}\texttt{\}}] % Replaces one or more semantic chip labels for this board. The accepted % nested keys are |high|, |medium|, |low|, and |done|. Omitted labels retain % their current document-wide values. % \end{description} % % The |break| key is board-local by design. It is not accepted as a package % option or by |\kanbansetup|. Without |break|, the package constructs a % two-row \textsf{tcolorbox} raster inside one full-width minipage. The first % row contains the synchronized headings and the second contains the % synchronized column bodies. The complete board is therefore one horizontal % object and does not break naturally across pages. This default is preferable % for compact boards. Task cards occupy the complete available width of the % column body in both layouts. % % \subsection{A first board} % % The following complete example applies the environment syntax and default % fixed layout described above. Because no column list is supplied, it uses % the built-in |Backlog|, |Doing|, and |Done| stages and assigns one task to % each stage. The deliberately varied capitalization of the task targets also % demonstrates case-insensitive assignment. % \begin{lstlisting} % \begin{kanban} % \kanbantask[prio=high,author=Alice] % {backlog}{Agree on the public API} % \kanbantask[due=07/31/2026] % {DoInG}{Write the implementation} % \kanbantask[completed] % {DONE}{Create the repository} % \end{kanban} % \end{lstlisting} % % The example produces the following board: % % \begin{kanban} % \kanbantask[prio=high,author=Alice] % {backlog}{Agree on the public API} % \kanbantask[due=07/31/2026] % {DoInG}{Write the implementation} % \kanbantask[completed] % {DONE}{Create the repository} % \end{kanban} % % \section{Configuration hierarchy} % % The package uses a consistent hierarchy for column lists, palettes, visual % modes, date formats, project start dates, reference dates, semantic labels, % and column separation. This % makes document-wide settings easy to reuse while keeping local exceptions % explicit. % % \begin{enumerate} % \item Package options establish the initial defaults. % \item |\kanbansetup| changes the defaults for boards that follow it. % \item Environment options override the defaults for one board only, including % the board-local |columns| key. % \end{enumerate} % % The most local value has priority. For example: % \begin{lstlisting} % \usepackage[ % columns={Planned,Active,Complete}, % palette=muted, % mode=light, % date-format=us, % reference-date=2026-07-18, % columnsep=2mm % ]{kanban-board} % % % Uses every package default, including the configured columns. % \begin{kanban} % ... % \end{kanban} % % % Changes defaults for subsequent boards. % \kbset{ % columns={Queued,Processing,Stored}, % palette=monochrome, % mode=dark, % date-format=iso, % reference-date=2026-07-18, % columnsep=1.5mm % } % % % Uses the revised document defaults. % \begin{kanban} % ... % \end{kanban} % % % Local columns, default palette, light mode, English dates, 3 mm gap. % \begin{kanban}[ % columns={Todo,Doing,Done}, % palette=default,mode=light,date-format=english,columnsep=3mm % ] % ... % \end{kanban} % % % Uses Queued, Processing, and Stored again. % \begin{kanban} % ... % \end{kanban} % \end{lstlisting} % % \DescribeMacro{\kanbansetup} % The setup command accepts a comma-separated key list: % \begin{quote} % |\kanbansetup{columns={|\meta{column list}|},palette=|\meta{name}|,|\\ % \hspace*{2em}|mode=|\meta{mode}|,date-format=|\meta{format}|,|\\ % \hspace*{2em}|startdate=|\meta{date}|,reference-date=|\meta{date}|,|\\ % \hspace*{2em}|columnsep=|\meta{length}|,labels={|\meta{label options}|}}| % \end{quote} % When the name is available, the shorter |\kbset| command is an exact alias. % The longer name is the canonical form because it is less likely to conflict % with another package. If |\kbset| already exists when \textsf{kanban-board} is % loaded, the package preserves the existing definition, issues a warning, and % leaves |\kanbansetup| fully available. % A key may be omitted when its current value should remain unchanged. Setup % calls affect later boards. They do not redraw boards that have already been % typeset. The |columns| value must be enclosed in braces because it is itself % a comma-separated list. An empty |columns| value is rejected with a warning, % and the previous document default remains active. % % \subsection{Default column lists} % % With no configuration, every board that omits its |columns| option uses the % three columns |Backlog|, |Doing|, and |Done|. This provides a useful % conventional board without requiring repeated declarations: % \begin{lstlisting} % \begin{kanban} % \kanbantask{backlog}{Record the request} % \kanbantask{Doing}{Prepare the response} % \kanbantask{dOnE}{Archive the decision} % \end{kanban} % \end{lstlisting} % % A document can establish different defaults when the package is loaded: % \begin{lstlisting} % \usepackage[columns={Planned,Active,Complete}]{kanban-board} % \end{lstlisting} % or change them from a particular point onward: % \begin{lstlisting} % \kbset{columns={Queued,Processing,Stored}} % \end{lstlisting} % In both cases, later environments may omit the |columns| key. Supplying a % board-local key remains the appropriate way to describe an exceptional board: % \begin{lstlisting} % \begin{kanban}[columns={Requested,Approved,Rejected}] % ... % \end{kanban} % \end{lstlisting} % This option is local. It does not change the default used by the next % environment. Letter case and formatting need not match, because % declarations and task targets share one purified uppercase lookup key. The % heading shows the spelling and the formatting used in the column list. % Other differences remain significant. For example, |In review| and % |Review| are distinct identifiers. A list such as |columns={Q{1},Q1}| % repeats the key |Q1|. If a list repeats a name after normalization, the % package reports an error, retains the first occurrence, and ignores the % repeated occurrence. This recovery permits the remaining unique columns to % be rendered if compilation is continued. % % \section{Declaring tasks} % % \DescribeMacro{\kanbantask} % \SpecialUsageIndex{\kbtask} % A task declaration has the syntax % \begin{quote} % |\kanbantask[|\meta{task options}|]{|\meta{column}|}{|\meta{text}|}| % \end{quote} % When the name is available, |\kbtask| is an exact alias with the same % signature and behavior. The longer |\kanbantask| name is the canonical % interface because it is less likely to conflict with another package. If % |\kbtask| already exists when \textsf{kanban-board} is loaded, the package % preserves the existing definition, issues a warning, and leaves % |\kanbantask| fully available. % The column must have been declared by the enclosing board. The target is % purified and converted to uppercase before lookup in the same way as a % declared column name. The assignment therefore ignores surrounding spaces, % letter case, formatting commands, and braces. The task text is ordinary % LaTeX material and may contain emphasis, citations, robust commands, and % other commands suitable for a |tcolorbox|. It may also contain paragraph % breaks, written as |\par| or as a blank line. They are rendered as separate % paragraphs in the card. The option list and the column argument do not % accept a paragraph break. A blank line inside either of them produces the % LaTeX error ``Paragraph ended before |\kanbantask| was complete''. LaTeX % then discards the declaration up to that point and reads the remainder as % ordinary text. Fragile or unusually complex material should be tested in % the intended document class. % % The column argument may not be empty. A missing assignment or a normalized % name that is absent from the board produces a package error. The diagnostic % identifies the invalid input, lists the valid columns by their purified % uppercase keys, and explains how to correct the declaration. The invalid % task is not counted or rendered, which leaves the remaining board data % structurally consistent if compilation is continued after the error. A task % declared outside a |kanban| environment similarly produces a direct error % instead of modifying residual board data. % % For example, both tasks below are assigned to the single displayed column % |Research|: % \begin{lstlisting} % \begin{kanban}[columns={Research,Review}] % \kanbantask{research}{Collect the evidence} % \kanbantask{ReSeArCh}{Document the method} % \end{kanban} % \end{lstlisting} % By contrast, the following fragments are invalid: % \begin{lstlisting} % \kanbantask{}{A task without a target} % \kanbantask{Archive}{A task for an undeclared stage} % \end{lstlisting} % For a board containing |RESEARCH| and |REVIEW|, the corresponding errors state % that the first task has no assigned column and that |Archive| is unknown. % Both diagnostics also report |RESEARCH,REVIEW| as the valid column set. % % Formatting in a column name is ignored for lookup in the same way as letter % case. The following board declares an emphasized heading and addresses it % with plain text. The heading shows the emphasized text, and an error for % this board would report |SOON,LATER| as the valid column set: % \begin{lstlisting} % \begin{kanban}[columns={\emph{Soon},Later}] % \kanbantask{soon}{Prepare the next release} % \kanbantask{\emph{Soon}}{Collect the release notes} % \end{kanban} % \end{lstlisting} % Both tasks are assigned to the first column. % % The package deliberately does not define the generic |\task| alias. That name % is used by several document classes and packages. Leaving it untouched % prevents load-order-dependent conflicts. The namespaced |\kbtask| form % provides a concise alternative without claiming the generic name. % % \subsection{Task options} % % \begin{description} % \item[|prio=high|] % Adds a red high-priority pill, labelled \textsc{high} by default. % \item[|prio=medium| or |prio=med|] % Adds an orange medium-priority pill, labelled \textsc{med} by default. % \item[|prio=low|] % Adds a green low-priority pill, labelled \textsc{low} by default. % \item[|author=|\meta{text}] % Places a neutral author chip at the right of the metadata row. % \item[|deadline=|\meta{value}] % Adds a deadline chip beneath the metadata row. The alias |due| has exactly % the same meaning. % \item[|late|] % Forces an existing deadline chip to use the overdue style. The option has % no visible effect unless |deadline| or |due| is also present. % \item[|completed|] % Adds a green marker, labelled \textsc{done} by default. Completion is % presentational: it does not move the task or suppress its deadline. % \item[|bg=|\meta{color}] % Tints the surface of the card with the given \textsf{xcolor} color or % mixing expression. The alias |background| has exactly the same meaning. % Section~\ref{sec:tints} describes the result in both modes. % \end{description} % % Task options are local to one declaration. An unknown option name generates % a warning that names the key: % \begin{kanbanManualMessage} % Unknown task option 'colour' on line 12. The option is ignored. % \end{kanbanManualMessage} % Priority values are trimmed and compared without regard to letter case. An % unrecognized value produces a warning, and the priority chip is omitted. A % background value must name a color known to \textsf{xcolor}. An unknown % value produces a warning, and the card keeps the default surface. % % Several options may be combined in one declaration: % \begin{lstlisting} % \kanbantask[ % prio=high, % author=Alice, % due=07/31/2026 % ]{Review}{Approve the release candidate} % \end{lstlisting} % The package does not infer workflow state from metadata. In particular, % |completed| adds a marker but does not move the task to a column named % ``Done''. The column argument remains the only source of task placement. % % Task text may contain ordinary inline markup: % \begin{lstlisting} % \kanbantask{Doing}{ % Compare \emph{pdfLaTeX} and \emph{LuaLaTeX} output % } % \end{lstlisting} % A card may also contain more than one paragraph. A blank line or |\par| in % the text argument starts a new paragraph inside the card: % \begin{lstlisting} % \kanbantask{Doing}{ % Compare the output of both engines. % % Record the differences in the project log. % } % \end{lstlisting} % Authors should keep card text concise. Long paragraphs are valid, but they % make narrow boards difficult to scan. % % \section{Deadline semantics} % % Deadline classification is performed when a card is rendered. By default, % the comparison day is obtained from the TeX primitives |\year|, |\month|, % and |\day|. Consequently, recompiling the same source on a later date may % change a deadline chip from neutral to current or overdue. The % |reference-date| key replaces that moving comparison day with a validated, % fixed date when reproducible output is required. The syntax of a deadline is % checked when the task is declared, so a warning about an invalid value names % the line of that declaration. % % \subsection{Calendar dates} % % A deadline is interpreted as a calendar date when its complete expanded % value has one of the supported numeric forms. Ordinary macros are expanded % before the check, so a macro that expands to a date is classified. Robust % and protected commands are not expanded. A value such as |\emph{soon}| or % |{\textbf{2026-07-18}}| is therefore a descriptive label. It is printed % with its formatting and without automatic classification. The parser % recognizes month-first and day-first dates with a final year, German dot % notation, ISO notation, and slash-separated year-first notation. For % example: % \begin{lstlisting} % \newcommand\releasedate{2026-08-15} % \kanbantask[due=07/31/2026]{Review}{Approve the release} % \kanbantask[due=\releasedate]{Planned}{Archive the release} % \kanbantask[due=\emph{soon}]{Planned}{Announce the release} % \end{lstlisting} % The first two deadlines are calendar dates. The third is a label. % A date before the active reference date is red, a date equal to it is orange, % and a future date is neutral. When no reference date has been configured, the % compilation date is the active reference. Every notation requires a % four-digit year from 0001 to 9999. Month and day may be written with one or % two digits. Dates are checked against the Gregorian month lengths, including % the leap-year rule. A value that has date syntax but does not denote a valid % date produces a warning and is retained as a neutral label. The same applies % to a value that has the shape of a date but a year of fewer than four digits. % The input |18.07.26| is therefore reported rather than read as a date in the % year 26. Other descriptive values, including labels beginning with |M| or % containing punctuation, are displayed without automatic classification. The % |late| option may be used when such a label must appear overdue. % % \subsection{Date formats} % % The |date-format| key selects how every validated calendar date is printed. % The package provides five common numeric conventions: % % \begin{center} % \begin{tabular}{@{}lll@{}} % \textbf{Key value} & \textbf{Convention} & \textbf{18 July 2026} \\ % \hline % |us| & month/day/year & |07/18/2026| \\ % |english| & day/month/year & |18/07/2026| \\ % |german| & day.month.year & |18.07.2026| \\ % |iso| & year-month-day & |2026-07-18| \\ % |ymd| & year/month/day & |2026/07/18| \\ % \end{tabular} % \end{center} % % |us| is the initial default. Output components are zero-padded. Month and % day may be entered with one or two digits, so |2026-7-8| and |2026-07-08| % denote the same date and are both printed as |07/08/2026| under the default. % Selecting a format follows the same three-level hierarchy as the other board % settings: % \begin{lstlisting} % \usepackage[date-format=english]{kanban-board} % initial document default % \kbset{date-format=german} % subsequent boards % % \begin{kanban}[date-format=iso] % this board only % ... % \end{kanban} % \end{lstlisting} % The compact spelling |dateformat| is accepted as an exact key alias, although % |date-format| is the canonical spelling used throughout this manual. Format % values are trimmed and compared without regard to letter case. The canonical % values in the table should be preferred in new documents. For compatibility, % |american| maps to |us|. The values |uk| and |british| map to |english|. % The values |de| and |deutsch| map to |german|, and |year-first| maps to % |ymd|. % % Calendar parsing is intentionally more permissive than display formatting: % an unambiguous date in any supported notation is accepted and normalized to % the selected output convention. A year-last slash date can be ambiguous. For % example, |07/08/2026| denotes either 8 July or 7 August. The |english| and % |german| selections interpret such a value as day/month/year. The |us|, % |iso|, and |ymd| selections use month/day/year for this otherwise ambiguous % input. If only one ordering denotes a valid Gregorian date, that ordering is % accepted regardless of the current selection. ISO input is consequently the % safest form for task data exchanged between documents, because its component % order is unambiguous. Project-month values such as |M2| and descriptive % labels are never reformatted. % % The |startdate| and |reference-date| settings are normalized to an internal % ISO representation as soon as their containing key list has been processed. % Their values are therefore immutable snapshots: a later macro redefinition % or board-local display-format change cannot reinterpret an inherited date. % Within one package, setup, or board option list, |date-format| is resolved % before either stored date is normalized, irrespective of the textual order % of those keys. Task deadlines remain board data and are interpreted under the % board's selected format when their cards are rendered. % % \subsection{Project months} % % A complete value of the form |M|\meta{n}, where \meta{n} is an integer from % 1 to 999999, denotes project month \meta{n}. Leading zeros are permitted, % so |M01| and |M0000001| both denote month 1. The bound of six digits % applies to the significant digits. It keeps malformed input outside TeX's % integer arithmetic. A value outside this range, such as |M0|, |M000|, or % |M1000000|, produces a warning and remains a neutral label. The initial % project start date may be supplied as a package option: % \begin{lstlisting} % \usepackage[startdate=07/15/2026]{kanban-board} % \end{lstlisting} % It may be changed for subsequent boards through the common setup interface: % \begin{lstlisting} % \kbset{startdate=2026-07-15} % \end{lstlisting} % Finally, a board can override the default locally: % \begin{lstlisting} % \begin{kanban}[columns={Planned,Active,Done},startdate=07/15/2026] % \end{kanban} % \end{lstlisting} % The precedence order is therefore board option, current |\kbset| default, % and package option. A board-local value does not alter subsequent boards. % An empty setup value clears the persistent start date for later boards. % An empty board value disables an inherited start date for that board only: % \begin{lstlisting} % \kbset{startdate={}} % \begin{kanban}[startdate={}] % ... % \end{kanban} % \end{lstlisting} % Accepted start dates are stored canonically rather than as their original % input tokens. For example, a US |07/08/2026| start date remains 8 July even % if a later board selects |date-format=english| for its visible deadlines. % This separation prevents a display preference from changing project-month % boundaries. % % Project months begin on the day number of the start date. Thus, for a project % beginning on 15 July, |M1| runs from 15 July until 14 August and |M2| begins % on 15 August. If that day does not exist in a later calendar month, the % boundary is clamped to the final valid day of that month. A project beginning % on 31 January therefore enters |M2| on 28 February, or on 29 February in a % leap year. Its following boundary is 31 March. This rule prevents a short % month from extending the preceding project month unintentionally. % % A project month earlier than the current one is overdue. The current project % month is orange, and a later month is neutral. If no start date is available, % the value is displayed without automatic classification. An invalid start % date produces a package warning and does not replace the previously valid % value. % % \subsection{Reproducible reference dates} % % The optional |reference-date| setting fixes the comparison day used by both % calendar deadlines and project months. It follows the same package, setup, % and board-local hierarchy as |startdate|: % \begin{lstlisting} % \usepackage[reference-date=2026-07-18]{kanban-board} % \kbset{reference-date=2026-08-01} % % \begin{kanban}[reference-date=2026-08-15] % ... % \end{kanban} % \end{lstlisting} % The key alias |today| has exactly the same meaning. An empty setup value % restores the compilation date for later boards, while an empty board value % restores it for that board only. Like a project start date, an accepted % reference date is validated, expanded, and stored canonically. Invalid input % produces a warning and preserves the preceding value. This facility is % useful for archived reports, regression tests, and automated publication % systems in which a rebuild should not alter status colors. % % \subsection{Worked deadline example} % % The following board uses both public key names and displays all three visual % states with calendar dates. The manual fixes its reference date as 18 July % 2026, so the first date lies in the past, the second equals the reference % date, and the third lies in the future. % \begin{lstlisting} % \begin{kanban}[columns={Overdue,Due now,Upcoming}] % \kanbantask[deadline=01/01/2000] % {Overdue}{Resolve the review comments} % \kanbantask[due=07/18/2026] % {Due now}{Complete the current milestone} % \kanbantask[deadline=2099-12-31] % {Upcoming}{Prepare the next milestone} % \end{kanban} % \end{lstlisting} % The red chip denotes a past date, the orange chip denotes the active reference % date, and the neutral chip denotes a future date. The first and third values % also demonstrate US and ISO calendar input. Both are printed in the selected % format, which is US notation here because the board uses the default. The keys % |deadline| and |due| are exact aliases. Their choice does not determine the % color. The fixed reference date keeps the rendered result stable whenever the % manual is compiled. % % \begin{kanban}[columns={Overdue,Due now,Upcoming}] % \kanbantask[deadline=01/01/2000] % {Overdue}{Resolve the review comments} % \kanbantask[due=07/18/2026] % {Due now}{Complete the current milestone} % \kanbantask[deadline=2099-12-31] % {Upcoming}{Prepare the next milestone} % \end{kanban} % % A complete version of this demonstration, in both light and dark mode, is % provided as |kanban-board-deadlines-example.tex|. % % \section{Color and layout model} % % By default, columns draw from an eight-color palette in declaration order: % slate, blue, teal, sage, amber, clay, rose, and plum. A selected custom % palette may contain a different number of colors. When the number of columns % exceeds the number of entries, the palette repeats. Priority and status % colors are independent of the column color. % % In the default layout, the nominal width of each column is calculated from % the available line width and the number of columns. Large boards can % therefore become too narrow for useful text. In practice, three or four % columns fit comfortably in portrait documents. Wider boards often benefit % from landscape orientation, a larger paper size, or the |break| layout. % % \subsection{Selecting a palette} % % Version 1.0.0 provides named palettes. The initial palette may be selected as % a package option: % \begin{lstlisting} % \usepackage[palette=muted]{kanban-board} % \end{lstlisting} % The built-in names are |default|, |muted|, and |monochrome|. The |default| % palette contains the original eight-color sequence. % % |\kbset{palette=|\meta{name}|}| changes the default for subsequent boards: % \begin{lstlisting} % \kbset{palette=monochrome} % \end{lstlisting} % A board may override that default without changing later boards: % \begin{lstlisting} % \begin{kanban}[columns={Todo,Doing,Done},palette=default] % ... % \end{kanban} % \end{lstlisting} % % \DescribeMacro{\kanbandefinepalette} % \SpecialUsageIndex{\kbdefinepalette} % A new palette is registered with % \begin{quote} % |\kanbandefinepalette{|\meta{name}|}{|\meta{color list}|}| % \end{quote} % where the second argument is a non-empty, comma-separated list of colors or % \textsf{xcolor} expressions. For example: % \begin{lstlisting} % \definecolor{universityBlue}{HTML}{164A7B} % \definecolor{universityGold}{HTML}{A67C00} % \kbdefinepalette{university}{ % universityBlue, % teal!70!black, % universityGold % } % \kbset{palette=university} % \end{lstlisting} % The unstarred form uses white heading text for every entry. If a palette % contains both dark and light backgrounds, the starred form records an % explicit foreground color with each background: % \begin{quote} % |\kanbandefinepalette*{|\meta{name}|}{|% % \meta{background}|/|\meta{foreground}|,...}| % \end{quote} % For example: % \begin{lstlisting} % \kbdefinepalette*{accessible}{ % facultyNavy/white, % facultyGold/kanbanInk, % facultyBerry/white % } % \end{lstlisting} % The slash separates the two \textsf{xcolor} expressions. Every entry in a % starred definition must contain exactly one slash and two non-empty values. % Otherwise the complete definition is rejected with a warning. This explicit % pairing permits suitable heading contrast for arbitrary custom colors. It % does not attempt to calculate or certify a contrast ratio, because % \textsf{xcolor} expressions may depend on the surrounding document's color % model and named-color definitions. % When its name is available, the concise command |\kbdefinepalette| is an % exact alias. If another package has already defined that name, % \textsf{kanban-board} preserves it, reports a warning, and requires the % canonical |\kanbandefinepalette| command. Surrounding spaces in a palette % name are ignored, but palette names are case-sensitive. Palette % registration is document-wide: the definition command creates or replaces % a named registry % entry, while package, setup, and board |palette| keys only select an existing % entry. % Defining an existing name replaces its stored color list. If that name is the % current document default, later boards immediately use the replacement. The % name does not need to be selected again. A board takes a local snapshot of % the palette and its foreground list when it begins, so redefining the name % while that board is being collected cannot alter the board already in % progress. An unknown or empty palette produces a warning and leaves the % current selection unchanged. % % A palette may contain any positive number of colors. When a board has more % columns than the palette has entries, selection wraps cyclically. A % three-color palette is therefore applied as colors 1, 2, 3, 1, 2, 3, and so % forth. The built-in colors are dark enough to give white heading text a % contrast ratio of at least 4.5:1. Authors of custom palettes remain % responsible for preserving adequate contrast. The starred interface makes % the foreground choice explicit for every palette entry. The following % example defines a three-color institutional palette with dark text on its % lighter gold background. Since the board has four columns, its % fourth heading reuses the first palette entry. % \begin{lstlisting} % \definecolor{facultyNavy}{HTML}{244A6C} % \definecolor{facultyGold}{HTML}{C69A32} % \definecolor{facultyBerry}{HTML}{843D60} % \kbdefinepalette*{faculty}{ % facultyNavy/white, % facultyGold/kanbanInk, % facultyBerry/white % } % % \begin{kanban}[ % columns={Proposed,Selected,In progress,Published}, % palette=faculty % ] % \kanbantask[deadline=12/31/2099] % {Proposed}{Collect research questions} % \kanbantask[prio=high,deadline=01/01/2000] % {Selected}{Approve the study design} % \kanbantask[author=Alice, % due=07/18/2026] % {In progress}{Complete the analysis} % \kanbantask[completed]{Published}{Deposit the article} % \end{kanban} % \end{lstlisting} % It produces the following board: % % \definecolor{kbManualNavy}{HTML}{244A6C} % \definecolor{kbManualGold}{HTML}{C69A32} % \definecolor{kbManualBerry}{HTML}{843D60} % \kbdefinepalette*{manualfaculty}{ % kbManualNavy/white, % kbManualGold/kanbanInk, % kbManualBerry/white % } % \begin{kanban}[ % columns={Proposed,Selected,In progress,Published}, % palette=manualfaculty % ] % \kanbantask[deadline=12/31/2099] % {Proposed}{Collect research questions} % \kanbantask[prio=high,deadline=01/01/2000] % {Selected}{Approve the study design} % \kanbantask[author=Alice, % due=07/18/2026] % {In progress}{Complete the analysis} % \kanbantask[completed]{Published}{Deposit the article} % \end{kanban} % % The complete compilable source is |kanban-board-palette-example.tex|. % % \subsection{Column geometry} % % The |columnsep| key controls the distance between adjacent columns. Its % default value is |2mm|. The key accepts three forms of value. The first % form is a non-negative explicit dimension such as |2mm| or |0.5em|. The % number and the unit may be separated by spaces, as in |2 mm|, and a % physical unit may carry the |true| prefix, as in |2truemm| or |2 true mm|. % The second form is a single LaTeX length register such as |\linewidth| or % a length declared with |\newlength|. The third form is a single TeX % dimension or glue parameter such as |\parindent|, |\baselineskip|, % |\hsize|, or |\parskip|. A |\let| copy of such a parameter is accepted as % well. A macro that expands to one of these forms is also accepted. Every % other value is rejected with a warning, and the current value is kept. % Rejected values include |\dimexpr| expressions, scaled registers such as % |0.5\linewidth|, the |true| prefix on a font-relative unit as in |2trueem|, % math glue such as |\thinmuskip|, a bare number, a bare unit, and robust % commands such as |\emph{2mm}|. The check takes place before TeX's dimension % scanner is entered, so a rejected value does not produce secondary % ``missing number'' or ``illegal unit'' errors. The help text of the warning % reads ``Use a non-negative explicit dimension such as 2mm, a LaTeX length % register, or a TeX length parameter such as |\hsize|.'' An initial value % may be set as a package option: % \begin{lstlisting} % \usepackage[columnsep=3mm]{kanban-board} % \end{lstlisting} % It may be changed for subsequent boards with the shared setup command: % \begin{lstlisting} % \kbset{columnsep=1.5mm} % \end{lstlisting} % A single board may override the current default without affecting later % boards: % \begin{lstlisting} % \begin{kanban}[columns={Todo,Doing,Done},columnsep=4mm] % ... % \end{kanban} % \end{lstlisting} % The same value is applied to the fixed layout and to the column separation % used by the |break| layout. In the fixed layout the package subtracts the % total separation from the available line width before dividing the remaining % width among the columns. Each task card then occupies the complete available % width of its column body. % % The value must also be feasible for the resolved number of columns. For % \meta{n} columns, the product of \meta{n} minus one and |columnsep| must be % smaller than |\linewidth|. If the total gap is equal to or wider than the % available line width, the package reports an error and uses |0pt| for that % board. This recovery value preserves positive column width while leaving the % document-wide default unchanged. % % The fixed layout is constructed as a two-row raster. All heading cells use % the height of the tallest heading, including headings that wrap onto more % than one line. All column bodies use the height of the body containing the % most material, so empty or short columns extend to the same bottom edge. The % column body itself is transparent in both visual modes. Only its bottom rule % remains visible, while the left and right rules are omitted. Task cards keep % their light or dark background, border, and colored accent. % % Equal-height measurements are stored in the document's auxiliary file. % Authors should therefore compile the document twice after changing a column % heading or task list. In the page-breakable layout, heading heights are also % synchronized at the beginning of the board, but column bodies remain % independent so that they can continue naturally across pages. The initial % headings are not repeated on continuation pages. % % The following example uses concise headings and includes an empty column. The % shorter labels are preferable in narrow boards because they keep the workflow % stages visually compact. Longer headings remain supported and are equalized % automatically when wrapping is unavoidable. % \begin{lstlisting} % \begin{kanban}[columns={Queued,Review,Complete}] % \kanbantask[prio=high]{Review} % {Prepare the response} % \kanbantask{Review} % {Check the revised figures} % \kanbantask[completed]{Complete}{Approve the revision} % \end{kanban} % \end{lstlisting} % \Needspace{10\baselineskip} % It produces a board whose headings and bottom edges remain aligned: % % \begin{kanban}[columns={Queued,Review,Complete}] % \kanbantask[prio=high]{Review} % {Prepare the response} % \kanbantask{Review} % {Check the revised figures} % \kanbantask[completed]{Complete}{Approve the revision} % \end{kanban} % % \subsection{Light and dark modes} % % The default |light| mode uses dark text on white cards, neutral gray metadata % chips, and white headings on the selected palette colors. The |dark| mode % uses light text on dark cards. Author chips and neutral |deadline| or |due| % chips deliberately retain their light-mode colors in both modes, giving % metadata a stable visual identity. Automatic status colors remain semantic: % overdue values are red and values due now are amber in either mode. In both % modes the area behind the cards is transparent, so the surrounding page % remains visible in the vertical space between cards and at the foot of a % synchronized column. Palette colors continue to identify columns in both % modes. % % The initial mode may be selected as a package option: % \begin{lstlisting} % \usepackage[mode=dark]{kanban-board} % \end{lstlisting} % It can be changed for subsequent boards through the common setup interface: % \begin{lstlisting} % \kbset{mode=dark} % \end{lstlisting} % A board may then override that default locally: % \begin{lstlisting} % \begin{kanban}[columns={Todo,Doing,Done},mode=light] % ... % \end{kanban} % \end{lstlisting} % % Mode selection affects only the board. It deliberately does not call % |\pagecolor| and does not alter the surrounding document text. A dark board % can therefore be embedded safely in an otherwise light document. Unknown % mode names produce a warning and leave the current selection unchanged. A % robust command in the value, as in |mode=\emph{dark}|, is reported as % unknown in the same way. % % The examples section below compares the two modes with identical column % geometry and explicit deadline states. A separate custom-palette example is % provided as |kanban-board-palette-example.tex|. % % \subsection{Card background tints} % \label{sec:tints} % % The surface of an individual card can carry a touch of color. The task % option |bg| accepts an \textsf{xcolor} color name or a mixing expression of % the form \meta{name}|!|\meta{percentage}|!|\meta{name}, optionally negated % with a leading minus sign. The alias |background| is accepted as well. In % light mode the surface is white with 15 percent of the color. In dark mode % the surface is the dark card color with 20 percent of the color. The larger % share keeps the tint visible on a dark surface, and the text keeps a % contrast ratio above 4.5:1 with the built-in text colors for any tint. % Heading, column accent, metadata chips, and text colors are unchanged, so % a tint groups cards visually without competing with the semantic colors. % \begin{lstlisting} % \begin{kanban}[columns={Planned,Active,Complete}] % \kanbantask[bg=yellow,prio=high]{Planned}{Clarify the scope} % \kanbantask[bg=kanbanTeal!60,author=Bob]{Active}{Write the draft} % \kanbantask[background=-red,completed]{Complete}{Archive the notes} % \kanbantask{Complete}{A card with the default surface} % \end{kanban} % \end{lstlisting} % It produces the following board: % % \begin{kanban}[columns={Planned,Active,Complete}] % \kanbantask[bg=yellow,prio=high]{Planned}{Clarify the scope} % \kanbantask[bg=kanbanTeal!60,author=Bob]{Active}{Write the draft} % \kanbantask[background=-red,completed]{Complete}{Archive the notes} % \kanbantask{Complete}{A card with the default surface} % \end{kanban} % % The same declarations on a dark board mix the tints into the dark surface: % % \begin{kanban}[columns={Planned,Active,Complete},mode=dark] % \kanbantask[bg=yellow,prio=high]{Planned}{Clarify the scope} % \kanbantask[bg=kanbanTeal!60,author=Bob]{Active}{Write the draft} % \kanbantask[background=-red,completed]{Complete}{Archive the notes} % \kanbantask{Complete}{A card with the default surface} % \end{kanban} % % The value is checked when the task is declared. Every name in the % expression must be known to \textsf{xcolor} at that point, and the % expression must follow the mixing grammar above. Any other value, including % a robust command, produces a warning that names the line of the task, and % the card keeps the default surface: % \begin{kanbanManualMessage} % Unknown color 'nosuchcolor' on line 12. The card keeps the default % background. % \end{kanbanManualMessage} % A tint is a property of one card. There is no board-level or document-level % default, because a tint marks an exception rather than a theme. The mixing % percentages are fixed in this release. % % \subsection{Labels and public style hooks} % % The visible semantic labels can be adapted without redefining internal % commands. The |labels| key accepts the nested keys |high|, |medium|, |low|, % and |done|. It follows the same package, setup, and board-local precedence as % the other configuration keys: % \begin{lstlisting} % \usepackage[ % labels={high=URGENT,medium=NORMAL,low=ROUTINE,done=FINISHED} % ]{kanban-board} % % \kbset{labels={done=APPROVED}} % % \begin{kanban}[labels={high=IMMEDIATE}] % ... % \end{kanban} % \end{lstlisting} % A board takes a snapshot of all four labels when it begins. An omitted label % keeps its current value. An empty value is rejected with a warning. Label % text is ordinary short LaTeX material, although concise uppercase terms are % normally easiest to read inside the small chips. % % Seven namespaced \textsf{tcolorbox} styles provide a controlled extension % point for typographic and spacing changes: % \begin{quote} % |kanban/header|, |kanban/card|, |kanban/column-body|,\\ % |kanban/priority-chip|, |kanban/author-chip|,\\ % |kanban/deadline-chip|, and |kanban/completed-chip|. % \end{quote} % The styles are initially empty and are applied after the structural package % defaults. For example: % \begin{lstlisting} % \tcbset{ % kanban/header/.append style={fontupper=\bfseries\sffamily}, % kanban/card/.append style={arc=1mm,outer arc=1mm}, % kanban/author-chip/.append style={left=1.5mm,right=1.5mm} % } % \end{lstlisting} % These hooks are document-wide \textsf{tcolorbox} settings. The header, card, % and chip styles apply to both rendering strategies. |kanban/column-body| % applies only to the fixed renderer because the page-breakable renderer leaves % each \textsf{paracol} stream without an enclosing body box. Authors should % preserve |width=\linewidth| for cards and should test changes to padding in % narrow columns. The named colors |kanbanHigh|, |kanbanMed|, and |kanbanLow| % remain available to advanced users, but changing either foreground or % background colors also transfers responsibility for readable contrast to the % document author. In the defaults, the orange medium and due-now chips use % dark ink. The red and green semantic chips use white. Together with the % revised built-in palettes, these pairs meet a 4.5:1 reference contrast ratio % for ordinary text. % % \section{Diagnostics and limitations} % % The package distinguishes warnings from errors. A warning reports input % that can be ignored safely. The package then keeps the current value or % omits the affected element. An error reports a declaration that cannot be % interpreted unambiguously. Errors use the LaTeX2e package error mechanism. % Every warning is a named message of the \textsf{l3msg} module |kanban-board|. % % \paragraph{Warnings.} % Every warning follows one pattern. The first sentence names the subject, % quotes the offending value, and states the line of the input that caused % the warning. The second sentence states how the package recovers. An % unknown setup, board, task, label, or board label option names the key % and is ignored: % \begin{kanbanManualMessage} % Unknown setup option 'colour' on line 3. The option is ignored.\\ % Unknown board label option 'urgent' on line 9. The option is ignored. % \end{kanbanManualMessage} % An unknown palette, mode, or date format keeps the current selection. The % board-local form names the scope, for example ``Unknown board palette'' or % ``Unknown board mode'': % \begin{kanbanManualMessage} % Unknown palette 'brand' on line 4. The current palette is kept.\\ % Unknown mode 'blue' on line 5. The current value is kept.\\ % Unknown date format 'dmy' on line 6. The current value is kept. % \end{kanbanManualMessage} % A robust command in such a value, as in |mode=\emph{dark}|, is reported as % unknown in the same way. A palette definition is rejected as a whole when % its name is empty, when its color list is empty, or when a starred % definition contains a malformed pair. The starred form reports ``has no % color/text pairs'' for an empty list: % \begin{kanbanManualMessage} % Empty palette name on line 7. The definition is ignored.\\ % Palette 'empty' on line 8 has no colors. The definition is ignored.\\ % Palette 'broken' on line 9 has a malformed color/text pair. The definition % is ignored. % \end{kanbanManualMessage} % An empty column list, an empty label, an invalid start or reference date, % and an invalid column separation keep the current value: % \begin{kanbanManualMessage} % Empty column list on line 10. The current list is kept.\\ % Empty label 'high' on line 11. The current value is kept.\\ % Invalid startdate '31.02.2026' on line 12. The current value is kept.\\ % Invalid columnsep value '2' on line 13. The current value is kept. % \end{kanbanManualMessage} % The board-local forms of these messages read ``Empty board label'', % ``Invalid board startdate'', ``Invalid board reference-date'', and % ``Invalid board columnsep value''. A malformed or negative column % separation is intercepted before TeX emits a low-level number or unit % error. An unknown priority omits the chip. An unknown card background keeps % the default surface. A deadline that resembles a calendar date or a project % month but lies outside the validated range is displayed as a neutral label: % \begin{kanbanManualMessage} % Unknown priority 'urgent' on line 14. The priority chip is omitted.\\ % Unknown color 'nosuchcolor' on line 15. The card keeps the default % background.\\ % Invalid deadline date '18.07.26' on line 16. The card shows a neutral % label.\\ % Invalid project-month deadline 'M0' on line 17. The card shows a neutral % label. % \end{kanbanManualMessage} % Deadline warnings are issued when the task is declared, so the line is % that of the declaration. Descriptive labels, including a deadline that % contains a robust command, remain neutral without a diagnostic. % % A diagnostic raised by a package option says ``in the package options'' % instead of naming a line, because the package file is being read at that % moment: % \begin{kanbanManualMessage} % Invalid startdate '31.02.2026' in the package options. The current value % is kept. % \end{kanbanManualMessage} % The optional short commands |\kbtask|, |\kbset|, and |\kbdefinepalette| % are installed only when their names are unused. A pre-existing definition % is never overwritten, and the canonical long command remains available in % every case. The warning is issued while the package loads and therefore % carries no line context: % \begin{kanbanManualMessage} % \textbackslash kbset is already defined. Use \textbackslash kanbansetup % instead. % \end{kanbanManualMessage} % The same pattern applies to |\kbtask| and |\kbdefinepalette|. % % \paragraph{Message identifiers.} % Every message belongs to the \textsf{l3msg} module |kanban-board|. The % following table lists the identifier of each message and the subject of % its text. % % \begin{center} % \begin{tabular}{@{}ll@{}} % \textbf{Identifier} & \textbf{Subject} \\ % \hline % |unknown-key| & Unknown setup, board, task, or label option \\ % |unknown-value| & Unknown mode or date format \\ % |unknown-palette| & Unknown palette \\ % |empty-palette-name| & Empty palette name \\ % |empty-palette| & Palette without colors or color/text pairs \\ % |malformed-palette-pair| & Malformed color/text pair \\ % |empty-column-list| & Empty column list \\ % |empty-label| & Empty label \\ % |invalid-date-setting| & Invalid start date or reference date \\ % |invalid-dimension| & Invalid column separation \\ % |unknown-priority| & Unknown priority \\ % |unknown-color| & Unknown card background \\ % |invalid-deadline| & Invalid deadline date \\ % |invalid-project-month| & Invalid project-month deadline \\ % |alias-taken| & Short command already defined \\ % \end{tabular} % \end{center} % % An individual message can be silenced or redirected with % |\msg_redirect_name:nnn|. The following preamble lines turn the % unknown-key warning off and demote the unknown-value warning to an entry % in the log file: % \begin{lstlisting} % \ExplSyntaxOn % \msg_redirect_name:nnn {kanban-board}{unknown-key}{none} % \msg_redirect_name:nnn {kanban-board}{unknown-value}{info} % \ExplSyntaxOff % \end{lstlisting} % A redirection is local to the current TeX group. Placed in the preamble, % it applies to the whole document. % % \paragraph{Errors.} % A task with an empty column argument, a task outside a board, a task % assigned to a column that is absent from the board, or a column list % containing a duplicate after normalization generates a package error with % corrective help. The error for a task lists the valid columns by their % purified uppercase keys, so a column declared as |\emph{Soon}| appears as % |SOON|. Duplicate names recover by keeping the first occurrence and % discarding later occurrences. Invalid tasks are neither counted nor % rendered. Nested |kanban| environments are also rejected because each % board owns one active collection context. The nested environment produces % one error, and task declarations inside it are then ignored without a % cascade of secondary ``outside a board'' errors. A non-negative column % separation whose combined gaps leave no column width produces an error % and is replaced by |0pt| for the affected board. A paragraph break inside % the option list or the column argument of a task produces the LaTeX error % ``Paragraph ended before |\kanbantask| was complete''. LaTeX then discards % the declaration up to that point and reads the remainder as ordinary text. % % \paragraph{Constraints.} % Authors should also observe the following constraints. % \begin{itemize} % \item The resolved default or explicit list must contain at least one column. % The built-in default satisfies this requirement, and an empty value passed % to the |columns| setup key is rejected. % \item Column lookup keys are the purified uppercase text of the names. % Ordinary macros are expanded, and formatting commands and braces are % removed before the comparison. Headings show the spelling and the % formatting of the column list. Names must not contain commas and must % remain unique after normalization. % \item Mode and priority values are trimmed and compared without regard to % letter case. Date-format values and their documented aliases follow the % same normalization rule. A robust command in any of these values is % reported as unknown. Palette names remain case-sensitive. % \item A card background must be a color name known to \textsf{xcolor} or a % mixing expression of the form \meta{name}|!|\meta{number}|!|\meta{name} % whose names are all known. Any other value is reported and ignored. % \item Column separation must be a non-negative explicit dimension, a single % LaTeX length register, or a single TeX length parameter, and the sum of % all inter-column gaps must be smaller than the available line width. % \item Calendar dates, project start dates, and reference dates may use US or % English slash notation with a final year, German dot notation, ISO hyphen % notation, or slash-separated year-first notation. The year always has four % digits. Ambiguous year-last slash dates follow the selected date format. % Calendar dates are validated for years from 0001 to 9999 and are % normalized for display. % \item Only complete calendar dates and values |M1| through |M999999| are % classified automatically. Leading zeros in the month number are % permitted. All other deadline values, including values that contain a % robust command, are treated as labels and remain neutral unless |late| % is present. The |M| in a project-month value is uppercase and % case-sensitive. % \item Task text is passed as a command argument, so verbatim material cannot % be used inside a card. Paragraph breaks are permitted in the text argument % but not in the option list or the column argument. % \item The fixed raster layout cannot split an individual board across pages. % Use |break| for long boards. % \item The |break| layout prints synchronized headings once at the beginning % of the board. It does not repeat them on continuation pages because the % supported \textsf{paracol} interface provides independent column streams, % not a repeating per-column heading row. % \item The |break| layout should not be used inside a % \textsf{pdflscape} |landscape| environment. Use the fixed layout for a % landscape board and ensure that the complete board fits on that page. % \item Task counts include every successfully assigned task, irrespective of % its completion status. % \end{itemize} % % \section{Further usage examples} % % The distribution contains eight independently compilable example documents. % The general overview is |kanban-board-example.tex|. The remaining files % isolate deadline states, date formats, custom palettes, visual modes, % column separation, page breaking, and landscape composition. % This section reproduces the essential source for each case and, where visual % behaviour is central, places the generated output directly below it. The % resulting comparison makes the effect of each option observable without % requiring the reader to compile a separate file. % % \subsection{Reusable document setup} % % A document containing several related boards should establish common values % at the highest appropriate configuration level. Package options provide the % initial policy, while environment options record deliberate exceptions. The % following example keeps the column list, palette, mode, project start date, % reference date, and column separation consistent across the document, but % gives the second board a local column list and a different mode: % \begin{lstlisting} % \documentclass{article} % \usepackage[ % columns={Planned,Active,Complete}, % palette=muted, % mode=light, % startdate=07/01/2026, % reference-date=2026-07-18, % columnsep=2mm % ]{kanban-board} % % \begin{document} % % \section{Research tasks} % \begin{kanban} % \kanbantask[prio=high,author=Alice,due=M1] % {Planned}{Validate the data set} % \kanbantask[author=Bob,due=M2] % {Active}{Draft the results section} % \kanbantask[completed] % {Complete}{Approve the analysis plan} % \end{kanban} % % \section{Archival tasks} % \begin{kanban}[columns={Queued,Processing,Stored},mode=dark] % \kanbantask{Queued}{Deposit the source data} % \kanbantask[author=Carol]{Processing}{Create metadata records} % \end{kanban} % % \end{document} % \end{lstlisting} % The first board inherits every package default, including the configured % column list. The second board inherits the |muted| palette, project start % date, and column separation, while replacing its columns and visual mode for % that board only. This pattern makes document-wide conventions explicit and % keeps local deviations easy to identify during review. % % \Needspace{18\baselineskip} % \subsection{Selecting a date format} % % A shared date convention should normally be established at package or setup % level. A board-local selection is useful when a report reproduces material % prepared for a different audience. The following source uses ISO input for % every task because that form is unambiguous, then requests each available % output convention independently: % \begin{lstlisting} % \begin{kanban}[columns={Upcoming},date-format=us] % \kanbantask[due=2099-07-18] % {Upcoming}{Prepare the scheduled release} % \end{kanban} % % \begin{kanban}[columns={Upcoming},date-format=english] % \kanbantask[due=2099-07-18] % {Upcoming}{Prepare the scheduled release} % \end{kanban} % % % The same structure also accepts german, iso, and ymd. % \end{lstlisting} % Only the printed date changes. Validation and overdue classification use the % same Gregorian components in all five cases. % % \paragraph{Rendered output.} % The boards below render the same future date. The labels state the component % order explicitly so that the result does not depend on national terminology. % % \noindent % \kanbanManualDateFormatBoard{us}{US: MM/DD/YYYY} % \hfill % \kanbanManualDateFormatBoard{english}{English: DD/MM/YYYY} % % \medskip % % \noindent % \kanbanManualDateFormatBoard{german}{German: DD.MM.YYYY} % \hfill % \kanbanManualDateFormatBoard{iso}{ISO: YYYY-MM-DD} % % \medskip % % \noindent % \kanbanManualDateFormatBoard{ymd}{Year first: YYYY/MM/DD} % % The complete compilable source is |kanban-board-date-formats-example.tex|. % It also shows how the five compact boards can be arranged in minipages % without changing their local configuration scope. % % \Needspace{18\baselineskip} % \subsection{Light and dark boards in one document} % % Visual mode is a property of the cards rather than of the page. Selecting % |dark| therefore changes card backgrounds, text, and borders % without changing the surrounding document or the transparent column body. % The source below keeps the column structure constant so that the change in % visual treatment can be assessed directly. Author chips and neutral deadline % chips keep the same light treatment in both boards. Red and amber deadline % states retain their semantic colors. Two cards in each board carry a % background tint, which is mixed into the surface of the respective mode. % % \begin{samepage} % \begin{lstlisting} % \begin{kanban}[columns={Planned,Active,Complete},mode=light] % \kanbantask[prio=high,author=Alice,deadline=01/01/2000] % {Planned}{Confirm the requirements} % \kanbantask[bg=yellow,author=Bob, % due=07/18/2026] % {Active}{Implement the package interface} % \kanbantask[bg=kanbanTeal,completed,deadline=12/31/2099] % {Complete}{Create the test files} % \end{kanban} % % \bigskip % % \begin{kanban}[columns={Planned,Active,Complete},mode=dark] % \kanbantask[prio=medium,author=Carol,deadline=01/01/2000] % {Planned}{Prepare the release notes} % \kanbantask[bg=yellow,author=David, % due=07/18/2026] % {Active}{Review the documentation} % \kanbantask[bg=kanbanTeal,completed,deadline=12/31/2099] % {Complete}{Select the license} % \end{kanban} % \end{lstlisting} % \end{samepage} % A document-wide mode may instead be selected as a package option or with % |\kbset|. The environment option remains the appropriate form when the change % applies to one board only. % % \Needspace{14\baselineskip} % \paragraph{Rendered output.} % The following pair is generated from the preceding source. In particular, % the dark board retains the selected column palette while using transparent % column bodies, dark cards, light foreground text, and light neutral author % and future-deadline chips matching those in the light board. Red and amber % deadline chips continue to communicate status independently of visual mode. % % \begin{kanban}[columns={Planned,Active,Complete},mode=light] % \kanbantask[prio=high,author=Alice,deadline=01/01/2000] % {Planned}{Confirm the requirements} % \kanbantask[bg=yellow,author=Bob, % due=07/18/2026] % {Active}{Implement the package interface} % \kanbantask[bg=kanbanTeal,completed,deadline=12/31/2099] % {Complete}{Create the test files} % \end{kanban} % % \medskip % % \begin{kanban}[columns={Planned,Active,Complete},mode=dark] % \kanbantask[prio=medium,author=Carol,deadline=01/01/2000] % {Planned}{Prepare the release notes} % \kanbantask[bg=yellow,author=David, % due=07/18/2026] % {Active}{Review the documentation} % \kanbantask[bg=kanbanTeal,completed,deadline=12/31/2099] % {Complete}{Select the license} % \end{kanban} % % The complete compilable source is provided as % |kanban-board-modes-example.tex|. % % \subsection{Changing the gap between columns} % % Column separation follows the same three-level configuration hierarchy as % the palette and mode. A package option establishes the initial value, % |\kbset| changes the value for subsequent boards, and an environment option % applies to one board. The following fragment demonstrates the scope of each % form: % % \begin{samepage} % \begin{lstlisting} % \usepackage[columnsep=3mm]{kanban-board} % % % Uses the 3 mm package default. % \begin{kanban}[columns={Todo,Doing,Done}] % \kanbantask[deadline=01/01/2000]{Todo}{Define the interface} % \kanbantask[due=07/18/2026] % {Doing}{Write the implementation} % \kanbantask[deadline=12/31/2099,completed]{Done}{Run the tests} % \end{kanban} % % % Changes the default for subsequent boards. % \kbset{columnsep=1mm} % \begin{kanban}[columns={Todo,Doing,Done}] % \kanbantask[deadline=01/01/2000]{Todo}{Define the interface} % \kanbantask[due=07/18/2026] % {Doing}{Write the implementation} % \kanbantask[deadline=12/31/2099,completed]{Done}{Run the tests} % \end{kanban} % % % Uses 4 mm here. The document default remains 1 mm. % \begin{kanban}[columns={Todo,Doing,Done},columnsep=4mm] % \kanbantask[deadline=01/01/2000]{Todo}{Define the interface} % \kanbantask[due=07/18/2026] % {Doing}{Write the implementation} % \kanbantask[deadline=12/31/2099,completed]{Done}{Run the tests} % \end{kanban} % \end{lstlisting} % \end{samepage} % The value must be a non-negative explicit dimension such as |2mm|, a LaTeX % length register such as |\linewidth|, or a TeX length parameter such as % |\parindent|. Increasing it strengthens the visual separation between % workflow stages, but reduces the width available to every task card. % % \paragraph{Rendered output.} % In the comparison below, palette, headings, and task content are held % constant. Only |columnsep| changes. Board-local values are used here so that % the manual's configuration remains unchanged after the demonstration. % % \noindent\textit{Column separation: 3 mm.} % \begin{kanban}[columns={Todo,Doing,Done},columnsep=3mm] % \kanbantask[prio=high,deadline=01/01/2000] % {Todo}{Define the interface} % \kanbantask[author=Alice, % due=07/18/2026] % {Doing}{Write the implementation} % \kanbantask[completed,deadline=12/31/2099]{Done}{Run the tests} % \end{kanban} % % \medskip % \noindent\textit{Column separation: 1 mm.} % \begin{kanban}[columns={Todo,Doing,Done},columnsep=1mm] % \kanbantask[prio=high,deadline=01/01/2000] % {Todo}{Define the interface} % \kanbantask[author=Alice, % due=07/18/2026] % {Doing}{Write the implementation} % \kanbantask[completed,deadline=12/31/2099]{Done}{Run the tests} % \end{kanban} % % \medskip % \Needspace{8\baselineskip} % \noindent\textit{Column separation: 4 mm.} % \begin{kanban}[columns={Todo,Doing,Done},columnsep=4mm] % \kanbantask[prio=high,deadline=01/01/2000] % {Todo}{Define the interface} % \kanbantask[author=Alice, % due=07/18/2026] % {Doing}{Write the implementation} % \kanbantask[completed,deadline=12/31/2099]{Done}{Run the tests} % \end{kanban} % % The complete source is |kanban-board-columnsep-example.tex|. % % \Needspace{10\baselineskip} % \subsection{A page-breakable board} % % Long task lists should use the |break| option. In this layout each Kanban % column is managed as a \textsf{paracol} column and may continue onto a later % page. The fixed layout, by contrast, treats the complete board as one % unbreakable object. The compact fragment below shows the public interface. % The rendered demonstration that follows deliberately contains more cards so % that a real page transition occurs. The synchronized headings appear once at % the beginning of the board. Continuation pages contain only the remaining % cards. This behavior follows the public \textsf{paracol} column-stream model % and avoids dependencies on its private output routine. % % \begin{samepage} % \begin{lstlisting} % \kbset{palette=default,mode=light,columnsep=2mm} % \begin{kanban}[ % columns={Backlog,In progress,Review,Done},break % ] % \kanbantask[prio=high,author=Alice,deadline=01/01/2000] % {Backlog}{Finalize the interface} % \kanbantask[prio=medium,author=Bob, % due=07/18/2026] % {In progress}{Write regression tests} % \kanbantask[bg=yellow,author=Carol,deadline=12/31/2099] % {Review}{Proofread the manual} % \kanbantask[completed,due=12/31/2099] % {Done}{Select the package license} % \end{kanban} % \end{lstlisting} % \end{samepage} % Task declarations need not follow the order of the columns. The package % collects each task under its named column and preserves source order within % that column. Since column bodies paginate independently, their bottom edges % are not synchronized in this layout. % % \paragraph{Rendered output.} % The next board begins below this paragraph and contains enough material to % continue onto the following page. Its headings are printed once at the % beginning. The cards that do not fit on this page continue in their % respective column streams on the next page. Twelve cards carry a % background tint in one of four colors, three cards per color, so the % demonstration also shows that a tint travels with its card onto the % continuation page. % % \Needspace{14\baselineskip} % \begin{kanban}[ % columns={Backlog,In progress,Review},break,columnsep=2mm % ] % \kanbanManualBreakDeadlineCard{Backlog}{Alice} % {deadline=01/01/2000}{Confirm the public interface} % \kanbanManualBreakCard[bg=yellow]{Backlog}{Bob} % {Collect compatibility requirements} % \kanbanManualBreakCard{Backlog}{Carol}{Review package dependencies} % \kanbanManualBreakCard{Backlog}{David}{Define the project date policy} % \kanbanManualBreakCard{Backlog}{Alice}{Select the release palette} % \kanbanManualBreakCard{Backlog}{Bob}{Identify supported engines} % \kanbanManualBreakCard[bg=kanbanRose]{Backlog}{Carol} % {Plan the documentation structure} % \kanbanManualBreakCard{Backlog}{David}{Prepare the release checklist} % \kanbanManualBreakCard[bg=kanbanTeal]{Backlog}{Alice} % {Confirm the archive structure} % \kanbanManualBreakCard{Backlog}{Bob}{Review installation instructions} % \kanbanManualBreakCard{Backlog}{Carol}{Assess documented limitations} % \kanbanManualBreakCard[bg=orange]{Backlog}{David} % {Schedule the release review} % % \kanbanManualBreakDeadlineCard{In progress}{Alice} % {due=07/18/2026} % {Implement configuration keys} % \kanbanManualBreakCard{In progress}{Bob}{Apply the visual modes} % \kanbanManualBreakCard[bg=kanbanTeal]{In progress}{Carol} % {Synchronize header heights} % \kanbanManualBreakCard{In progress}{David}{Equalize fixed column bodies} % \kanbanManualBreakCard[bg=orange]{In progress}{Alice} % {Remove outer side rules} % \kanbanManualBreakCard{In progress}{Bob}{Extend the user manual} % \kanbanManualBreakCard{In progress}{Carol}{Compile example documents} % \kanbanManualBreakCard[bg=yellow]{In progress}{David} % {Add regression assertions} % \kanbanManualBreakCard{In progress}{Alice}{Run the pdfTeX checks} % \kanbanManualBreakCard{In progress}{Bob}{Run the LuaTeX checks} % \kanbanManualBreakCard[bg=kanbanRose]{In progress}{Carol} % {Generate the release archive} % \kanbanManualBreakCard{In progress}{David}{Inspect the rendered output} % % \kanbanManualBreakDeadlineCard{Review}{Alice} % {deadline=12/31/2099}{Inspect the generated style file} % \kanbanManualBreakCard[bg=kanbanRose]{Review}{Bob} % {Compare regression logs} % \kanbanManualBreakCard{Review}{Carol}{Proofread the public interface} % \kanbanManualBreakCard[bg=yellow]{Review}{David} % {Examine color contrast} % \kanbanManualBreakCard{Review}{Alice}{Validate the documented source} % \kanbanManualBreakCard{Review}{Bob}{Review the CTAN metadata} % \kanbanManualBreakCard{Review}{Carol}{Check the license statements} % \kanbanManualBreakCard[bg=orange]{Review}{David} % {Inspect the manual PDF} % \kanbanManualBreakCard{Review}{Alice}{Test the installation procedure} % \kanbanManualBreakCard{Review}{Bob}{Verify all example files} % \kanbanManualBreakCard[bg=kanbanTeal]{Review}{Carol} % {Confirm the change history} % \kanbanManualBreakCard{Review}{David}{Approve the release candidate} % \end{kanban} % % The continuation demonstrates why body heights remain independent when % |break| is active. The complete standalone example is % |kanban-board-break-example.tex|. % % \subsection{A fixed board on a landscape page} % % A landscape page increases |\linewidth| and is therefore useful when a % workflow has five or more stages that would be too narrow in portrait % orientation. The \textsf{pdflscape} package establishes the rotated page and % records the appropriate PDF rotation metadata. The board itself requires no % rotation commands. Page margins should be chosen before the board is opened, % and |columnsep| can then be reduced modestly if the available width is still % insufficient. % % The board must use the fixed layout. The |break| option is deliberately % absent because its \textsf{paracol}-based pagination is intended for ordinary % portrait text pages and is not compatible with this use. A fixed board is % kept as one indivisible object, including its header and body rows. It will % therefore move to the next page when the remaining vertical space is too % small. If the complete board is taller than one landscape page, the content % should be reduced or presented as a separate page-breakable portrait board. % % Concise stage names are especially important when six columns share the page. % The example uses |Build| and |Docs| as familiar abbreviations for % implementation and documentation. Less familiar abbreviations should be % defined in the surrounding text so that the board remains understandable % without relying on source-code comments. % % \begin{samepage} % \begin{lstlisting} % \documentclass[a4paper]{article} % \usepackage[margin=18mm]{geometry} % \usepackage{pdflscape} % \usepackage[columnsep=2mm]{kanban-board} % % \begin{document} % \begin{landscape} % \section*{Release workflow} % % % Deliberately omit the break option in a landscape environment. % \begin{kanban}[ % columns={Ideas,Selected,Build,Review,Docs,Released}, % mode=light % ] % \kanbantask[deadline=01/01/2000] % {Ideas}{Collect feature requests} % \kanbantask{Ideas}{Record user feedback} % \kanbantask[prio=high, % due=07/18/2026] % {Selected}{Approve the release scope} % \kanbantask[author=Alice,deadline=12/31/2099] % {Build}{Complete the changes} % \kanbantask[author=Bob]{Review}{Run the acceptance review} % \kanbantask[author=Carol]{Docs}{Update the user manual} % \kanbantask[completed]{Released}{Publish the archive} % \end{kanban} % \end{landscape} % \end{document} % \end{lstlisting} % \end{samepage} % The supporting package is needed only by a document that requests rotated % pages. It is not a dependency of \textsf{kanban-board}. The excerpt shows the % structural pattern. The standalone example adds three tasks to every stage so % that the use of the available landscape area can be assessed realistically. % % \paragraph{Rendered output.} % The next page is generated directly in a |landscape| environment. The board % uses six fixed columns, short one-line headings, three cards per column, and % no |break| option. Equal body heights make the workflow read as one coherent % table even though individual task cards have different amounts of metadata. % % \begin{landscape} % \section*{Landscape release workflow} % \begin{kanban}[ % columns={Ideas,Selected,Build,Review,Docs,Released}, % mode=light, % columnsep=2mm % ] % \kanbantask[author=Alice,deadline=01/01/2000] % {Ideas}{Collect feature requests} % \kanbantask[author=Bob] % {Ideas}{Record user feedback} % \kanbantask[author=Carol] % {Ideas}{Identify compatibility risks} % % \kanbantask[prio=high,author=Bob, % due=07/18/2026] % {Selected}{Approve the release scope} % \kanbantask[author=Carol] % {Selected}{Confirm supported engines} % \kanbantask[author=David] % {Selected}{Assign milestone owners} % % \kanbantask[author=Carol,deadline=12/31/2099] % {Build}{Complete the package changes} % \kanbantask[author=David] % {Build}{Update date validation} % \kanbantask[author=Alice] % {Build}{Generate the style file} % % \kanbantask[author=David] % {Review}{Run the technical review} % \kanbantask[author=Alice] % {Review}{Compare engine output} % \kanbantask[author=Bob] % {Review}{Check regression logs} % % \kanbantask[author=Alice] % {Docs}{Update the user manual} % \kanbantask[author=Bob] % {Docs}{Compile usage examples} % \kanbantask[author=Carol] % {Docs}{Verify CTAN metadata} % % \kanbantask[completed] % {Released}{Publish the source archive} % \kanbantask[author=Alice,completed] % {Released}{Tag version 1.0.0} % \kanbantask[author=Bob,completed] % {Released}{Announce the release} % \end{kanban} % \end{landscape} % % The output confirms that the fixed layout uses the landscape line width while % retaining synchronized headings and column bodies. The task count in each % heading is derived from the declarations, and the palette continues cyclically % if a later board contains more stages than palette entries. A complete version % is provided as |kanban-board-landscape-example.tex|. % % \section{License and maintenance} % % The package is distributed under the LaTeX Project Public License, version % 1.3c or, at the user's option, any later version. Its LPPL status is % ``maintained'', and the Current Maintainer is Andreas Willibald Weber. % Defect reports should include a minimal complete document, the relevant log % messages, and the versions of LaTeX and \textsf{kanban-board} used to % reproduce the problem. The package information page is % \url{https://ctan.org/pkg/kanban-board}. Development takes place at % \url{https://github.com/AndreasWillibaldWeber/kanban-board}. Defects and % focused enhancement proposals should be submitted through the public issue % tracker at % \url{https://github.com/AndreasWillibaldWeber/kanban-board/issues}. The % development repository also contains the contribution guidelines and the % release procedure of the maintainer. % % \StopEventually{\clearpage\PrintChanges\PrintIndex} % % \section{Implementation} % % The implementation is organized as six documented parts that % |kanban-board.ins| assembles into one style file. This part holds the % package declaration, the dependencies, and the shared state. The remaining % parts hold the palette and column registries, the deadline engine, the % persistent % configuration, the card renderers, and the board lifecycle. The commentary % explains the responsibility of each definition and the design decisions % behind it. It does not restate the semantics of the LaTeX3 programming % layer, which is documented in |interface3.pdf|. % % \subsection{Public command contracts} % % The implementation distinguishes persistent defaults, one-board state, and % task data. The |kanban| environment establishes a collection scope, copies % the persistent defaults, applies its local options, and selects one of the % two renderers. It is the only public operation that creates board state. % |\kanbantask| may mutate that state only while a board is active. Otherwise % it reports an error and discards the declaration. A nested board is % rejected at its entry point, and its task declarations enter a temporary % discard state so that the structural error is not obscured by secondary % diagnostics. % % |\kanbansetup| changes persistent defaults for boards that begin later. % When a short name is unused, the alias is defined by control-sequence % equivalence rather than by a forwarding wrapper. This applies to |\kbset|, % |\kbdefinepalette|, and |\kbtask|. Existing short definitions are preserved % and diagnosed. Palette definition changes the registry. Palette selection % changes the current palette name, its background list, and any paired % foreground list. Redefining the selected name refreshes the persistent % lists for later boards, whereas a board already in progress keeps its local % snapshot. No generic |\task| command is defined, because that name has a % material risk of collision with classes and unrelated packages. % % \subsection{Configuration and data collection} % % A board begins by copying the current document defaults for columns, % palette, visual mode, date format, project start date, reference date, % semantic labels, and column separation into board-local state. Its % optional key list is then applied to that state. Every column name is % trimmed. Its lookup key is the uppercase form of its plain text, with % formatting commands and braces removed, and its original spelling is the % heading text. A board-local property list maps each key to a % consecutive numeric identifier. Task lists and counters use that identifier % together with a monotonically increasing board identifier, so user-provided % names never form part of an internal control-sequence name. Duplicate keys % are diagnosed before rendering. Configuration is parsed by the key families % |kanban/task|, |kanban/board|, and |kanban/setup|, with subordinate label % families. Start and reference dates are deferred until the complete % surrounding key list has resolved its date format. They are then validated % and stored in canonical ISO form. Package options are accumulated and % passed through the same setup transaction rather than through a second % parser. Their diagnostics name the package options as the context, % because the line number at that moment lies inside the package file. % % Task declarations do not typeset cards immediately. Each declaration % normalizes and validates the target column, increments its counter, and % appends a protected call to the card renderer to the list of that column. % Empty and unknown targets produce explicit errors and are not appended. % Task text and metadata remain unexpanded while they are stored. Collection % is global for the lifetime of the active board, so a declaration inside an % ordinary TeX group is retained. The deadline of an accepted task is checked % at this point, which gives every deadline warning the line number of the % task. After the columns are resolved, the package evaluates the complete % gap width. Dimension syntax is checked before assignment, and a value that % would leave no positive width for cards is diagnosed once and replaced % locally by |0pt|. % % \subsection{Rendering strategies} % % The fixed renderer creates two raster rows, one containing every heading % and one containing every column body. Row-wise equalization gives all % headings the height of the tallest heading and all bodies the height of % the fullest body. The complete raster is enclosed in a minipage, which % makes the header and body rows indivisible and prevents an orphaned header % row at the foot of a page. The column body hides its frame and interior % rather than painting a transparent background, so the PDF contains no % transparency group and remains suitable for PDF/A workflows. % % When |break| is selected, the package constructs parallel \textsf{paracol} % columns. Header heights are synchronized through a board-specific % equal-height group, while the card lists remain outside any fixed-height % box, so each column may continue on a later page. Headers are emitted once % before the streams diverge and are not repeated on continuation pages. The % two renderers share the same card command and visual styles but use % different body-height and pagination rules. % % \subsection{Metadata and validation} % % Calendar and project-month classification is performed when a card is % rendered, against the reference date of the board or the compilation date. % All five supported calendar notations are reduced to the same year, month, % and day components, which are checked against month lengths and the % leap-year rule and then normalized for display. Every notation requires a % four-digit year. Input with the shape of a date but a shorter year is % reported rather than misread. Ambiguous year-last slash values follow the % date-format snapshot of the board, with a validity-based swap when only the % opposite ordering forms a real date. Project-month numbers are stripped of % leading zeros and bounded before integer conversion, and project-month % boundaries use the start-day number where possible and the last valid day % in shorter months. Every other value remains ordinary label text. An % optional card background is validated against the mixing grammar of % \textsf{xcolor} and the defined color names when the task is declared, and % the renderer mixes it into the surface of the active mode. % % Card surfaces, metadata chips, and deadline indicators are named % \textsf{tcolorbox} styles. Seven empty public styles are applied after the % structural defaults, which permits controlled presentation changes without % exposing internal environment names. Built-in header and semantic color % pairs were selected against a 4.5:1 contrast threshold. Internal LaTeX2e % control sequences use three prefixes. The |kanban@| prefix marks package % state and helpers, the |kb@| prefix marks short-lived values of card % rendering and choice normalization, and the |kbtask@| prefix marks the % metadata of the task being declared. LaTeX3 variables and functions use % the |__kanban| module name. The package allocates its own % LaTeX3 variables for every role and does not rely on the scratch variables % of the kernel. The regression suite exercises configuration scope, % diagnostics, canonical date snapshots, fixed reference dates, metadata % flags, malformed dimensions, compatibility with the declared LaTeX format, % all three supported engines, all five date formats, custom heading % foregrounds, full-width cards, synchronized break-layout headings, % cross-page continuation, impossible-gap recovery, robust commands and % paragraphs in user text, brace groups in column names, TeX length % parameters as gaps, and a strict run with expl3 declaration and % deprecation checking enabled. % % \subsection{Bootstrap state} % % The bootstrap code identifies the package, loads the packages on which % rendering depends, and allocates the persistent and board-local state used % by the configuration, collection, validation, and rendering stages. % % \paragraph{Package declaration and runtime dependencies.} % The docstrip guard |%<*package>| begins the part of the documented source % that is copied into |kanban-board.sty|. Each source part opens and closes % its own guarded region, and |kanban-board.ins| assembles the parts in % dependency order. % The package declares the minimum LaTeX format and loads each facility that % its public behavior requires rather than relying on another package to load % that facility incidentally. \textsf{xcolor} provides named colors and color % expressions. \textsf{etoolbox} supplies Booleans, string tests, and % expandable list construction. \textsf{tikz} draws the clock symbol used by % deadlines. \textsf{tcolorbox} constructs headers, cards, chips, and the % fixed-board raster, with the |skins| and |raster| libraries. % \textsf{paracol} provides the independent page-breakable column streams of % the |break| renderer. % \begin{macrocode} %<*package> \NeedsTeXFormat{LaTeX2e}[2020-10-01] \ProvidesPackage{kanban-board}[2026/11/15 v1.0.0 Kanban project boards] \RequirePackage{xcolor} \RequirePackage{etoolbox} \RequirePackage{tikz} \RequirePackage{tcolorbox} \RequirePackage{paracol} \tcbuselibrary{skins,raster} % \end{macrocode} % % \paragraph{Built-in color constants.} % The semantic colors and the colors of the built-in palettes are defined % once under stable symbolic names. The three semantic colors represent % overdue or high-priority work, work due at the reference date, and % completed or low-priority work. The other names are palette entries. Text % colors are not hard-coded into the palette registry here, because a % starred palette definition may provide an explicit foreground for each % background. % \begin{macrocode} \definecolor{kanbanInk}{HTML}{263238} \definecolor{kanbanHigh}{HTML}{B23A48} \definecolor{kanbanMed}{HTML}{E8A06A} \definecolor{kanbanLow}{HTML}{477455} \definecolor{kanbanSlate}{HTML}{4C5A6B} \definecolor{kanbanBlue}{HTML}{3B7CA6} \definecolor{kanbanTeal}{HTML}{267363} \definecolor{kanbanSage}{HTML}{4F7D43} \definecolor{kanbanAmber}{HTML}{876515} \definecolor{kanbanClay}{HTML}{9B5030} \definecolor{kanbanRose}{HTML}{AF5C74} \definecolor{kanbanPlum}{HTML}{7C5C95} \definecolor{kanbanMutedBlue}{HTML}{52758C} \definecolor{kanbanMutedGreen}{HTML}{597C6E} \definecolor{kanbanMutedPurple}{HTML}{746680} \definecolor{kanbanMutedBrown}{HTML}{8A6F5A} % \end{macrocode} % % \paragraph{Boolean flags, board identity, and dimensions.} % Rendering needs a small set of state flags. They record whether a board % uses the page-breakable renderer, whether task declarations currently % belong to an active board, whether the environment should render when it % closes, and whether tasks inside a rejected nested board must be discarded. % Two further flags carry the result of deadline classification. A unique % board number keeps the temporary data of different boards apart, and % dedicated length registers hold the persistent gap, its board-local % snapshot, a validation candidate, and the combined width of all gaps. % Separate registers let validation inspect a candidate without modifying a % previously accepted value. % \Needspace{16\baselineskip} % \begin{macrocode} \newbool{kanban@break} \newbool{kanban@active} \newbool{kanban@render} \newbool{kanban@discardtasks} \newbool{kb@overdue} \newbool{kb@duenow} \newcounter{kanban@board} \def\kanban@boardgroup{0} \newlength\kanban@columnsep \newlength\kanban@boardcolumnsep \newlength\kanban@candidatecolumnsep \newlength\kanban@totalgaps \setlength\kanban@columnsep{2mm} % \end{macrocode} % % \paragraph{Persistent defaults and board-local scalar snapshots.} % Configuration values such as the start date, reference date, date format, % visual mode, card colors, and semantic labels are simple token values. Most % occur in pairs. One member is the persistent default for later boards, and % the other is the snapshot used by the board currently being rendered. This % separation implements the documented package, setup, and board precedence. % Empty date macros mean that no fixed date has been supplied, in which case % the compilation date is the reference. The color macros contain a named % color or an \textsf{xcolor} expression and are expanded only when a box is % rendered. % \begin{macrocode} \def\kanban@startdate{} \def\kanban@thestart{} \def\kanban@referencedate{} \def\kanban@thereference{} \def\kanban@dateformat{us} \def\kanban@boarddateformat{us} \def\kanban@mode{light} \def\kanban@boardmode{light} \def\kanban@textcolor{kanbanInk} \def\kanban@cardcolor{white} \def\kanban@cardtint{15} \def\kanban@bordercolor{black!15} \def\kanban@authorback{black!6} \def\kanban@authortext{black!58} \def\kanban@deadlineback{black!7} \def\kanban@deadlinetext{black!62} \def\kanban@headingtext{white} \def\kanban@hightext{white} \def\kanban@mediumtext{kanbanInk} \def\kanban@lowtext{white} \def\kanban@highlabel{HIGH} \def\kanban@mediumlabel{MED} \def\kanban@lowlabel{LOW} \def\kanban@donelabel{DONE} \def\kanban@boardhighlabel{HIGH} \def\kanban@boardmediumlabel{MED} \def\kanban@boardlowlabel{LOW} \def\kanban@boarddonelabel{DONE} % \end{macrocode} % % \paragraph{LaTeX3 state containers.} % Palettes and columns require structured data rather than isolated scalar % macros, and every role receives its own typed variable. The two global % property lists form the palette registry, one for heading backgrounds and % one for optional heading foregrounds. Global comma lists hold the selected % persistent palette and the default column keys, and a global property list % maps each column key to its heading text. Their local counterparts are the % snapshot for an active board. The remaining local containers support % palette-pair validation, column normalization, numeric column lookup, % normalized choices, and the deferred processing of start and reference % dates. The scratch variables of the kernel are not used, because other % packages may overwrite them between calls. % \Needspace{30\baselineskip} % \begin{macrocode} \ExplSyntaxOn \prop_new:N \g__kanban_palettes_prop \prop_new:N \g__kanban_palette_texts_prop \clist_new:N \g__kanban_palette_clist \clist_new:N \g__kanban_palette_fg_clist \tl_new:N \g__kanban_palette_name_tl \clist_new:N \l__kanban_board_palette_clist \clist_new:N \l__kanban_board_palette_fg_clist \clist_new:N \l__kanban_palette_colors_clist \clist_new:N \l__kanban_palette_bg_clist \clist_new:N \l__kanban_palette_fg_clist \tl_new:N \l__kanban_palette_bg_tl \tl_new:N \l__kanban_palette_fg_tl \tl_new:N \l__kanban_pair_bg_tl \tl_new:N \l__kanban_pair_fg_tl \tl_new:N \l__kanban_palette_item_tl \int_new:N \l__kanban_palette_count_int \int_new:N \l__kanban_palette_index_int \seq_new:N \l__kanban_palette_pair_seq \bool_new:N \l__kanban_bad_palette_bool \clist_new:N \g__kanban_columns_clist \prop_new:N \g__kanban_column_display_prop \clist_new:N \l__kanban_board_columns_clist \prop_new:N \l__kanban_board_column_display_prop \clist_new:N \l__kanban_columns_tmp_clist \prop_new:N \l__kanban_column_display_tmp_prop \prop_new:N \l__kanban_column_ids_prop \int_new:N \l__kanban_column_index_int \tl_new:N \l__kanban_palette_name_tl \tl_new:N \l__kanban_column_tl \tl_new:N \l__kanban_column_display_tl \tl_new:N \l__kanban_column_id_tl \tl_new:N \l__kanban_choice_tl \tl_new:N \l__kanban_background_tl \seq_new:N \l__kanban_background_seq \bool_new:N \l__kanban_background_ok_bool \tl_new:N \l__kanban_pending_startdate_tl \tl_new:N \l__kanban_pending_reference_date_tl \bool_new:N \l__kanban_pending_startdate_bool \bool_new:N \l__kanban_pending_reference_date_bool % \end{macrocode} % % \paragraph{Named diagnostics.} % Every warning of the package is a named message, so the main text and the % help text stay consistent whether invalid input originates in a package % option, in |\kbset|, in a board option, in a palette definition, or in a % task declaration. Each message states the line context after the subject % of its first sentence, because \textsf{l3msg} warnings do not add it on % their own. Messages that share a shape take the scope or the kind of the % setting as a parameter. The alias message is issued while the package % loads and therefore carries no line context. A message text that % continues on a second source line ends the first line with a tilde. The % tilde is a space character in expl3 syntax, and TeX discards a space % character at the start of a line. For the same reason a tilde directly % after |\msg_line_context:| is absorbed as the end of that control word, so % a word space at that position is written as |\c_space_tl|. The % LaTeX2e-facing wrapper lets the parts written in LaTeX2e syntax issue a % named message with two parameters. A call site that needs an expanded % argument, such as the name of an unknown key, expands the complete call % with |\use:x| and then invokes the base message function. The x-type % message variants are separate definitions on older kernels, so a call % through them would bypass a test harness that intercepts the base % function. % \Needspace{14\baselineskip} % \begin{macrocode} \msg_new:nnnn {kanban-board}{invalid-date-setting} {Invalid~#1~'#2'~\msg_line_context:.~The~current~value~is~kept.} {Use~a~valid~Gregorian~date~with~a~four-digit~year~in~one~of~the~ documented~numeric~forms,~for~example~2026-07-18.} \msg_new:nnnn {kanban-board}{invalid-dimension} {Invalid~#1~value~'#2'~\msg_line_context:.~The~current~value~ is~kept.} {Use~a~non-negative~explicit~dimension~such~as~2mm,~a~LaTeX~length~ register,~or~a~TeX~length~parameter~such~as~\iow_char:N\\hsize.} \msg_new:nnnn {kanban-board}{unknown-key} {Unknown~#1~option~'#2'~\msg_line_context:.~The~option~is~ignored.} {Check~the~spelling~and~the~documented~scope~of~the~key.} \msg_new:nnnn {kanban-board}{unknown-value} {Unknown~#1~'#2'~\msg_line_context:.~The~current~value~is~kept.} {Check~the~spelling~of~the~value~against~the~documented~choices.} \msg_new:nnnn {kanban-board}{unknown-palette} {Unknown~#1~'#2'~\msg_line_context:.~The~current~palette~is~kept.} {Define~the~palette~with~\iow_char:N\\kanbandefinepalette~before~ selecting~it.~The~built-in~names~are~default,~muted,~and~ monochrome.} \msg_new:nnnn {kanban-board}{empty-palette-name} {Empty~palette~name~\msg_line_context:.~The~definition~is~ignored.} {Give~the~palette~a~non-empty~name.} \msg_new:nnnn {kanban-board}{empty-palette} {Palette~'#1'~\msg_line_context:\c_space_tl has~no~#2.~ The~definition~is~ignored.} {List~at~least~one~entry,~for~example~kanbanBlue~or~ kanbanBlue/white.} \msg_new:nnnn {kanban-board}{malformed-palette-pair} {Palette~'#1'~\msg_line_context:\c_space_tl has~a~malformed~ color/text~pair.~The~definition~is~ignored.} {Write~every~entry~as~background/foreground~with~two~non-empty~ color~names,~for~example~kanbanSlate/white.} \msg_new:nnnn {kanban-board}{empty-column-list} {Empty~column~list~\msg_line_context:.~The~current~list~is~kept.} {Give~at~least~one~column~name,~for~example~columns={Backlog,Done}.} \msg_new:nnnn {kanban-board}{empty-label} {Empty~#1~'#2'~\msg_line_context:.~The~current~value~is~kept.} {Give~every~label~a~non-empty~text,~for~example~ labels={high=URGENT}.} \msg_new:nnnn {kanban-board}{unknown-color} {Unknown~color~'#1'~\msg_line_context:.~The~card~keeps~the~default~ background.} {Use~a~color~name~known~to~xcolor,~or~an~expression~such~as~ yellow!50~or~red!30!blue~whose~names~are~all~known.} \msg_new:nnnn {kanban-board}{unknown-priority} {Unknown~priority~'#1'~\msg_line_context:.~The~priority~chip~is~ omitted.} {Use~high,~medium,~med,~or~low.} \msg_new:nnnn {kanban-board}{invalid-deadline} {Invalid~deadline~date~'#1'~\msg_line_context:.~The~card~shows~a~ neutral~label.} {Write~calendar~deadlines~with~a~four-digit~year~in~one~of~the~ documented~numeric~forms,~for~example~2026-07-18.} \msg_new:nnnn {kanban-board}{invalid-project-month} {Invalid~project-month~deadline~'#1'~\msg_line_context:.~The~card~ shows~a~neutral~label.} {Write~project~months~as~M~followed~by~an~integer~from~1~to~999999.} \msg_new:nnnn {kanban-board}{alias-taken} {\iow_char:N\\#1~is~already~defined.~Use~\iow_char:N\\#2~instead.} {Another~package~or~the~document~owns~the~short~name.~The~existing~ definition~is~kept.} \cs_new_protected:Npn \kanban@warning #1#2#3 {\msg_warning:nnnn {kanban-board}{#1}{#2}{#3}} % \end{macrocode} % % At this point the package has allocated, but not yet populated, the % palette registries and the column maps. The following parts define the % functions that validate and populate those containers. % % \begin{macrocode} % % \end{macrocode}