Skip to content

Commit 2f98606

Browse files
committed
Set up extension
1 parent 9967b14 commit 2f98606

File tree

7 files changed

+185
-1
lines changed

7 files changed

+185
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/.quarto/

.quartoignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hexgrid-listing-demo.png

README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,21 @@
11
# quarto-hexgrid-listing
2-
WIP Quarto extension to turn listings into hex grids.
2+
3+
Show off your open source contributions on your [Quarto](https://quarto.org) website with this [custom listing](https://quarto.org/docs/websites/website-listings-custom.html).
4+
5+
![Screenshot of quarto-hexgrid-listing](hexgrid-listing-demo.png)
6+
7+
## Installing
8+
9+
10+
```bash
11+
quarto use template jimjam-slam/quarto-hexgrid-listing
12+
```
13+
14+
This will copy `hexlisting.ejs` into the folder where you intend to have the listing.
15+
16+
> [!IMPORTANT]
17+
> Note that `quarto add` does not presently work with custom listings, and if you use quarto-hexgrid-listing in a subdirectory of your Quarto website, you must run `quarto use template` in that subdirectory.
18+
19+
Once it's installed, provide [`template: hexlisting.ejs`](https://quarto.org/docs/websites/website-listings-custom.html#listing-templates) under the `listing` you want to use.
20+
21+
Having problems with the extension? Got a great idea? [Submit an issue!](/issues/new)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
title: Hexgrid-listing
2+
author: James Goldie
3+
version: 1.0.0
4+
quarto-required: ">=1.6"
5+
6+

hexgrid-listing-demo.png

371 KB
Loading

hexlisting.ejs

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<!-- hex badge listing by jamesgoldie.dev, jan 2025 -->
2+
3+
<%
4+
// wrap pairs of hexes
5+
let pairs = [];
6+
for (let i = 0; i < items.length; i += 2) {
7+
pairs.push([
8+
items[i],
9+
items[i + 1] || null]
10+
)
11+
}
12+
%>
13+
14+
```{=html}
15+
<style>
16+
.hex-listing-container {
17+
display: flex;
18+
flex-flow: row wrap;
19+
--hex-width: 150px;
20+
--hex-height: calc(var(--hex-width) * 1.1547);
21+
--hex-margin: 4px;
22+
--hex-shape: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%);
23+
padding-inline-start: calc(var(--hex-width) * 0.5 - var(--hex-margin));
24+
padding-block-start: calc(0.25 * var(--hex-height) - 2 * var(--hex-margin));
25+
}
26+
27+
.hex-listing-pair {
28+
display: inline-flex;
29+
align-items: start;
30+
height: calc(2 * var(--hex-height) + 2 * var(--hex-margin) - 0.25 * var(--hex-height));
31+
margin-inline-start: calc(var(--hex-width) * -0.5 + var(--hex-margin));
32+
margin-block-start: calc(-0.25 * var(--hex-height) + 2 * var(--hex-margin));
33+
}
34+
35+
.hex-listing-item {
36+
place-content: center;
37+
text-align: center;
38+
transition-delay: 0;
39+
transition:
40+
transform 0.25s ease-in-out,
41+
filter 0.25s linear;
42+
filter: drop-shadow(0px 0px 8px #00000011);
43+
}
44+
45+
.hex-listing-item:has(a:hover),
46+
.hex-listing-item:has(a:focus-visible) {
47+
transition-delay: 0.2s;
48+
transform: scale(1.15);
49+
filter: drop-shadow(0px 0px 8px #00000044);
50+
z-index: 1;
51+
}
52+
53+
.hex-listing-container a {
54+
display: inline-grid;
55+
width: var(--hex-width);
56+
height: var(--hex-height);
57+
clip-path: var(--hex-shape);
58+
text-decoration: none;
59+
}
60+
61+
.hex-listing-item a:focus-visible {
62+
outline: 3px solid red;
63+
}
64+
65+
.hex-listing-item:nth-child(2) {
66+
margin-inline-start: calc(-0.5 * var(--hex-width) + var(--hex-margin));
67+
align-self: end;
68+
}
69+
70+
/* hex contents */
71+
72+
.hex-listing-container a > * {
73+
grid-area: 1 / 1;
74+
}
75+
76+
77+
.hex-listing-container a img {
78+
width: var(--hex-width);
79+
height: var(--hex-height);
80+
object-fit: cover;
81+
}
82+
83+
.hex-listing-container a p {
84+
color: grey;
85+
font-size: 70%;
86+
align-self: center;
87+
margin: 0;
88+
padding-inline: 0.75em;
89+
}
90+
91+
/* fallback appearance when there's no image */
92+
93+
.hex-listing-container a:not(:has(img)) {
94+
background-color: #efefef;
95+
}
96+
97+
/* mobile sizing */
98+
99+
@media (max-width: 767.98px) {
100+
.hex-listing-container {
101+
--hex-width: 100px;
102+
}
103+
104+
.hex-listing-container a p {
105+
font-size: 50%;
106+
}
107+
108+
}
109+
110+
</style>
111+
112+
<div class="hex-listing-container">
113+
<% for (const pair of pairs) { %>
114+
<div class="hex-listing-pair">
115+
<div class="hex-listing-item">
116+
<a href="<%- pair[0].path %>">
117+
<p><%= pair[0].title %></p>
118+
<% if (pair[0].image) { %>
119+
<img loading="lazy" src="<%- pair[0].image %>" alt="<%= pair[0].title %>"/>
120+
<% } %>
121+
</a>
122+
</div>
123+
<% if (pair[1] != null) {%>
124+
<div class="hex-listing-item">
125+
<a href="<%- pair[1].path %>">
126+
<p><%= pair[1].title %></p>
127+
<% if (pair[1].image) { %>
128+
<img loading="lazy" src="<%- pair[1].image %>" alt="<%= pair[1].title %>"/>
129+
<% } %>
130+
</a>
131+
</div>
132+
<% } %>
133+
</div>
134+
<% } %>
135+
</ul>
136+
137+
```

template.qmd

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
title: Hex grid listing example
3+
format: html
4+
author: jimjamslam
5+
listing:
6+
id: hex-listing
7+
template: hexlisting.ejs
8+
contents:
9+
- title: Post A
10+
path: a
11+
- title: Post B
12+
path: b
13+
- title: Post C
14+
path: c
15+
- title: Post D
16+
path: d
17+
---
18+
19+
:::{#hex-listing}
20+
:::

0 commit comments

Comments
 (0)