---
title: "λέξις"
subtitle: "a Quarto theme"
author: "John Paul Helveston"
date: "2026-07-08"
format: lexis-revealjs
mouse-wheel: true 
progress: false
footer: "<https://github.com/jhelvy/quarto-lexis>"
footer-align: center
execute:
  echo: false
  warning: false
  message: false
---

<!--
Title slide: just a normal lexis slide. Quarto's built-in `meta` shortcode
pulls values straight from the YAML front matter above, so there's nothing to
duplicate — edit the metadata and this slide updates. Drop/add lines for
whichever of subtitle/author/institute/date you're using; nothing here is
conditional.
-->

{{< inverse >}}
{{< center >}}
{{< middle >}}
{{< no-slide-number >}}

# {{< meta title >}}

## [{{< meta subtitle >}}]{.fancy}

<br>

[{{< meta author >}}]{.large}

{{< meta date >}}

---

```{r}
#| label: setup
#| include: false
library(tidyverse)
knitr::opts_chunk$set(
  fig.width = 7.252,
  fig.height = 4,
  fig.retina = 3,
  comment = "#>",
  dev = "png"
)
```

---

# [Text styling]{.center}

::: {.col}
# Header level 1

## Header level 2

### Header level 3

#### Header level 4

##### Header level 5

###### Header level 6
:::

::: {.col}
Regular

_Italics_

**Bold**

***Bold italics***

~~Strikethrough~~

[Fancy text]{.fancy}

[external link](https://github.com/jhelvy/lexis)<br>

`Inline code`
:::

---

{{< inverse >}}

# [Inverse text styling]{.center}

::: {.col}
# Header level 1

## Header level 2

### Header level 3

#### Header level 4

##### Header level 5

###### Header level 6
:::

::: {.col}
Regular

_Italics_

**Bold**

***Bold italics***

~~Strikethrough~~

[Fancy text]{.fancy}

[external link](https://github.com/jhelvy/lexis)<br>

`Inline code`
:::

---

# [Colors!]{.center}

::: {.col}
Use this...

- `[text]{.red}`
- `[text]{.orange}`
- `[text]{.yellow}`
- `[text]{.green}`
- `[text]{.darkgreen}`
- `[text]{.blue}`
- `[text]{.darkblue}`
- `[text]{.purple}`
- `[text]{.black}`
:::

::: {.col}
...to get this

- **[text]{.red}**
- **[text]{.orange}**
- **[text]{.yellow}**
- **[text]{.green}**
- **[text]{.darkgreen}**
- **[text]{.blue}**
- **[text]{.darkblue}**
- **[text]{.purple}**
- **[text]{.black}**
:::

---

# Tables

```{r}
knitr::kable(head(mpg))
```

---

# Block quotes

Use the `>` to make block quotes:

```markdown
> This is what a block quote looks like.
```

> This is what a block quote looks like.

---

# Incremental content

Use `. . .` on its own line (xaringan's `--`) to reveal the rest of the slide on
the next click:

::: {.col}
```markdown
Everyone sees this first.

. . .

Then this appears.

. . .

And finally this.
```
:::

::: {.col}
Everyone sees this first.

. . .

Then this appears.

. . .

And finally this.
:::

---

# [Github code chunk highlighting]{.center}

::: {.col width="80%"}
::: {.font90}
```r
foo <- function(arg1 = 100, arg2 = "character string") {
  if (TRUE) {
    x = NULL  # if, function, NULL are keywords a
    for (i in 1:10) x = c(x, mean(3 * rnorm(100) + 1))
  }
}
```
:::
:::

---

# Line highlighting

Highlight lines with the `code-line-numbers` cell option:

::: {.col}
### Code

````{.markdown}
```{{r}}
#| code-line-numbers: "4,5"

library(ggplot2)

ggplot(mtcars) +
  aes(mpg, disp) +
  geom_point() +
  geom_smooth()
```
````
:::

::: {.col}
### Output

```{r}
#| echo: true
#| eval: false
#| code-line-numbers: "4,5"

library(ggplot2)

ggplot(mtcars) +
  aes(mpg, disp) +
  geom_point() +
  geom_smooth()
```
:::

---

# Sizing text and code

One system for everything: wrap any content in a `.fontNN` div to scale it to
NN% of the slide's base size (5% steps, `font10`–`font200`). It works the same
on paragraphs, lists, and code chunks — a chunk and its printed output always
match. For inline text there's also `[text]{.fontNN}` plus the `.small` and
`.large` shortcuts.

::: {.col}
Normal size:

```{r}
#| echo: true
head(mtcars[, 1:4], 3)
```
:::

::: {.col}
Wrapped in `::: {.font70}`:

::: {.font70}
```{r}
#| echo: true
head(mtcars[, 1:4], 3)
```
:::
:::

---

{{< inverse >}}
{{< middle >}}
{{< center >}}

# Layouts!

---

# Tabset panels!

::: {.panel-tabset}

### R Code

```{r}
#| label: ggplot-mtcars
#| echo: true
#| fig-show: hide
ggplot(mtcars, aes(x = mpg, y = hp)) +
  geom_point() +
  theme_bw() +
  labs(color = "Cylinders")
```

### Plot

```{r}
#| echo: false
#| fig-height: 3
#| fig-width: 4
#| out-width: 50%
#| fig-align: center

ggplot(mtcars, aes(x = mpg, y = hp)) +
  geom_point() +
  theme_bw() +
  labs(color = "Cylinders")
```

:::

---

## [Three (or more) equal columns]{.center}

::: {.col}
`.col`, no `width`

Any number of `.col` divs in a row auto-splits the space evenly — no separate class for 2 vs 3 vs 4 columns.
:::

::: {.col}
`.col`, no `width`

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
:::

::: {.col}
`.col`, no `width`

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
:::

---

## [Two equal columns]{.center}

::: {.col}
`.col`

Two consecutive `.col` divs with no `width` split 50/50 automatically. No outer `::: {.columns}` wrapper needed either — just write the columns.
:::

::: {.col}
`.col`

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
:::

---

## [Any split you want]{.center}

::: {.col width="65%"}
`.col width="65%"`

`width` takes any percentage — 65/35, 42/58, whatever the content needs. No fixed set of splits to remember.
:::

::: {.col width="35%"}
`.col width="35%"`

Only one side needs a `width`; a column left without one just takes whatever space remains.
:::

---

## [Uneven columns, custom gap \& alignment]{.center}

::: {.col width="50%" gap="3em" valign="middle"}
### `gap` and `valign`

Set `gap` or `valign` on any `.col` in the row and it applies to the whole row — handy here since this column's text is shorter than the code beside it, so `valign="middle"` centers them against each other.
:::

::: {.col width="25%" .font70}

```r
foo <- function(x) {
  x + 1
}
```
:::

::: {.col width="25%" .font70}

```r
bar <- function(y) {
  y * 2
}
```

:::

---

{{< center >}}
{{< middle >}}

# Cards!

## [Grids of icon + text boxes]{.gray}

---

## [Card grids]{.center}

::: {.card .icon-left cols="2" color="dodgerblue"}
{{< fa map >}}

### Plan

Make a plan before doing big work.

[read-only]{.tag}
:::

::: {.card .icon-left color="gray"}
{{< fa hand >}}

### Manual

Approve or deny each edit.

[safe but slow]{.tag}
:::

::: {.card .icon-left color="darkgreen"}
{{< fa pen >}}

### Accept Edits

Auto-applies file edits.

[semi engagement]{.tag}
:::

::: {.card .icon-left .highlight color="orange"}
{{< fa bolt >}}

### Auto

Approves everything.

[use with care]{.tag}
:::

---

## [Just write the boxes]{.center}

::: {.col width="55%" .font80}

Consecutive `::: {.card}` divs are grouped into a grid automatically — same idea as `.col`, no wrapper to write. The previous slide is just:

```markdown
::: {.card .icon-left color="dodgerblue"}
{{< fa map >}}

### Plan

Make a plan before doing big work.

[read-only]{.tag}
:::

::: {.card .icon-left color="gray"}
{{< fa hand >}}
...
:::
```

An icon on the card's **first line** becomes the tile — from any icon
library, since the shortcode has already expanded by the time lexis sees it.

:::

::: {.col width="45%" .font70}

| Attribute | Effect |
|---|---|
| first line | `{{< fa map >}}`, `{{< bi map >}}`, an emoji, `![](icon.svg)` |
| `icon=` | Shorthand for an image file or an emoji |
| `image=` | A cropped photo band across the card top |
| `color=` | Accent color: a palette name or any CSS color |
| `badge=` | Small accent flag in the top-right corner |
| `cols=` | Cards per row (default: up to 4 in one row) |
| `gap=` | Gutter between cards |

| Class | Effect |
|---|---|
| `.icon-left` | Icon beside the heading instead of above it |
| `.tint` | Paint the accent color through an SVG icon *file* |
| `.highlight` | Accent fill + halo — "this one" |
| `.center` | Center the card's contents |
| `.fragment` | Reveal this card on its own click |

:::

---

## [Eight cards, `cols="4"`]{.center}

::: {.card .center cols="4" color="purple"}
{{< fa code >}}

### Write code
:::

::: {.card .center color="darkgreen"}
{{< fa bug >}}

### Debug
:::

::: {.card .center color="dodgerblue"}
{{< fa chart-column >}}

### Analyze data
:::

::: {.card .center color="purple"}
{{< fa image >}}

### Generate images
:::

::: {.card .center color="orange"}
{{< fa book-open >}}

### Summarize docs
:::

::: {.card .center color="darkgreen"}
{{< fa pen >}}

### Write & edit
:::

::: {.card .center color="gray"}
{{< fa terminal >}}

### Automate tasks
:::

::: {.card .center .highlight color="red" badge="today's focus"}
{{< fa file-code >}}

### Build HTML
:::

---

## [Cards with images: `image=`]{.center}

::: {.card color="darkgreen" image="images/blue_ridge_mountains.jpg"}
### Blue Ridge

`image=` crops a photo band across the top of the card, bled out to the rounded corners.

[morning]{.tag}
:::

::: {.card color="orange" image="images/blue_ridge_sunset.jpg"}
### Sunset

The band is `object-fit: cover`, so any aspect ratio fills it without squashing.

[evening]{.tag}
:::

::: {.card .center color="dodgerblue" icon="🏔️"}
### Emoji work too

An `icon=` that isn't a file path is set as text in the tile.
:::

::: {.card .center .tint color="purple" icon="images/icons/map.svg"}
### So do SVG files

`.tint` paints the accent color through the file, so one gray icon set works with any color.
:::

---

{{< inverse >}}

## [Cards on an inverse slide]{.center}

::: {.card .icon-left cols="3" color="dodgerblue"}
{{< fa map >}}

### Plan

Same accent, mixed toward black instead of white.
:::

::: {.card .icon-left color="orange"}
{{< fa bolt >}}

### Auto

No extra classes needed — the card reads the slide.
:::

::: {.card .icon-left .highlight color="green"}
{{< fa pen >}}

### Edit

`.highlight` still marks one out.
:::

---

{{< center >}}

{{< bg-image "images/blue_ridge_mountains.jpg" >}}

# [Full image background]{.fancy}{.white}

<br><br>

::: {.col width="70%"}

```r
{{{< bg-image "images/blue_ridge_mountains.jpg" >}}}
```

:::

---

{{< center >}}
{{< bg-color "#909099" >}}

# [[Full background color]{.white}]{.fancy}

<br><br><br>

::: {.col width="40%"}

```r
{{{< bg-color "#909099" >}}}
```

:::

---

{{< inverse >}}
{{< middle >}}
{{< center >}}

# Images!

---

# Images have no border by default

::: {.col width="60%"}
This code produces the image on the right:

```markdown
![](images/blue_ridge_sunset.jpg)
```
:::

::: {.col width="40%"}
![](images/blue_ridge_sunset.jpg)
:::

---

# Add a thin border with `.border`

::: {.col width="60%"}
This code produces the image on the right:

```markdown
::: {.border}
![](images/blue_ridge_sunset.jpg)
:::
```
:::

::: {.col width="40%"}
::: {.border}
![](images/blue_ridge_sunset.jpg)
:::
:::

---

## Or modify the border: `.borderthick`

::: {.col width="60%"}
This code produces the image on the right:

```markdown
::: {.borderthick}
![](images/blue_ridge_sunset.jpg)
:::
```
:::

::: {.col width="40%"}
::: {.borderthick}
![](images/blue_ridge_sunset.jpg)
:::
:::

---

{{< inverse >}}

## Or modify the border: `.whiteborder`

::: {.col width="60%"}
This code produces the image on the right:

```markdown
::: {.whiteborder}
![](images/blue_ridge_sunset.jpg)
:::
```
:::

::: {.col width="40%"}
::: {.whiteborder}
![](images/blue_ridge_sunset.jpg)
:::
:::

---

{{< inverse >}}

## Or modify the border: `.whiteborderthick`

::: {.col width="60%"}
This code produces the image on the right:

```markdown
::: {.whiteborderthick}
![](images/blue_ridge_sunset.jpg)
:::
```
:::

::: {.col width="40%"}
::: {.whiteborderthick}
![](images/blue_ridge_sunset.jpg)
:::
:::

---

# Make a polaroid image: `.polaroid`

::: {.col width="60%"}
This code produces the image on the right:

```markdown
::: {.polaroid}
![](images/blue_ridge_sunset.jpg)
:::
```
:::

::: {.col width="40%"}
::: {.polaroid}
![](images/blue_ridge_sunset.jpg){width="400"}
:::
:::

---

# Make a circle image: `.circle`

::: {.col width="60%"}
This code produces the image on the right:

```markdown
::: {.circle}
![](images/blue_ridge_sunset.jpg)
:::
```
:::

::: {.col width="40%"}
::: {.circle}
![](images/blue_ridge_sunset.jpg){width="400"}
:::
:::

---

# Make a thumbnail image: `.thumbnail`

::: {.col width="60%"}
This code produces the image on the right:

```markdown
::: {.thumbnail}
![](images/blue_ridge_sunset.jpg)
:::
```
:::

::: {.col width="40%"}
<br><br><br><br>

::: {.thumbnail}
![](images/blue_ridge_sunset.jpg)
:::
:::

---

# Image classes work on rendered charts too

::: {.col}
````markdown
::: {.border}

```{{r}}
ggplot(mtcars, aes(mpg, hp)) +
  geom_point()
```

:::
````

::: {.border}
```{r}
#| echo: false
#| fig-height: 3
#| fig-width: 4
#| fig-align: center
ggplot(mtcars, aes(x = mpg, y = hp)) +
  geom_point() +
  theme_bw()
```
:::
:::

::: {.col}
````markdown
::: {.circle}

```{{r}}
ggplot(mtcars, aes(mpg, hp)) +
  geom_point()
```

:::
````

::: {.circle}
```{r}
#| echo: false
#| fig-height: 3
#| fig-width: 4
#| fig-align: center
ggplot(mtcars, aes(x = mpg, y = hp)) +
  geom_point() +
  theme_bw()
```
:::
:::

---

{{< center >}}
{{< middle >}}
{{< inverse >}}
{{< no-slide-number >}}

# Thanks!

::: {.footer-large}
::: {.right}
[jhelvy.com [{{< fa link >}}]{.white}](https://www.jhelvy.com)<br>
[jph@gwu.edu [{{< fa paper-plane >}}]{.white}](mailto:jph@gwu.edu)<br>
[@jhelvy [{{< fa brands github >}}]{.white}](http://github.com/jhelvy)
:::
:::
