2

I'm trying to make a little style package to make some nice blocks with icons and so on. I'm using environ package + tikz. Actually the document compiles and shows me my boxes but with errors saying that some environments are not closed.

I created a "iconbox" environment with environ package that accepts some arguments (title, icon, colors...) and I want to use it to generalize some boxes: info box, danger box...

The problem begins when I want to create a new environment that uses the iconbox I've created.

If I want to use \NewEnviron that calls another one, LaTeX crashes in recursion.

If I use the legacy newenvironment so LaTeX says that I didn't close the iconbox block.

And of course, I tried \beginiconbox and \endiconbox in start and end block but it doesn't work.

Here is a "copy/paste" that should give you the problem

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[francais]{babel}
\usepackage[T1]{fontenc}
\usepackage{xcolor}
\usepackage[tikz]{bclogo}
\usepackage[framemethod=tikz]{mdframed}
\usepackage{environ} % NewEnviron
\usepackage{fontawesome} % font awesome icons
%Options: Sonny, Lenny, Glenn, Conny, Rejne, Bjarne, Bjornstrup
\usepackage[Sonny]{fncychap}

\usepackage{tikz}
\usetikzlibrary{babel}
\usetikzlibrary{shadows.blur}

\usepackage{color}
\usepackage{pbsi} % for handwriting
\usepackage{bera}

\definecolor{m3dorange}{HTML}{ff9966}
\definecolor{m3dred}{HTML}{c9453e}
\definecolor{m3dgreen}{HTML}{4f9c45}
\definecolor{m3dblue}{HTML}{2499d0}

% title, icon, color, title color
\NewEnviron{iconbox}[4]{%
    \begin{center}
        \begin{tikzpicture}
        \node [
            top color=#3!10,
            bottom color = white,
            inner sep=2em,
            rounded corners=1em,
            draw=#3!60,
            inner sep=1.2em,
            text width=\textwidth*.7,
            drop shadow = {opacity=.4},
            shadow yshift = -4,
            shadow xshift = 4,
            font=\par\itshape
        ] (frame) at (0, 0)  {\hspace{1.5em}\textbf{\bsifamily{\centering\Large\textcolor{#4}{#1}}}\vspace{.8em}\par\BODY};%
        \node [
            shape=circle,
            top color=#4!90,
            bottom color=white!50,
            color=white,
            circular drop shadow={opacity = .7},
            font=\Huge,
            inner sep=6pt] at (frame.north west) {\centering\textbf{#2}};
        \end{tikzpicture}
    \end{center}
}

\newenvironment{danger}[1]
    {\begin{iconbox}{#1}{\faExclamation}{m3dorange}{red}}
    {\end{iconbox}}
\newenvironment{success}[1]
    {\begin{iconbox}{#1}{\faStickyNoteO}{m3dgreen}{m3dgreen}}
    {\end{iconbox}}
\newenvironment{info}[1]
    {\begin{iconbox}{#1}{\faBookmark}{m3dblue}{m3dblue}}
    {\end{iconbox}}

\begin{document}
\begin{danger}{Warning}
You do it wrong.
\end{danger}
\end{document}

It generates that kind of box:

enter image description here

But... with errors...

So, how can I do ?

Thanks a lot.

5
  • 1
    Is there any reason why you are not using tcolorbox?
    – user121799
    Commented Feb 12, 2019 at 1:40
  • @matmot Yes, the fact is that I want to draw nodes, place element exactly where I want, and so on - I will add a preview (I don't know how you do that here, except by using a screenshot)
    – Metal3d
    Commented Feb 12, 2019 at 1:42
  • AFAIK tcolorbox does not forbid you doing this.
    – user121799
    Commented Feb 12, 2019 at 1:43
  • Take a look on the picture I've just added, this is what I expect to do. Actually the problem is not the drawing, the problem is "how to use environ package in nested environments" ;)
    – Metal3d
    Commented Feb 12, 2019 at 1:46
  • +1 for the beautiful picture. ;-) (it is clear what happens, the iconbox environment does not "see" the closing \end{iconbox} because it is replaced by \end{danger} which would expand to \end{iconbox}. I am sure there are posts on this...)
    – user121799
    Commented Feb 12, 2019 at 2:17

2 Answers 2

1

This seems to work...

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[francais]{babel}
\usepackage[T1]{fontenc}
\usepackage{xcolor}
\usepackage[tikz]{bclogo}
\usepackage[framemethod=tikz]{mdframed}
\usepackage{environ} % NewEnviron
\usepackage{fontawesome} % font awesome icons
%Options: Sonny, Lenny, Glenn, Conny, Rejne, Bjarne, Bjornstrup
\usepackage[Sonny]{fncychap}

\usepackage{tikz}
\usetikzlibrary{babel}
\usetikzlibrary{shadows.blur}

\usepackage{color}
\usepackage{pbsi} % for handwriting
\usepackage{bera}

\definecolor{m3dorange}{HTML}{ff9966}
\definecolor{m3dred}{HTML}{c9453e}
\definecolor{m3dgreen}{HTML}{4f9c45}
\definecolor{m3dblue}{HTML}{2499d0}

% title, icon, color, title color
\NewEnviron{iconbox}[4]{%
    \begin{center}
        \begin{tikzpicture}
        \node [
            top color=#3!10,
            bottom color = white,
            inner sep=2em,
            rounded corners=1em,
            draw=#3!60,
            inner sep=1.2em,
            text width=\textwidth*.7,
            drop shadow = {opacity=.4},
            shadow yshift = -4,
            shadow xshift = 4,
            font=\par\itshape
        ] (frame) at (0, 0)  {\hspace{1.5em}\textbf{\bsifamily{\centering\Large\textcolor{#4}{#1}}}\vspace{.8em}\par\BODY};%
        \node [
            shape=circle,
            top color=#4!90,
            bottom color=white!50,
            color=white,
            circular drop shadow={opacity = .7},
            font=\Huge,
            inner sep=6pt] at (frame.north west) {\centering\textbf{#2}};
        \end{tikzpicture}
    \end{center}
}

\NewEnviron{danger}[1]
    {\let\oldBODY\BODY
    \def\BODY{\empty}
    \begin{iconbox}{#1}{\faExclamation}{m3dorange}{red}
    \oldBODY
    \end{iconbox}}
\NewEnviron{success}[1]
    {\let\oldBODY\BODY
    \def\BODY{\empty}
    \begin{iconbox}{#1}{\faStickyNoteO}{m3dgreen}{m3dgreen}
    \oldBODY
    \end{iconbox}}
\NewEnviron{info}[1]
    {\let\oldBODY\BODY
    \def\BODY{\empty}
    \begin{iconbox}{#1}{\faBookmark}{m3dblue}{m3dblue}
    \oldBODY
    \end{iconbox}}

\begin{document}
\begin{danger}{Warning}
You do it wrong.
\end{danger}

\begin{info}{Yes}
I agree. I tried to improve.
\end{info}

\begin{success}{;-)}
This seems to work.
\end{success}
\end{document}

enter image description here

6
  • As I said, it works but you have errors in the output logs, right ?
    – Metal3d
    Commented Feb 12, 2019 at 2:27
  • Wow sorry. You have forget to put \BODY in the danger block. So you only have the title. Put the body and you'll have a recursion.
    – Metal3d
    Commented Feb 12, 2019 at 2:30
  • @Metal3d You're right. Apologies! I added a hopefully better version.
    – user121799
    Commented Feb 12, 2019 at 4:54
  • This is the solution ! Thanks a lot. The problem was the \BODY that seems to be interpreted in a infinite loop. Setting a temporary variable fixed the problem. Maybe you can edit the solution to explain a bit more, but really: Thanks a lot !
    – Metal3d
    Commented Feb 12, 2019 at 10:05
  • Note: right, my question was answered in another question, but I didn't find it... maybe bad keywords... ;)
    – Metal3d
    Commented Feb 12, 2019 at 10:10
2

Pass the outer body as argument:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[francais]{babel}
\usepackage[T1]{fontenc}
\usepackage{xcolor}
\usepackage[tikz]{bclogo}
\usepackage[framemethod=tikz]{mdframed}
\usepackage{environ} % NewEnviron
\usepackage{fontawesome} % font awesome icons
%Options: Sonny, Lenny, Glenn, Conny, Rejne, Bjarne, Bjornstrup
\usepackage[Sonny]{fncychap}

\usepackage{tikz}
\usetikzlibrary{babel}
\usetikzlibrary{shadows.blur}

\usepackage{color}
\usepackage{pbsi} % for handwriting
\usepackage{bera}

\definecolor{m3dorange}{HTML}{ff9966}
\definecolor{m3dred}{HTML}{c9453e}
\definecolor{m3dgreen}{HTML}{4f9c45}
\definecolor{m3dblue}{HTML}{2499d0}

% title, icon, color, title color
\newenvironment{iconbox}[5]{%
    \begin{center}
        \begin{tikzpicture}
        \node [
            top color=#3!10,
            bottom color = white,
            inner sep=2em,
            rounded corners=1em,
            draw=#3!60,
            inner sep=1.2em,
            text width=\textwidth*.7,
            drop shadow = {opacity=.4},
            shadow yshift = -4,
            shadow xshift = 4,
            font=\par\itshape
        ] (frame) at (0, 0)  {\hspace{1.5em}\textbf{\bsifamily{\centering\Large\textcolor{#4}{#1}}}\vspace{.8em}\par\BODY};%
        \node [
            shape=circle,
            top color=#4!90,
            bottom color=white!50,
            color=white,
            circular drop shadow={opacity = .7},
            font=\Huge,
            inner sep=6pt] at (frame.north west) {\centering\textbf{#2}};
        \end{tikzpicture}
    \end{center}
}

\NewEnviron{danger}[1]
    {\begin{iconbox}{#1}{\faExclamation}{m3dorange}{red}{\BODY}\end{iconbox}}

\NewEnviron{success}[1]
    {\begin{iconbox}{#1}{\faStickyNoteO}{m3dgreen}{m3dgreen}{\BODY}\end{iconbox}}

\NewEnviron{info}[1]
    {\begin{iconbox}{#1}{\faBookmark}{m3dblue}{m3dblue}{\BODY}\end{iconbox}}

\begin{document}
\begin{danger}{Warning}
You do it wrong.
\end{danger}
\end{document}
3
  • As explained, \BODY make an infinite loop and interpretation is not ok. I already tried that (as I said in my question) - the solution is the @matmot answer that is to create a temporary variable to store old \BODY, thanks
    – Metal3d
    Commented Feb 12, 2019 at 10:07
  • 1
    I tested my example and it doesn't run in a loop. Be aware that in my code only the outer enviroment uses \NewEnviron, the inner is a normal environment. Commented Feb 12, 2019 at 10:15
  • ho sorry, right ! Yes that could be a solution so. I didn't realize that \BODY can be "used" in a \newenvironement as we are calling that one from \NewEnviron, it's a nice solution. The only problem is that "iconbox" cannot be called directly without to make a \NewEnviron - but as this block is a base env, why not. Sorry to not have correctly checked what you did.
    – Metal3d
    Commented Feb 12, 2019 at 10:22

Not the answer you're looking for? Browse other questions tagged .