Skip to content

Commit e3f2aad

Browse files
committed
make messy homepage preview
1 parent 481968f commit e3f2aad

File tree

4 files changed

+186
-97
lines changed

4 files changed

+186
-97
lines changed

src/index.njk

Lines changed: 66 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,57 @@ layout: layout.njk
88
We have further grouped these extensions into {{ extensionGroups | length }} <strong>extension groups</strong> based on their common functionality. These extension groups are listed below for your convenience, in relative order of importance. Feel free to explore!
99
<p>
1010

11+
<p>Search by mnemonic or long name. Hit Enter on an exact mnemonic match to jump straight to the instruction details.</p>
12+
13+
<input id="search" placeholder="Search mnemonic, e.g. addi" style="padding:8px; width: 100%; max-width: 480px;" />
14+
15+
{# Creates box divide between checkboxes and rest of page #}
16+
<fieldset id="extension-filters-fieldset" class="filters">
17+
<legend>Filter by extension group</legend>
18+
<div id="extension-filters" class="filter-options"></div>
19+
</fieldset>
20+
1121
{% for extGroupName, extGroupInfo in extensionGroups %}
1222
<div class="dropdown-callout {% if loop.first %} open{% endif %}">
1323
<div class="header">
14-
<strong>{{ extGroupName }}</strong> - <span class="group-description">{{ extGroupInfo.description }}</span>
24+
<strong>{{ extGroupName }}</strong> - {{ extGroupInfo.description }}
1525
</div>
1626
<div class="content">
17-
<ul>
27+
<ul class="extension-list">
1828
{% for ext in extensions %}
1929
{% if ext.group == extGroupName %}
20-
<li>
21-
<strong>{{ ext.name }}</strong>
22-
<a href="/extensions/{{ ext.slug }}/">({{ ext.description }})</a>:
23-
{% for inst in ext.instructions %}
24-
<a href="/instructions/{{ inst.name }}/" style="color: #000000">{{ inst.name }}</a>,
25-
{% endfor %}
30+
<li class="extension-entry">
31+
<div class="extension-header">
32+
<strong>{{ ext.name }}</strong>
33+
(<a href="/extensions/{{ ext.slug }}/" class="extension-desc">{{ ext.description }}</a>)
34+
- Add small description here...
35+
</div>
36+
37+
{% set limit = 28 %}
38+
{% set total = ext.instructions | length %}
39+
40+
<div class="instruction-grid">
41+
{% for inst in ext.previewInstructions %}
42+
<a href="/instructions/{{ inst.name }}/" class="instruction-pill">
43+
{{ inst.name }}
44+
</a>
45+
{% endfor %}
46+
</div>
47+
48+
{% if total > limit %}
49+
<div class="instruction-grid" style="display: none;">
50+
{% for inst in ext.instructions %}
51+
<a href="/instructions/{{ inst.name }}/" class="instruction-pill">
52+
{{ inst.name }}
53+
</a>
54+
{% endfor %}
55+
</div>
56+
57+
<button class="show-more" data-total="{{ total }}" onclick="toggleInstructions(this)">
58+
Show all {{ total }} instructions
59+
</button>
60+
61+
{% endif %}
2662
</li>
2763
{% endif %}
2864
{% endfor %}
@@ -38,23 +74,28 @@ layout: layout.njk
3874
parent.classList.toggle("open");
3975
});
4076
});
77+
78+
function toggleInstructions(button) {
79+
const hiddenGrid = button.previousElementSibling;
80+
const originalGrid = hiddenGrid.previousElementSibling;
81+
82+
hiddenGrid.style.display = hiddenGrid.style.display === "none" ? "grid" : "none";
83+
originalGrid.style.display = originalGrid.style.display === "none" ? "grid" : "none";
84+
85+
if (hiddenGrid.style.display === "grid") button.textContent = "Show first 49 instructions";
86+
else button.textContent = `Show all ${button.dataset.total} instructions`;
87+
}
4188
</script>
4289

43-
<ul id="extensions">
44-
{% for ext in extensions %}
45-
<li data-name="{{ ext.name | lower }}">
46-
<a href="/extensions/{{ ext.slug }}/">{{ ext.name }}</a>
47-
<p class="extension-description">
48-
{% if ext.description %}
49-
{{ ext.description }}
50-
{% else %}
51-
Description coming soon.
52-
{% endif %}
53-
</p>
54-
</li>
55-
{% endfor %}
56-
</ul>
90+
<div id="instruction_list" class="instruction-grid" style="display: none;">
91+
{% for inst in instructions %}
92+
<a data-search="{{ (inst.name ~ ' ' ~ inst.longName) | lower }}"
93+
data-mnemonic="{{ inst.name | lower }}"
94+
data-extension="{{ inst.extension }}"
95+
data-extension-slug="{{ inst.extensionSlug }}"
96+
data-extension-group="{{ inst.extensionGroup }}"
97+
href="/instructions/{{ inst.name }}/" class="instruction-pill" style="display: none;">{{ inst.name }}</a>
98+
{% endfor %}
99+
</div>
57100

58-
<p class="secondary-callout">
59-
<a href="/search/">Try the searchable instruction index.</a>
60-
</p>
101+
<script src="/scripts/search.js"></script>

src/lib/loadExtensions.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ export default () => {
1313
}
1414
}
1515

16+
for (const inst of instructions) {
17+
inst.extensionGroup = extensionsToGroup[inst.extension] || "Remaining Instructions";
18+
}
19+
1620
const extensions = {}
1721
for (const inst of instructions) {
1822
const name = inst.extension || "unknown";
@@ -33,6 +37,7 @@ export default () => {
3337
for (const entry of list) {
3438
entry.instructions.sort((a, b) => a.name.localeCompare(b.name));
3539
entry.count = entry.instructions.length;
40+
entry.previewInstructions = entry.instructions.slice(0, 49);
3641
}
3742

3843
list.sort((a, b) => a.name.localeCompare(b.name));

src/scripts/search.ts

Lines changed: 78 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,104 @@
11
const input = document.getElementById("search");
22
const instruction_list = document.getElementById("instruction_list");
33
const filtersFieldset = document.getElementById("extension-filters-fieldset");
4-
// the blank area where we’ll insert checkboxes
4+
// The blank area where we’ll insert checkboxes
55
const filtersContainer = document.getElementById("extension-filters");
6-
const items = Array.from(instruction_list.querySelectorAll("li"));
7-
const activeExtensions = new Set();
6+
const items = Array.from(instruction_list.querySelectorAll("a"));
7+
const dropdowns = Array.from(document.querySelectorAll(".dropdown-callout"));
8+
const activeExtensionGroups = new Set();
89

910
// Gather unique extension names from the rendered instruction <li> items.
10-
const extensionSet = new Set();
11-
for (const li of items) {
12-
const extension = li.dataset.extension;
13-
extensionSet.add(extension);
11+
const extensionGroupSet = new Set();
12+
for (const a of items) {
13+
const extension = a.dataset.extensionGroup;
14+
extensionGroupSet.add(extension);
1415
}
1516

16-
const extensions = Array.from(extensionSet).sort();
17-
for (const extension of extensions) {
18-
const id = `ext-${extension}`;
19-
const label = document.createElement("label");
20-
label.className = "filter-option";
21-
22-
const checkbox = document.createElement("input");
23-
checkbox.type = "checkbox";
24-
checkbox.value = extension;
25-
checkbox.id = id;
26-
checkbox.addEventListener("change", () => {
27-
if (checkbox.checked) {
28-
activeExtensions.add(extension);
17+
const extensionGroups = Array.from(extensionGroupSet).sort();
18+
for (const extensionGroup of extensionGroups) {
19+
const id = `ext-group-${extensionGroup}`;
20+
const label = document.createElement("label");
21+
label.className = "filter-option";
22+
23+
const checkbox = document.createElement("input");
24+
checkbox.type = "checkbox";
25+
checkbox.value = extensionGroup;
26+
checkbox.id = id;
27+
28+
checkbox.addEventListener("change", () => {
29+
if (checkbox.checked) activeExtensionGroups.add(extensionGroup);
30+
else activeExtensionGroups.delete(extensionGroup);
31+
applyFilters();
32+
});
33+
34+
const text = document.createElement("span");
35+
text.textContent = extensionGroup;
36+
37+
label.appendChild(checkbox);
38+
label.appendChild(text);
39+
filtersContainer.appendChild(label);
40+
}
41+
42+
function applyFilters() {
43+
const q = input.value.trim().toLowerCase();
44+
const filtersActive = activeExtensionGroups.size > 0;
45+
46+
if (q || filtersActive) {
47+
// If there’s a search query, hide the dropdowns to save space
48+
instruction_list.style.display = "grid";
49+
for (const dropdown of dropdowns) {
50+
dropdown.style.display = "none";
51+
}
2952
} else {
30-
activeExtensions.delete(extension);
53+
// If the search box is empty, show the dropdowns again
54+
instruction_list.style.display = "none";
55+
for (const dropdown of dropdowns) {
56+
dropdown.style.display = "block";
57+
}
3158
}
32-
applyFilters();
33-
});
3459

35-
const text = document.createElement("span");
36-
text.textContent = extension;
60+
for (const a of items) {
61+
/* Check if the item matches the text search
62+
- If the search box is empty, match everything
63+
- Otherwise, match if the search string includes the query */
64+
const matchesQuery = !q || (a.dataset.search || "").includes(q);
3765

38-
label.appendChild(checkbox);
39-
label.appendChild(text);
40-
filtersContainer.appendChild(label);
41-
}
66+
/* Check if the item matches an active extension filter
67+
- If no filters are active, match everything
68+
- Otherwise, show only if its extension is selected */
69+
const matchesExtensionGroup = !filtersActive || activeExtensionGroups.has(a.dataset.extensionGroup);
4270

43-
function applyFilters() {
44-
const q = input.value.trim().toLowerCase();
45-
const filtersActive = activeExtensions.size > 0;
46-
for (const li of items) {
47-
/* Check if the item matches the text search
48-
- If the search box is empty, match everything
49-
- Otherwise, match if the search string includes the query */
50-
const matchesQuery = !q || (li.dataset.search || "").includes(q);
51-
52-
/* Check if the item matches an active extension filter
53-
- If no filters are active, match everything
54-
- Otherwise, show only if its extension is selected */
55-
const matchesExtension =
56-
!filtersActive || activeExtensions.has(li.dataset.extension);
57-
58-
// Show or hide this <li> depending on whether both match conditions are true
59-
li.style.display = matchesQuery && matchesExtension ? "" : "none";
60-
}
71+
// Show or hide this <li> depending on whether both match conditions are true
72+
a.style.display = matchesQuery && matchesExtensionGroup ? "grid" : "none";
73+
}
6174
}
6275

6376
input.addEventListener("input", applyFilters);
6477

6578
input.addEventListener("keydown", (e) => {
66-
// Only act if Enter is pressed
67-
if (e.key !== "Enter") return;
79+
// Only act if Enter is pressed
80+
if (e.key !== "Enter") return;
6881

69-
const q = input.value.trim().toLowerCase();
82+
const q = input.value.trim().toLowerCase();
7083

71-
// Do nothing if the box is empty
72-
if (!q) return;
84+
// Do nothing if the box is empty
85+
if (!q) return;
7386

74-
const filtersActive = activeExtensions.size > 0;
87+
const filtersActive = activeExtensionGroups.size > 0;
7588

76-
/* Look for an exact mnemonic match among all instructions
89+
/* Look for an exact mnemonic match among all instructions
7790
- If filters are active, also ensure it belongs to one of the selected extensions */
78-
const exact = items.find((li) => {
79-
if (li.dataset.mnemonic !== q) return false;
80-
if (!filtersActive) return true;
81-
return activeExtensions.has(li.dataset.extension);
82-
});
83-
84-
// If an exact match is found, redirect to that instruction's detail page
85-
if (exact) {
86-
const link = exact.querySelector("a").getAttribute("href");
87-
location.href = link;
88-
}
91+
const exact = items.find((a) => {
92+
if (a.dataset.mnemonic !== q) return false;
93+
if (!filtersActive) return true;
94+
return activeExtensionGroups.has(a.dataset.extensionGroup);
95+
});
96+
97+
// If an exact match is found, redirect to that instruction's detail page
98+
if (exact) {
99+
const link = exact.getAttribute("href");
100+
location.href = link;
101+
}
89102
});
90103

91104
applyFilters();

src/style.css

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ small {
106106
margin-left: 3px;
107107
}
108108

109+
/* Dropdown Styling For Extension Groups */
109110
.dropdown-callout {
110111
background: #f1f8ff;
111112
border-left: 4px solid #0366d6;
@@ -132,14 +133,7 @@ small {
132133
border-radius: 4px;
133134
}
134135

135-
.group-description {
136-
font-weight: normal;
137-
font-size: 0.95rem;
138-
margin-left: 0.5rem;
139-
}
140-
141136
.dropdown-callout .content {
142-
margin-top: 12px;
143137
display: none;
144138
}
145139

@@ -159,3 +153,39 @@ small {
159153
.dropdown-callout.open .header::after {
160154
transform: rotate(90deg);
161155
}
156+
157+
/* Instruction List Styling */
158+
.instruction-grid {
159+
display: grid;
160+
grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
161+
gap: 6px;
162+
margin-top: 6px;
163+
}
164+
165+
.instruction-pill {
166+
display: inline-block;
167+
padding: 4px 8px;
168+
background: #dee5ef;
169+
border-radius: 6px;
170+
font-size: 0.85rem;
171+
color: #0346b6;
172+
text-align: center;
173+
}
174+
175+
.instruction-pill:hover {
176+
background: #dceeff;
177+
text-decoration: none;
178+
}
179+
180+
.show-more {
181+
all: unset;
182+
cursor: pointer;
183+
display: block;
184+
margin: 1rem auto;
185+
padding: 8px 12px;
186+
background: #dee5ef;
187+
border-radius: 6px;
188+
font-size: 0.85rem;
189+
color: #000000;
190+
text-align: center;
191+
}

0 commit comments

Comments
 (0)