# tcolorbox and tabularx - toprule and settings conflict

While transforming some tabularx tables into tcolorboxed ones I found that tcolorbox does many things which are not "authorized", but not to turn off. F.i. it changes the general rule color for the table and the arraystretch. Using a customized booktabs setup this really destructs consistency.

The main two issues I already mentioned. Therefore two questions (I haven't found any settings in the manual):

• How can one turn off the change of the rule color in a not-workaround way? Doing the change twice (once by tcolorbox and once by using before upper app) can't be a good solution.
• How can one turn off the change of the arraystretch? I haven't found any good solution. Do I really have to patch one of those internal tcolorbox macros?

And what would be very nice too:

• I do not want to change all tables concerning content. So I would really appreciate a workaround to be able to use a first line of the table starting with \toprule (currently results in errors and I use a tcolorbox rule).

To illustrate the problem:

MWE:

\documentclass{scrbook}
\usepackage{array,tabularx}
\usepackage[table]{xcolor}
\usepackage[most]{tcolorbox}
\usepackage{booktabs}

\renewcommand*{\arraystretch}{1.4}

\def\tabletitle#1{%
\refstepcounter{table}Table\ \thetable\ --\ #1%
}
\newtcolorbox{tablebox}[3][]{
enhanced, sharp corners=all,colback=white,colframe=white,tabularx={#2},title={\tabletitle{#3}},label=#1,attach boxed title to top right={xshift=1cm,yshift=-2mm},before upper app={\arrayrulecolor{black}}
}

\begin{document}

\begin{tabularx}{.5\linewidth}{lX}
\toprule \textbf{Stufe} & \textbf{Name}\\\midrule
-1 & Teil\\
0 & Kapitel\\
1 & Abschnitt\\
2 & Unterabschnitt\\
3 & Unterunterabschnitt\\
4 & Absatz\\
5 & Unterabsatz\\\bottomrule
\end{tabularx}
\captionof{table}{Test}

\begin{tablebox}{lX}{Test}
\textbf{Stufe} & \textbf{Name}\\\midrule%\toprule
-1 & Teil\\
0 & Kapitel\\
1 & Abschnitt\\
2 & Unterabschnitt\\
3 & Unterunterabschnitt\\
4 & Absatz\\
5 & Unterabsatz\\\bottomrule
\end{tablebox}
\end{document}


Update: The code that causes all those problems (options set by tabularx key):

boxsep=\z@,top=\z@,bottom=\z@,leftupper=\z@,rightupper=\z@,
toptitle=1mm,bottomtitle=1mm,boxrule=0.5mm,
before upper={\arrayrulecolor{tcbcol@frame}\def\arraystretch{1.1}#1%
\tcb@hack@currenvir\tabularx{\linewidth}{#2}},
after upper=\endtabularx\arrayrulecolor{black}},

• @ChristianHupfer No, that's one of the problems. Probably that's hooked anywhere in the before upper code, but even renewing in before upper app does not help. – TeXnician Jul 12 '17 at 14:20

You gave an answer yourself, but you also wrote that you do not think that your question is answered with it. I do not see, why not.

Anyway, since you asked for a less invasive way, I can give two alternatives. Both alternatives do not use tcolorbox for the top rule, but insert a \toprule where it does not hurt.

• tableboxA is quite similar to your own answer, but defines a mytablarx* instead of redefining tabularx*. Note \toprule\let\toprule\relax for my top rule alternative.

• tableboxB does not need a redefined tabularx* or a mytabularx* which both use some internal code. Array stretch and array rule color are set directly. In your question you expressed that defining the color twice is not a good solution... But, well, it is a solution and I figure it is not a bad solution either...

In my eyes, the only annoying thing is that \toprule cannot be used directly as one would expect. Here, we need a workaround like in your answer or in mine, but adjusting color and array stretch (even twice) is more or less harmless:

\documentclass{scrbook}
\usepackage[table]{xcolor}
\usepackage{booktabs}
\usepackage{array}
\usepackage{tabularx}
\usepackage[most]{tcolorbox}

\renewcommand{\arraystretch}{1.4}

\makeatletter
\tcbset{%
mytabularx*/.style 2 args={%
boxsep=\z@,top=\z@,bottom=\z@,leftupper=\z@,rightupper=\z@,
toptitle=1mm,bottomtitle=1mm,boxrule=0pt,
before upper={#1\tcb@hack@currenvir\tabularx{\linewidth}{#2}\toprule\let\toprule\relax},            % through deleting: solve the arraystretch and color issue
after upper=\endtabularx}
}
\makeatother

\newtcolorbox[use counter*=table]{tableboxA}[3][]{%
enhanced jigsaw, sharp corners=all, colback=white,colframe=black,
title={Table\ \thetable\ --\ #3},list text={#3},add to list={lot}{section},label=#1,
mytabularx*={}{#2},
attach boxed title to top right={xshift=1cm,yshift=2mm},
}

\newtcolorbox[use counter*=table]{tableboxB}[3][]{%
blank, sharp corners=all, colback=white,colframe=black,
title={Table\ \thetable\ --\ #3},list text={#3},add to list={lot}{section},label=#1,
tabularx*={\arrayrulecolor{black}\renewcommand{\arraystretch}{1.4}}{#2},
before upper app={\toprule\let\toprule\relax},
boxrule=0pt,
attach boxed title to top right={xshift=1cm,yshift=2mm},
}

\begin{document}

\captionof{table}{Test}
\begin{tabularx}{\linewidth}{lX}
\toprule \textbf{Stufe} & \textbf{Name}\\\midrule
-1 & Teil\\
0 & Kapitel\\
1 & Abschnitt\\
2 & Unterabschnitt\\
3 & Unterunterabschnitt\\
4 & Absatz\\
5 & Unterabsatz\\\bottomrule
\end{tabularx}

\vskip2\baselineskip

\begin{tableboxA}{lX}{Test}
\toprule \textbf{Stufe} & \textbf{Name}\\\midrule
-1 & Teil\\
0 & Kapitel\\
1 & Abschnitt\\
2 & Unterabschnitt\\
3 & Unterunterabschnitt\\
4 & Absatz\\
5 & Unterabsatz\\\bottomrule
\end{tableboxA}

\vskip2\baselineskip

\begin{tableboxB}{lX}{Test}
\toprule \textbf{Stufe} & \textbf{Name}\\\midrule
-1 & Teil\\
0 & Kapitel\\
1 & Abschnitt\\
2 & Unterabschnitt\\
3 & Unterunterabschnitt\\
4 & Absatz\\
5 & Unterabsatz\\\bottomrule
\end{tableboxB}

\end{document}

• I really like tableboxB. Probably I missed the typical configurable tcolorbox style with keys for nearly everything. – TeXnician Jul 17 '17 at 14:57
• @TeXnician Yes, the tabularx key is some kind of special application key which I added to the tcolorbox core, because of the \tcb@hack@currenvir trick. The color and arrayrule settings are coming from my own applications - possibly too specialized ... – Thomas F. Sturm Jul 18 '17 at 5:36
• Maybe that's an idea for the next update to be able to change that behavior (a key for document defaults would be sufficient I think). But that's up to you. – TeXnician Jul 18 '17 at 6:30

The following is a workaround (if anyone knows a less invasive way, please post it here). It does explicitly NOT solve the question. What it does:

• redefining the tabularx style to kick out every unwanted and unneeded piece of code and
• letting \toprule to \relax and then emulating the toprule with the box rules

Code:

\documentclass{scrbook}
\usepackage[table]{xcolor}
\usepackage{booktabs}
\usepackage{array}
\usepackage{tabularx}
\usepackage[most]{tcolorbox}

\renewcommand{\arraystretch}{1.4}

\makeatletter
\tcbset{%
tabularx*/.style 2 args={%
boxsep=\z@,top=\z@,bottom=\z@,leftupper=\z@,rightupper=\z@,
toptitle=1mm,bottomtitle=1mm,boxrule=0pt, toprule=1pt, top=2.25pt,        % "solve" toprule issue (i)
before upper={#1\tcb@hack@currenvir\tabularx{\linewidth}{#2}},            % through deleting: solve the arraystretch and color issue
before upper app = {\let\toprule\relax},                                  % "solve" toprule issue (ii)
after upper=\endtabularx}
}
\makeatother

\newtcolorbox[use counter*=table]{tablebox}[3][]{%
enhanced jigsaw, sharp corners=all, colback=white,colframe=black,
title={Table\ \thetable\ --\ #3},list text={#3},add to list={lot}{section},label=#1,
tabularx*={}{#2},
attach boxed title to top right={xshift=1cm,yshift=2mm},
}

\begin{document}

\captionof{table}{Test}
\begin{tabularx}{\linewidth}{lX}
\toprule \textbf{Stufe} & \textbf{Name}\\\midrule
-1 & Teil\\
0 & Kapitel\\
1 & Abschnitt\\
2 & Unterabschnitt\\
3 & Unterunterabschnitt\\
4 & Absatz\\
5 & Unterabsatz\\\bottomrule
\end{tabularx}

\vskip2\baselineskip

\begin{tablebox}{lX}{Test}
\toprule \textbf{Stufe} & \textbf{Name}\\\midrule
-1 & Teil\\
0 & Kapitel\\
1 & Abschnitt\\
2 & Unterabschnitt\\
3 & Unterunterabschnitt\\
4 & Absatz\\
5 & Unterabsatz\\\bottomrule
\end{tablebox}
\end{document}