The web framework bootstrap, which Quarto uses for HTML files calls this Collapse. There is a github discussion in the quarto-dev repo. I adjusted the example provided there to provide the functionality you want.
---
title: "Research"
---
### Publications
------------------------------------------------------------------------
#### 2022
Authors. Year. ["Title".](https://stackoverflow.com/) *Journal*
<a data-bs-toggle="collapse" data-bs-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
Show Abstract
</a> <br>
<div class="collapse" id="collapseExample">
<div class="card card-body">
Some placeholder content for the collapse component. This panel is hidden by default but revealed when the user activates the relevant trigger.
</div>
</div>
Authors. Year. ["Title".](https://stackoverflow.com/) *Journal* <br>
You can wrap this in a function that creates a single entry with collapsed abstract. That way you don't have to insert the HTML directly into your qmd file.
---
title: "Research"
---
### Publications
---
#### 2022
```{r}
#| results: asis
library(tidyverse)
library(glue)
df <- tibble(authors = words[1:3], year = 2012:2014, title = words[4:6], abstract = words[7:9])
add_lit_entry <-
function(data) {
glue('<span>{data$authors}. {data$year}. {data$title}.</span>
<a data-bs-toggle="collapse" data-bs-target="#collapse{data$title}" aria-expanded="false" aria-controls="collapseExample">
Show Abstract
</a>
<div class="collapse" id="collapse{data$title}">
<div class="card card-body">
{data$abstract}
</div>
</div><br>') |> print()
}
df |>
split(1:nrow(df)) |>
walk(add_lit_entry)
```