Create a custom numbered list with little balls and gray rectangle (also with the shadows)
See ADDENDUM for OP's follow-on.
EDITED to make a separate environment, benumerate
.
Here, inside the benumerate
environment, the optional argument to \item
indicates the difficulty level.
Here is a brief description of what the new/revised macros do, since they may require some alteration if fonts are changed, as desired by the OP.
\difbox
: creates the "difficulty-box" under the item number. The size and color of the gray box are provided by a \rule
and \color
macro. It calls on \makeballs
to set the proper number of circles in the gray box.
\makeballs
: the recursive macro that places a set of sequential \bullet
s as the circles in the box.
benumerate
: the environment that accomplishes all this, by redefining a few things and calling on enumerate
.
\item
: inside benumerate
, \item
is redefined to take the difficulty level as the optional argument (default 1
), which it saves before calling on the usual \item
.
\labelenumi
: the label redefinition inside benumerate
, which stacks the \difbox
1pt
below the enumeration label (which has been set in bold, sans font of an altered color).
EDITED to \smash
the \labelenumi
, since the low-hanging box was affecting line spacing of the item content.
\documentclass{article}
\usepackage{stackengine,xcolor,lipsum}
\let\svitem\item
\newcommand\difbox[1]{\stackengine{0pt}{\color{gray!30}\rule{5ex}{1.15ex}}{%
\color{cyan!60!black}$\mkern1mu\makeballs{#1}$}{O}{c}{F}{F}{L}}
\def\makeballs#1{\ifnum#1>0\relax{\bullet}%
\expandafter\makeballs\the\numexpr#1-1\relax\fi}
\newenvironment{benumerate}
{\renewcommand\item[1][1]{\def\difficulty{##1}\svitem}%
\def\labelenumi{\smash{\stackunder[1pt]{\color{cyan!60!black}%
\bfseries\sffamily\theenumi}{\difbox{\difficulty}}}}%
\enumerate}{\endenumerate}
\begin{document}
\begin{benumerate}
\setcounter{enumi}{32}
\item[2] \lipsum[4]
\item[3] \lipsum[4]
\item[4] \lipsum[3]
\end{benumerate}
\end{document}
ADDENDUM
To handle the OP's follow on extension request, the solution is trivial. After the invocation of \makeballs{#1}
in the difbox
macro, add \textcolor{red}{\makeballs{\the\numexpr4-#1\relax}}
.
\documentclass{article}
\usepackage{stackengine,xcolor,lipsum}
\let\svitem\item
\newcommand\difbox[1]{\stackengine{0pt}{\color{gray!30}\rule{5ex}{1.15ex}}{%
\color{cyan!60!black}$\mkern1mu\makeballs{#1}%
\textcolor{red}{\makeballs{\the\numexpr4-#1\relax}}$}{O}{c}{F}{F}{L}}
\def\makeballs#1{\ifnum#1>0\relax{\bullet}%
\expandafter\makeballs\the\numexpr#1-1\relax\fi}
\newenvironment{benumerate}
{\renewcommand\item[1][1]{\def\difficulty{##1}\svitem}%
\def\labelenumi{\smash{\stackunder[1pt]{\color{cyan!60!black}%
\bfseries\sffamily\theenumi}{\difbox{\difficulty}}}}%
\enumerate}{\endenumerate}
\begin{document}
\begin{benumerate}
\setcounter{enumi}{32}
\item[2] \lipsum[4]
\item[3] \lipsum[4]
\item[4] \lipsum[3]
\end{benumerate}
\end{document}
Another implementation with tcolorbox
. Instead of an \item
inside an enumerate
environment, a new environment problem
will be used. This environment uses a mandatory parameter (difficulty 1 to 4) and an optional one to change particular formatting options in one or more problems.
\documentclass{article}
\usepackage[most]{tcolorbox}
\usepackage{lipsum}
\newtcolorbox[auto counter]{problem}[2][]{%
breakable,
blankest,
enhanced,
attach boxed title to top left={yshift=-\tcboxedtitleheight},
left=\tcboxedtitlewidth+1mm,
top=0pt,
colback=white,
fonttitle=\bfseries\sffamily,
coltitle={cyan!60!black},
colbacktitle=white,
colframe=white,
title=\thetcbcounter,
overlay unbroken and first={%
\node[fill=gray!30, inner sep=1pt, minimum width=\tcboxedtitlewidth,
outer sep=0pt, text=cyan!60!black, anchor=north] at (title.south)
{\foreach \i in {1,...,#2}{\if#2gt1{\,}\fi$\bullet$}};},
#1}
\begin{document}
\lipsum[1]
\begin{problem}{1}
\lipsum[2]
\end{problem}
\begin{problem}{4}
\lipsum[3]
\end{problem}
\begin{problem}{2}
\lipsum[4]
\end{problem}
\end{document}
ADDENDUM
In this case, four balls are placed below the title and their color is decided with a conditional.
\documentclass{article}
\usepackage[most]{tcolorbox}
\usepackage{lipsum}
\newtcolorbox[auto counter]{problem}[2][]{%
breakable,
blankest,
enhanced,
attach boxed title to top left={yshift=-\tcboxedtitleheight},
left=\tcboxedtitlewidth+2mm,
top=0pt,
colback=white,
fonttitle=\bfseries\sffamily,
coltitle={cyan!60!black},
colbacktitle=white,
colframe=white,
title=\thetcbcounter,
overlay unbroken and first={%
\node[fill=gray!30, inner sep=1pt,
minimum width=\tcboxedtitlewidth,
outer sep=0pt,
anchor=north] at (title.south) {%
\foreach \i in {1,...,4}{%
\ifnum\i>#2%
\,\textcolor{cyan!60!black}{$\bullet$}%
\else
\,\textcolor{red}{$\bullet$}%
\fi}};},
#1}
\begin{document}
\lipsum[2]
\begin{problem}{1}
\lipsum[2]
\end{problem}
\begin{problem}{2}
\lipsum[2]
\end{problem}
\begin{problem}{3}
\lipsum[2]
\end{problem}
\begin{problem}{4}
\lipsum[2]
\end{problem}
\end{document}
Here is a third solution using a standard enumitem environment together with tikz.
The idea is to create a new enumerate
environment, which I have called questions
, and then use before=\fakeitem
to replace the standard \item
command in this environment with a new command that typesets the "difficulty dots". The "difficulty dots" are then drawn using a pics
construct inside a \tikz
call.
Here is the code:
\documentclass{article}
\usepackage{enumitem}
\usepackage{tikz}
\usepackage{lipsum}
\tikzset{pics/question/.style args={#1,#2}{
code={
\node[teal] at (0.5,0.35) {\textsf{#1}};
\fill[gray!30] (0.1,0) rectangle (0.9,0.2);
\foreach \ball [evaluate=\ball as \x using {0.5+(\ball-0.5-#2/2)*0.2)}] in {1,...,#2} {
\fill[teal] (\x,0.1) circle (2.5pt);
}
}
}
}
\let\realitem\item% save a copy of the \item command
\newcommand\fakeitem[1][\relax]{%
\refstepcounter{questionsi}% increment the counter
\realitem[\smash{\tikz[baseline]{\draw(0,-0.2) pic{question={\thequestionsi,#1}};}}]%
}
\newlist{questions}{enumerate}{1}% define a new enumerate environment
\setlist[questions]{ % set properties of the questions environment
label=\arabic*., % label format
leftmargin=*, % indent labels
before=\let\item\fakeitem, % change the \item command
resume, % continuous numbering
}
\begin{document}
\begin{questions}[start=32]
\item[2] \lipsum[4]
\item[3] \lipsum[4]
\item[4] \lipsum[3]
\end{questions}
\end{document}
and here is the output:
Addendum
I small tweak of the \fakeitem
macro answers the followup question in the post:
\documentclass{article}
\usepackage{enumitem}
\usepackage{tikz}
\usepackage{lipsum}
\tikzset{
pics/question/max/.initial = 5, % maximum number of balls
pics/question/.style args={#1,#2}{
code={
\node[teal] at (0.5,0.35) {\textsf{#1}};
\fill[gray!30] (0.1,0) rectangle (0.9,0.2);
\def\qmax{\pgfkeysvalueof{/tikz/pics/question/max}}
\foreach \ball [evaluate=\ball as \x using {0.1+(\ball-0.5)*0.8/\qmax}] in {1,...,\qmax} {
\fill[\ifnum\ball>#2 teal\else red\fi] (\x,0.1) circle (2.5pt);
}
}
}
}
\let\realitem\item% save a copy of the \item command
\newcommand\fakeitem[1][\relax]{%
\refstepcounter{questionsi}% increment the counter
\realitem[\smash{\tikz[baseline]{\draw(0,-0.2) pic{question={\thequestionsi,#1}};}}]%
}
\newlist{questions}{enumerate}{1}% define a new enumerate environment
\setlist[questions]{ % set properties of the questions environment
label=\arabic*., % label format
leftmargin=*, % indent labels
before=\let\item\fakeitem, % change the \item command
resume, % continuous numbering
}
\begin{document}
\begin{questions}[start=32]
\item[2] \lipsum[4]
\item[3] \lipsum[4]
\item[4] \lipsum[3]
\end{questions}
\end{document}
By default, 5 dots are printed for each question. This can be changed using, for example, \tikzset{pics/question/max=4}
to set it to 4 dots. In theory this could be arbitrary but in practice it should be in the range 2-5. Here is a sample of the new output: