@kolkrabbi/kol-styleguide 0.18.1 → 0.18.3

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-styleguide",
3
- "version": "0.18.1",
3
+ "version": "0.18.3",
4
4
  "private": false,
5
5
  "description": "Brand guide components and the brand tool",
6
6
  "license": "MIT",
@@ -22,11 +22,11 @@
22
22
  "react-dom": "^18.3.0 || ^19.0.0"
23
23
  },
24
24
  "devDependencies": {
25
- "@kolkrabbi/kol-icons": "^0.53.1",
25
+ "@kolkrabbi/kol-component": "^0.317.3",
26
+ "@kolkrabbi/kol-icons": "^0.53.3",
26
27
  "@kolkrabbi/kol-print": "^0.1.1",
27
- "@kolkrabbi/kol-component": "^0.317.1",
28
- "@kolkrabbi/kol-theme": "^0.200.1",
29
- "@kolkrabbi/kol-framework": "^0.65.0"
28
+ "@kolkrabbi/kol-framework": "^0.65.0",
29
+ "@kolkrabbi/kol-theme": "^0.200.3"
30
30
  },
31
31
  "files": [
32
32
  "src",
package/src/ColorLab.jsx CHANGED
@@ -261,10 +261,10 @@ export default function ColorLab({ value: valueProp, onChange, samples = [], lib
261
261
  /* HARMONIES (review 3): the DS's glyphs, each named on hover, the mode named in the label — on the Wheel tab only
262
262
  * (review 6 — *"you know there is a tab for wheel. why do you put it on every page?"*) */
263
263
  <>
264
- {/* the label in the rail's one text style (review 7 — *"why does wheel page have this text style"*): the word, the mode in meta */}
265
- <div className="flex items-baseline gap-2 kol-sans-body-02"><span className="text-emphasis">Harmony</span><span className="text-meta">{harmonyLabel(c.relation)}</span></div>
266
- /* review 5 — *"use bigger icons, and dont use background color"*, the row across the rail's width: no chip, the
267
- * glyph in OPAQUE ink (oq, never fg — a translucent stroke shows where the ring crosses a dot), full when chosen */
264
+ {/* THE EYEBROW IS THE RAIL'S LABEL (review 8 — *"IT WAS PERFECT!!! I was saying why is it only used here"*): the
265
+ * settings rail's section label, now on every label in the rail */}
266
+ <p className="kol-eyebrow text-fg-80">Harmony: {harmonyLabel(c.relation)}</p>
267
+ {/* review 5 — bigger glyphs across the rail's width, no chip, OPAQUE ink (oq, never fg), full when chosen */}
268
268
  <div className="grid w-full grid-cols-9">
269
269
  {HARMONY_TILES.map((id) => (
270
270
  <Tooltip key={id} label={harmonyLabel(id)}>
@@ -303,7 +303,7 @@ export default function ColorLab({ value: valueProp, onChange, samples = [], lib
303
303
  <span className="relative flex flex-col items-center gap-2">
304
304
  <Button size="md" tone="inverted" iconLeft="upload" onClick={(e) => { e.stopPropagation(); fileInput.current?.click() }}>Upload your image</Button>
305
305
  <span className="kol-sans-body-02 text-emphasis">Or drag and drop here</span>
306
- <span className="kol-sans-body-02 text-meta">File must be JPEG, JPG, PNG or WebP and up to 40MB</span>
306
+ <span className="whitespace-nowrap kol-sans-body-03 text-meta">File must be JPEG, JPG, PNG or WebP and up to 40MB</span>
307
307
  </span>
308
308
  )}
309
309
  <input ref={fileInput} type="file" accept="image/jpeg,image/png,image/webp" className="hidden" onChange={(e) => { fromFile(e.target.files?.[0]); e.target.value = '' }} />
@@ -313,7 +313,7 @@ export default function ColorLab({ value: valueProp, onChange, samples = [], lib
313
313
  * and linked beside them */
314
314
  <div className="flex flex-col gap-3">
315
315
  <div className="flex items-baseline justify-between gap-3">
316
- <span className="kol-sans-body-02 text-emphasis">Don’t have an image? Try one of ours:</span>
316
+ <span className="min-w-0 truncate kol-sans-body-02 text-emphasis">Don’t have an image? Try one of ours:</span>
317
317
  {library && <a href={library.href} target="_blank" rel="noreferrer" className="group inline-flex shrink-0 items-center gap-1 kol-sans-body-02 text-meta hover:text-emphasis">{library.label}<Icon name="external-link" size={12} className="text-oq-48 group-hover:text-oq-96" /></a>}
318
318
  </div>
319
319
  <div className="grid grid-cols-4 gap-2">
@@ -338,9 +338,10 @@ export default function ColorLab({ value: valueProp, onChange, samples = [], lib
338
338
  <div className="flex h-8 w-60 overflow-hidden rounded" aria-label="Palette">
339
339
  {c.swatches.map((s) => <span key={s.index} className="flex-1" style={{ background: s.hex }} title={s.hex} />)}
340
340
  </div>
341
- {/* RANDOMISE (review 6, Adobe's shuffle): the nav rung, like the header's controls; Copy CSS is in the header, where
342
- * every lab keeps it */}
343
- {view === 'palette' && <Button variant="nav" size="sm" iconLeft="shuffle" className="ml-auto" onClick={roll}>Randomise</Button>}
341
+ {/* RANDOMISE (review 6, Adobe's shuffle; review 8 — *"WRONG FUCKING BUTTON TONE"*): an explicit tone, so no wrapper's
342
+ * ground repaints it — the inverted button this window already wears on Upload your image. Copy CSS is in the header,
343
+ * where every lab keeps it. His review decides the rung. */}
344
+ {view === 'palette' && <Button tone="inverted" size="sm" iconLeft="shuffle" className="ml-auto" onClick={roll}>Randomise</Button>}
344
345
  </div>
345
346
  )
346
347
  const paletteStage = (
@@ -410,7 +411,7 @@ export default function ColorLab({ value: valueProp, onChange, samples = [], lib
410
411
  /* the pair, Adobe's: Foreground and Background side by side, swap between them, each colour's lightness under it */
411
412
  const pairCol = (label, i, key) => (
412
413
  <div className="flex min-w-0 flex-col gap-2">
413
- <span className="kol-sans-body-02 text-meta">{label}</span>
414
+ <span className="kol-eyebrow text-fg-80">{label}</span>
414
415
  <div className="flex items-center gap-2">
415
416
  <span className="size-4 shrink-0 rounded-full" style={{ background: c.colors[i] }} />
416
417
  <Dropdown size="sm" value={String(i)} onChange={(v) => setPair({ fg: fgI, bg: bgI, [key]: Number(v) })} options={colourOptions} className="min-w-0 flex-1" ariaLabel={`${label} colour`} />
@@ -421,7 +422,7 @@ export default function ColorLab({ value: valueProp, onChange, samples = [], lib
421
422
  const pairHead = (
422
423
  <div className="flex flex-col gap-4">
423
424
  <div className="flex items-center justify-between gap-3">
424
- <span className="kol-sans-body-02 text-emphasis">Contrast ratio</span>
425
+ <span className="kol-eyebrow text-fg-80">Contrast ratio</span>
425
426
  <span className={`inline-flex items-center gap-1 rounded px-2 py-0.5 kol-mono-12 ${ratio >= 4.5 ? 'bg-oq-08 text-emphasis' : 'bg-oq-04 text-meta'}`}><Icon name={ratio >= 4.5 ? 'check' : 'alert-triangle'} size={12} className={ratio >= 4.5 ? 'text-oq-96' : 'text-oq-48'} />{ratioText(ratio)} : 1</span>
426
427
  </div>
427
428
  <div className="grid grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-start gap-2">
@@ -433,7 +434,7 @@ export default function ColorLab({ value: valueProp, onChange, samples = [], lib
433
434
  )
434
435
  const summaryTable = (
435
436
  <div className="flex flex-col">
436
- <div className="grid grid-cols-[minmax(0,1fr)_64px_64px] border-b border-oq-16 pb-2 kol-sans-body-02 text-meta"><span>Category</span><span>AA</span><span>AAA</span></div>
437
+ <div className="grid grid-cols-[minmax(0,1fr)_64px_64px] border-b border-oq-16 pb-2 kol-eyebrow text-fg-80"><span>Category</span><span>AA</span><span>AAA</span></div>
437
438
  {SUMMARY.map((r) => (
438
439
  <div key={r.id} className="grid grid-cols-[minmax(0,1fr)_64px_64px] items-center border-b border-oq-08 py-3 kol-sans-body-02 text-emphasis"><span>{r.label}</span><Verdict ok={r.aa} /><Verdict ok={r.aaa} na={r.aaa === null} /></div>
439
440
  ))}
@@ -442,7 +443,7 @@ export default function ColorLab({ value: valueProp, onChange, samples = [], lib
442
443
  /* KOL's text levels: the foreground at every ink stop over the background, each measured */
443
444
  const ladder = (
444
445
  <div className="flex flex-col gap-2">
445
- <span className="kol-sans-body-02 text-emphasis">Text levels</span>
446
+ <span className="kol-eyebrow text-fg-80">Text levels</span>
446
447
  <div className="flex w-full flex-col rounded p-3" style={{ background: bg }}>
447
448
  {c.text.map((x) => {
448
449
  const r = contrastRatio(over(fg, bg, x.stop / 100), bg)
@@ -463,7 +464,7 @@ export default function ColorLab({ value: valueProp, onChange, samples = [], lib
463
464
  <>
464
465
  {pairHead}
465
466
  <div className="flex flex-col">
466
- <span className="border-b border-oq-16 pb-2 kol-sans-body-02 text-meta">Foreground colors that pass AA</span>
467
+ <span className="border-b border-oq-16 pb-2 kol-eyebrow text-fg-80">Foreground colors that pass AA</span>
467
468
  {suggestions.length === 0 && <span className="py-3 kol-sans-body-02 text-meta">None at this hue. Move the background’s lightness.</span>}
468
469
  {suggestions.map((x) => (
469
470
  <button key={x.hex} type="button" onClick={() => editAt(fgI, x.hex)} className="grid cursor-pointer grid-cols-[16px_minmax(0,1fr)_auto] items-center gap-3 border-b border-oq-08 py-2 text-left kol-mono-12 text-emphasis hover:bg-oq-04">
@@ -477,23 +478,27 @@ export default function ColorLab({ value: valueProp, onChange, samples = [], lib
477
478
  <>
478
479
  {pairHead}
479
480
  <div className="flex flex-col gap-2">
480
- <span className="kol-sans-body-02 text-emphasis">Target ratio</span>
481
+ <span className="kol-eyebrow text-fg-80">Target ratio</span>
481
482
  <Slider className="w-full" min={1} max={21} step={0.5} value={target ?? Math.round(ratio * 2) / 2} onChange={(t) => { setTarget(t); editAt(fgI, solveFor(t)) }} readout="input" displayWidth={4} readoutPreset="rail" aria-label="Target contrast ratio" />
482
483
  <span className="kol-sans-body-02 text-meta">The foreground’s lightness moves until the pair reaches it.</span>
483
484
  </div>
484
485
  </>
485
486
  ) },
486
487
  ]
487
- const previewImage = image ?? samples[0]?.src
488
+ /* THE PREVIEW IN THE PALETTE'S OWN FORMS (review 8 — *"how is this using ANYTHING but the colors?? … show some
489
+ * forms that use the pallette"*): the page in bg and fg, the other colours as forms beside the text; the DS Button */
490
+ const FORMS = ['left-[8%] top-[10%] w-[52%] aspect-square rounded-full', 'right-[8%] bottom-[8%] w-[38%] aspect-square rounded-[12%]', 'left-[6%] bottom-[12%] h-[14%] w-[48%] rounded-full', 'right-[10%] top-[8%] h-[9%] w-[32%] rounded']
491
+ const forms = c.colors.filter((_, i) => i !== fgI && i !== bgI)
488
492
  const contrastStage = (
489
- /* ADOBE'S PREVIEW: the image beside the pair as a page would use it — a headline, body text and a button */
490
493
  <div className="flex h-full min-h-[240px] flex-col gap-3">
491
- <div className={`grid min-h-0 flex-1 grid-rows-[minmax(0,1fr)] overflow-hidden rounded ${previewImage ? 'grid-cols-2' : ''}`} style={{ background: bg, color: fg }}>
492
- {previewImage && <img src={previewImage} alt="" className="h-full min-h-0 w-full object-cover" />}
494
+ <div className="grid min-h-0 flex-1 grid-cols-2 grid-rows-[minmax(0,1fr)] overflow-hidden rounded" style={{ background: bg, color: fg }}>
495
+ <div className="relative min-h-0 overflow-hidden">
496
+ {(forms.length ? forms : [fg]).slice(0, 4).map((hex, i) => <span key={`${hex}${i}`} className={`absolute ${FORMS[i]}`} style={{ background: hex }} />)}
497
+ </div>
493
498
  <div className="flex min-h-0 flex-col justify-center gap-6 p-10">
494
499
  <span className="kol-sans-heading-01 leading-none">The quick brown fox</span>
495
500
  <span className="max-w-[48ch] kol-sans-body-02">Body text in the foreground on the background, the size most of a page is read at. If this line is hard to read, so is the page.</span>
496
- <span className="inline-flex self-start rounded px-6 py-3 kol-mono-12" style={{ background: fg, color: bg }}>Button</span>
501
+ <Button size="md" className="self-start" style={{ '--kol-tone-bg': fg, '--kol-tone-hover-bg': fg, '--kol-tone-fg': bg, '--kol-tone-hover-fg': bg, '--kol-tone-image': 'none', '--kol-tone-hover-image': 'none' }}>Button</Button>
497
502
  </div>
498
503
  </div>
499
504
  {paletteFoot}
@@ -510,7 +515,7 @@ export default function ColorLab({ value: valueProp, onChange, samples = [], lib
510
515
  const visionRail = [{ id: 'conflicts', label: 'Conflicts', content: (
511
516
  <>
512
517
  <div className="flex items-center justify-between gap-3 rounded bg-oq-04 p-3">
513
- <span className="kol-sans-body-02 text-emphasis">Potential color blind conflicts</span>
518
+ <span className="kol-eyebrow text-fg-80">Potential color blind conflicts</span>
514
519
  <span className={`inline-flex shrink-0 items-center gap-1 rounded px-2 py-0.5 kol-mono-12 ${conflicts ? 'bg-oq-08 text-emphasis' : 'text-meta'}`}>{conflicts && <Icon name="alert-triangle" size={12} className="text-oq-96" />}{conflicts ? 'Conflicts found' : 'None'}</span>
515
520
  </div>
516
521
  <PaletteDots colors={c.colors} />
@@ -65,7 +65,7 @@ export default function LabWindow({ title, actions, tabs = [], tab: tabProp, onT
65
65
  <div {...grabProps} className="kol-rail-grab kol-rail-grab--left hidden md:block" />
66
66
  {/* THE TABSROW AT THE TOP OF EVERY WINDOW (review 6 — *"why dont we make it a rule at top of each window?"*):
67
67
  * one section or many, the rail opens on its tabs */}
68
- {tabs.length > 0 && <TabsRow size="md" tabs={tabs.map(({ id, label, icon }) => ({ id, label, icon }))} value={open?.id} onChange={setTab} ariaLabel={`${title} sections`} />}
68
+ {tabs.length > 0 && <TabsRow type="sans" tabs={tabs.map(({ id, label, icon }) => ({ id, label, icon }))} value={open?.id} onChange={setTab} ariaLabel={`${title} sections`} />}
69
69
  <div className="flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto">{open?.content}</div>
70
70
  {foot && <div className="flex flex-wrap items-center gap-1">{foot}</div>}
71
71
  </aside>