How to Modify Fancy Table of Contents in TikZ

table of contentstikz-pgftitletoctocloft

I am creating a fancy ToC based on @pluton 's question How to customize the table of contents using TikZ?

Although this code works fine, it seems that it missbehaves when using an appendix. Instead of adding an entry Appendix A it adds Chapter A.

Also when adding an unumbered chapter, i'd rather not to have a Chapter as an entry but either a coloured box or nothing at all.

My code is

\documentclass[11pt,a4paper]{book}

\usepackage{tikz,pgf}
\usepackage{tocloft,titletoc,titlesec}
\definecolor{doc}{RGB}{0,60,110}
\definecolor{myblueii}{RGB}{63,200,244}
\usepackage{lipsum}

\contentsmargin{0cm}
\titlecontents{chapter}[0pc]
{\addvspace{30pt}%
\begin{tikzpicture}[remember picture, overlay]%
\draw[fill=myblueii,draw=myblueii, rounded corners] (-4,-.1) rectangle (-0.15,.5);%
\pgftext[left,x=-2.7cm,y=0.2cm]{\color{white}\Large \chaptertitlename\ \thecontentslabel};%
\end{tikzpicture}\color{myblueii}\large\bfseries}%
{}
{}
{\hspace*{6pt}\titlerule\hspace*{6pt}\large\bfseries \thecontentspage
\begin{tikzpicture}[remember picture, overlay]
\draw[fill=doc!25,draw=myblueii, rounded corners=0pt] (2pt,0) rectangle (6,0.1pt);
\end{tikzpicture}}%
\titlecontents{section}[2.4pc]
{\addvspace{1pt}}
{\contentslabel[\thecontentslabel]{2.4pc}}
{}
{\hfill\small \thecontentspage}
[]
\titlecontents{subsection}[4.8pc]
{\addvspace{1.0pt}}
{\contentslabel[\thecontentslabel]{2.4pc}}
{}
{\hfill\small\thecontentspage}
[]

\makeatletter
\renewcommand{\tableofcontents}{%
\chapter*{%
\vspace*{-20\p@}%
\begin{tikzpicture}[remember picture, overlay]%
\pgftext[right,x=15cm,y=0.2cm]{\color{myblueii}\Huge \contentsname};%
\draw[fill=myblueii,draw=myblueii, rounded corners=15pt] (13,-.75) rectangle (20,1);%
\clip (13,-.75) rectangle (20,1);
\pgftext[right,x=15cm,y=0.2cm]{\color{white}\Huge \contentsname};%
\end{tikzpicture}}%
\@starttoc{toc}}
\makeatother

\begin{document}
 \tableofcontents
 \chapter{First Chapter}
 \lipsum[1]
 \chapter{Second Chapter}
 \lipsum[1]
 \chapter{Third Chapter}
 \lipsum[1]
 \appendix
 \chapter{First Appendix Chapter}
 \lipsum[1]
 \chapter{Second Appendix Chapter}
 \lipsum[1]
 \chapter*{Chapter}
 \addcontentsline{toc}{chapter}{Chapter}
 \lipsum[1]
\end{document}

and my output is

enter image description here

Is there a way to achieve those two requirements?

Best Answer

I think that this is an oversight, or even a bug, in the way that the table of contents is generated.

Inside a latex file the \appendix command changes \@chapapp from \chaptername to \appendixname and this is used to get the right title in the chapter and appendix headings. Unfortunately, this information is NOT passed through to the table of contents file (toc). Currently, for example in book.cls, the entry for a chapter or appendix is written to the toc file via:

\addcontentsline{toc}{chapter}{\protect\numberline{\thechapter}#1}

This means that chapter and appendix entries in the toc file look exactly the same when the \tableofcontents is executed, so the toc file cannot differentiate between chapters and appendices (without some hacking). It would be better if there were also

\addcontentsline{toc}{appendix}{\protect\numberline{\thechapter}#1}

lines -- although you can not use \@chapapp to generate these lines because the value of \@hapapp is language dependent...so the code would not be as elegant:(

To get around this problem one solution is to replace the use of \chaptertitlename in Pluton's code with, say, \tocchaptername and then add the following code to the top of your file:

\let\tocchaptername\chaptertitlename
\let\originalAppendix\appendix
\renewcommand\appendix{\originalAppendix%
    \addtocontents{toc}{\let\string\tocchaptername\string\appendixname}%
 }

With this in place the appendices are labelled as the OP wants. (The use of \addtocontents is a hack to write some lines to the toc file without using \makeatletter\@writefile{toc}...\makeatother.)

enter image description here

Actually, the image above requires slightly more than what I have said so far. First, because "appendix" has one more character than "chapter" the spacing requires a small amount of additional tweaking. (To centre chapter and appendix these numbers need to be adjusted more carefully:)

More seriously, the use of \chapter* for the last "appendix" results in a blue "appendix" label, which is probably not what you want. It would be a pain to fix this properly (for example, to cope with the case where there are alternating \chapter{..} and \chapter*{...} commands in the document). Assuming that the OP wants empty labels from this point onwards (as in the image above), then you can just add the line

\addtocontents{toc}{\let\string\tocchaptername\string\relax}

before the \chapter*{} command. If some one wanted to alternate the use of starred and unstarred chapters/appendixes then they would need to type

\addtocontents{toc}{\let\string\tocchaptername\string\chaptertitlename}

to let the toc file know what is happening (using the obvious appendix variation in the appendices).

Here is the actual code that I used:

\documentclass[11pt,a4paper]{book}

\usepackage{tikz,pgf}
\usepackage{tocloft,titletoc,titlesec}
\definecolor{doc}{RGB}{0,60,110}
\definecolor{myblueii}{RGB}{63,200,244}
\usepackage{lipsum}

\let\tocchaptername\chaptertitlename
\let\originalAppendix\appendix
\renewcommand\appendix{\originalAppendix\addtocontents{toc}{\let\string\tocchaptername\string\appendixname}}

\contentsmargin{0cm}
\titlecontents{chapter}[0pc]
{\addvspace{30pt}%
\begin{tikzpicture}[remember picture, overlay]%
\draw[fill=myblueii,draw=myblueii, rounded corners] (-4,-.1) rectangle (0.10,.5);%
\pgftext[left,x=-2.7cm,y=0.2cm]{\color{white}\Large \tocchaptername\ \thecontentslabel};%
\end{tikzpicture}\color{myblueii}\large\bfseries\quad}%
{}
{}
{\hspace*{6pt}\titlerule\hspace*{6pt}\large\bfseries \thecontentspage
\begin{tikzpicture}[remember picture, overlay]
\draw[fill=doc!25,draw=myblueii, rounded corners=0pt] (2pt,0) rectangle (6,0.1pt);
\end{tikzpicture}}%
\titlecontents{section}[2.4pc]
{\addvspace{1pt}}
{\contentslabel[\thecontentslabel]{2.4pc}}
{}
{\hfill\small \thecontentspage}
[]
\titlecontents{subsection}[4.8pc]
{\addvspace{1.0pt}}
{\contentslabel[\thecontentslabel]{2.4pc}}
{}
{\hfill\small\thecontentspage}
[]

\makeatletter
\renewcommand{\tableofcontents}{%
\chapter*{%
\vspace*{-20\p@}%
\begin{tikzpicture}[remember picture, overlay]%
\pgftext[right,x=15cm,y=0.2cm]{\color{myblueii}\Huge \contentsname};%
\draw[fill=myblueii,draw=myblueii, rounded corners=15pt] (13,-.75) rectangle (20,1);%
\clip (13,-.75) rectangle (20,1);
\pgftext[right,x=15cm,y=0.2cm]{\color{white}\Huge \contentsname};%
\end{tikzpicture}}%
\@starttoc{toc}}
\makeatother

\begin{document}
 \tableofcontents
 \chapter{First Chapter}
 \lipsum[1]
 \chapter{Second Chapter}
 \lipsum[1]
 \chapter{Third Chapter}
 \lipsum[1]
 \appendix
 \chapter{First Appendix Chapter}
 \lipsum[1]
 \chapter{Second Appendix Chapter}
 \lipsum[1]
 \addtocontents{toc}{\let\string\tocchaptername\string\relax}
 \chapter*{Chapter}
 \addcontentsline{toc}{chapter}{Chapter}
 \lipsum[1]
\end{document}

Edit - unnumbered chapters

Finally, to answer your question in the comments, in order to get rid of the empty blue marker for unnumbered chapters replace the tikzpicture environment insde the \titlecontents{chapter} command above with the following variation (actually, I've improved the code a little at the same time):

\begin{tikzpicture}[remember picture, overlay]%
  \ifx\tocchaptername\relax\relax%
  \else%
    \draw(-0.15,0.15)node[anchor=east,align=center,fill=myblueii,text=white,rounded corners,
              rectangle, minimum width=8.5em]{\Large \tocchaptername\ \thecontentslabel};
  \fi%
\end{tikzpicture}\color{myblueii}\large\bfseries}%

Using this the output now looks like:

enter image description here

If there are going to be lots of unnumbered chapters/appendices inbetween numbered ones then you probably want to define a command like the following:

\newcommand\unnumberedchapter[1]{%
   \addtocontents{toc}{\let\string\tocchaptername\string\relax}%
   \chapter*{#1}%
   \addtocontents{toc}{\let\string\tocchaptername\string\chaptertitlename}%
}

Then you can just type \unnumberedchapter{Chapter title} when you need it.