|
5 | 5 |
|
6 | 6 | let selected_slug = $state<string | null>(null); |
7 | 7 | let search_query = $state(''); |
| 8 | + let sort_order = $state<'default' | 'largest' | 'smallest'>('default'); |
8 | 9 |
|
9 | | - let filtered_sections = $derived( |
10 | | - data.sections.filter( |
| 10 | + let filtered_sections = $derived.by(() => { |
| 11 | + // First, filter sections |
| 12 | + const filtered = data.sections.filter( |
11 | 13 | (section) => |
12 | 14 | section.slug.toLowerCase().includes(search_query.toLowerCase()) || |
13 | 15 | section.summary.toLowerCase().includes(search_query.toLowerCase()), |
14 | | - ), |
15 | | - ); |
| 16 | + ); |
| 17 | +
|
| 18 | + // Then, sort based on selected sort order |
| 19 | + if (sort_order === 'largest') { |
| 20 | + return [...filtered].sort((a, b) => b.space_savings - a.space_savings); |
| 21 | + } else if (sort_order === 'smallest') { |
| 22 | + return [...filtered].sort((a, b) => a.space_savings - b.space_savings); |
| 23 | + } |
| 24 | +
|
| 25 | + return filtered; |
| 26 | + }); |
16 | 27 |
|
17 | 28 | let selected_section = $derived( |
18 | 29 | selected_slug ? data.sections.find((s) => s.slug === selected_slug) : null, |
|
48 | 59 |
|
49 | 60 | <div class="main-content"> |
50 | 61 | <aside class="sidebar"> |
| 62 | + <div class="sort-controls"> |
| 63 | + <span class="sort-label">Sort by:</span> |
| 64 | + <div class="sort-buttons"> |
| 65 | + <button |
| 66 | + class="sort-button" |
| 67 | + class:active={sort_order === 'default'} |
| 68 | + onclick={() => (sort_order = 'default')} |
| 69 | + > |
| 70 | + Default |
| 71 | + </button> |
| 72 | + <button |
| 73 | + class="sort-button" |
| 74 | + class:active={sort_order === 'largest'} |
| 75 | + onclick={() => (sort_order = 'largest')} |
| 76 | + > |
| 77 | + Largest Reduction |
| 78 | + </button> |
| 79 | + <button |
| 80 | + class="sort-button" |
| 81 | + class:active={sort_order === 'smallest'} |
| 82 | + onclick={() => (sort_order = 'smallest')} |
| 83 | + > |
| 84 | + Smallest Reduction |
| 85 | + </button> |
| 86 | + </div> |
| 87 | + </div> |
51 | 88 | <div class="search-box"> |
52 | 89 | <input |
53 | 90 | type="search" |
|
64 | 101 | class:active={selected_slug === section.slug} |
65 | 102 | onclick={() => select_section(section.slug)} |
66 | 103 | > |
67 | | - <div class="section-title">{section.slug}</div> |
| 104 | + <div class="section-header"> |
| 105 | + <div class="section-title">{section.slug}</div> |
| 106 | + <div class="section-savings" class:negative={section.space_savings < 0}> |
| 107 | + {section.space_savings.toFixed(1)}% |
| 108 | + </div> |
| 109 | + </div> |
68 | 110 | <div class="section-preview"> |
69 | 111 | {is_distilled |
70 | 112 | ? section.summary.slice(0, 100) + (section.summary.length > 100 ? '...' : '') |
|
156 | 198 | flex-direction: column; |
157 | 199 | } |
158 | 200 |
|
| 201 | + .sort-controls { |
| 202 | + padding: 1rem; |
| 203 | + border-bottom: 1px solid #e0e0e0; |
| 204 | + display: flex; |
| 205 | + flex-direction: column; |
| 206 | + gap: 0.5rem; |
| 207 | + } |
| 208 | +
|
| 209 | + .sort-label { |
| 210 | + font-size: 0.8125rem; |
| 211 | + font-weight: 500; |
| 212 | + color: #666; |
| 213 | + } |
| 214 | +
|
| 215 | + .sort-buttons { |
| 216 | + display: flex; |
| 217 | + gap: 0.5rem; |
| 218 | + flex-wrap: wrap; |
| 219 | + } |
| 220 | +
|
| 221 | + .sort-button { |
| 222 | + padding: 0.375rem 0.75rem; |
| 223 | + border: 1px solid #e0e0e0; |
| 224 | + border-radius: 4px; |
| 225 | + background: white; |
| 226 | + font-size: 0.8125rem; |
| 227 | + font-family: inherit; |
| 228 | + cursor: pointer; |
| 229 | + transition: all 0.15s; |
| 230 | + color: #666; |
| 231 | + } |
| 232 | +
|
| 233 | + .sort-button:hover { |
| 234 | + background: #f9fafb; |
| 235 | + border-color: #d0d0d0; |
| 236 | + } |
| 237 | +
|
| 238 | + .sort-button.active { |
| 239 | + background: #3b82f6; |
| 240 | + border-color: #3b82f6; |
| 241 | + color: white; |
| 242 | + } |
| 243 | +
|
159 | 244 | .search-box { |
160 | 245 | padding: 1rem; |
161 | 246 | border-bottom: 1px solid #e0e0e0; |
|
204 | 289 | border-left: 3px solid #3b82f6; |
205 | 290 | } |
206 | 291 |
|
| 292 | + .section-header { |
| 293 | + display: flex; |
| 294 | + justify-content: space-between; |
| 295 | + align-items: center; |
| 296 | + gap: 0.5rem; |
| 297 | + margin-bottom: 0.25rem; |
| 298 | + } |
| 299 | +
|
207 | 300 | .section-title { |
208 | 301 | font-size: 0.9375rem; |
209 | 302 | font-weight: 500; |
210 | 303 | color: #1a1a1a; |
211 | | - margin-bottom: 0.25rem; |
| 304 | + flex: 1; |
| 305 | + overflow: hidden; |
| 306 | + text-overflow: ellipsis; |
| 307 | + white-space: nowrap; |
| 308 | + } |
| 309 | +
|
| 310 | + .section-savings { |
| 311 | + font-size: 0.75rem; |
| 312 | + font-weight: 600; |
| 313 | + color: #10b981; |
| 314 | + padding: 0.125rem 0.375rem; |
| 315 | + background: #d1fae5; |
| 316 | + border-radius: 3px; |
| 317 | + white-space: nowrap; |
| 318 | + } |
| 319 | +
|
| 320 | + .section-savings.negative { |
| 321 | + color: #ef4444; |
| 322 | + background: #fee2e2; |
212 | 323 | } |
213 | 324 |
|
214 | 325 | .section-preview { |
|
0 commit comments