In all the years that I have studied culinary typography, I have avoided essaying timeline recipes. Even the simplest recipe is, once you start taking it apart, surprisingly complex: merging that complexity with the mechanism of a timeline seemed too much. It is, therefore, with a good deal of diffidence that I submit this. Still, your question sparked my interest. You don't give specifics for what you'd like to see, so that has left me with few restraints save for the timeline itself.
What is required in recipes in this and similar formats (as, for example, tabular recipe notation which can be seen at https://www.cookingforengineers.com/recipe/58/Peanut-Butter-Cookies -- towards the bottom), is brevity, often not a salient feature of culinary writing. In any event, a recipe in this and similar formats is more likely to be a summary, or an aide memoire rather than a full, detailed recipe.
Colors: Randomly chosen, are not mere eye-candy, but distinguish steps and their location on the timeline (particularly the connectors indicating the start points and barred rules showing the end points) clearer. Can be turned off if desired.
Varwidth: The steps are contained in varwidth
environments to conserve space. These environments are only as wide as they need to be, with the maximum possible being \stepwd
, the fourth (and optional) argument of the \step
macro -- the default is currently 1-inch, but that can be changed in the preamble. To use minipages, add the dominipg
option to the recipe
environment
The code is verbose, but reasonably well commented, and there is some additional material after \end{document}
.
I have attempted to make the entry of the information as straightforward as possible.
\documentclass{article}
\usepackage[%showframe,
papersize={11in,8.5in},margin=0.5in]{geometry}
\usepackage[rgb]{xcolor}% <<-necessary for use of hsb color space>>
\usepackage{fontspec,xparse,tikz,varwidth,keyval}
\usetikzlibrary{calc,positioning,backgrounds,chains,arrows.meta}
\newcounter{stepnum}
\newif\ifbotrec
\newif\ifdominipg
\newif\ifnocolor
\newsavebox{\recbox}
\newtoks\tlntox
\newlength{\tlnwidth}
\newlength{\stepwd}
\newlength{\mvstep}
\newlength{\stepoffset}
\newlength{\nodedist}
\colorlet{recipecolor}{red}
\setlength{\tlnwidth}{\textwidth}
\setlength{\stepwd}{1in}
\setlength{\mvstep}{2pt}
\setlength{\stepoffset}{18pt}
\setlength{\nodedist}{6pt}
\def\nocolorcolor{}
%% |=====8><-----| %%
\makeatletter
%% \step options:
\define@key{timelst}{Bot}[true]{\csname botrec#1\endcsname}%% below timeline
\define@key{timelst}{Top}[false]{\csname botrec#1\endcsname}%% above timeline
%% recipe environment options:
\define@key{timel}{dominipg}[true]{\csname dominipg#1\endcsname}%% if true, use minipages, not varwidth
\define@key{timel}{nocolor}[true]{\csname nocolor#1\endcsname}%if true, stop random colors
\define@key{timel}{nocolorcolor}{\def\nocolorcolor{#1}}% if nocolor=true use this color
\define@key{timel}{recipecolor}{\colorlet{recipecolor}{#1}}%% main recipe color
\define@key{timel}{tlnwidth}{\setlength{\tlnwidth}{#1}}%% width of timeline
\define@key{timel}{mvstep}{\setlength{\mvstep}{#1}}%% small vertical offset to avoid line colisions
\define@key{timel}{stepoffset}{\setlength{\stepoffset}{#1}}%%dist. timeline to first connector bend
\define@key{timel}{nodedist}{\setlength{\nodedist}{#1}}%% horizontal distance between steps
\makeatother
%% |=====8><-----| %%
\makeatletter %% {\foo}{A}{B}
\def\instring#1#2{TT\fi\begingroup\edef\x{\endgroup\noexpand\in@{#1}{#2}}\x\ifin@}
\makeatother
\def\whyph#1-#2|{\def\FROM{#1}\def\TO{#2}}
\def\wohyph#1|{\def\FROM{#1}\def\TO{}}
\NewDocumentCommand{\mkrule}{O{recipecolor}}{%
\nointerlineskip
\vskip0pt
\textcolor{#1}{\hrulefill}%
\par
\nointerlineskip
\vskip0pt
}
%% format the ingredients -- bold; the hanging indentation happens in the varwidth environments
\NewDocumentCommand{\ingreds}{ >{\SplitList{;}}m }{\ProcessList{#1}{\fooaux}}
\NewDocumentCommand{\fooaux}{ m } {\expandafter\fooauxa#1|}% #1*=\hrulefill?; #2=ingredients
\NewDocumentCommand{\fooauxa}{s O{0pt} u{|}}{%
\bfseries\strut#3\strut\par
\IfBooleanT{#1}{%
\mkrule
}%
}
%% #1*=?; [#2=keyval]l #3=title; #4=start #5=end
\NewDocumentEnvironment{recipe}{s O{} m m m}{%
\setkeys{timel}{#2}%
\colorlet{cmpreccol}{rgb:-recipecolor, 5;black, 3}% complement, darkened
\pgfmathsetmacro{\tlndur}{#5 - #4}%
\pgfmathsetmacro{\startrec}{#4}%
\pgfmathsetmacro{\finishrec}{#5}%
\tlntox={}%
\setcounter{stepnum}{0}%
}{%
\centering
\begin{tikzpicture}[draw,%
start chain=toprec going {right=of \tikzchainprevious.south east},
start chain=botrec going {right=of \tikzchainprevious.north east},
outer sep=0pt,
node distance=\nodedist]
\draw[timeline](0,0)coordinate(ST) -- (\tlnwidth,0)coordinate(ET); %timeline
\begin{scope}[on background layer]
\foreach \n [count=\m from 0] in {#4,...,#5}
{\node[font=\Huge\bfseries,text=lightgray,name=H\n]
at ($(ST)!\m/\tlndur!(ET)$) {\n};}%% numbers on timeline
\end{scope}
\the\tlntox
\node[above right=0pt and 0pt of current bounding box.north west -| ST,
name=T,font=\Large\bfseries\itshape,text=recipecolor] {#3};%% title node
\end{tikzpicture}%
\par
\bigskip
}
\tikzset{%
stepnode/.style n args = {3}{thick,fill=stephue!10,draw=stephue,name=#1,on chain=#2,anchor=#3},
connector/.style={stephue,very thick,-{Stealth[]},rounded corners=3pt},
timeline/.style={recipecolor,very thick,{Latex[]}-{Latex[]}},
endshow/.style={ultra thick,stephue!50,-{Bar[]}},
stnum/.style={font=\sffamily\scriptsize,draw=stephue,very thin,
fill=stephue!10,circle,inner sep=1pt}
}
\NewDocumentCommand{\mkstep}{+m o m}{%utility macro: #1=method text; [#2=ingredients]; #3=step width
\ifdominipg \begin{minipage}{#3} \else \begin{varwidth}{#3}\fi% or minipage if you like
\IfNoValueF{#2}{%
\begingroup
\leftskip1.25em
\parindent-1.25em
\rightskip0pt plus 3em
\ingreds{#2}%
\mkrule[cmpreccol]
\endgroup
\smallskip
}
\rightskip0pt plus 3em
\strut#1\strut\par
\ifdominipg \end{minipage} \else\end{varwidth}\fi% or minipage
}
%% #1 keyval,#2 method, [#3 ingredients] (;-separated list), #4 start<-end>; #5=[step width]
\NewDocumentCommand{\step}{O{} +m o m O{\stepwd} D<>{0pt}}{%
\setkeys{timelst}{#1}%
\if\instring{-}{#4}\expandafter\whyph#4| \else \wohyph#4|\fi
\stepcounter{stepnum}%
\edef\foo{\tlntox={\the\tlntox
\ifnocolor
\ifx\empty\nocolorcolor
\noexpand\colorlet{stephue}{recipecolor}%
\else
\noexpand\colorlet{stephue}{\nocolorcolor}
\fi
\else
\noexpand\pgfmathsetmacro{\noexpand\huenum}{rnd}%
\noexpand\definecolor{stephue}{hsb}{\noexpand\huenum,0.8,0.8}%
\fi
\ifbotrec % below the timeline
\noexpand\begin{scope}[yshift=-\stepoffset,xshift=#6]
\noexpand\node[stepnode={BOT\thestepnum}{botrec}{north west},yshift=-\mvstep]
{%content
\noexpand\mkstep{#2}[#3]{#5}% Does the work of formatting the step
};
\noexpand\end{scope}
\noexpand\draw[connector] (BOT\thestepnum.north) --
++(0,8pt) -|
($(ST)!{(\FROM-\startrec)/\tlndur}!(ET)$); %% draw connector
\ifx\empty\TO \else %% draw completion arrow if \TO exists
\noexpand\begin{scope}[on background layer]
\noexpand\draw[endshow](BOT\thestepnum) --
(BOT\thestepnum -| H\TO);
\noexpand\end{scope}
\fi
\noexpand\node[stnum]
at (BOT\thestepnum.north west){\thestepnum};
\else % above the timeline
\noexpand\begin{scope}[yshift=\stepoffset,xshift=#6]
\noexpand\node[stepnode={TOP\thestepnum}{toprec}{south west},yshift=\mvstep]
{%content
\noexpand\mkstep{#2}[#3]{#5}% Does the work of formatting the step
};
\noexpand\end{scope}
\noexpand\draw[connector] (TOP\thestepnum.south) --
++(0,-8pt) -|
($(ST)!{(\FROM-\startrec)/\tlndur}!(ET)$); %% draw connector
\ifx\empty\TO \else %% draw completion arrow if \TO exists
\noexpand\begin{scope}[on background layer]
\noexpand\draw[endshow](TOP\thestepnum) --
(TOP\thestepnum -| H\TO);
\noexpand\end{scope}
\fi
\noexpand\node[stnum]at (TOP\thestepnum.north west){\thestepnum};
\fi
}%
}\foo
\botrecfalse
}
%% |=====8><-----| %%
\parindent0pt
\begin{document}
\small
\thispagestyle{empty}
\begin{recipe}[dominipg,tlnwidth=7in]{Testing Timeline}{7}{16}
\step{Here is a step with absolutely no ingredients whatsoever that should finish up around noon or so.}{8-12}[2in]
\step{Mix it up and serve it forth at one o'clock.}[*1 cup extra virgin olive oil;2 tsp. henbane;3 cups vinegar]{10-13}
\step[Bot]{bla}[a;*b;c]{11}[1.25in]
\step[Bot]{more bla\par bla bla that just might be excessive}{11.75-13}[1.5in]
\step[Bot]{yada yada yada}{14-15}
\end{recipe}
\begin{recipe}[recipecolor=orange,tlnwidth=9.5in,mvstep=3pt,stepoffset=18pt,nodedist=18pt]{Testing Timeline II}{7}{16}
\step{blablabla which might go on and on for an useemly time\dots}{8-12}[1in]
\step{more bla bla bla}[*1 cup extra virgin olive oil;2;3]{10}
\step[Bot]{blablabla}[a;*b;c]{11}[3.5in]<2in>
\step[Bot]{more bla\endgraf bla bla which could go on and on seemingly forever, and on and on and on ad infinitum}{11.25-13}[1in]
\step[Top]{$A=\pi r^2$ \par more bla\par bla bla}[*1 cup extra virgin olive oil;2;3]{14}
\step[Bot]{Open the Champagne!}{16}
\end{recipe}
\end{document}
Chains: two `TikZ` `chain`s are used to place the steps; the distance between the chain elements is controlled by an option to `recipe`, `nodedist`.
The `recipe` environment takes 4 arguments:
#1 (optional) keyval options:
dominipg: use minipage instead of varwidth
nocolor: turns off random coloring of steps, uses recipecolor
nocolorcolor: if specified and nocolor is in effect, specifies the color
to use instead of recipecolor
recipecolor: main recipe color
tlnwidth: width of timeline, if not set, defaults to \textwidth
mvstep: small vertical offset to avoid connector line colisions
stepoffset: distance from timeline to first connector bend
nodedist: horizontal distance between steps, sets for *all* steps
#2 the title of the timeline
#3 the start of the time line (in 24-hour decimal format)
#4 the end of the time line (in 24-hour decimal format)
The `\step` macro takes 6 arguments:
#1 keyval, optional: `Top` (default) for above the timeline, `Bot` for below.
#2 required, method: text of the method, can have implicit or explicit `\par`s
#3 optional, ingredients in a ;-separated list
#4 required, start<-end>: A single digit will show only the start time; two digits with a hyphen (e.g., 3-5) will show `3` as the start, with a barred rule showing the duration at `5`.
#5 [step width] optional; if not given will use default.
#6 The sixth argument (optional) to `\step` (`<...>`) (+ right, - left), works, but only once for the two layers of steps - above and below the timeline. Given as a dimension.
Step numbers are shown at the upper left of the step boxes, and reflect the order in which the steps were input.
The `Top` and `Bot` options to the `\step` macro: `Top` is the default, and is optional at the start of input.