It seems that both the aspect ratio of the plot (set by the size of the plot pane in RStudio) and the corresponding ratio of the axis ranges are required:

library(tidyverse)
library(ggtext)
tibble(x = 1:3, y = 1:3) %>%
ggplot(aes(x, y)) +
geom_line() +
geom_richtext(
x = 2, y = 2,
label = 'slope',
angle =
atan(
# slope
1 *
# aspect ratio of plot:
unit(0, 'npc') %>% grid::convertY('native', valueOnly = T) /
unit(1, 'npc') %>% grid::convertX('native', valueOnly = T) /
# ratio of y-range to x-range of plot:
( 2 / 2 )
) * 180 / pi
)

tibble(x = 1:3, y = 1:3) %>%
ggplot(aes(x, y)) +
geom_line() +
geom_richtext(
x = 2, y = 2,
label = 'slope',
angle =
atan(
# slope
1 *
# aspect ratio of plot:
unit(0, 'npc') %>% grid::convertY('native', valueOnly = T) /
unit(1, 'npc') %>% grid::convertX('native', valueOnly = T) /
# ratio of y-range to x-range of plot:
( 4 / 2 )
) * 180 / pi
) +
coord_cartesian(
ylim = c(0, 4)
)

^{Created on 2021-03-24 by the reprex package (v0.3.0)}