Chat bubbles with picture and name attached

text-decorationstypography

I'd like to modify the code from (the improved version of the top voted answer of) this post to make the sequence of speech bubbles look more like a chat window. Specifically, I'd like to include a picture and name of the authors.

Ideally, the setup would allow for several speakers. For that reason, I'd like to give the name + picture + color as parameters to the bubble command itself.

For reference, I want something along these lines:

enter image description here

This was achieved after some tinkering with the code in the linked post, but it's still not exactly right, for a couple of reasons.

The first is that the alignment of the photo with the bubble looks strange when the text is only one or two lines (e.g., in the bottom bubble).

The second is that I'd like to use this in beamer slides for teaching, and for that I want the option of having bubbles uncovered sequentially, i.e., at slide 2, 3, etc. The current solution, which makes a new bubble out of every new paragraph, doesn't work so well with the beamer overlays: if I wrap Nash's second paragraph with \onslide<2>{}, what I get is the awkward result of an empty bubble on slide 1 and the text appearing on slide 2.

I'm thinking now that a more pragmatic solution would be to just define different types of environments, one for each type of bubble, so that I can choose which one to use depending on what I need. But I have no idea how to do that starting from the present solution.

This is the code I used to obtain the image above:

\documentclass{article}
\usepackage[many]{tcolorbox}
\usepackage{xcolor}
\usepackage{varwidth}
\usepackage{environ}
\usepackage{xparse}

\newlength{\bubblesep}
\newlength{\bubblewidth}
\setlength{\bubblesep}{2pt}
\AtBeginDocument{\setlength{\bubblewidth}{.75\textwidth}}
\definecolor{bubblegreen}{RGB}{103,184,104}
\definecolor{bubblegray}{RGB}{241,240,240}

\newcommand{\bubble}[4]{%
  \tcbox[
    on line,
    arc=4.5mm,
    colback=#1,
    colframe=#1,
    #2,
  ]{\color{#3}\begin{varwidth}{\bubblewidth}#4\end{varwidth}}%
}

\ExplSyntaxOn
\seq_new:N \l__ooker_bubbles_seq
\tl_new:N \l__ooker_bubbles_first_tl
\tl_new:N \l__ooker_bubbles_last_tl

\NewEnviron{rightbubbles}[3]
{
    \begin{minipage}[t]{0.85\textwidth}    
        \begin{flushright}
        \sffamily
        \seq_set_split:NnV 
        \l__ooker_bubbles_seq {\par} 
        \BODY
        \int_compare:nTF {\seq_count:N \l__ooker_bubbles_seq < 2}
        {
            \bubble{#1}{rounded~corners}{white}{\BODY}\par
        }
        {
            \seq_pop_left:NN \l__ooker_bubbles_seq \l__ooker_bubbles_first_tl
            \seq_pop_right:NN \l__ooker_bubbles_seq \l__ooker_bubbles_last_tl
            \bubble{#1}{sharp~corners=southeast}{white}{
                \hfill\textbf{{#2}:}\\
                \l__ooker_bubbles_first_tl
                }
            \par\nointerlineskip
            \addvspace{\bubblesep}
            \seq_map_inline:Nn \l__ooker_bubbles_seq
            {
                \bubble{#1}{sharp~corners=east}{white}{##1}
                \par\nointerlineskip
                \addvspace{\bubblesep}
            }
            \bubble{#1}{sharp~corners=northeast}{white}{\l__ooker_bubbles_last_tl}
            \par
        }
        \end{flushright}
    \end{minipage}\hskip0.3em
    \begin{minipage}[t]{0.1\textwidth}
        \includegraphics[width=\textwidth]{#3}
    \end{minipage}
}

\NewEnviron{leftbubbles}[3]
{
    \begin{minipage}[t]{0.1\textwidth}
        \includegraphics[width=\textwidth]{#3}
    \end{minipage}\hskip0.3em
    \begin{minipage}[t]{0.85\textwidth}
        \begin{flushleft}
        \sffamily
        \seq_set_split:NnV \l__ooker_bubbles_seq { \par } \BODY
        \int_compare:nTF { \seq_count:N \l__ooker_bubbles_seq < 2 }
        {
            \bubble{#1}{rounded~corners}{black}{\BODY}\par
        }
        {
            \seq_pop_left:NN \l__ooker_bubbles_seq \l__ooker_bubbles_first_tl
            \seq_pop_right:NN \l__ooker_bubbles_seq \l__ooker_bubbles_last_tl
            \bubble{#1}{sharp~corners=southwest}{black}{
                \textbf{{#2}:}\\
                \l__ooker_bubbles_first_tl
                }
            \par\nointerlineskip
            \addvspace{\bubblesep}
            \seq_map_inline:Nn \l__ooker_bubbles_seq
            {
            \bubble{#1}{sharp~corners=west}{black}{##1}
            \par\nointerlineskip
            \addvspace{\bubblesep}
            }
            \bubble{#1}{sharp~corners=northwest}{black}{\l__ooker_bubbles_last_tl}\par
        }
        \end{flushleft}        
    \end{minipage}
}
\ExplSyntaxOff

\begin{document}
\begin{rightbubbles}{bubblegreen}{John Nash}{nash.png}
    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, 
    totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. 
    
    Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. 
\end{rightbubbles}

\begin{leftbubbles}{black!15}{Robert Aumann}{aumann.png}
    Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. 
    
    Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? 
\end{leftbubbles}

\begin{rightbubbles}{bubblegreen}{John Nash}{nash.png}
    Quis autem vel eum iure!  
\end{rightbubbles}
\end{document}

Note that this is an edited version of an earlier post that featured a rougher version of what I want to get. After working on it a bit I managed to make some progress, but I got stuck at the alignment issue. This also doesn't work so well with multiple speakers, but I don't understand the existing code well enough to figure out how to reconfigure the bubbles.

Of course, I don't expect the answer to follow this code exactly. Any hints toward a solution would be greatly appreciated.

Best Answer

What about using tcolorbox?

I copy-pasted the images from your question, so maybe you'll need to adjust some lengths.

Here's the images I used: enter image description here enter image description here

\documentclass{article}
\usepackage{environ}
\usepackage{varwidth}
\usepackage[most]{tcolorbox}
\definecolor{bubblegreen}{RGB}{103,184,104}
\definecolor{bubblegray}{RGB}{241,240,240}

\tcbset{
  commonoptions/.style={
    enhanced,
    enhanced jigsaw,    
    fonttitle=\bfseries,
    boxed title style={opacityback=0, opacityframe=0},
    sharp corners,
    arc=4mm,
    opacityframe=0,
    after skip=0mm,
    },
  }

\newtcolorbox{rightbubbles}[4][]{
    commonoptions,    
    attach boxed title to top right={yshift=-7mm, xshift=-2mm},
    top=6mm,
    right skip=1.5cm,
    finish={\node[anchor=north west, yshift=2mm] at (frame.north east) {\includegraphics{#4}};},
    title={#3:}, 
    rounded corners=north,
    rounded corners=southwest,
    colback=#2,
    colupper=white,
    before skip=1mm,
    #1}

\newtcolorbox{rightbubblesfinal}[2][]{
    commonoptions,    
    right skip=1.5cm,
    rounded corners=northwest,
    rounded corners=south,
    colback=#2,
    colupper=white,
    before skip=0mm,
    #1}

\NewEnviron{rightbubbleslittle}[2]{\vspace{1mm}%
\tcbox[commonoptions,    
    finish={\node[anchor=north west, yshift=2mm] at (frame.north east) {\includegraphics{#2}};},
    rounded corners,
    colback=#1,
    colupper=white,
    before=\hfill,
    right skip=1.5cm,
    varwidth upper]
    {\BODY}
}    
\newtcolorbox{leftbubbles}[4][]{
    commonoptions,    
    attach boxed title to top left={yshift=-7mm, xshift=2mm},
    top=6mm,
    left skip=1.5cm,
    finish={\node[anchor=north east, yshift=2mm] at (frame.north west) {\includegraphics{#4}};},
    title={#3:}, 
    rounded corners=north,
    rounded corners=southeast,
    colback=#2,
    colupper=black,
    coltitle=black,
    before skip=1mm,
    #1}

\newtcolorbox{leftbubblesfinal}[2][]{
    commonoptions,    
    left skip=1.5cm,
    rounded corners=northeast,
    rounded corners=south,
    colback=#2,
    colupper=black,
    before skip=0mm,
    #1}
    
\NewEnviron{leftbubbleslittle}[2]{\vspace{1mm}%
\tcbox[commonoptions,    
    finish={\node[anchor=north east, yshift=2mm] at (frame.north west) {\includegraphics{#2}};},
    rounded corners,
    colback=#1,
    colupper=black,
    left skip=1.5cm,    
    varwidth upper]
    {\BODY}
}

\begin{document}
\begin{rightbubbles}{bubblegreen}{John Nash}{nash.png}
    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, 
    totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. 
    
    Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. 
\end{rightbubbles}
\begin{rightbubblesfinal}{bubblegreen}
    Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. 
\end{rightbubblesfinal}
\begin{leftbubbles}{black!15}{Robert Aumann}{aumann.png}
    Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. 
\end{leftbubbles}
\begin{leftbubblesfinal}{black!15}
    Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? 
\end{leftbubblesfinal}
\begin{rightbubbleslittle}{bubblegreen}{nash.png}
    Quis autem vel eum iure!
\end{rightbubbleslittle}
\begin{leftbubbleslittle}{black!15}{aumann.png}
    Bye! 
\end{leftbubbleslittle}
\end{document}

enter image description here

And with beamer:

\documentclass{beamer}
\usepackage{environ}
\usepackage{varwidth}
\usepackage[most]{tcolorbox}
\definecolor{bubblegreen}{RGB}{103,184,104}
\definecolor{bubblegray}{RGB}{241,240,240}

\tcbset{
  commonoptions/.style={
    enhanced,
    enhanced jigsaw,    
    fonttitle=\bfseries\scriptsize,
    fontupper=\tiny,
    boxed title style={opacityback=0, opacityframe=0},
    sharp corners,
    arc=4mm,
    opacityframe=0,
    after skip=0mm,
    },
  }

\newtcolorbox{rightbubbles}[4][]{
    commonoptions,    
    attach boxed title to top right={yshift=-7mm, xshift=-2mm},
    top=6mm,
    right skip=1.5cm,
    finish={\node[anchor=north west, yshift=2mm] at (frame.north east) {\includegraphics{#4}};},
    title={#3:}, 
    rounded corners=north,
    rounded corners=southwest,
    colback=#2,
    colupper=white,
    before skip=1mm,
    #1}

\newtcolorbox{rightbubblesfinal}[2][]{
    commonoptions,    
    right skip=1.5cm,
    rounded corners=northwest,
    rounded corners=south,
    colback=#2,
    colupper=white,
    before skip=0mm,
    #1}

\NewEnviron{rightbubbleslittle}[2]{\vspace{1mm}%
\tcbox[commonoptions,    
    finish={\node[anchor=north west, yshift=2mm] at (frame.north east) {\includegraphics{#2}};},
    rounded corners,
    colback=#1,
    colupper=white,
    before=\hfill,
    right skip=1.5cm,
    varwidth upper]
    {\BODY}
}    
\newtcolorbox{leftbubbles}[4][]{
    commonoptions,    
    attach boxed title to top left={yshift=-7mm, xshift=2mm},
    top=6mm,
    left skip=1.5cm,
    finish={\node[anchor=north east, yshift=2mm] at (frame.north west) {\includegraphics{#4}};},
    title={#3:}, 
    rounded corners=north,
    rounded corners=southeast,
    colback=#2,
    colupper=black,
    coltitle=black,
    before skip=1mm,
    #1}

\newtcolorbox{leftbubblesfinal}[2][]{
    commonoptions,    
    left skip=1.5cm,
    rounded corners=northeast,
    rounded
    corners=south,
    colback=#2,
    colupper=black,
    before skip=0mm,
    #1}
    
\NewEnviron{leftbubbleslittle}[2]{\vspace{1mm}%
\tcbox[commonoptions,    
    finish={\node[anchor=north east, yshift=2mm] at (frame.north west) {\includegraphics{#2}};},
    rounded corners,
    colback=#1,
    colupper=black,
    left skip=1.5cm,    
    varwidth upper]
    {\BODY}
}

\begin{document}
\begin{frame}\footnotesize
\begin{rightbubbles}{bubblegreen}{John Nash}{nash.png}
    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, 
    totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. 
    
    Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. 
\end{rightbubbles}
\onslide<2->{\begin{rightbubblesfinal}{bubblegreen}
    Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. 
\end{rightbubblesfinal}}
\onslide<3->{\begin{leftbubbles}{black!15}{Robert Aumann}{aumann.png}
    Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. 
\end{leftbubbles}}
\onslide<4->{\begin{leftbubblesfinal}{black!15}
    Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? 
\end{leftbubblesfinal}}
\onslide<5->{\begin{rightbubbleslittle}{bubblegreen}{nash.png}
    Quis autem vel eum iure!
\end{rightbubbleslittle}}
\onslide<6->{
\begin{leftbubbleslittle}{black!15}{aumann.png}
    Bye! 
\end{leftbubbleslittle}}
\end{frame}
\end{document}

enter image description here