4

so I have this:

\newcommand{\boxx}[2]{
    \colorbox{white}{\begin{varwidth}{\textwidth}
        % Heading
        \colorbox{green!30}{#1}\\
        % Content
        \fcolorbox{green}{yellow}{\begin{varwidth}{\textwidth}
            #2
        \end{varwidth}}
    \end{varwidth}}
}

Using it looks like this:

\boxx{Heading}{Some \\ fancy \\ content}

I'd like to create a 3th and 4th argument for the border color of my fcolorboy and the backgroundcolor.

So that I can do e.g.:

\boxx{Heading}{Some \\ fancy \\ content}{green}
\boxx{Heading}{Some \\ fancy \\ content}{}{yellow}
\boxx{Heading}{Some \\ fancy \\ content}{blue}{red}

so basically:

 \newcommand{\boxx}[4]{
    % Do something to set #3, #4 a default value
    \colorbox{white}{\begin{varwidth}{\textwidth}
        % Heading
        \colorbox{green!30}{#1}\\
        % Content
        \fcolorbox{#3}{#4}{\begin{varwidth}{\textwidth}
            #2
        \end{varwidth}}
    \end{varwidth}}
}
koleygr
  • 20,105
xotix
  • 266
  • 1
    It's straightforward to set up LaTeX macros with 1 optional argument. (In such macros, the optional argument must come at the beginning, not the end.) I don't think it's possible -- at least not via \newcommand -- to set up a 4-argument macro, of which 2 are optional. – Mico Mar 08 '18 at 11:57
  • Look at xparse, e.g. https://tex.stackexchange.com/a/29975/ – Torbjørn T. Mar 08 '18 at 12:09
  • @xitx, It looks like you have 3 great answers and haven't selected one yet? – PatrickT Mar 10 '18 at 01:06
  • 1
    yeah I was very busy at work, so I had to take my time to look at them all. :) I'm always astouned about the responses on here. – xotix Mar 10 '18 at 13:03

3 Answers3

4

Something like a solution using pgffor and some ifs:

\documentclass{article}
\usepackage{varwidth}
\usepackage{xcolor}
\usepackage{pgffor}
\newcommand{\boxx}[3][red,brown]{
  \global\expandafter\let\csname mycol 0\endcsname\undefined
  \global\expandafter\let\csname mycol 1\endcsname\undefined
  \foreach \col[count=\i from 0] in {#1}{\global\expandafter\let\csname mycol \i\endcsname\col}
  \xdef\myfirst{red}
  \xdef\mysecond{brown}
  \ifcsname mycol 0\endcsname\xdef\myfirst{\csname mycol 0\endcsname}\fi
  \ifcsname mycol 1\endcsname\xdef\mysecond{\csname mycol 1\endcsname}\fi
    % Do something to set #3, #4 a default value
    \colorbox{white}{\begin{varwidth}{\textwidth}
        % Heading
        \colorbox{green!30}{#2}\\
        % Content
        \fcolorbox{\myfirst}{\mysecond}{\begin{varwidth}{\textwidth}
            #3
        \end{varwidth}}
    \end{varwidth}}
}
\begin{document}
\boxx[green]{Heading}{Some \\ fancy \\ content}
\boxx[blue,red]{Heading}{Some \\ fancy \\ content}
\boxx[yellow,gray]{Heading}{Some \\ fancy \\ content}
\end{document}

Output:

enter image description here

koleygr
  • 20,105
  • Optional parameter means that can be missing too, and in this case the default colors will be used. (Forgot to run it without parameter) – koleygr Mar 08 '18 at 12:52
3

The following example defines two keys - border and fill, which can be specified in any order. The use of keys provides a contextual reference as to what is set and with what colour.

enter image description here

\documentclass{article}

\usepackage{varwidth,xcolor,xkeyval}

\makeatletter
\define@cmdkey{boxx}[boxx@]{border}{}
\define@cmdkey{boxx}[boxx@]{fill}{}

% \boxx[<options>]{<heading>}{<content>}
\newcommand{\boxx}[3][]{
  \setkeys{boxx}{
    border = yellow, fill = brown, % default settings
    #1} % local changes to default
  \noindent
  \colorbox{white}{\begin{varwidth}{\textwidth}
    % Heading
    \colorbox{green!30}{#2} \\
    % Content
    \fcolorbox{\boxx@border}{\boxx@fill}{\begin{varwidth}{\textwidth}
      #3
    \end{varwidth}}%
  \end{varwidth}}
}
\makeatother

\begin{document}

\boxx[border = green]{Heading}{Some \\ fancy \\ content}
\boxx[border = blue, fill = red]{Heading}{Some \\ fancy \\ content}
\boxx[fill = gray, border = yellow]{Heading}{Some \\ fancy \\ content}

\end{document}

The defaults (border = yellow and fill = brown) are set before it is changed to whatever is specified with the optional argument to \boxx[<options>]{<heading>}{<content>}.

Werner
  • 603,163
2

With this approach, one can omit both, the second or the first optional paramater.

enter image description here

\documentclass{article}
\usepackage{varwidth}
\usepackage{xcolor}
\usepackage{pgffor}

\usepackage{xstring}
\newcommand{\boxx}[3][]{
\StrCut{#1}{,}{\myfirst}{\mysecond}
\IfEq{\myfirst}{}{\def\myfirst{red}}{}      % first default
\IfEq{\mysecond}{}{\def\mysecond{brown}}{}  % second default
    \colorbox{white}{\begin{varwidth}{\textwidth}
        % Heading
        \colorbox{green!30}{#2}\\
        % Content
        \fcolorbox{\myfirst}{\mysecond}{\begin{varwidth}{\textwidth}
            #3
        \end{varwidth}}
    \end{varwidth}}
}
\begin{document}
\boxx[]{Heading}{Some \\ fancy \\ content}
\boxx[green]{Heading}{Some \\ fancy \\ content}
\boxx[,green]{Heading}{Some \\ fancy \\ content}
\boxx[blue,red]{Heading}{Some \\ fancy \\ content}
\boxx[yellow,gray]{Heading}{Some \\ fancy \\ content}
\end{document}
Tarass
  • 16,912