Skip to content

Commit f6fed5c

Browse files
authored
site: add filter type filter to the extensions page (#459)
Part of #370 and #375 Signed-off-by: Ignasi Barrera <ignasi@tetrate.io>
1 parent a784940 commit f6fed5c

5 files changed

Lines changed: 28 additions & 6 deletions

File tree

website/src/components/ExtensionCard.astro

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ interface Props {
66
description: string;
77
href: string;
88
tags?: string[];
9+
filterTypes?: string[];
910
}
1011
11-
const { name, type, categories, description, href, tags = [] } = Astro.props;
12+
const { name, type, categories, description, href, tags = [], filterTypes = [] } = Astro.props;
1213
const sortedCategories = [...categories].sort((a, b) => a.localeCompare(b));
1314
const sortedTags = [...tags].sort((a, b) => a.localeCompare(b));
1415
---
1516

1617
<a href={href} class="extension-card-link">
17-
<div class="extension-card" data-type={type} data-tags={tags.join(',')}>
18+
<div class="extension-card" data-type={type} data-tags={tags.join(',')} data-filter-types={filterTypes.join(',')}>
1819
<div class="extension-header">
1920
<h3>{name}</h3>
2021
<div class="extension-badges">

website/src/components/Extensions.astro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const featuredExtensions = loadExtensions().filter(ext => ext.featured === true)
1919
description={ext.description}
2020
href={`/extensions/${ext.name}`}
2121
tags={ext.tags}
22+
filterTypes={ext.filterType}
2223
/>
2324
))}
2425
</div>

website/src/pages/extensions.astro

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ const sortedTypes = [...new Set(extensions.map(ext => ext.type))]
1717
const sortedCategories = [...new Set(extensions.flatMap(ext => ext.categories))]
1818
.sort((a, b) => a.localeCompare(b));
1919
20+
// Collect unique filterTypes from extensions and sort alphabetically
21+
const sortedFilterTypes = [...new Set(extensions.flatMap(ext => ext.filterType))]
22+
.sort((a, b) => a.localeCompare(b));
23+
2024
// Helper function to format type names (snake_case to Title Case)
2125
function formatTypeName(type: string): string {
2226
return type
@@ -69,6 +73,14 @@ function formatTypeName(type: string): string {
6973
))}
7074
</select>
7175
</div>
76+
<div class="filter-type-filter">
77+
<select id="filter-type-filter" aria-label="Filter by filter type">
78+
<option value="">All Filter Types</option>
79+
{sortedFilterTypes.map(filterType => (
80+
<option value={filterType}>{formatTypeName(filterType)}</option>
81+
))}
82+
</select>
83+
</div>
7284
</div>
7385
</div>
7486
</section>
@@ -87,6 +99,7 @@ function formatTypeName(type: string): string {
8799
description={ext.description}
88100
href={`/extensions/${ext.name}`}
89101
tags={ext.tags}
102+
filterTypes={ext.filterType}
90103
/>
91104
</div>
92105
))}
@@ -114,13 +127,15 @@ function formatTypeName(type: string): string {
114127
const searchInput = document.getElementById('search-input') as HTMLInputElement;
115128
const typeFilter = document.getElementById('type-filter') as HTMLSelectElement;
116129
const categoryFilter = document.getElementById('category-filter') as HTMLSelectElement;
130+
const filterTypeFilter = document.getElementById('filter-type-filter') as HTMLSelectElement;
117131
const extensionsGrid = document.getElementById('extensions-grid');
118132
const noResults = document.getElementById('no-results');
119133

120134
function filterExtensions() {
121135
const searchTerm = searchInput?.value.toLowerCase() || '';
122136
const selectedType = typeFilter?.value || '';
123137
const selectedCategory = categoryFilter?.value || '';
138+
const selectedFilterType = filterTypeFilter?.value || '';
124139

125140
const cardWrappers = extensionsGrid?.querySelectorAll('[data-categories]');
126141
let visibleCount = 0;
@@ -132,15 +147,17 @@ function formatTypeName(type: string): string {
132147
const type = (card as HTMLElement)?.dataset.type || '';
133148
const tags = (card as HTMLElement)?.dataset.tags?.toLowerCase() || '';
134149
const categories = (wrapper as HTMLElement).dataset.categories?.split(',') || [];
150+
const filterTypes = (card as HTMLElement)?.dataset.filterTypes?.split(',') || [];
135151

136152
const matchesSearch = searchTerm === '' ||
137153
name.includes(searchTerm) ||
138154
description.includes(searchTerm) ||
139155
tags.includes(searchTerm);
140156
const matchesType = selectedType === '' || type === selectedType;
141157
const matchesCategory = selectedCategory === '' || categories.includes(selectedCategory);
158+
const matchesFilterType = selectedFilterType === '' || filterTypes.includes(selectedFilterType);
142159

143-
if (matchesSearch && matchesType && matchesCategory) {
160+
if (matchesSearch && matchesType && matchesCategory && matchesFilterType) {
144161
(wrapper as HTMLElement).style.display = '';
145162
visibleCount++;
146163
} else {
@@ -164,6 +181,7 @@ function formatTypeName(type: string): string {
164181
searchInput?.addEventListener('input', filterExtensions);
165182
typeFilter?.addEventListener('change', filterExtensions);
166183
categoryFilter?.addEventListener('change', filterExtensions);
184+
filterTypeFilter?.addEventListener('change', filterExtensions);
167185
</script>
168186
</body>
169187
</html>

website/src/styles/extensions.css

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
.filters {
2424
display: flex;
2525
gap: 16px;
26-
max-width: 800px;
27-
margin: 0 auto;
2826
}
2927

3028
.search-box {
@@ -54,6 +52,7 @@
5452
}
5553

5654
.type-filter select,
55+
.filter-type-filter select,
5756
.category-filter select {
5857
padding: 14px 40px 14px 20px;
5958
border: 2px solid var(--border);
@@ -72,13 +71,15 @@
7271
}
7372

7473
.type-filter select:focus,
74+
.filter-type-filter select:focus,
7575
.category-filter select:focus {
7676
outline: none;
7777
border-color: var(--primary);
7878
box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
7979
}
8080

8181
.type-filter select:hover,
82+
.filter-type-filter select:hover,
8283
.category-filter select:hover {
8384
border-color: var(--primary-light);
8485
}
@@ -132,6 +133,7 @@
132133
}
133134

134135
.type-filter select,
136+
.filter-type-filter select,
135137
.category-filter select {
136138
width: 100%;
137139
min-width: 0;

website/src/utils/extensions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface Extension {
2727
sourcePath: string;
2828
sourceUrl: string;
2929
configReferencePath?: string;
30+
filterType: string[];
3031
}
3132

3233
/**
@@ -44,4 +45,3 @@ export function loadExtensions(): Extension[] {
4445
}))
4546
.sort((a, b) => a.name.localeCompare(b.name));
4647
}
47-

0 commit comments

Comments
 (0)