@tollerud/ui 3.0.0 → 3.1.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.
Files changed (86) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +35 -0
  3. package/SKILL.md +5 -4
  4. package/dist/avatar.d.ts +3 -2
  5. package/dist/avatar.js +1 -1
  6. package/dist/bento-dashboard.js +6 -1
  7. package/dist/button.d.ts +1 -1
  8. package/dist/button.js +1 -1
  9. package/dist/{chunk-7TOT5ME3.js → chunk-3LTW224O.js} +6 -6
  10. package/dist/chunk-3LTW224O.js.map +1 -0
  11. package/dist/{chunk-RWJELAS6.js → chunk-ADE22JSR.js} +12 -4
  12. package/dist/chunk-ADE22JSR.js.map +1 -0
  13. package/dist/chunk-AQT3FZRQ.js +23 -0
  14. package/dist/chunk-AQT3FZRQ.js.map +1 -0
  15. package/dist/{chunk-VTRUUT5K.js → chunk-IUPVQWO5.js} +4 -4
  16. package/dist/chunk-IUPVQWO5.js.map +1 -0
  17. package/dist/{chunk-ISHZ6ZPJ.js → chunk-JFOW2DI5.js} +17 -5
  18. package/dist/chunk-JFOW2DI5.js.map +1 -0
  19. package/dist/{chunk-OONIUDST.js → chunk-OLHMMFQ7.js} +3 -8
  20. package/dist/chunk-OLHMMFQ7.js.map +1 -0
  21. package/dist/chunk-ONMTHBZ4.js +54 -0
  22. package/dist/chunk-ONMTHBZ4.js.map +1 -0
  23. package/dist/{chunk-XR5QBVEV.js → chunk-OVSIOZHJ.js} +3 -3
  24. package/dist/{chunk-XR5QBVEV.js.map → chunk-OVSIOZHJ.js.map} +1 -1
  25. package/dist/{chunk-V3P5QLLX.js → chunk-Q54CVE3W.js} +3 -3
  26. package/dist/{chunk-V3P5QLLX.js.map → chunk-Q54CVE3W.js.map} +1 -1
  27. package/dist/chunk-QEIEWGHA.js +62 -0
  28. package/dist/chunk-QEIEWGHA.js.map +1 -0
  29. package/dist/{chunk-CBQ63EBL.js → chunk-QQHBEACI.js} +9 -6
  30. package/dist/chunk-QQHBEACI.js.map +1 -0
  31. package/dist/chunk-T3UQ7G4T.js +58 -0
  32. package/dist/chunk-T3UQ7G4T.js.map +1 -0
  33. package/dist/{chunk-DGCRHVWW.js → chunk-VFS3V3VY.js} +12 -5
  34. package/dist/chunk-VFS3V3VY.js.map +1 -0
  35. package/dist/chunk-VOARBYVQ.js +44 -0
  36. package/dist/chunk-VOARBYVQ.js.map +1 -0
  37. package/dist/{chunk-3TGMGBKM.js → chunk-YPP7QHYT.js} +5 -5
  38. package/dist/{chunk-3TGMGBKM.js.map → chunk-YPP7QHYT.js.map} +1 -1
  39. package/dist/{chunk-O57QMLNI.js → chunk-YTU7BRDW.js} +16 -12
  40. package/dist/chunk-YTU7BRDW.js.map +1 -0
  41. package/dist/{chunk-DFM7UUKB.js → chunk-ZTFOR3AN.js} +4 -4
  42. package/dist/{chunk-DFM7UUKB.js.map → chunk-ZTFOR3AN.js.map} +1 -1
  43. package/dist/cta-band.js +1 -1
  44. package/dist/data-table.js +3 -3
  45. package/dist/date-picker.js +1 -1
  46. package/dist/footer.js +2 -1
  47. package/dist/form-row.d.ts +4 -0
  48. package/dist/form-row.js +1 -1
  49. package/dist/hero-block.js +3 -3
  50. package/dist/index.d.ts +1 -0
  51. package/dist/index.js +22 -21
  52. package/dist/monogram.d.ts +20 -0
  53. package/dist/monogram.js +5 -0
  54. package/dist/monogram.js.map +1 -0
  55. package/dist/noir-glow-background.d.ts +7 -1
  56. package/dist/noir-glow-background.js +1 -1
  57. package/dist/pill.d.ts +5 -2
  58. package/dist/pill.js +1 -1
  59. package/dist/pricing-card.js +2 -2
  60. package/dist/skeleton.d.ts +10 -2
  61. package/dist/skeleton.js +1 -1
  62. package/dist/slider.js +1 -1
  63. package/dist/switch.js +1 -1
  64. package/dist/timeline.js +1 -1
  65. package/globals-layers.css +84 -0
  66. package/package.json +5 -3
  67. package/registry.json +17 -1
  68. package/tokens.css +20 -0
  69. package/tollerud-avatar-full.png +0 -0
  70. package/dist/chunk-7TOT5ME3.js.map +0 -1
  71. package/dist/chunk-CBQ63EBL.js.map +0 -1
  72. package/dist/chunk-DGCRHVWW.js.map +0 -1
  73. package/dist/chunk-FGXOV2QH.js +0 -23
  74. package/dist/chunk-FGXOV2QH.js.map +0 -1
  75. package/dist/chunk-HYQGOC2E.js +0 -79
  76. package/dist/chunk-HYQGOC2E.js.map +0 -1
  77. package/dist/chunk-ISHZ6ZPJ.js.map +0 -1
  78. package/dist/chunk-O57QMLNI.js.map +0 -1
  79. package/dist/chunk-OONIUDST.js.map +0 -1
  80. package/dist/chunk-PLF3BBQI.js +0 -139
  81. package/dist/chunk-PLF3BBQI.js.map +0 -1
  82. package/dist/chunk-Q74VRQEX.js +0 -26
  83. package/dist/chunk-Q74VRQEX.js.map +0 -1
  84. package/dist/chunk-RWJELAS6.js.map +0 -1
  85. package/dist/chunk-VTRUUT5K.js.map +0 -1
  86. /package/{tia-full-figure.svg → tollerud-avatar-full.svg} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/Switch.tsx"],"names":[],"mappings":";;;;AASA,IAAM,MAAA,GAAS,UAAA;AAAA,EACb,CAAC,EAAE,SAAA,EAAW,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,OAAA,EAAS,cAAA,EAAgB,QAAA,EAAU,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AACtF,IAAA,MAAM,SAAS,KAAA,EAAM;AACrB,IAAA,MAAM,KAAK,MAAA,IAAU,MAAA;AACrB,IAAA,MAAM,eAAe,OAAA,KAAY,MAAA;AACjC,IAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,IAAI,QAAA,CAAS,CAAC,CAAC,cAAc,CAAA;AACvE,IAAA,MAAM,IAAA,GAAO,eAAe,OAAA,GAAU,eAAA;AAEtC,IAAA,uBACE,IAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAS,EAAA;AAAA,QACT,SAAA,EAAW,EAAA;AAAA,UACT,mEAAA;AAAA,UACA,oCAAA;AAAA,UACA,MAAM,QAAA,IAAY,mDAAA;AAAA,UAClB;AAAA,SACF;AAAA,QAEA,QAAA,EAAA;AAAA,0BAAA,IAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,EAAA;AAAA,gBACT,sEAAA;AAAA,gBACA,yCAAA;AAAA,gBACA,OAAO,wDAAA,GAA2D;AAAA,eACpE;AAAA,cAEA,QAAA,EAAA;AAAA,gCAAA,GAAA;AAAA,kBAAC,OAAA;AAAA,kBAAA;AAAA,oBACC,GAAA;AAAA,oBACA,EAAA;AAAA,oBACA,IAAA,EAAK,UAAA;AAAA,oBACL,IAAA,EAAK,QAAA;AAAA,oBACL,OAAA,EAAS,IAAA;AAAA,oBACT,SAAA,EAAU,8DAAA;AAAA,oBACV,QAAA,EAAU,CAAC,CAAA,KAAM;AACf,sBAAA,IAAI,CAAC,YAAA,EAAc,kBAAA,CAAmB,CAAA,CAAE,OAAO,OAAO,CAAA;AACtD,sBAAA,QAAA,GAAW,CAAC,CAAA;AAAA,oBACd,CAAA;AAAA,oBACC,GAAG;AAAA;AAAA,iBACN;AAAA,gCACA,GAAA;AAAA,kBAAC,MAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAW,EAAA;AAAA,sBACT,8DAAA;AAAA,sBACA,sCAAA;AAAA,sBACA,OAAO,sCAAA,GAAyC;AAAA;AAClD;AAAA;AACF;AAAA;AAAA,WACF;AAAA,UACC,KAAA,oBAAS,GAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA;AAAA,KACzB;AAAA,EAEJ;AACF;AACA,MAAA,CAAO,WAAA,GAAc,QAAA","file":"chunk-YTU7BRDW.js","sourcesContent":["'use client'\n\nimport { type InputHTMLAttributes, forwardRef, useId, useState } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {\n label?: string\n}\n\nconst Switch = forwardRef<HTMLInputElement, SwitchProps>(\n ({ className, label, id: idProp, checked, defaultChecked, onChange, ...props }, ref) => {\n const autoId = useId()\n const id = idProp ?? autoId\n const isControlled = checked !== undefined\n const [internalChecked, setInternalChecked] = useState(!!defaultChecked)\n const isOn = isControlled ? checked : internalChecked\n\n return (\n <label\n htmlFor={id}\n className={cn(\n 'inline-flex items-center gap-2.5 cursor-pointer select-none group',\n 'text-sm text-tollerud-text-primary',\n props.disabled && 'opacity-40 pointer-events-none cursor-not-allowed',\n className\n )}\n >\n <span\n className={cn(\n 'relative inline-flex items-center h-5 w-9 flex-shrink-0 rounded-full',\n 'transition-colors duration-200 ease-out',\n isOn ? 'bg-tollerud-yellow group-hover:bg-tollerud-yellow-warm' : 'bg-tollerud-noir-600 group-hover:bg-tollerud-noir-500'\n )}\n >\n <input\n ref={ref}\n id={id}\n type=\"checkbox\"\n role=\"switch\"\n checked={isOn}\n className=\"absolute inset-0 opacity-0 w-full h-full cursor-pointer z-10\"\n onChange={(e) => {\n if (!isControlled) setInternalChecked(e.target.checked)\n onChange?.(e)\n }}\n {...props}\n />\n <span\n className={cn(\n 'block h-3.5 w-3.5 rounded-full shadow-sm pointer-events-none',\n 'transition-all duration-200 ease-out',\n isOn ? 'translate-x-[18px] bg-tollerud-black' : 'translate-x-[3px] bg-tollerud-white'\n )}\n />\n </span>\n {label && <span>{label}</span>}\n </label>\n )\n }\n)\nSwitch.displayName = 'Switch'\n\nexport { Switch }\n"]}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
- import { NoirGlowBackground } from './chunk-CBQ63EBL.js';
3
- import { Pill } from './chunk-ISHZ6ZPJ.js';
2
+ import { NoirGlowBackground } from './chunk-QQHBEACI.js';
3
+ import { Pill } from './chunk-JFOW2DI5.js';
4
4
  import { cn } from './chunk-WSQNPRGN.js';
5
5
  import { forwardRef } from 'react';
6
6
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -75,5 +75,5 @@ var HeroBlock = forwardRef(
75
75
  HeroBlock.displayName = "HeroBlock";
76
76
 
77
77
  export { HeroBlock };
78
- //# sourceMappingURL=chunk-DFM7UUKB.js.map
79
- //# sourceMappingURL=chunk-DFM7UUKB.js.map
78
+ //# sourceMappingURL=chunk-ZTFOR3AN.js.map
79
+ //# sourceMappingURL=chunk-ZTFOR3AN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../components/HeroBlock.tsx"],"names":[],"mappings":";;;;;;AAgBA,IAAM,SAAA,GAAY,UAAA;AAAA,EAChB,CACE;AAAA,IACE,SAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,WAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,SAAA,GAAY,GAAA;AAAA,IACZ,OAAA,GAAU,KAAA;AAAA,IACV,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,MAAM,QAAA,GAAW,CAAC,CAAC,KAAA;AAEnB,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACT,4EAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,KAAA,EAAO,EAAE,SAAA,EAAU;AAAA,QAClB,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UAAA,OAAA,mBACC,GAAA,CAAC,kBAAA,EAAA,EAAmB,SAAA,EAAU,MAAA,EAAO,KAAA,EAAM,QAAA,EAAS,CAAA,mBAEpD,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mDAAA,EAAoD,aAAA,EAAY,MAAA,EAAO,CAAA;AAAA,0BAExF,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,EAAA;AAAA,gBACT,mCAAA;AAAA,gBACA,UAAU,YAAA,GAAe;AAAA,eAC3B;AAAA,cACA,aAAA,EAAY;AAAA;AAAA,WACd;AAAA,0BACA,IAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,EAAA;AAAA,gBACT,8CAAA;AAAA,gBACA,WAAW,4BAAA,GAA+B;AAAA,eAC5C;AAAA,cAEA,QAAA,EAAA;AAAA,gCAAA,IAAA,CAAC,SAAI,SAAA,EAAW,EAAA,CAAG,CAAC,QAAA,IAAY,eAAe,CAAA,EAC5C,QAAA,EAAA;AAAA,kBAAA,OAAA,wBACE,IAAA,EAAA,EAAK,OAAA,EAAQ,SAAA,EAAU,SAAA,EAAU,QAC/B,QAAA,EAAA,OAAA,EACH,CAAA;AAAA,kCAEF,GAAA;AAAA,oBAAC,IAAA;AAAA,oBAAA;AAAA,sBACC,SAAA,EAAW,EAAA;AAAA,wBACT,yDAAA;AAAA,wBACA,OAAA,IAAW;AAAA,uBACb;AAAA,sBAEC,QAAA,EAAA;AAAA;AAAA,mBACH;AAAA,kBACC,WAAA,oBACC,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,sEACV,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,kBAED,OAAA,oBAAW,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0CAA0C,QAAA,EAAA,OAAA,EAAQ;AAAA,iBAAA,EAC/E,CAAA;AAAA,gBACC,QAAA,oBACC,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oCAAoC,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA;AAAA;AAE7D;AAAA;AAAA,KACF;AAAA,EAEJ;AACF;AACA,SAAA,CAAU,WAAA,GAAc,WAAA","file":"chunk-DFM7UUKB.js","sourcesContent":["import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\nimport { Pill } from './Pill'\nimport { NoirGlowBackground } from './NoirGlowBackground'\n\nexport interface HeroBlockProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n eyebrow?: React.ReactNode\n title: React.ReactNode\n description?: React.ReactNode\n actions?: React.ReactNode\n media?: React.ReactNode\n minHeight?: number\n /** When true, renders the live shader background via NoirGlowBackground. */\n intense?: boolean\n}\n\nconst HeroBlock = forwardRef<HTMLDivElement, HeroBlockProps>(\n (\n {\n className,\n eyebrow,\n title,\n description,\n actions,\n media,\n minHeight = 280,\n intense = false,\n ...props\n },\n ref\n ) => {\n const hasMedia = !!media\n\n return (\n <div\n ref={ref}\n className={cn(\n 'relative overflow-hidden rounded-xl border border-tollerud-border bg-black',\n className\n )}\n style={{ minHeight }}\n {...props}\n >\n {intense ? (\n <NoirGlowBackground intensity=\"loud\" speed=\"medium\" />\n ) : (\n <div className=\"tollerud-noir-glow-bg absolute inset-0 opacity-50\" aria-hidden=\"true\" />\n )}\n <div\n className={cn(\n 'tollerud-grid-bg absolute inset-0',\n intense ? 'opacity-25' : 'opacity-50'\n )}\n aria-hidden=\"true\"\n />\n <div\n className={cn(\n 'relative flex items-center gap-6 px-11 py-12',\n hasMedia ? 'grid grid-cols-[1.4fr_1fr]' : 'block'\n )}\n >\n <div className={cn(!hasMedia && 'max-w-[560px]')}>\n {eyebrow && (\n <Pill variant=\"outline\" className=\"mb-0\">\n {eyebrow}\n </Pill>\n )}\n <h2\n className={cn(\n 'tollerud-display text-[40px] text-tollerud-text-primary',\n eyebrow && 'mt-[18px]'\n )}\n >\n {title}\n </h2>\n {description && (\n <p className=\"mt-3.5 text-[15.5px] leading-relaxed text-tollerud-text-primary/70\">\n {description}\n </p>\n )}\n {actions && <div className=\"mt-6 flex flex-wrap items-center gap-3\">{actions}</div>}\n </div>\n {hasMedia && (\n <div className=\"flex items-center justify-center\">{media}</div>\n )}\n </div>\n </div>\n )\n }\n)\nHeroBlock.displayName = 'HeroBlock'\n\nexport { HeroBlock }\n"]}
1
+ {"version":3,"sources":["../components/HeroBlock.tsx"],"names":[],"mappings":";;;;;;AAgBA,IAAM,SAAA,GAAY,UAAA;AAAA,EAChB,CACE;AAAA,IACE,SAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,WAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,SAAA,GAAY,GAAA;AAAA,IACZ,OAAA,GAAU,KAAA;AAAA,IACV,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,MAAM,QAAA,GAAW,CAAC,CAAC,KAAA;AAEnB,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACT,4EAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,KAAA,EAAO,EAAE,SAAA,EAAU;AAAA,QAClB,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UAAA,OAAA,mBACC,GAAA,CAAC,kBAAA,EAAA,EAAmB,SAAA,EAAU,MAAA,EAAO,KAAA,EAAM,QAAA,EAAS,CAAA,mBAEpD,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mDAAA,EAAoD,aAAA,EAAY,MAAA,EAAO,CAAA;AAAA,0BAExF,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,EAAA;AAAA,gBACT,mCAAA;AAAA,gBACA,UAAU,YAAA,GAAe;AAAA,eAC3B;AAAA,cACA,aAAA,EAAY;AAAA;AAAA,WACd;AAAA,0BACA,IAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,EAAA;AAAA,gBACT,8CAAA;AAAA,gBACA,WAAW,4BAAA,GAA+B;AAAA,eAC5C;AAAA,cAEA,QAAA,EAAA;AAAA,gCAAA,IAAA,CAAC,SAAI,SAAA,EAAW,EAAA,CAAG,CAAC,QAAA,IAAY,eAAe,CAAA,EAC5C,QAAA,EAAA;AAAA,kBAAA,OAAA,wBACE,IAAA,EAAA,EAAK,OAAA,EAAQ,SAAA,EAAU,SAAA,EAAU,QAC/B,QAAA,EAAA,OAAA,EACH,CAAA;AAAA,kCAEF,GAAA;AAAA,oBAAC,IAAA;AAAA,oBAAA;AAAA,sBACC,SAAA,EAAW,EAAA;AAAA,wBACT,yDAAA;AAAA,wBACA,OAAA,IAAW;AAAA,uBACb;AAAA,sBAEC,QAAA,EAAA;AAAA;AAAA,mBACH;AAAA,kBACC,WAAA,oBACC,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,sEACV,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,kBAED,OAAA,oBAAW,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0CAA0C,QAAA,EAAA,OAAA,EAAQ;AAAA,iBAAA,EAC/E,CAAA;AAAA,gBACC,QAAA,oBACC,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oCAAoC,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA;AAAA;AAE7D;AAAA;AAAA,KACF;AAAA,EAEJ;AACF;AACA,SAAA,CAAU,WAAA,GAAc,WAAA","file":"chunk-ZTFOR3AN.js","sourcesContent":["import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\nimport { Pill } from './Pill'\nimport { NoirGlowBackground } from './NoirGlowBackground'\n\nexport interface HeroBlockProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n eyebrow?: React.ReactNode\n title: React.ReactNode\n description?: React.ReactNode\n actions?: React.ReactNode\n media?: React.ReactNode\n minHeight?: number\n /** When true, renders the live shader background via NoirGlowBackground. */\n intense?: boolean\n}\n\nconst HeroBlock = forwardRef<HTMLDivElement, HeroBlockProps>(\n (\n {\n className,\n eyebrow,\n title,\n description,\n actions,\n media,\n minHeight = 280,\n intense = false,\n ...props\n },\n ref\n ) => {\n const hasMedia = !!media\n\n return (\n <div\n ref={ref}\n className={cn(\n 'relative overflow-hidden rounded-xl border border-tollerud-border bg-black',\n className\n )}\n style={{ minHeight }}\n {...props}\n >\n {intense ? (\n <NoirGlowBackground intensity=\"loud\" speed=\"medium\" />\n ) : (\n <div className=\"tollerud-noir-glow-bg absolute inset-0 opacity-50\" aria-hidden=\"true\" />\n )}\n <div\n className={cn(\n 'tollerud-grid-bg absolute inset-0',\n intense ? 'opacity-25' : 'opacity-50'\n )}\n aria-hidden=\"true\"\n />\n <div\n className={cn(\n 'relative flex items-center gap-6 px-11 py-12',\n hasMedia ? 'grid grid-cols-[1.4fr_1fr]' : 'block'\n )}\n >\n <div className={cn(!hasMedia && 'max-w-[560px]')}>\n {eyebrow && (\n <Pill variant=\"outline\" className=\"mb-0\">\n {eyebrow}\n </Pill>\n )}\n <h2\n className={cn(\n 'tollerud-display text-[40px] text-tollerud-text-primary',\n eyebrow && 'mt-[18px]'\n )}\n >\n {title}\n </h2>\n {description && (\n <p className=\"mt-3.5 text-[15.5px] leading-relaxed text-tollerud-text-primary/70\">\n {description}\n </p>\n )}\n {actions && <div className=\"mt-6 flex flex-wrap items-center gap-3\">{actions}</div>}\n </div>\n {hasMedia && (\n <div className=\"flex items-center justify-center\">{media}</div>\n )}\n </div>\n </div>\n )\n }\n)\nHeroBlock.displayName = 'HeroBlock'\n\nexport { HeroBlock }\n"]}
package/dist/cta-band.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { CTABand } from './chunk-VTRUUT5K.js';
2
+ export { CTABand } from './chunk-IUPVQWO5.js';
3
3
  import './chunk-WSQNPRGN.js';
4
4
  //# sourceMappingURL=cta-band.js.map
5
5
  //# sourceMappingURL=cta-band.js.map
@@ -1,12 +1,12 @@
1
1
  'use client';
2
- export { DataTable } from './chunk-3TGMGBKM.js';
2
+ export { DataTable } from './chunk-YPP7QHYT.js';
3
+ import './chunk-AQT3FZRQ.js';
3
4
  import './chunk-NSMU66ZX.js';
4
- import './chunk-FGXOV2QH.js';
5
5
  import './chunk-RJTDQOT2.js';
6
6
  import './chunk-435JHF7G.js';
7
7
  import './chunk-T3TQPOVM.js';
8
8
  import './chunk-QEHTPQHL.js';
9
- import './chunk-RWJELAS6.js';
9
+ import './chunk-ADE22JSR.js';
10
10
  import './chunk-WSQNPRGN.js';
11
11
  //# sourceMappingURL=data-table.js.map
12
12
  //# sourceMappingURL=data-table.js.map
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { DatePicker } from './chunk-V3P5QLLX.js';
2
+ export { DatePicker } from './chunk-Q54CVE3W.js';
3
3
  import './chunk-WSQNPRGN.js';
4
4
  //# sourceMappingURL=date-picker.js.map
5
5
  //# sourceMappingURL=date-picker.js.map
package/dist/footer.js CHANGED
@@ -1,5 +1,6 @@
1
1
  'use client';
2
- export { Footer } from './chunk-HYQGOC2E.js';
2
+ export { Footer } from './chunk-QEIEWGHA.js';
3
+ import './chunk-VOARBYVQ.js';
3
4
  import './chunk-WSQNPRGN.js';
4
5
  //# sourceMappingURL=footer.js.map
5
6
  //# sourceMappingURL=footer.js.map
@@ -5,10 +5,14 @@ interface FormRowProps extends HTMLAttributes<HTMLDivElement> {
5
5
  label?: React.ReactNode;
6
6
  /** Hint text rendered below the label */
7
7
  description?: React.ReactNode;
8
+ /** Alias for `description` — used in docs/settings layouts */
9
+ hint?: React.ReactNode;
8
10
  error?: React.ReactNode;
9
11
  required?: boolean;
10
12
  /** Forwarded to the label's `htmlFor` — should match the control's `id` */
11
13
  htmlFor?: string;
14
+ /** `settings` = label/hint left, control right; `stack` = vertical field layout */
15
+ layout?: 'settings' | 'stack';
12
16
  }
13
17
  declare const FormRow: react.ForwardRefExoticComponent<FormRowProps & react.RefAttributes<HTMLDivElement>>;
14
18
 
package/dist/form-row.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { FormRow } from './chunk-Q74VRQEX.js';
2
+ export { FormRow } from './chunk-T3UQ7G4T.js';
3
3
  import './chunk-WSQNPRGN.js';
4
4
  //# sourceMappingURL=form-row.js.map
5
5
  //# sourceMappingURL=form-row.js.map
@@ -1,7 +1,7 @@
1
1
  'use client';
2
- export { HeroBlock } from './chunk-DFM7UUKB.js';
3
- import './chunk-CBQ63EBL.js';
4
- import './chunk-ISHZ6ZPJ.js';
2
+ export { HeroBlock } from './chunk-ZTFOR3AN.js';
3
+ import './chunk-QQHBEACI.js';
4
+ import './chunk-JFOW2DI5.js';
5
5
  import './chunk-WSQNPRGN.js';
6
6
  //# sourceMappingURL=hero-block.js.map
7
7
  //# sourceMappingURL=hero-block.js.map
package/dist/index.d.ts CHANGED
@@ -29,6 +29,7 @@ export { Checkbox, CheckboxProps } from './checkbox.js';
29
29
  export { Switch, SwitchProps } from './switch.js';
30
30
  export { Radio, RadioGroup, RadioGroupProps, RadioProps } from './radio-group.js';
31
31
  export { Footer, FooterLabels, FooterProps } from './footer.js';
32
+ export { Monogram, MonogramColor, MonogramProps } from './monogram.js';
32
33
  export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './dialog.js';
33
34
  export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './tooltip.js';
34
35
  export { Tabs, TabsContent, TabsList, TabsTrigger } from './tabs.js';
package/dist/index.js CHANGED
@@ -1,33 +1,31 @@
1
1
  'use client';
2
+ export { TagInput } from './chunk-6IS2AYYG.js';
2
3
  export { Textarea } from './chunk-HWJVRTWO.js';
3
- export { Timeline } from './chunk-7TOT5ME3.js';
4
+ export { Timeline } from './chunk-3LTW224O.js';
4
5
  export { Toaster } from './chunk-CDI7353B.js';
5
6
  export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './chunk-6UXW5YUC.js';
6
- export { Slider } from './chunk-OONIUDST.js';
7
+ export { Slider } from './chunk-OLHMMFQ7.js';
7
8
  export { Sparkline } from './chunk-EVHZFYWX.js';
8
- export { StatCard } from './chunk-LUM2YJBH.js';
9
9
  export { Stepper } from './chunk-2QWKOCWF.js';
10
- export { Switch } from './chunk-O57QMLNI.js';
10
+ export { Switch } from './chunk-YTU7BRDW.js';
11
11
  export { Tabs, TabsContent, TabsList, TabsTrigger } from './chunk-T56TTOI6.js';
12
- export { TagInput } from './chunk-6IS2AYYG.js';
12
+ export { PricingCard } from './chunk-OVSIOZHJ.js';
13
13
  export { Progress } from './chunk-5GWHUJ5D.js';
14
14
  export { Radio, RadioGroup } from './chunk-6SKTH45H.js';
15
15
  export { RollbackPlan } from './chunk-WDANALHD.js';
16
16
  export { Select } from './chunk-GTM2DE4C.js';
17
- export { ServiceHealthCard } from './chunk-7EP2T3OW.js';
18
17
  export { Sheet, SheetClose, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from './chunk-ILADNTUB.js';
19
18
  export { LogViewer } from './chunk-RZK2S2OO.js';
20
19
  export { Meter } from './chunk-A6L5C3IJ.js';
21
20
  export { Panel } from './chunk-T7EFDE2L.js';
22
21
  export { PasswordInput } from './chunk-NOLWJJHT.js';
23
- export { PricingCard } from './chunk-XR5QBVEV.js';
24
- export { Footer } from './chunk-HYQGOC2E.js';
25
- export { FormRow } from './chunk-Q74VRQEX.js';
22
+ export { Footer } from './chunk-QEIEWGHA.js';
23
+ export { Monogram } from './chunk-VOARBYVQ.js';
24
+ export { FormRow } from './chunk-T3UQ7G4T.js';
26
25
  export { GlowCard } from './chunk-ZOXO3G3I.js';
27
- export { HeroBlock } from './chunk-DFM7UUKB.js';
28
- export { NoirGlowBackground } from './chunk-CBQ63EBL.js';
29
- export { Pill } from './chunk-ISHZ6ZPJ.js';
30
- export { HostCard } from './chunk-DOUDJU4P.js';
26
+ export { HeroBlock } from './chunk-ZTFOR3AN.js';
27
+ export { NoirGlowBackground } from './chunk-QQHBEACI.js';
28
+ export { Pill } from './chunk-JFOW2DI5.js';
31
29
  export { Input } from './chunk-BPCH5LJ3.js';
32
30
  export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './chunk-KI6OTVID.js';
33
31
  export { Divider } from './chunk-CKNWXYMA.js';
@@ -41,22 +39,25 @@ export { CodeBlock } from './chunk-DRCMGIQ6.js';
41
39
  export { Combobox } from './chunk-H3ZVGTJM.js';
42
40
  export { CommandMenu } from './chunk-RQ3RXKAZ.js';
43
41
  export { Container } from './chunk-DNJI65VQ.js';
44
- export { DataTable } from './chunk-3TGMGBKM.js';
42
+ export { DataTable } from './chunk-YPP7QHYT.js';
43
+ export { Skeleton } from './chunk-AQT3FZRQ.js';
45
44
  export { Segmented } from './chunk-NSMU66ZX.js';
46
- export { Skeleton } from './chunk-FGXOV2QH.js';
47
45
  export { Pagination } from './chunk-RJTDQOT2.js';
48
46
  export { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from './chunk-435JHF7G.js';
49
47
  export { Checkbox } from './chunk-T3TQPOVM.js';
50
- export { DatePicker } from './chunk-V3P5QLLX.js';
51
- export { Avatar, AvatarGroup } from './chunk-DGCRHVWW.js';
48
+ export { DatePicker } from './chunk-Q54CVE3W.js';
49
+ export { Avatar, AvatarGroup } from './chunk-VFS3V3VY.js';
52
50
  export { BackupStatusPanel } from './chunk-JRFSUVSO.js';
53
- export { StatusDot } from './chunk-NHPISZWS.js';
54
51
  export { Badge } from './chunk-QEHTPQHL.js';
55
52
  export { BarChart } from './chunk-4PA2ACNF.js';
56
- export { BentoDashboard } from './chunk-PLF3BBQI.js';
53
+ export { BentoDashboard } from './chunk-ONMTHBZ4.js';
54
+ export { StatCard } from './chunk-LUM2YJBH.js';
55
+ export { ServiceHealthCard } from './chunk-7EP2T3OW.js';
56
+ export { HostCard } from './chunk-DOUDJU4P.js';
57
+ export { StatusDot } from './chunk-NHPISZWS.js';
57
58
  export { Breadcrumb } from './chunk-7J5QXUQN.js';
58
- export { Button, buttonVariants } from './chunk-RWJELAS6.js';
59
- export { CTABand } from './chunk-VTRUUT5K.js';
59
+ export { Button, buttonVariants } from './chunk-ADE22JSR.js';
60
+ export { CTABand } from './chunk-IUPVQWO5.js';
60
61
  export { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './chunk-YYWODLER.js';
61
62
  export { ActionDiff } from './chunk-3XTZPDNV.js';
62
63
  export { ActionRow } from './chunk-OGVSZ7NV.js';
@@ -0,0 +1,20 @@
1
+ import * as react from 'react';
2
+ import { SVGAttributes } from 'react';
3
+
4
+ type MonogramColor = 'yellow' | 'black' | 'white';
5
+ interface MonogramProps extends SVGAttributes<SVGSVGElement> {
6
+ /**
7
+ * Fill color via `currentColor`.
8
+ * - `yellow` — default on dark surfaces (#FFFF00)
9
+ * - `black` — light-mode surfaces (#0A0A0A)
10
+ * - `white` — on tinted or photographic backgrounds
11
+ */
12
+ color?: MonogramColor;
13
+ /** Height in px; width scales from the 130×143 viewBox. */
14
+ size?: number;
15
+ /** Accessible name — rendered as `<title>` and `aria-label`. */
16
+ title?: string;
17
+ }
18
+ declare const Monogram: react.ForwardRefExoticComponent<MonogramProps & react.RefAttributes<SVGSVGElement>>;
19
+
20
+ export { Monogram, type MonogramColor, type MonogramProps };
@@ -0,0 +1,5 @@
1
+ 'use client';
2
+ export { Monogram } from './chunk-VOARBYVQ.js';
3
+ import './chunk-WSQNPRGN.js';
4
+ //# sourceMappingURL=monogram.js.map
5
+ //# sourceMappingURL=monogram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"monogram.js"}
@@ -32,6 +32,12 @@ interface NoirGlowBackgroundProps {
32
32
  forceCssFallback?: boolean;
33
33
  /** Disable pointer events so content above remains clickable. */
34
34
  inert?: boolean;
35
+ /** Horizontal shader offset (-1 to 1). Use for edge-biased layouts. */
36
+ offsetX?: number;
37
+ /** Vertical shader offset (-1 to 1). */
38
+ offsetY?: number;
39
+ /** Shader scale multiplier. Values > 1 push glow toward edges. */
40
+ scale?: number;
35
41
  }
36
42
  /**
37
43
  * NoirGlowBackground
@@ -45,6 +51,6 @@ interface NoirGlowBackgroundProps {
45
51
  * The CSS fallback classes live in `globals.css` and are used during Suspense,
46
52
  * reduced-motion contexts, or when `forceCssFallback` is true.
47
53
  */
48
- declare function NoirGlowBackground({ className, style, shape, intensity, speed, grain, softness, colorBack, colors, preserveCenter, noiseOverlay, forceCssFallback, inert, }: NoirGlowBackgroundProps): react.JSX.Element;
54
+ declare function NoirGlowBackground({ className, style, shape, intensity, speed, grain, softness, colorBack, colors, preserveCenter, noiseOverlay, forceCssFallback, inert, offsetX, offsetY, scale, }: NoirGlowBackgroundProps): react.JSX.Element;
49
55
 
50
56
  export { NoirGlowBackground, type NoirGlowBackgroundProps };
@@ -1,4 +1,4 @@
1
1
  'use client';
2
- export { NoirGlowBackground } from './chunk-CBQ63EBL.js';
2
+ export { NoirGlowBackground } from './chunk-QQHBEACI.js';
3
3
  //# sourceMappingURL=noir-glow-background.js.map
4
4
  //# sourceMappingURL=noir-glow-background.js.map
package/dist/pill.d.ts CHANGED
@@ -2,8 +2,11 @@ import * as react from 'react';
2
2
  import { HTMLAttributes } from 'react';
3
3
 
4
4
  declare const pillVariants: {
5
- readonly outline: "bg-transparent border border-tollerud-border text-tollerud-text-secondary";
6
- readonly solid: "bg-tollerud-surface-raised text-tollerud-text-primary";
5
+ readonly outline: "";
6
+ readonly muted: "";
7
+ readonly success: "";
8
+ readonly error: "";
9
+ readonly solid: "bg-tollerud-surface-raised text-tollerud-text-primary border-transparent";
7
10
  readonly accent: "bg-tollerud-yellow/15 border border-tollerud-yellow/30 text-tollerud-yellow";
8
11
  };
9
12
  interface PillProps extends HTMLAttributes<HTMLSpanElement> {
package/dist/pill.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { Pill } from './chunk-ISHZ6ZPJ.js';
2
+ export { Pill } from './chunk-JFOW2DI5.js';
3
3
  import './chunk-WSQNPRGN.js';
4
4
  //# sourceMappingURL=pill.js.map
5
5
  //# sourceMappingURL=pill.js.map
@@ -1,6 +1,6 @@
1
1
  'use client';
2
- export { PricingCard } from './chunk-XR5QBVEV.js';
3
- import './chunk-RWJELAS6.js';
2
+ export { PricingCard } from './chunk-OVSIOZHJ.js';
3
+ import './chunk-ADE22JSR.js';
4
4
  import './chunk-WSQNPRGN.js';
5
5
  //# sourceMappingURL=pricing-card.js.map
6
6
  //# sourceMappingURL=pricing-card.js.map
@@ -1,5 +1,13 @@
1
1
  import * as react from 'react';
2
2
 
3
- declare function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): react.JSX.Element;
3
+ interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {
4
+ /** Shorthand height in px (or any CSS length via className) */
5
+ h?: number | string;
6
+ /** Shorthand width in px or percentage string e.g. "60%" */
7
+ w?: number | string;
8
+ /** Shorthand border-radius in px */
9
+ r?: number | string;
10
+ }
11
+ declare function Skeleton({ className, h, w, r, style, ...props }: SkeletonProps): react.JSX.Element;
4
12
 
5
- export { Skeleton };
13
+ export { Skeleton, type SkeletonProps };
package/dist/skeleton.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { Skeleton } from './chunk-FGXOV2QH.js';
2
+ export { Skeleton } from './chunk-AQT3FZRQ.js';
3
3
  import './chunk-WSQNPRGN.js';
4
4
  //# sourceMappingURL=skeleton.js.map
5
5
  //# sourceMappingURL=skeleton.js.map
package/dist/slider.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { Slider } from './chunk-OONIUDST.js';
2
+ export { Slider } from './chunk-OLHMMFQ7.js';
3
3
  import './chunk-WSQNPRGN.js';
4
4
  //# sourceMappingURL=slider.js.map
5
5
  //# sourceMappingURL=slider.js.map
package/dist/switch.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { Switch } from './chunk-O57QMLNI.js';
2
+ export { Switch } from './chunk-YTU7BRDW.js';
3
3
  import './chunk-WSQNPRGN.js';
4
4
  //# sourceMappingURL=switch.js.map
5
5
  //# sourceMappingURL=switch.js.map
package/dist/timeline.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { Timeline } from './chunk-7TOT5ME3.js';
2
+ export { Timeline } from './chunk-3LTW224O.js';
3
3
  import './chunk-WSQNPRGN.js';
4
4
  //# sourceMappingURL=timeline.js.map
5
5
  //# sourceMappingURL=timeline.js.map
@@ -390,6 +390,76 @@
390
390
  background: var(--gradient-yellow);
391
391
  margin: 3rem 0;
392
392
  }
393
+ .tollerud-accent-bar--inline {
394
+ margin: 0;
395
+ }
396
+
397
+ /* ═══ Range slider ═══ */
398
+ .tollerud-slider {
399
+ -webkit-appearance: none;
400
+ appearance: none;
401
+ width: 100%;
402
+ height: 6px;
403
+ border-radius: 999px;
404
+ background: var(--muted);
405
+ outline: none;
406
+ }
407
+ .tollerud-slider::-webkit-slider-thumb {
408
+ -webkit-appearance: none;
409
+ appearance: none;
410
+ width: 16px;
411
+ height: 16px;
412
+ border-radius: 50%;
413
+ background: var(--tollerud-yellow);
414
+ border: 2px solid var(--card);
415
+ cursor: pointer;
416
+ box-shadow: 0 0 0 1px var(--border);
417
+ }
418
+ .tollerud-slider::-moz-range-thumb {
419
+ width: 16px;
420
+ height: 16px;
421
+ border-radius: 50%;
422
+ background: var(--tollerud-yellow);
423
+ border: 2px solid var(--card);
424
+ cursor: pointer;
425
+ }
426
+
427
+ /* ═══ Form row (settings layout) ═══ */
428
+ .tollerud-formrow {
429
+ display: grid;
430
+ grid-template-columns: 1fr auto;
431
+ gap: 16px;
432
+ align-items: center;
433
+ padding: 16px 0;
434
+ border-bottom: 1px solid var(--border);
435
+ }
436
+ .tollerud-formrow:last-child {
437
+ border-bottom: none;
438
+ }
439
+ .tollerud-formrow__title {
440
+ font-size: 14px;
441
+ font-weight: 500;
442
+ color: var(--foreground);
443
+ }
444
+ .tollerud-formrow__hint {
445
+ font-size: 12.5px;
446
+ color: var(--text-muted);
447
+ margin-top: 3px;
448
+ line-height: 1.45;
449
+ max-width: 46ch;
450
+ }
451
+ .tollerud-formrow__control {
452
+ justify-self: end;
453
+ }
454
+ @media (max-width: 560px) {
455
+ .tollerud-formrow {
456
+ grid-template-columns: 1fr;
457
+ gap: 10px;
458
+ }
459
+ .tollerud-formrow__control {
460
+ justify-self: start;
461
+ }
462
+ }
393
463
 
394
464
  /* ═══ Gradient Text ═══ */
395
465
  .tollerud-gradient-text {
@@ -623,6 +693,20 @@
623
693
  .tollerud-timeline__dot--active {
624
694
  animation: tollerud-timeline-pulse 2s infinite;
625
695
  }
696
+ .tollerud-timeline__dot--online {
697
+ background: var(--success);
698
+ box-shadow: 0 0 6px rgba(34, 197, 94, 0.5);
699
+ }
700
+ .tollerud-timeline__dot--warning {
701
+ background: var(--tollerud-yellow);
702
+ box-shadow: 0 0 6px rgba(232, 213, 0, 0.5);
703
+ }
704
+ .tollerud-timeline__dot--offline {
705
+ background: var(--destructive);
706
+ }
707
+ .tollerud-timeline__dot--idle {
708
+ background: var(--tollerud-noir-400);
709
+ }
626
710
  @keyframes tollerud-timeline-pulse {
627
711
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,255,0,0.4); }
628
712
  50% { box-shadow: 0 0 0 6px rgba(255,255,0,0); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tollerud/ui",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "Tollerud User Interface — dark, monochrome + yellow accent. Noir aesthetic meets modern utility.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -40,7 +40,8 @@
40
40
  "./tollerud-logo.svg": "./tollerud-logo.svg",
41
41
  "./tollerud-avatar.svg": "./tollerud-avatar.svg",
42
42
  "./tollerud-avatar.png": "./tollerud-avatar.png",
43
- "./tia-full-figure.svg": "./tia-full-figure.svg",
43
+ "./tollerud-avatar-full.svg": "./tollerud-avatar-full.svg",
44
+ "./tollerud-avatar-full.png": "./tollerud-avatar-full.png",
44
45
  "./registry.json": "./registry.json",
45
46
  "./*": {
46
47
  "import": {
@@ -66,7 +67,8 @@
66
67
  "tollerud-logo.svg",
67
68
  "tollerud-avatar.svg",
68
69
  "tollerud-avatar.png",
69
- "tia-full-figure.svg",
70
+ "tollerud-avatar-full.svg",
71
+ "tollerud-avatar-full.png",
70
72
  "AGENTS.md",
71
73
  "SKILL.md"
72
74
  ],
package/registry.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tollerud-noir",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "Tollerud Design System \u2014 dark, cinematic, keyboard-first infrastructure UI",
5
5
  "components": {
6
6
  "button": {
@@ -394,6 +394,22 @@
394
394
  "clsx",
395
395
  "tailwind-merge"
396
396
  ],
397
+ "registryDependencies": [
398
+ "monogram"
399
+ ],
400
+ "type": "components:ui"
401
+ },
402
+ "monogram": {
403
+ "name": "Monogram",
404
+ "description": "Tollerud monogram SVG with yellow, black, or white fill",
405
+ "files": [
406
+ "components/Monogram.tsx",
407
+ "components/monogram-geometry.ts"
408
+ ],
409
+ "dependencies": [
410
+ "clsx",
411
+ "tailwind-merge"
412
+ ],
397
413
  "registryDependencies": [],
398
414
  "type": "components:ui"
399
415
  },
package/tokens.css CHANGED
@@ -411,6 +411,16 @@ code, pre {
411
411
  color: rgba(232, 213, 0, 0.55);
412
412
  border-color: rgba(232, 213, 0, 0.15);
413
413
  }
414
+ .tollerud-pill--success {
415
+ background: rgba(34, 197, 94, 0.06);
416
+ color: var(--success);
417
+ border-color: rgba(34, 197, 94, 0.35);
418
+ }
419
+ .tollerud-pill--error {
420
+ background: rgba(239, 68, 68, 0.06);
421
+ color: var(--destructive);
422
+ border-color: rgba(239, 68, 68, 0.35);
423
+ }
414
424
 
415
425
  /* ── Gradient Accent Bar ── */
416
426
  .tollerud-accent-bar {
@@ -512,6 +522,16 @@ code, pre {
512
522
  .tollerud-timeline__dot-group { display: flex; flex-direction: column; align-items: center; }
513
523
  .tollerud-timeline__dot { width: 10px; height: 10px; border-radius: 50%; background: var(--tollerud-noir-500); flex-shrink: 0; }
514
524
  .tollerud-timeline__dot--active { animation: tollerud-timeline-pulse 2s infinite; }
525
+ .tollerud-timeline__dot--online {
526
+ background: var(--success);
527
+ box-shadow: 0 0 6px rgba(34, 197, 94, 0.5);
528
+ }
529
+ .tollerud-timeline__dot--warning {
530
+ background: var(--tollerud-yellow);
531
+ box-shadow: 0 0 6px rgba(232, 213, 0, 0.5);
532
+ }
533
+ .tollerud-timeline__dot--offline { background: var(--destructive); }
534
+ .tollerud-timeline__dot--idle { background: var(--tollerud-noir-400); }
515
535
  @keyframes tollerud-timeline-pulse {
516
536
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,255,0,.4); }
517
537
  50% { box-shadow: 0 0 0 6px rgba(255,255,0,0); }
Binary file
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../components/Timeline.tsx"],"names":[],"mappings":";;;;AA6BA,IAAM,QAAA,GAAW,UAAA;AAAA,EACf,CAAC,EAAE,SAAA,EAAW,KAAA,EAAO,QAAQ,OAAA,EAAS,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AACxD,IAAA,uBACE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAW,EAAA,CAAG,mBAAA,EAAqB,OAAA,IAAW,iBAAiB,SAAS,CAAA;AAAA,QACxE,IAAA,EAAK,MAAA;AAAA,QACL,YAAA,EAAW,mBAAA;AAAA,QACV,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,EAAM,CAAA,KAAM;AACtB,UAAA,MAAM,MAAA,GAAS,CAAA,KAAM,KAAA,CAAM,MAAA,GAAS,CAAA;AAEpC,UAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAkB,SAAA,EAAU,yBAAA,EAA0B,MAAK,UAAA,EAE1D,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,SAAI,SAAA,EAAU,2BAAA,EACb,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,8BAAA,EACZ,QAAA,EAAA;AAAA,cAAA,IAAA,CAAK,uBACJ,GAAA,CAAC,MAAA,EAAA,EAAK,WAAU,yBAAA,EAA2B,QAAA,EAAA,IAAA,CAAK,MAAK,CAAA,mBAErD,GAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAW,EAAA;AAAA,oBACT,wBAAA;AAAA,oBACA,MAAA,IAAU,gCAAA;AAAA,oBACV,IAAA,CAAK,WAAW,QAAA,IAAY,0DAAA;AAAA,oBAC5B,IAAA,CAAK,WAAW,SAAA,IAAa,mBAAA;AAAA,oBAC7B,IAAA,CAAK,WAAW,SAAA,IAAa,yDAAA;AAAA,oBAC7B,CAAC,KAAK,MAAA,IAAU;AAAA;AAClB;AAAA,eACF;AAAA,cAED,CAAC,MAAA,oBAAU,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,yBAAA,EAA0B;AAAA,aAAA,EACvD,CAAA,EACF,CAAA;AAAA,4BAGA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4BAAA,EACb,QAAA,EAAA;AAAA,8BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,wCAAA,EACb,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0BAAA,EAA4B,QAAA,EAAA,IAAA,CAAK,KAAA,EAAM,CAAA;AAAA,gCACvD,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yBAAA,EAA2B,eAAK,IAAA,EAAK;AAAA,eAAA,EACvD,CAAA;AAAA,cACC,KAAK,WAAA,oBACJ,GAAA,CAAC,OAAE,SAAA,EAAU,gCAAA,EAAkC,eAAK,WAAA,EAAY,CAAA;AAAA,cAEjE,IAAA,CAAK,QAAQ,IAAA,CAAK,IAAA,CAAK,SAAS,CAAA,oBAC/B,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6BAAA,EACZ,QAAA,EAAA,IAAA,CAAK,KAAK,GAAA,CAAI,CAAC,sBACd,GAAA,CAAC,MAAA,EAAA,EAAa,WAAU,yBAAA,EAA2B,QAAA,EAAA,CAAA,EAAA,EAAxC,CAA0C,CACtD,CAAA,EACH;AAAA,aAAA,EAEJ;AAAA,WAAA,EAAA,EAtCQ,KAAK,EAuCf,CAAA;AAAA,QAEJ,CAAC;AAAA;AAAA,KACH;AAAA,EAEJ;AACF;AACA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-7TOT5ME3.js","sourcesContent":["import { type HTMLAttributes, type ReactNode, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\nimport type { Status } from './StatusDot'\n\nexport interface TimelineItemData {\n id: string\n /** Timestamp label */\n time: string\n /** Title/headline of the event */\n title: string\n /** Description */\n description?: string\n /** Status indicator dot */\n status?: Status\n /** Optional icon to replace dot */\n icon?: ReactNode\n /** Optional metadata badges */\n meta?: string[]\n}\n\nexport interface TimelineProps extends HTMLAttributes<HTMLDivElement> {\n /** Timeline events */\n items: TimelineItemData[]\n /** Whether items are active (show animated dot pulse) */\n active?: boolean\n /** Whether the timeline is loading */\n loading?: boolean\n}\n\nconst Timeline = forwardRef<HTMLDivElement, TimelineProps>(\n ({ className, items, active, loading, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn('tollerud-timeline', loading && 'animate-pulse', className)}\n role=\"list\"\n aria-label=\"Activity timeline\"\n {...props}\n >\n {items.map((item, i) => {\n const isLast = i === items.length - 1\n\n return (\n <div key={item.id} className=\"tollerud-timeline__item\" role=\"listitem\">\n {/* Dot column */}\n <div className=\"tollerud-timeline__marker\">\n <div className=\"tollerud-timeline__dot-group\">\n {item.icon ? (\n <span className=\"tollerud-timeline__icon\">{item.icon}</span>\n ) : (\n <span\n className={cn(\n 'tollerud-timeline__dot',\n active && 'tollerud-timeline__dot--active',\n item.status === 'online' && 'bg-tollerud-success shadow-[0_0_6px_rgba(34,197,94,0.5)]',\n item.status === 'offline' && 'bg-tollerud-error',\n item.status === 'warning' && 'bg-tollerud-yellow shadow-[0_0_6px_rgba(232,213,0,0.5)]',\n !item.status && 'bg-tollerud-noir-500'\n )}\n />\n )}\n {!isLast && <div className=\"tollerud-timeline__line\" />}\n </div>\n </div>\n\n {/* Content */}\n <div className=\"tollerud-timeline__content\">\n <div className=\"flex items-start justify-between gap-2\">\n <span className=\"tollerud-timeline__title\">{item.title}</span>\n <span className=\"tollerud-timeline__time\">{item.time}</span>\n </div>\n {item.description && (\n <p className=\"tollerud-timeline__description\">{item.description}</p>\n )}\n {item.meta && item.meta.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5 mt-1\">\n {item.meta.map((m) => (\n <span key={m} className=\"tollerud-timeline__meta\">{m}</span>\n ))}\n </div>\n )}\n </div>\n </div>\n )\n })}\n </div>\n )\n }\n)\nTimeline.displayName = 'Timeline'\n\nexport { Timeline }"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../components/NoirGlowBackground.tsx"],"names":[],"mappings":"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","file":"chunk-CBQ63EBL.js","sourcesContent":["\"use client\"\n\nimport { lazy, Suspense, type CSSProperties } from \"react\"\n\nconst GrainGradient = lazy(() =>\n import(\"@paper-design/shaders-react\").then((module) => ({\n default: module.GrainGradient,\n }))\n)\n\ntype ShaderShape = \"corners\" | \"wave\" | \"dots\" | \"truchet\" | \"ripple\" | \"blob\" | \"sphere\"\ntype Intensity = \"subtle\" | \"medium\" | \"loud\"\ntype Speed = \"still\" | \"slow\" | \"medium\" | \"fast\"\ntype Grain = \"none\" | \"soft\" | \"high\"\n\nexport interface NoirGlowBackgroundProps {\n /** Extra class names for the outer positioning wrapper. */\n className?: string\n /** Inline style for the outer positioning wrapper. */\n style?: CSSProperties\n /** Canvas/WebGL shape. `corners` matches Tollerud.no. */\n shape?: ShaderShape\n /** Visual strength of the yellow glow. */\n intensity?: Intensity\n /** Ambient animation speed. */\n speed?: Speed\n /** Shader grain/noise amount. */\n grain?: Grain\n /** Softness/falloff of the glow blooms. */\n softness?: number\n /** Background color behind the glow. */\n colorBack?: string\n /** Glow colors. Defaults to the Tollerud/Tia yellow ramp. */\n colors?: string[]\n /** Whether to render a readable center vignette on top of the shader. */\n preserveCenter?: boolean\n /** Add the grain/noise CSS overlay. */\n noiseOverlay?: boolean\n /** Prefer the CSS fallback even if shaders are available. Useful for docs/static contexts. */\n forceCssFallback?: boolean\n /** Disable pointer events so content above remains clickable. */\n inert?: boolean\n}\n\nconst intensityMap: Record<Intensity, number> = {\n subtle: 0.24,\n medium: 0.45,\n loud: 0.68,\n}\n\nconst speedMap: Record<Speed, number> = {\n still: 0,\n slow: 0.45,\n medium: 1,\n fast: 1.8,\n}\n\nconst grainMap: Record<Grain, number> = {\n none: 0,\n soft: 0.12,\n high: 0.28,\n}\n\nfunction cx(...classes: Array<string | false | null | undefined>) {\n return classes.filter(Boolean).join(\" \")\n}\n\nfunction CssFallback({ preserveCenter = true, noiseOverlay = true }: Pick<NoirGlowBackgroundProps, \"preserveCenter\" | \"noiseOverlay\">) {\n return (\n <>\n <div className=\"tollerud-noir-glow-bg\" aria-hidden=\"true\" />\n {preserveCenter && <div className=\"tollerud-noir-glow-vignette\" aria-hidden=\"true\" />}\n {noiseOverlay && <div className=\"tollerud-noir-noise\" aria-hidden=\"true\" />}\n </>\n )\n}\n\n/**\n * NoirGlowBackground\n *\n * Tia/Tollerud signature background primitive. The defaults replicate\n * MathiasOki/tollerud-landing's `GradientBackground` component.\n *\n * Install dependency in consuming Next.js apps:\n * npm install @paper-design/shaders-react\n *\n * The CSS fallback classes live in `globals.css` and are used during Suspense,\n * reduced-motion contexts, or when `forceCssFallback` is true.\n */\nexport function NoirGlowBackground({\n className,\n style,\n shape = \"corners\",\n intensity = \"medium\",\n speed = \"medium\",\n grain = \"none\",\n softness = 0.76,\n colorBack = \"hsl(0, 0%, 0%)\",\n colors = [\"hsl(54, 85%, 66%)\", \"hsl(56, 100%, 80%)\", \"hsl(56, 100%, 50%)\"],\n preserveCenter = false,\n noiseOverlay = false,\n forceCssFallback = false,\n inert = true,\n}: NoirGlowBackgroundProps) {\n const wrapperClassName = cx(\n \"tollerud-noir-glow-root absolute inset-0 z-0 overflow-hidden\",\n inert && \"pointer-events-none\",\n className\n )\n\n if (forceCssFallback) {\n return (\n <div className={wrapperClassName} style={style} aria-hidden=\"true\">\n <CssFallback preserveCenter={preserveCenter} noiseOverlay={noiseOverlay} />\n </div>\n )\n }\n\n return (\n <div className={wrapperClassName} style={style} aria-hidden=\"true\">\n <Suspense fallback={<CssFallback preserveCenter={preserveCenter} noiseOverlay={noiseOverlay} />}>\n <GrainGradient\n style={{ height: \"100%\", width: \"100%\" }}\n colorBack={colorBack}\n softness={softness}\n intensity={intensityMap[intensity]}\n noise={grainMap[grain]}\n shape={shape}\n offsetX={0}\n offsetY={0}\n scale={1}\n rotation={0}\n speed={speedMap[speed]}\n colors={colors}\n />\n </Suspense>\n {preserveCenter && <div className=\"tollerud-noir-glow-vignette\" aria-hidden=\"true\" />}\n {noiseOverlay && <div className=\"tollerud-noir-noise\" aria-hidden=\"true\" />}\n </div>\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../components/Avatar.tsx"],"names":[],"mappings":"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","file":"chunk-DGCRHVWW.js","sourcesContent":["'use client'\n\nimport { type HTMLAttributes, forwardRef, useState } from 'react'\nimport { cn } from '@/lib/utils'\n\nconst avatarSizes = {\n sm: 'h-6 w-6 text-[10px]',\n md: 'h-8 w-8 text-xs',\n lg: 'h-11 w-11 text-sm',\n} as const\n\nfunction initialsFrom(name: string) {\n const parts = name.trim().split(/\\s+/).filter(Boolean)\n if (parts.length === 0) return ''\n if (parts.length === 1) return parts[0]!.slice(0, 2).toUpperCase()\n return (parts[0]![0] + parts[parts.length - 1]![0]).toUpperCase()\n}\n\nexport interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {\n /** Image source */\n src?: string\n /** Accessible name / used to derive initials fallback */\n name?: string\n /** Explicit fallback content (overrides derived initials) */\n fallback?: React.ReactNode\n size?: keyof typeof avatarSizes\n}\n\nconst Avatar = forwardRef<HTMLSpanElement, AvatarProps>(\n ({ className, src, name, fallback, size = 'md', ...props }, ref) => {\n const [errored, setErrored] = useState(false)\n const showImage = !!src && !errored\n\n return (\n <span\n ref={ref}\n className={cn(\n 'relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full select-none',\n 'bg-tollerud-surface-raised text-tollerud-text-secondary font-medium',\n 'ring-1 ring-tollerud-border',\n avatarSizes[size],\n className\n )}\n {...props}\n >\n {showImage ? (\n <img\n src={src}\n alt={name ?? ''}\n className=\"h-full w-full object-cover\"\n onError={() => setErrored(true)}\n />\n ) : (\n <span aria-hidden={!!name}>{fallback ?? (name ? initialsFrom(name) : null)}</span>\n )}\n </span>\n )\n }\n)\nAvatar.displayName = 'Avatar'\n\nexport interface AvatarGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Maximum avatars to render before collapsing into a \"+N\" overflow indicator */\n max?: number\n size?: keyof typeof avatarSizes\n children: React.ReactNode\n}\n\nconst AvatarGroup = forwardRef<HTMLDivElement, AvatarGroupProps>(\n ({ className, max, size = 'md', children, ...props }, ref) => {\n const items = Array.isArray(children) ? children : [children]\n const visible = max ? items.slice(0, max) : items\n const overflow = max ? items.length - max : 0\n\n return (\n <div\n ref={ref}\n className={cn('flex items-center -space-x-2', className)}\n {...props}\n >\n {visible.map((child, i) => (\n <span key={i} className=\"ring-2 ring-tollerud-surface rounded-full\">\n {child}\n </span>\n ))}\n {overflow > 0 && (\n <span\n className={cn(\n 'relative inline-flex shrink-0 items-center justify-center rounded-full select-none',\n 'bg-tollerud-surface-raised text-tollerud-text-muted font-medium',\n 'ring-2 ring-tollerud-surface',\n avatarSizes[size]\n )}\n >\n +{overflow}\n </span>\n )}\n </div>\n )\n }\n)\nAvatarGroup.displayName = 'AvatarGroup'\n\nexport { Avatar, AvatarGroup }\n"]}