@kolkrabbi/kol-component 0.54.0 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolkrabbi/kol-component",
3
- "version": "0.54.0",
3
+ "version": "0.55.0",
4
4
  "description": "KOL design-system components — atoms through organisms, emitting canonical kol-* classes. Pairs with @kolkrabbi/kol-theme for styling.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -3,6 +3,7 @@ import Tag from '../atoms/Tag.jsx'
3
3
  import Divider from '../atoms/Divider.jsx'
4
4
  import Button from '../atoms/Button.jsx'
5
5
  import { Icon } from '@kolkrabbi/kol-icons'
6
+ import { glyphSize } from '../hooks/glyphLadders.js'
6
7
  import IconFrame from '../atoms/IconFrame.jsx'
7
8
 
8
9
  /**
@@ -228,7 +229,11 @@ const ContentFilters = ({
228
229
  aria-label="Toggle filters"
229
230
  style={{ background: 'transparent', border: 'none', cursor: 'pointer', color: 'inherit' }}
230
231
  >
231
- <IconSeam name="filter" size={16} />
232
+ {/* SOLO ladder, md rung — a 32px square takes a 20px glyph.
233
+ * Both header glyphs were 16 (the sm rung) in md boxes, which is
234
+ * the exact hand-transcription hooks/glyphLadders.js exists to
235
+ * stop and the one ActionButton's docstring already names. */}
236
+ <IconSeam name="filter" size={glyphSize('md', true)} />
232
237
  </button>
233
238
  <div
234
239
  className="kol-expand flex items-center justify-center rounded-sm cursor-pointer hover:bg-fg-04"
@@ -254,7 +259,7 @@ const ContentFilters = ({
254
259
  position: searchOpen ? 'absolute' : 'relative',
255
260
  }}
256
261
  >
257
- <IconSeam name="search" size={16} />
262
+ <IconSeam name="search" size={glyphSize('md', true)} />
258
263
  </span>
259
264
  {searchOpen && (
260
265
  <input
@@ -284,6 +289,34 @@ const ContentFilters = ({
284
289
  </div>
285
290
 
286
291
  <div className="flex items-center gap-8">
292
+ {/* The count and LIST/GRID ride the HEADER row, above the divider.
293
+ *
294
+ * "N of N" appears ONLY while the filter panel is open (user ruling
295
+ * 2026-08-15) — with nothing filtered it always reads "12 of 12",
296
+ * which is a number that has never once told anyone anything. It
297
+ * earns its place the moment a filter can change it.
298
+ *
299
+ * Ink stays `text-fg-64`: static information, not a toggle, so it
300
+ * takes neither the 96 active nor the 32 rest. */}
301
+ {showCount && isExpanded && (
302
+ <span className={countClassName} style={{ letterSpacing: 1 }}>
303
+ {filteredItems.length} of {totalCount}
304
+ </span>
305
+ )}
306
+ {layoutOptions && (
307
+ <div className="flex items-center gap-4">
308
+ {layoutOptions.map((opt) => (
309
+ <span
310
+ key={opt.value}
311
+ onClick={() => setLayout(opt.value)}
312
+ className={`${layoutClassName} cursor-pointer select-none ${layout === opt.value ? stripActiveClassName : stripRestClassName}`}
313
+ style={{ letterSpacing: 1 }}
314
+ >
315
+ {opt.label}
316
+ </span>
317
+ ))}
318
+ </div>
319
+ )}
287
320
  {/* RECENT / SAVED is the SAME STRIP as LIST / GRID, not a ViewToggle.
288
321
  * Read off kol-monitor's original (_tmp/2026-08-15-shell-adoption/
289
322
  * ContentFilters.jsx:225-232): inline spans, `kol-helper-14`,
@@ -312,16 +345,15 @@ const ContentFilters = ({
312
345
 
313
346
  <Divider className="mb-4" />
314
347
 
315
- {/* ONE ROW BELOW THE DIVIDER (user ruling 2026-08-15, four rounds of QA
316
- * against a fork of this file). Filter groups are left-aligned COLUMNS
317
- * label above values — and appear only while the filter toggle is open.
318
- * The layout strip is right-aligned and ALWAYS visible.
348
+ {/* BELOW the divider: the filter GROUPS only. Left-aligned columns
349
+ * label above values visible only while the filter toggle is open.
319
350
  *
320
- * `items-start` is load-bearing: it pins the strip to the label row so
321
- * the values hang beneath it. The strip previously rendered in its own
322
- * row AFTER this block, which is why expanding a filter group pushed it
323
- * down the page the defect that started the whole ticket. */}
324
- {(layoutOptions || isExpanded || showCount) && (
351
+ * The count + layout strip moved ABOVE the divider into the header row
352
+ * (user ruling 2026-08-15, later pass), reversing the earlier "one row
353
+ * below the divider" cut. It also settles the defect that ruling was
354
+ * fighting for good: the strip cannot be pushed down the page by an
355
+ * expanding filter group if it is not in the same row as one. */}
356
+ {isExpanded && (
325
357
  <div className="flex items-start justify-between gap-16 pb-4">
326
358
  <div className="flex items-start gap-16">
327
359
  {isExpanded && filterGroups.map((group) => renderFilterGroup(group))}
@@ -336,31 +368,6 @@ const ContentFilters = ({
336
368
  </button>
337
369
  )}
338
370
  </div>
339
- {/* The count rides the LAYOUT row, not the header (user ruling
340
- * 2026-08-15) — same `kol-helper-12` + 1px tracking as LIST/GRID
341
- * beside it. Ink stays `text-fg-64`: it is static information, not
342
- * a toggle, so it takes neither the 96 active nor the 32 rest. */}
343
- <div className="flex items-center gap-4 flex-shrink-0">
344
- {showCount && (
345
- <span className={countClassName} style={{ letterSpacing: 1 }}>
346
- {filteredItems.length} of {totalCount}
347
- </span>
348
- )}
349
- {layoutOptions && (
350
- <div className="flex items-center gap-4">
351
- {layoutOptions.map((opt) => (
352
- <span
353
- key={opt.value}
354
- onClick={() => setLayout(opt.value)}
355
- className={`${layoutClassName} cursor-pointer select-none ${layout === opt.value ? stripActiveClassName : stripRestClassName}`}
356
- style={{ letterSpacing: 1 }}
357
- >
358
- {opt.label}
359
- </span>
360
- ))}
361
- </div>
362
- )}
363
- </div>
364
371
  </div>
365
372
  )}
366
373