Skip to content

Commit 3d73ae1

Browse files
authored
Merge pull request #218 from javaevolved/brunoborges-frontpage-pattern-discovery
Improve homepage pattern discovery
2 parents 9640aaa + 6aada91 commit 3d73ae1

18 files changed

Lines changed: 241 additions & 85 deletions

File tree

site/app.js

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@
210210

211211
let activeCategory = null;
212212
let activeJdk = null;
213+
let hasSelection = false;
214+
let showingAll = false;
213215

214216
// LTS cycle ranges: each entry covers all versions introduced since the previous LTS
215217
const LTS_RANGES = {
@@ -220,6 +222,17 @@
220222
};
221223

222224
const noResultsMsg = document.getElementById('noResultsMessage');
225+
const startMessage = document.getElementById('patternStartMessage');
226+
const showAllButton = document.getElementById('showAllButton');
227+
const isDiscoveryHome = !!showAllButton;
228+
hasSelection = !isDiscoveryHome;
229+
230+
const updateShowAllButton = () => {
231+
if (!showAllButton) return;
232+
showAllButton.textContent = showingAll
233+
? showAllButton.dataset.hideLabel
234+
: showAllButton.dataset.showLabel;
235+
};
223236

224237
const applyFilters = () => {
225238
let visibleCount = 0;
@@ -231,13 +244,17 @@
231244
const range = LTS_RANGES[activeJdk];
232245
matchesJdk = range && version >= range[0] && version <= range[1];
233246
}
234-
const visible = matchesCategory && matchesJdk;
247+
const visible = hasSelection && matchesCategory && matchesJdk;
235248
card.classList.toggle('filter-hidden', !visible);
236249
if (visible) visibleCount++;
237250
});
238251

252+
if (startMessage) {
253+
startMessage.hidden = hasSelection;
254+
}
255+
239256
if (noResultsMsg) {
240-
noResultsMsg.style.display = visibleCount === 0 ? '' : 'none';
257+
noResultsMsg.style.display = hasSelection && visibleCount === 0 ? '' : 'none';
241258
}
242259

243260
if (window.updateViewToggleState) {
@@ -246,7 +263,7 @@
246263
};
247264

248265
// Generic helper to wire up a dropdown
249-
const initDropdown = (dropdownEl, onSelect) => {
266+
const initDropdown = (dropdownEl, dataAttribute, onSelect) => {
250267
if (!dropdownEl) return;
251268
const toggleBtn = dropdownEl.querySelector('.jdk-dropdown-toggle');
252269
const labelEl = dropdownEl.querySelector('.jdk-label');
@@ -298,7 +315,7 @@
298315
});
299316

300317
return { closeDropdown, setActive: (value) => {
301-
const target = list.querySelector(`li[data-filter="${value}"]`);
318+
const target = list.querySelector(`li[data-${dataAttribute}="${value}"]`);
302319
if (target) {
303320
selectItem(target);
304321
toggleBtn.classList.toggle('has-filter', value !== 'all');
@@ -310,9 +327,12 @@
310327

311328
// Category dropdown
312329
const categoryDropdown = document.getElementById('categoryDropdown');
313-
const catDropdownCtrl = initDropdown(categoryDropdown, (li, toggleBtn) => {
330+
const catDropdownCtrl = initDropdown(categoryDropdown, 'filter', (li, toggleBtn) => {
314331
const category = li.dataset.filter;
332+
hasSelection = true;
315333
activeCategory = category !== 'all' ? category : null;
334+
showingAll = !activeCategory && !activeJdk;
335+
updateShowAllButton();
316336
toggleBtn.classList.toggle('has-filter', !!activeCategory);
317337
if (activeCategory) {
318338
history.replaceState(null, '', '#' + activeCategory);
@@ -324,31 +344,54 @@
324344

325345
// JDK dropdown
326346
const jdkDropdown = document.getElementById('jdkDropdown');
327-
initDropdown(jdkDropdown, (li, toggleBtn) => {
347+
const jdkDropdownCtrl = initDropdown(jdkDropdown, 'jdk-filter', (li, toggleBtn) => {
328348
const version = li.dataset.jdkFilter;
349+
hasSelection = true;
329350
activeJdk = version !== 'all' ? version : null;
351+
showingAll = !activeCategory && !activeJdk;
352+
updateShowAllButton();
330353
toggleBtn.classList.toggle('has-filter', !!activeJdk);
331354
applyFilters();
332355
});
333356

357+
if (showAllButton) {
358+
showAllButton.addEventListener('click', () => {
359+
activeCategory = null;
360+
activeJdk = null;
361+
if (catDropdownCtrl) catDropdownCtrl.setActive('all');
362+
if (jdkDropdownCtrl) jdkDropdownCtrl.setActive('all');
363+
history.replaceState(null, '', window.location.pathname + window.location.search);
364+
showingAll = !showingAll;
365+
hasSelection = showingAll;
366+
updateShowAllButton();
367+
applyFilters();
368+
});
369+
}
370+
334371
// Apply filter from a given category string (or "all" / empty for no filter)
335372
const applyHashFilter = (category) => {
336373
if (category && catDropdownCtrl && catDropdownCtrl.setActive(category)) {
374+
hasSelection = true;
337375
activeCategory = category;
376+
showingAll = false;
377+
updateShowAllButton();
338378
applyFilters();
339379
const section = document.getElementById('all-comparisons');
340380
if (section) section.scrollIntoView({ behavior: 'smooth' });
341381
} else if (catDropdownCtrl) {
342382
catDropdownCtrl.setActive('all');
343383
activeCategory = null;
384+
hasSelection = !isDiscoveryHome;
385+
showingAll = false;
386+
updateShowAllButton();
344387
applyFilters();
345388
} else {
346389
// No filter dropdowns (e.g. topic pages) — show all cards
347390
applyFilters();
348391
}
349392
};
350393

351-
// On load, apply filter from URL hash or default to "All"
394+
// On load, a category hash reveals its matches; otherwise keep the discovery state.
352395
applyHashFilter(window.location.hash.slice(1));
353396

354397
// Also react to browser back/forward hash changes

site/styles.css

Lines changed: 81 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -286,20 +286,6 @@ nav {
286286
margin: 0 auto;
287287
}
288288

289-
.hero-badge {
290-
display: inline-flex;
291-
align-items: center;
292-
gap: 6px;
293-
font-size: 0.8rem;
294-
font-weight: 500;
295-
color: var(--accent);
296-
background: rgba(251, 146, 60, .1);
297-
border: 1px solid rgba(251, 146, 60, .2);
298-
padding: 5px 14px;
299-
border-radius: 999px;
300-
margin-bottom: 24px;
301-
}
302-
303289
.hero h1 {
304290
font-size: clamp(2.2rem, 5vw, 3.4rem);
305291
font-weight: 800;
@@ -453,20 +439,6 @@ nav {
453439
margin-bottom: 12px;
454440
}
455441

456-
.section-badge {
457-
display: inline-flex;
458-
align-items: center;
459-
gap: 6px;
460-
font-size: 0.78rem;
461-
font-weight: 500;
462-
color: var(--accent);
463-
background: rgba(251, 146, 60, .08);
464-
border: 1px solid rgba(251, 146, 60, .15);
465-
padding: 4px 12px;
466-
border-radius: 999px;
467-
margin-bottom: 16px;
468-
}
469-
470442
/* ---------- Tips / Card Grid ---------- */
471443
.tips-grid {
472444
display: grid;
@@ -486,6 +458,62 @@ nav {
486458
width: 100%;
487459
}
488460

461+
.pattern-start-message {
462+
display: flex;
463+
flex-direction: column;
464+
align-items: center;
465+
max-width: 540px;
466+
margin: 32px auto 0;
467+
padding: 36px 24px;
468+
text-align: center;
469+
color: var(--text);
470+
border: 1px dashed var(--border-light);
471+
border-radius: var(--radius);
472+
background: var(--surface);
473+
}
474+
475+
.pattern-start-message[hidden] {
476+
display: none;
477+
}
478+
479+
.pattern-start-message p {
480+
max-width: 42ch;
481+
margin: 12px 0 0;
482+
line-height: 1.6;
483+
}
484+
485+
.pattern-start-icon {
486+
color: var(--accent);
487+
font-size: 2rem;
488+
line-height: 1;
489+
}
490+
491+
.show-all-btn {
492+
padding: 10px 20px;
493+
color: var(--text);
494+
font: inherit;
495+
font-size: 0.88rem;
496+
font-weight: 500;
497+
background: var(--surface);
498+
border: 1px solid var(--border);
499+
border-radius: var(--radius-sm);
500+
cursor: pointer;
501+
transition: all 0.25s;
502+
}
503+
504+
.show-all-btn:hover {
505+
transform: translateY(-2px);
506+
background: var(--surface-2);
507+
border-color: var(--border-light);
508+
}
509+
510+
.show-all-btn:focus-visible,
511+
.jdk-dropdown-toggle:focus-visible,
512+
.view-toggle-btn:focus-visible {
513+
outline: 3px solid var(--blue);
514+
outline-offset: 3px;
515+
}
516+
489517
.tip-card {
490518
background: var(--surface);
491519
border: 1px solid var(--border);
@@ -695,6 +723,7 @@ nav {
695723
/* ---------- View Toggle Button ---------- */
696724
.view-toggle-wrap {
697725
display: flex;
726+
flex-wrap: wrap;
698727
justify-content: center;
699728
align-items: center;
700729
gap: 10px;
@@ -2086,8 +2115,11 @@ footer a:hover {
20862115
margin-bottom: 8px;
20872116
}
20882117
.copilot-icon {
2089-
font-size: 1.8rem;
2118+
width: 36px;
2119+
height: 36px;
20902120
flex-shrink: 0;
2121+
color: var(--text);
2122+
fill: currentColor;
20912123
}
20922124
.copilot-callout-text {
20932125
flex: 1;
@@ -2101,18 +2133,23 @@ footer a:hover {
21012133
flex-shrink: 0;
21022134
}
21032135
.copilot-callout-links a {
2136+
display: inline-flex;
2137+
align-items: center;
21042138
white-space: nowrap;
2105-
padding: 8px 16px;
2106-
border-radius: 8px;
2107-
background: var(--accent);
2108-
color: #fff;
2109-
font-size: 0.85rem;
2139+
padding: 5px 10px;
2140+
border: 1px solid var(--border-light);
2141+
border-radius: 6px;
2142+
background: var(--surface-2);
2143+
color: var(--text-muted);
2144+
font-size: 0.8rem;
21102145
font-weight: 600;
21112146
text-decoration: none;
2112-
transition: opacity 0.2s;
2147+
transition: color 0.2s, border-color 0.2s, background 0.2s;
21132148
}
21142149
.copilot-callout-links a:hover {
2115-
opacity: 0.85;
2150+
color: var(--blue);
2151+
border-color: var(--blue);
2152+
background: var(--surface);
21162153
}
21172154
@media (max-width: 640px) {
21182155
.copilot-callout-inner {
@@ -2121,7 +2158,7 @@ footer a:hover {
21212158
}
21222159
.copilot-callout-links {
21232160
flex-direction: column;
2124-
width: 100%;
2161+
align-self: center;
21252162
}
21262163
.copilot-callout-links a {
21272164
text-align: center;
@@ -2165,8 +2202,13 @@ footer a:hover {
21652202
border-color: var(--accent);
21662203
color: #fff;
21672204
}
2168-
.share-li { font-family: Georgia, serif; font-weight: 800; font-size: 0.85rem; }
2169-
.share-reddit { font-size: 1.1rem; }
2205+
.share-li svg,
2206+
.share-bsky svg,
2207+
.share-reddit svg {
2208+
width: 16px;
2209+
height: 16px;
2210+
fill: currentColor;
2211+
}
21702212

21712213
/* ============================
21722214
Contribute Dropdown

templates/index.html

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,6 @@
199199
</nav>
200200

201201
<section class="hero">
202-
<div class="hero-badge">{{site.heroSnippetCount}}</div>
203202
<h1>{{site.tagline_line1}}<br><span class="gradient">{{site.tagline_line2}}</span></h1>
204203
<p>{{site.description}}</p>
205204
<div class="hero-actions">
@@ -227,29 +226,42 @@ <h1>{{site.tagline_line1}}<br><span class="gradient">{{site.tagline_line2}}</spa
227226
<div class="social-share" id="socialShare">
228227
<span class="share-label">{{share.label}}</span>
229228
<a href="https://x.com/intent/tweet?url=https%3A%2F%2Fjavaevolved.github.io&text=java.evolved%20%E2%80%93%20Every%20old%20Java%20pattern%20next%20to%20its%20modern%20replacement%2C%20side%20by%20side." target="_blank" rel="noopener" class="share-btn share-x" aria-label="Share on X">𝕏</a>
230-
<a href="https://bsky.app/intent/compose?text=java.evolved%20%E2%80%93%20Every%20old%20Java%20pattern%20next%20to%20its%20modern%20replacement%2C%20side%20by%20side.%20https%3A%2F%2Fjavaevolved.github.io" target="_blank" rel="noopener" class="share-btn share-bsky" aria-label="Share on Bluesky">🦋</a>
231-
<a href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fjavaevolved.github.io" target="_blank" rel="noopener" class="share-btn share-li" aria-label="Share on LinkedIn">in</a>
232-
<a href="https://www.reddit.com/submit?url=https%3A%2F%2Fjavaevolved.github.io&title=java.evolved%20%E2%80%93%20Old%20Java%20vs%20Modern%20Java%2C%20side%20by%20side" target="_blank" rel="noopener" class="share-btn share-reddit" aria-label="Share on Reddit"></a>
229+
<a href="https://bsky.app/intent/compose?text=java.evolved%20%E2%80%93%20Every%20old%20Java%20pattern%20next%20to%20its%20modern%20replacement%2C%20side%20by%20side.%20https%3A%2F%2Fjavaevolved.github.io" target="_blank" rel="noopener" class="share-btn share-bsky" aria-label="Share on Bluesky">
230+
<svg viewBox="0 0 24 24" aria-hidden="true">
231+
<path d="M5.202 2.857C7.954 4.922 10.913 9.11 12 11.358c1.087-2.247 4.046-6.436 6.798-8.501C20.783 1.366 24 .213 24 3.883c0 .732-.42 6.156-.667 7.037-.856 3.061-3.978 3.842-6.755 3.37 4.854.826 6.089 3.562 3.422 6.299-5.065 5.196-7.28-1.304-7.847-2.97-.104-.305-.152-.448-.153-.327 0-.121-.05.022-.153.327-.568 1.666-2.782 8.166-7.847 2.97-2.667-2.737-1.432-5.473 3.422-6.3-2.777.473-5.899-.308-6.755-3.369C.42 10.04 0 4.615 0 3.883c0-3.67 3.217-2.517 5.202-1.026"/>
232+
</svg>
233+
</a>
234+
<a href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fjavaevolved.github.io" target="_blank" rel="noopener" class="share-btn share-li" aria-label="Share on LinkedIn">
235+
<svg viewBox="0 0 16 16" aria-hidden="true">
236+
<path d="M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854zm4.943 12.248V6.169H2.542v7.225zM3.743 5.182c.837 0 1.358-.554 1.358-1.248-.015-.709-.521-1.248-1.342-1.248S2.4 3.225 2.4 3.934c0 .694.521 1.248 1.327 1.248zm3.105 8.212h2.401V9.359c0-.216.016-.432.079-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.251c0-2.219-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016l.016-.025V6.169H6.848c.03.678 0 7.225 0 7.225"/>
237+
</svg>
238+
</a>
239+
<a href="https://www.reddit.com/submit?url=https%3A%2F%2Fjavaevolved.github.io&title=java.evolved%20%E2%80%93%20Old%20Java%20vs%20Modern%20Java%2C%20side%20by%20side" target="_blank" rel="noopener" class="share-btn share-reddit" aria-label="Share on Reddit">
240+
<svg viewBox="0 0 24 24" aria-hidden="true">
241+
<path d="M12 0C5.373 0 0 5.373 0 12c0 3.314 1.343 6.314 3.515 8.485l-2.286 2.286C.775 23.225 1.097 24 1.738 24H12c6.627 0 12-5.373 12-12S18.627 0 12 0Zm4.388 3.199c1.104 0 1.999.895 1.999 1.999 0 1.105-.895 2-1.999 2-.946 0-1.739-.657-1.947-1.539v.002c-1.147.162-2.032 1.15-2.032 2.341v.007c1.776.067 3.4.567 4.686 1.363.473-.363 1.064-.58 1.707-.58 1.547 0 2.802 1.254 2.802 2.802 0 1.117-.655 2.081-1.601 2.531-.088 3.256-3.637 5.876-7.997 5.876-4.361 0-7.905-2.617-7.998-5.87-.954-.447-1.614-1.415-1.614-2.538 0-1.548 1.255-2.802 2.803-2.802.645 0 1.239.218 1.712.585 1.275-.79 2.881-1.291 4.64-1.365v-.01c0-1.663 1.263-3.034 2.88-3.207.188-.911.993-1.595 1.959-1.595Zm-8.085 8.376c-.784 0-1.459.78-1.506 1.797-.047 1.016.64 1.429 1.426 1.429.786 0 1.371-.369 1.418-1.385.047-1.017-.553-1.841-1.338-1.841Zm7.406 0c-.786 0-1.385.824-1.338 1.841.047 1.017.634 1.385 1.418 1.385.785 0 1.473-.413 1.426-1.429-.046-1.017-.721-1.797-1.506-1.797Zm-3.703 4.013c-.974 0-1.907.048-2.77.135-.147.015-.241.168-.183.305.483 1.154 1.622 1.964 2.953 1.964 1.33 0 2.47-.81 2.953-1.964.057-.137-.037-.29-.184-.305-.863-.087-1.795-.135-2.769-.135Z"/>
242+
</svg>
243+
</a>
233244
</div>
234245

235246
<section class="copilot-callout">
236247
<div class="copilot-callout-inner">
237-
<span class="copilot-icon">🤖</span>
248+
<svg class="copilot-icon" viewBox="0 0 48 48" aria-hidden="true">
249+
<path d="M47.801 34.003c-1.72 2.988-11.706 10.037-23.82 10.037S1.881 36.991.161 34.003a1.309 1.309 0 0 1-.161-.57v-5.615c.012-.17.047-.338.11-.498.744-1.867 2.692-4.58 5.206-5.308.333-.855.826-2.106 1.287-3.029a20.112 20.112 0 0 1-.104-2.171c0-2.659.563-4.992 2.262-6.729.793-.811 1.777-1.433 2.945-1.901C14.502 5.911 18.483 4 23.938 4c5.455 0 9.523 1.911 12.319 4.182 1.167.468 2.151 1.09 2.944 1.901 1.699 1.737 2.263 4.07 2.263 6.729 0 .736-.027 1.465-.105 2.171.461.923.954 2.174 1.288 3.029 2.513.728 4.461 3.441 5.205 5.308.081.205.115.424.115.645v5.318c0 .252-.04.502-.166.72ZM24.325 22.031h-.688a8.52 8.52 0 0 1-.709 1.016c-1.537 1.892-3.833 2.98-7.008 2.98-3.447 0-5.972-.717-7.557-2.514a4.408 4.408 0 0 1-.171-.21l-.195.21v13.155c2.867 1.558 9.02 4.353 15.984 4.353s13.117-2.795 15.984-4.353V23.513l-.195-.21s-.066.091-.171.21c-1.584 1.797-4.11 2.514-7.557 2.514-3.175 0-5.47-1.088-7.008-2.98a8.637 8.637 0 0 1-.709-1.016h-.033.033Zm-1.969-5.864a14.31 14.31 0 0 0 .127-1.785v-.042c-.003-1.537-.339-2.538-.876-3.152-.681-.78-2.09-1.378-5.06-1.057-3.008.326-4.69 1.073-5.643 2.048-.923.944-1.408 2.356-1.408 4.633 0 2.42.348 3.849 1.115 4.719.729.827 2.165 1.499 5.309 1.499 2.417 0 3.799-.786 4.683-1.873.948-1.168 1.482-2.878 1.753-4.99Zm3.25 0c.271 2.112.805 3.822 1.754 4.99.883 1.087 2.265 1.873 4.682 1.873 3.145 0 4.58-.672 5.309-1.499.767-.87 1.116-2.299 1.116-4.719 0-2.277-.485-3.689-1.408-4.633-.954-.975-2.635-1.722-5.644-2.048-2.969-.321-4.378.277-5.06 1.057-.537.614-.873 1.615-.876 3.152v.042c.002.53.042 1.123.127 1.785Z"/>
250+
<path d="M28.998 28.516c1.104 0 1.999.895 1.999 1.999v3.998a2 2 0 1 1-3.998 0v-3.998c0-1.104.895-1.999 1.999-1.999Zm-9.996 0c1.104 0 1.999.895 1.999 1.999v3.998a2 2 0 1 1-3.998 0v-3.998c0-1.104.895-1.999 1.999-1.999Z"/>
251+
</svg>
238252
<div class="copilot-callout-text">
239253
<strong>{{copilot.headline}}</strong>
240254
{{copilot.description}}
241255
</div>
242256
<div class="copilot-callout-links">
243-
<a href="https://github.com/solutions/use-case/app-modernization" target="_blank" rel="noopener">{{copilot.appModernization}}</a>
244-
<a href="https://docs.github.com/en/enterprise-cloud@latest/copilot/tutorials/modernize-java-applications" target="_blank" rel="noopener">{{copilot.javaGuide}}</a>
257+
<a href="https://learn.microsoft.com/en-us/azure/developer/github-copilot-app-modernization/" target="_blank" rel="noopener">{{copilot.appModernization}}</a>
245258
</div>
246259
</div>
247260
</section>
248261

249262
<section class="section" id="all-comparisons" style="padding-top:24px">
250263
<div class="section-header">
251264
<h2 class="section-title">{{site.allComparisons}}</h2>
252-
<span class="section-badge">{{site.snippetsBadge}}</span>
253265
</div>
254266
<div class="view-toggle-wrap">
255267
<div class="jdk-dropdown" id="categoryDropdown">
@@ -283,6 +295,10 @@ <h2 class="section-title">{{site.allComparisons}}</h2>
283295
<li data-jdk-filter="25">Java 25</li>
284296
</ul>
285297
</div>
298+
<button class="show-all-btn" id="showAllButton" type="button"
299+
data-show-label="{{filters.showAll}}" data-hide-label="{{filters.hideAll}}">
300+
{{filters.showAll}}
301+
</button>
286302
<button class="view-toggle-btn" id="viewToggle" aria-label="Toggle view mode">
287303
<span class="view-toggle-icon"></span>
288304
<span class="view-toggle-text">{{view.expandAll}}</span>
@@ -291,6 +307,10 @@ <h2 class="section-title">{{site.allComparisons}}</h2>
291307
<div class="tips-grid" id="tipsGrid">
292308
{{tipCards}}
293309
</div>
310+
<div class="pattern-start-message" id="patternStartMessage">
311+
<span class="pattern-start-icon" aria-hidden="true"></span>
312+
<p>{{filters.browsePrompt}}</p>
313+
</div>
294314
<p class="no-results-message" id="noResultsMessage" style="display:none">{{filters.noResults}}</p>
295315
</section>
296316

0 commit comments

Comments
 (0)