% ====================================================================== % callout-itembox.sty -- colored callout boxes with bullet/numbered marker % v1.0 % % Two content layouts: % \callout [] {}{} -- heading + body % \callout*[] {} -- body only, no heading % % Built-in themes: blue (default), red, teal, green, purple, orange, slate % Marker: dot (default white circle) | number= | number=,vertical % Corners: corners=sharp (default) | corners=rounded | arc= % Shadow: shadow=off (default) | shadow=on % Custom colours: barcolor=, bgcolor=, headcolor= (any xcolor expression) % % Examples: % \callout{Primary Objective}{To establish a correlation ...} % \callout[theme=red]{Warning}{Do not proceed ...} % \callout[number=1]{Step one}{First do this ...} % \callout*[theme=red]{All parameters recorded post-op ...} % \callout*[theme=blue,number=2]{Body text only, numbered ...} % % Copyright (C) 2026 % Released under the MIT License (see the LICENSE file). % Project home: https://github.com//callout-itembox % ====================================================================== \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{callout-itembox}[2026/06/07 v1.2 colored callout boxes] \RequirePackage{xparse} \RequirePackage{xcolor} \RequirePackage{tikz} \RequirePackage{tcolorbox} \tcbuselibrary{skins,breakable} \usetikzlibrary{calc} % ---------------------------------------------------------------- colors \definecolor{callout@blue@bar} {RGB}{1,32,96} \definecolor{callout@blue@bg} {RGB}{234,237,242} \definecolor{callout@blue@head}{RGB}{1,32,96} \definecolor{callout@red@bar} {RGB}{192,0,0} \definecolor{callout@red@bg} {RGB}{252,238,232} \definecolor{callout@red@head} {RGB}{192,0,0} \colorlet{callout@teal@bar} {teal!70!black} \colorlet{callout@teal@bg} {teal!8} \colorlet{callout@teal@head}{teal!60!black} \definecolor{callout@green@bar} {HTML}{1B5E20} \definecolor{callout@green@bg} {HTML}{E8F0E9} \definecolor{callout@green@head}{HTML}{1B5E20} \colorlet{callout@purple@bar} {purple!75!black} \colorlet{callout@purple@bg} {purple!8} \colorlet{callout@purple@head}{purple!70!black} \colorlet{callout@orange@bar} {orange!85!black} \colorlet{callout@orange@bg} {orange!13} \colorlet{callout@orange@head}{orange!70!black} \definecolor{callout@slate@bar} {HTML}{37474F} \definecolor{callout@slate@bg} {HTML}{ECEFF1} \definecolor{callout@slate@head}{HTML}{263238} % colors actually used (set by theme / overridden by custom keys) \colorlet{callout@bar} {callout@blue@bar} \colorlet{callout@bg} {callout@blue@bg} \colorlet{callout@head}{callout@blue@head} % ---------------------------------------------------------------- lengths \newlength{\callout@barwd} \setlength{\callout@barwd}{0.95cm} % width of colored bar \newlength{\callout@gap} \setlength{\callout@gap}{0.2cm} % gap bar -> text \newlength{\callout@rad} \setlength{\callout@rad}{4.6pt} % marker radius \newlength{\callout@arc} \setlength{\callout@arc}{0pt} % corner radius (0 = sharp) % ---------------------------------------------------------------- keys \newif\ifcallout@number \callout@numberfalse \newif\ifcallout@shadow \callout@shadowfalse \newif\ifcallout@vert \callout@vertfalse \def\callout@num{1} % apply a named theme by copying its three colors into the active ones \newcommand{\callout@settheme}[1]{% \colorlet{callout@bar}{callout@#1@bar}% \colorlet{callout@bg}{callout@#1@bg}% \colorlet{callout@head}{callout@#1@head}} \pgfkeys{ /callout/.is family, /callout/.cd, theme/.is choice, theme/blue/.code = {\callout@settheme{blue}}, theme/red/.code = {\callout@settheme{red}}, theme/teal/.code = {\callout@settheme{teal}}, theme/green/.code = {\callout@settheme{green}}, theme/purple/.code = {\callout@settheme{purple}}, theme/orange/.code = {\callout@settheme{orange}}, theme/slate/.code = {\callout@settheme{slate}}, number/.code = {\callout@numbertrue\def\callout@num{#1}}, % vertical (rotated) number marker vertical/.is choice, vertical/on/.code = {\callout@verttrue}, vertical/off/.code = {\callout@vertfalse}, vertical/true/.code = {\callout@verttrue}, vertical/false/.code = {\callout@vertfalse}, vertical/.default = on, % corner style corners/.is choice, corners/sharp/.code = {\setlength{\callout@arc}{0pt}}, corners/rounded/.code = {\setlength{\callout@arc}{4pt}}, arc/.code = {\setlength{\callout@arc}{#1}}, % drop shadow shadow/.is choice, shadow/on/.code = {\callout@shadowtrue}, shadow/off/.code = {\callout@shadowfalse}, shadow/true/.code = {\callout@shadowtrue}, shadow/false/.code = {\callout@shadowfalse}, shadow/.default = on, % custom colour overrides (optional) barcolor/.code = {\colorlet{callout@bar}{#1}}, bgcolor/.code = {\colorlet{callout@bg}{#1}}, headcolor/.code = {\colorlet{callout@head}{#1}}, % geometry overrides (optional) barwidth/.code = {\setlength{\callout@barwd}{#1}}, gap/.code = {\setlength{\callout@gap}{#1}}, } % ------------------------------------------------------------ internal box % #1 = key/value options #2 = heading (may be empty) #3 = body \newcommand{\callout@build}[3]{% % reset to defaults each call, then apply user keys \callout@numberfalse \def\callout@num{1}\setlength{\callout@arc}{0pt}\callout@shadowfalse\callout@vertfalse% \pgfkeys{/callout/.cd, theme=blue}% \pgfkeys{/callout/.cd, #1}% % decide shadow as a style (kept out of the option list so the comma % inside the shadow spec does not break key parsing) \ifcallout@shadow \tcbset{callout@shadowstyle/.style={drop fuzzy shadow={black!45}}}% \else \tcbset{callout@shadowstyle/.style={}}% \fi \begin{tcolorbox}[ enhanced, breakable, arc=\callout@arc, outer arc=\callout@arc, boxrule=0pt, frame hidden, colback=callout@bg, left=\dimexpr\callout@barwd+\callout@gap\relax, right=5pt, top=4pt, bottom=4pt, before skip=4pt, after skip=4pt, callout@shadowstyle, overlay={% % clip to the (possibly rounded) box outline so the bar follows the corners \begin{scope} \clip[rounded corners=\callout@arc] (frame.south west) rectangle (frame.north east); \fill[callout@bar] (frame.north west) rectangle ([xshift=\callout@barwd]frame.south west); \end{scope} % marker, vertically centered on the bar \ifcallout@number \ifcallout@vert \node[anchor=center, white, font=\bfseries\large, rotate=90] at ([xshift=0.5\callout@barwd]frame.west) {\callout@num}; \else \node[anchor=center, white, font=\bfseries\large] at ([xshift=0.5\callout@barwd]frame.west) {\callout@num}; \fi \else \fill[white] ([xshift=0.5\callout@barwd]frame.west) circle[radius=\callout@rad]; \fi }, ] \callout@maybehead{#2}#3% \end{tcolorbox}% } % print heading only when non-empty \newcommand{\callout@maybehead}[1]{% \begingroup\edef\callout@tmp{#1}% \ifx\callout@tmp\empty\else {\normalfont\bfseries\large\color{callout@head}#1\par\nobreak\vspace{2pt}}% \fi\endgroup} % ------------------------------------------------------------ public macro % star -> body only \callout*[keys]{body} % plain -> heading + body \callout[keys]{heading}{body} \NewDocumentCommand{\callout}{ s O{} m G{\NoValue} }{% \IfBooleanTF{#1} {\callout@build{#2}{}{#3}}% starred: #3 = body {\IfNoValueTF{#4} {\callout@build{#2}{}{#3}}% only one arg given -> treat as body {\callout@build{#2}{#3}{#4}}}% heading + body } \endinput