@particle-academy/react-fancy 5.72.0 → 6.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 (96) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/dist/badge.cjs +3 -2
  3. package/dist/badge.js +2 -1
  4. package/dist/button.cjs +3 -3
  5. package/dist/button.js +1 -1
  6. package/dist/callout.cjs +2 -2
  7. package/dist/callout.js +1 -1
  8. package/dist/chat-thread.cjs +7 -6
  9. package/dist/chat-thread.js +5 -4
  10. package/dist/{chunk-GUCUYDFB.js → chunk-23KQF47X.js} +5 -5
  11. package/dist/{chunk-GUCUYDFB.js.map → chunk-23KQF47X.js.map} +1 -1
  12. package/dist/{chunk-2MDU3W7E.js → chunk-3AA2KGZG.js} +3 -3
  13. package/dist/{chunk-2MDU3W7E.js.map → chunk-3AA2KGZG.js.map} +1 -1
  14. package/dist/{chunk-3KF3OYWS.js → chunk-4GPH7HOR.js} +12 -3
  15. package/dist/chunk-4GPH7HOR.js.map +1 -0
  16. package/dist/{chunk-TW52N55D.js → chunk-B6WTCAGY.js} +4 -3
  17. package/dist/chunk-B6WTCAGY.js.map +1 -0
  18. package/dist/{chunk-A5CACIHR.cjs → chunk-CKO2KCUN.cjs} +9 -9
  19. package/dist/{chunk-A5CACIHR.cjs.map → chunk-CKO2KCUN.cjs.map} +1 -1
  20. package/dist/{chunk-BQFPC5FL.js → chunk-ESCIXKFT.js} +3 -3
  21. package/dist/{chunk-BQFPC5FL.js.map → chunk-ESCIXKFT.js.map} +1 -1
  22. package/dist/{chunk-B6AIHYOP.js → chunk-F4OYQ2XZ.js} +4 -4
  23. package/dist/{chunk-B6AIHYOP.js.map → chunk-F4OYQ2XZ.js.map} +1 -1
  24. package/dist/{chunk-NWB6YCZY.cjs → chunk-FKZB27OM.cjs} +6 -6
  25. package/dist/{chunk-NWB6YCZY.cjs.map → chunk-FKZB27OM.cjs.map} +1 -1
  26. package/dist/{chunk-EZA6GWZL.cjs → chunk-GK7IGL7N.cjs} +195 -8
  27. package/dist/chunk-GK7IGL7N.cjs.map +1 -0
  28. package/dist/{chunk-EWE4TOG7.js → chunk-GSMD5NK5.js} +3 -3
  29. package/dist/{chunk-EWE4TOG7.js.map → chunk-GSMD5NK5.js.map} +1 -1
  30. package/dist/{chunk-KDISJ64Q.cjs → chunk-I2VAGZXY.cjs} +4 -4
  31. package/dist/{chunk-KDISJ64Q.cjs.map → chunk-I2VAGZXY.cjs.map} +1 -1
  32. package/dist/{chunk-5WVEW3Q5.cjs → chunk-K7JOZQRK.cjs} +15 -15
  33. package/dist/{chunk-5WVEW3Q5.cjs.map → chunk-K7JOZQRK.cjs.map} +1 -1
  34. package/dist/{chunk-H2YRZYKK.cjs → chunk-KFA7B6WP.cjs} +4 -4
  35. package/dist/{chunk-H2YRZYKK.cjs.map → chunk-KFA7B6WP.cjs.map} +1 -1
  36. package/dist/{chunk-ZXZJYVWP.js → chunk-KPRSRWNM.js} +3 -3
  37. package/dist/{chunk-ZXZJYVWP.js.map → chunk-KPRSRWNM.js.map} +1 -1
  38. package/dist/{chunk-7DSHA4CL.cjs → chunk-KSSTFLV2.cjs} +20 -20
  39. package/dist/{chunk-7DSHA4CL.cjs.map → chunk-KSSTFLV2.cjs.map} +1 -1
  40. package/dist/{chunk-YJHP5FVA.js → chunk-MTDOFZIB.js} +196 -9
  41. package/dist/chunk-MTDOFZIB.js.map +1 -0
  42. package/dist/{chunk-FBGCSGCE.cjs → chunk-NZHVDWOM.cjs} +12 -3
  43. package/dist/chunk-NZHVDWOM.cjs.map +1 -0
  44. package/dist/chunk-OCHUZ7J3.cjs +60 -0
  45. package/dist/chunk-OCHUZ7J3.cjs.map +1 -0
  46. package/dist/{chunk-C2LVHAIG.cjs → chunk-OUNGGQIS.cjs} +7 -6
  47. package/dist/chunk-OUNGGQIS.cjs.map +1 -0
  48. package/dist/chunk-OZ4QFJ7N.js +58 -0
  49. package/dist/chunk-OZ4QFJ7N.js.map +1 -0
  50. package/dist/{chunk-MOU6O324.cjs → chunk-S53A6JIE.js} +3 -58
  51. package/dist/chunk-S53A6JIE.js.map +1 -0
  52. package/dist/{chunk-L6TFJIFB.cjs → chunk-SRICSNL4.cjs} +12 -12
  53. package/dist/{chunk-L6TFJIFB.cjs.map → chunk-SRICSNL4.cjs.map} +1 -1
  54. package/dist/{chunk-QIH7DDRO.js → chunk-TH4JZAMK.js} +5 -5
  55. package/dist/{chunk-QIH7DDRO.js.map → chunk-TH4JZAMK.js.map} +1 -1
  56. package/dist/{chunk-VIQEWB6M.js → chunk-WF6AYHOS.js} +4 -4
  57. package/dist/{chunk-VIQEWB6M.js.map → chunk-WF6AYHOS.js.map} +1 -1
  58. package/dist/{chunk-LCNHEYIM.cjs → chunk-WNWEC5OU.cjs} +3 -3
  59. package/dist/{chunk-LCNHEYIM.cjs.map → chunk-WNWEC5OU.cjs.map} +1 -1
  60. package/dist/{chunk-6FCQD2KQ.js → chunk-X6LGRB4H.cjs} +7 -55
  61. package/dist/chunk-X6LGRB4H.cjs.map +1 -0
  62. package/dist/content-renderer.cjs +5 -5
  63. package/dist/content-renderer.js +2 -2
  64. package/dist/editor.cjs +5 -5
  65. package/dist/editor.js +3 -3
  66. package/dist/index.cjs +51 -50
  67. package/dist/index.cjs.map +1 -1
  68. package/dist/index.d.cts +1 -1
  69. package/dist/index.d.ts +1 -1
  70. package/dist/index.js +13 -12
  71. package/dist/index.js.map +1 -1
  72. package/dist/json-editor.cjs +16 -15
  73. package/dist/json-editor.js +5 -4
  74. package/dist/magic-wand.cjs +5 -4
  75. package/dist/magic-wand.js +4 -3
  76. package/dist/prompt-input.cjs +5 -5
  77. package/dist/prompt-input.js +2 -2
  78. package/dist/reason-tag.cjs +3 -3
  79. package/dist/reason-tag.js +2 -2
  80. package/dist/sidebar.cjs +4 -3
  81. package/dist/sidebar.d.cts +49 -4
  82. package/dist/sidebar.d.ts +49 -4
  83. package/dist/sidebar.js +2 -1
  84. package/dist/toast.cjs +5 -4
  85. package/dist/toast.js +3 -2
  86. package/docs/Button.md +21 -0
  87. package/docs/Sidebar.md +75 -1
  88. package/package.json +1 -1
  89. package/dist/chunk-3KF3OYWS.js.map +0 -1
  90. package/dist/chunk-6FCQD2KQ.js.map +0 -1
  91. package/dist/chunk-C2LVHAIG.cjs.map +0 -1
  92. package/dist/chunk-EZA6GWZL.cjs.map +0 -1
  93. package/dist/chunk-FBGCSGCE.cjs.map +0 -1
  94. package/dist/chunk-MOU6O324.cjs.map +0 -1
  95. package/dist/chunk-TW52N55D.js.map +0 -1
  96. package/dist/chunk-YJHP5FVA.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkNWB6YCZY_cjs = require('./chunk-NWB6YCZY.cjs');
3
+ var chunkFKZB27OM_cjs = require('./chunk-FKZB27OM.cjs');
4
4
  require('./chunk-MAZEX4EZ.cjs');
5
5
  require('./chunk-MRZXTL46.cjs');
6
6
  require('./chunk-P53432AK.cjs');
@@ -11,9 +11,10 @@ require('./chunk-L3V3BYVS.cjs');
11
11
  require('./chunk-MKHYENKR.cjs');
12
12
  require('./chunk-TI7D4QDM.cjs');
13
13
  require('./chunk-VBWRH4UW.cjs');
14
- require('./chunk-MOU6O324.cjs');
14
+ require('./chunk-OCHUZ7J3.cjs');
15
+ require('./chunk-X6LGRB4H.cjs');
15
16
  require('./chunk-M5MUGSON.cjs');
16
- require('./chunk-FBGCSGCE.cjs');
17
+ require('./chunk-NZHVDWOM.cjs');
17
18
  require('./chunk-XCZZVRBY.cjs');
18
19
  require('./chunk-MXWR3T3N.cjs');
19
20
  require('./chunk-ZU5Q77OT.cjs');
@@ -22,7 +23,7 @@ require('./chunk-ZU5Q77OT.cjs');
22
23
 
23
24
  Object.defineProperty(exports, "MagicWand", {
24
25
  enumerable: true,
25
- get: function () { return chunkNWB6YCZY_cjs.MagicWand; }
26
+ get: function () { return chunkFKZB27OM_cjs.MagicWand; }
26
27
  });
27
28
  //# sourceMappingURL=magic-wand.cjs.map
28
29
  //# sourceMappingURL=magic-wand.cjs.map
@@ -1,4 +1,4 @@
1
- export { MagicWand } from './chunk-B6AIHYOP.js';
1
+ export { MagicWand } from './chunk-F4OYQ2XZ.js';
2
2
  import './chunk-UVUBV4VZ.js';
3
3
  import './chunk-KXYMMNNV.js';
4
4
  import './chunk-WX5XYDVN.js';
@@ -9,9 +9,10 @@ import './chunk-NRXK42LO.js';
9
9
  import './chunk-5VMILVWD.js';
10
10
  import './chunk-RBCMKPBX.js';
11
11
  import './chunk-IQ4KQJAO.js';
12
- import './chunk-6FCQD2KQ.js';
12
+ import './chunk-OZ4QFJ7N.js';
13
+ import './chunk-S53A6JIE.js';
13
14
  import './chunk-LQ4ICCN2.js';
14
- import './chunk-3KF3OYWS.js';
15
+ import './chunk-4GPH7HOR.js';
15
16
  import './chunk-45BBNJQD.js';
16
17
  import './chunk-J3A4Z2P7.js';
17
18
  import './chunk-MMW2JGKZ.js';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkC2LVHAIG_cjs = require('./chunk-C2LVHAIG.cjs');
3
+ var chunkOUNGGQIS_cjs = require('./chunk-OUNGGQIS.cjs');
4
4
  require('./chunk-OASSZI6M.cjs');
5
5
  require('./chunk-I27K6NLX.cjs');
6
6
  require('./chunk-JKD6CFIP.cjs');
@@ -15,7 +15,7 @@ require('./chunk-TI7D4QDM.cjs');
15
15
  require('./chunk-57FQGQJK.cjs');
16
16
  require('./chunk-OUYC6EIL.cjs');
17
17
  require('./chunk-M5MUGSON.cjs');
18
- require('./chunk-FBGCSGCE.cjs');
18
+ require('./chunk-NZHVDWOM.cjs');
19
19
  require('./chunk-XCZZVRBY.cjs');
20
20
  require('./chunk-MXWR3T3N.cjs');
21
21
  require('./chunk-SNHU2AI4.cjs');
@@ -25,15 +25,15 @@ require('./chunk-ZU5Q77OT.cjs');
25
25
 
26
26
  Object.defineProperty(exports, "PromptInput", {
27
27
  enumerable: true,
28
- get: function () { return chunkC2LVHAIG_cjs.PromptInput; }
28
+ get: function () { return chunkOUNGGQIS_cjs.PromptInput; }
29
29
  });
30
30
  Object.defineProperty(exports, "promptDataUrlToFile", {
31
31
  enumerable: true,
32
- get: function () { return chunkC2LVHAIG_cjs.promptDataUrlToFile; }
32
+ get: function () { return chunkOUNGGQIS_cjs.promptDataUrlToFile; }
33
33
  });
34
34
  Object.defineProperty(exports, "promptFileToDataUrl", {
35
35
  enumerable: true,
36
- get: function () { return chunkC2LVHAIG_cjs.promptFileToDataUrl; }
36
+ get: function () { return chunkOUNGGQIS_cjs.promptFileToDataUrl; }
37
37
  });
38
38
  //# sourceMappingURL=prompt-input.cjs.map
39
39
  //# sourceMappingURL=prompt-input.cjs.map
@@ -1,4 +1,4 @@
1
- export { PromptInput, promptDataUrlToFile, promptFileToDataUrl } from './chunk-TW52N55D.js';
1
+ export { PromptInput, promptDataUrlToFile, promptFileToDataUrl } from './chunk-B6WTCAGY.js';
2
2
  import './chunk-GR2WKBER.js';
3
3
  import './chunk-SV5BW3IA.js';
4
4
  import './chunk-J6IQHJET.js';
@@ -13,7 +13,7 @@ import './chunk-RBCMKPBX.js';
13
13
  import './chunk-RGANGU7X.js';
14
14
  import './chunk-YX6FTJ6N.js';
15
15
  import './chunk-LQ4ICCN2.js';
16
- import './chunk-3KF3OYWS.js';
16
+ import './chunk-4GPH7HOR.js';
17
17
  import './chunk-45BBNJQD.js';
18
18
  import './chunk-J3A4Z2P7.js';
19
19
  import './chunk-EDYAXGUM.js';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkKDISJ64Q_cjs = require('./chunk-KDISJ64Q.cjs');
3
+ var chunkI2VAGZXY_cjs = require('./chunk-I2VAGZXY.cjs');
4
4
  require('./chunk-MKGWHSNV.cjs');
5
5
  require('./chunk-J2DI6RMR.cjs');
6
6
  require('./chunk-MKHYENKR.cjs');
@@ -8,7 +8,7 @@ require('./chunk-TI7D4QDM.cjs');
8
8
  require('./chunk-57FQGQJK.cjs');
9
9
  require('./chunk-OUYC6EIL.cjs');
10
10
  require('./chunk-M5MUGSON.cjs');
11
- require('./chunk-FBGCSGCE.cjs');
11
+ require('./chunk-NZHVDWOM.cjs');
12
12
  require('./chunk-XCZZVRBY.cjs');
13
13
  require('./chunk-MXWR3T3N.cjs');
14
14
  require('./chunk-ZU5Q77OT.cjs');
@@ -17,7 +17,7 @@ require('./chunk-ZU5Q77OT.cjs');
17
17
 
18
18
  Object.defineProperty(exports, "ReasonTag", {
19
19
  enumerable: true,
20
- get: function () { return chunkKDISJ64Q_cjs.ReasonTag; }
20
+ get: function () { return chunkI2VAGZXY_cjs.ReasonTag; }
21
21
  });
22
22
  //# sourceMappingURL=reason-tag.cjs.map
23
23
  //# sourceMappingURL=reason-tag.cjs.map
@@ -1,4 +1,4 @@
1
- export { ReasonTag } from './chunk-EWE4TOG7.js';
1
+ export { ReasonTag } from './chunk-GSMD5NK5.js';
2
2
  import './chunk-QTS4Q2NK.js';
3
3
  import './chunk-MQ6VGG62.js';
4
4
  import './chunk-5VMILVWD.js';
@@ -6,7 +6,7 @@ import './chunk-RBCMKPBX.js';
6
6
  import './chunk-RGANGU7X.js';
7
7
  import './chunk-YX6FTJ6N.js';
8
8
  import './chunk-LQ4ICCN2.js';
9
- import './chunk-3KF3OYWS.js';
9
+ import './chunk-4GPH7HOR.js';
10
10
  import './chunk-45BBNJQD.js';
11
11
  import './chunk-J3A4Z2P7.js';
12
12
  import './chunk-MMW2JGKZ.js';
package/dist/sidebar.cjs CHANGED
@@ -1,12 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var chunkEZA6GWZL_cjs = require('./chunk-EZA6GWZL.cjs');
3
+ var chunkGK7IGL7N_cjs = require('./chunk-GK7IGL7N.cjs');
4
4
  require('./chunk-A2JUTNE6.cjs');
5
5
  require('./chunk-T6YELZPJ.cjs');
6
6
  require('./chunk-4GOOSZEK.cjs');
7
7
  require('./chunk-TXTRTTG7.cjs');
8
8
  require('./chunk-FQZE5N2N.cjs');
9
9
  require('./chunk-J2DI6RMR.cjs');
10
+ require('./chunk-X6LGRB4H.cjs');
10
11
  require('./chunk-57FQGQJK.cjs');
11
12
  require('./chunk-OUYC6EIL.cjs');
12
13
  require('./chunk-SNHU2AI4.cjs');
@@ -16,11 +17,11 @@ require('./chunk-ZU5Q77OT.cjs');
16
17
 
17
18
  Object.defineProperty(exports, "Sidebar", {
18
19
  enumerable: true,
19
- get: function () { return chunkEZA6GWZL_cjs.Sidebar; }
20
+ get: function () { return chunkGK7IGL7N_cjs.Sidebar; }
20
21
  });
21
22
  Object.defineProperty(exports, "useSidebar", {
22
23
  enumerable: true,
23
- get: function () { return chunkEZA6GWZL_cjs.useSidebar; }
24
+ get: function () { return chunkGK7IGL7N_cjs.useSidebar; }
24
25
  });
25
26
  //# sourceMappingURL=sidebar.cjs.map
26
27
  //# sourceMappingURL=sidebar.cjs.map
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { N as NavigableProps } from './types-DJI492iY.cjs';
3
+ import { N as NavigableProps, C as Color } from './types-DJI492iY.cjs';
4
4
 
5
5
  type SidebarCollapseMode = "icons" | "letters";
6
6
  interface SidebarProps {
@@ -29,14 +29,57 @@ interface SidebarProps {
29
29
  * @default "icons"
30
30
  */
31
31
  collapseMode?: SidebarCollapseMode;
32
+ /**
33
+ * Wrap the children in `<nav aria-label={navLabel}>`, so the items form a
34
+ * navigation landmark. The root stays an `<aside>`; the `<nav>` sits inside
35
+ * it and takes over the column layout. Omitted (or empty), no `<nav>` is
36
+ * rendered and the markup is exactly what it was before this prop existed.
37
+ */
38
+ navLabel?: string;
39
+ /**
40
+ * Arrow-key movement between items with a roving tabindex: the rail becomes
41
+ * ONE tab stop (the active item, else the first enabled one), and
42
+ * ArrowUp / ArrowDown / Home / End move focus within it. Disabled items and
43
+ * items inside a closed `Sidebar.Submenu` are skipped; a submenu's trigger
44
+ * is part of the sequence. Keys pressed in an input, textarea, select or
45
+ * contenteditable inside the sidebar are never intercepted, and
46
+ * `Sidebar.Toggle` keeps its own tab stop.
47
+ *
48
+ * Opt-in because it changes Tab order: without it every item is its own
49
+ * tab stop, as before.
50
+ * @default false
51
+ */
52
+ keyboardNav?: boolean;
32
53
  className?: string;
33
54
  }
55
+ /** Colour of a {@link SidebarItemProps.dot}. `dot={true}` is red. */
56
+ type SidebarDotColor = Color;
34
57
  interface SidebarItemProps extends NavigableProps {
35
58
  children: ReactNode;
36
59
  icon?: ReactNode;
37
60
  active?: boolean;
38
61
  disabled?: boolean;
39
62
  badge?: ReactNode;
63
+ /**
64
+ * Also render `badge` when the sidebar is collapsed, as an overlay at the
65
+ * corner of the icon (or of the letters). Off by default: a collapsed rail
66
+ * has never shown badges, and a wide badge ("Beta") over a 20px icon is not
67
+ * something to switch on for every existing consumer. Best for short counts.
68
+ * Handle: `data-react-fancy-sidebar-badge`.
69
+ */
70
+ collapsedBadge?: boolean;
71
+ /**
72
+ * A small attention dot at the icon's corner (unread, warning, "needs
73
+ * you"), shown expanded AND collapsed. `true` is red; pass any Badge colour
74
+ * for another. Purely visual: pair it with `dotLabel`. Handle:
75
+ * `data-react-fancy-sidebar-dot`, with `data-color`.
76
+ */
77
+ dot?: boolean | SidebarDotColor;
78
+ /**
79
+ * Screen-reader text for the dot ("3 unread"), rendered visually hidden and
80
+ * appended to the item's accessible name. Ignored without `dot`.
81
+ */
82
+ dotLabel?: string;
40
83
  onClick?: () => void;
41
84
  className?: string;
42
85
  }
@@ -59,9 +102,11 @@ interface SidebarContextValue {
59
102
  collapsed: boolean;
60
103
  collapseMode: SidebarCollapseMode;
61
104
  setCollapsed: (collapsed: boolean) => void;
105
+ /** Whether the root has `keyboardNav` on. */
106
+ keyboardNav?: boolean;
62
107
  }
63
108
 
64
- declare function SidebarItem({ children, href, as: As, icon, active, disabled, badge, onClick, className, ...rest }: SidebarItemProps): react.JSX.Element;
109
+ declare function SidebarItem({ children, href, as: As, icon, active, disabled, badge, collapsedBadge, dot, dotLabel, onClick, className, ...rest }: SidebarItemProps): react.JSX.Element;
65
110
  declare namespace SidebarItem {
66
111
  var displayName: string;
67
112
  }
@@ -81,7 +126,7 @@ declare namespace SidebarToggle {
81
126
  var displayName: string;
82
127
  }
83
128
 
84
- declare function SidebarRoot({ children, collapsed: controlledCollapsed, defaultCollapsed, onCollapsedChange, collapseMode, embedded, className, }: SidebarProps): react.JSX.Element;
129
+ declare function SidebarRoot({ children, collapsed: controlledCollapsed, defaultCollapsed, onCollapsedChange, collapseMode, embedded, navLabel, keyboardNav, className, }: SidebarProps): react.JSX.Element;
85
130
  declare const Sidebar: typeof SidebarRoot & {
86
131
  Item: typeof SidebarItem;
87
132
  Group: typeof SidebarGroup;
@@ -91,4 +136,4 @@ declare const Sidebar: typeof SidebarRoot & {
91
136
 
92
137
  declare function useSidebar(): SidebarContextValue;
93
138
 
94
- export { Sidebar, type SidebarCollapseMode, type SidebarContextValue, type SidebarGroupProps, type SidebarItemProps, type SidebarProps, type SidebarSubmenuProps, type SidebarToggleProps, useSidebar };
139
+ export { Sidebar, type SidebarCollapseMode, type SidebarContextValue, type SidebarDotColor, type SidebarGroupProps, type SidebarItemProps, type SidebarProps, type SidebarSubmenuProps, type SidebarToggleProps, useSidebar };
package/dist/sidebar.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { N as NavigableProps } from './types-DJI492iY.js';
3
+ import { N as NavigableProps, C as Color } from './types-DJI492iY.js';
4
4
 
5
5
  type SidebarCollapseMode = "icons" | "letters";
6
6
  interface SidebarProps {
@@ -29,14 +29,57 @@ interface SidebarProps {
29
29
  * @default "icons"
30
30
  */
31
31
  collapseMode?: SidebarCollapseMode;
32
+ /**
33
+ * Wrap the children in `<nav aria-label={navLabel}>`, so the items form a
34
+ * navigation landmark. The root stays an `<aside>`; the `<nav>` sits inside
35
+ * it and takes over the column layout. Omitted (or empty), no `<nav>` is
36
+ * rendered and the markup is exactly what it was before this prop existed.
37
+ */
38
+ navLabel?: string;
39
+ /**
40
+ * Arrow-key movement between items with a roving tabindex: the rail becomes
41
+ * ONE tab stop (the active item, else the first enabled one), and
42
+ * ArrowUp / ArrowDown / Home / End move focus within it. Disabled items and
43
+ * items inside a closed `Sidebar.Submenu` are skipped; a submenu's trigger
44
+ * is part of the sequence. Keys pressed in an input, textarea, select or
45
+ * contenteditable inside the sidebar are never intercepted, and
46
+ * `Sidebar.Toggle` keeps its own tab stop.
47
+ *
48
+ * Opt-in because it changes Tab order: without it every item is its own
49
+ * tab stop, as before.
50
+ * @default false
51
+ */
52
+ keyboardNav?: boolean;
32
53
  className?: string;
33
54
  }
55
+ /** Colour of a {@link SidebarItemProps.dot}. `dot={true}` is red. */
56
+ type SidebarDotColor = Color;
34
57
  interface SidebarItemProps extends NavigableProps {
35
58
  children: ReactNode;
36
59
  icon?: ReactNode;
37
60
  active?: boolean;
38
61
  disabled?: boolean;
39
62
  badge?: ReactNode;
63
+ /**
64
+ * Also render `badge` when the sidebar is collapsed, as an overlay at the
65
+ * corner of the icon (or of the letters). Off by default: a collapsed rail
66
+ * has never shown badges, and a wide badge ("Beta") over a 20px icon is not
67
+ * something to switch on for every existing consumer. Best for short counts.
68
+ * Handle: `data-react-fancy-sidebar-badge`.
69
+ */
70
+ collapsedBadge?: boolean;
71
+ /**
72
+ * A small attention dot at the icon's corner (unread, warning, "needs
73
+ * you"), shown expanded AND collapsed. `true` is red; pass any Badge colour
74
+ * for another. Purely visual: pair it with `dotLabel`. Handle:
75
+ * `data-react-fancy-sidebar-dot`, with `data-color`.
76
+ */
77
+ dot?: boolean | SidebarDotColor;
78
+ /**
79
+ * Screen-reader text for the dot ("3 unread"), rendered visually hidden and
80
+ * appended to the item's accessible name. Ignored without `dot`.
81
+ */
82
+ dotLabel?: string;
40
83
  onClick?: () => void;
41
84
  className?: string;
42
85
  }
@@ -59,9 +102,11 @@ interface SidebarContextValue {
59
102
  collapsed: boolean;
60
103
  collapseMode: SidebarCollapseMode;
61
104
  setCollapsed: (collapsed: boolean) => void;
105
+ /** Whether the root has `keyboardNav` on. */
106
+ keyboardNav?: boolean;
62
107
  }
63
108
 
64
- declare function SidebarItem({ children, href, as: As, icon, active, disabled, badge, onClick, className, ...rest }: SidebarItemProps): react.JSX.Element;
109
+ declare function SidebarItem({ children, href, as: As, icon, active, disabled, badge, collapsedBadge, dot, dotLabel, onClick, className, ...rest }: SidebarItemProps): react.JSX.Element;
65
110
  declare namespace SidebarItem {
66
111
  var displayName: string;
67
112
  }
@@ -81,7 +126,7 @@ declare namespace SidebarToggle {
81
126
  var displayName: string;
82
127
  }
83
128
 
84
- declare function SidebarRoot({ children, collapsed: controlledCollapsed, defaultCollapsed, onCollapsedChange, collapseMode, embedded, className, }: SidebarProps): react.JSX.Element;
129
+ declare function SidebarRoot({ children, collapsed: controlledCollapsed, defaultCollapsed, onCollapsedChange, collapseMode, embedded, navLabel, keyboardNav, className, }: SidebarProps): react.JSX.Element;
85
130
  declare const Sidebar: typeof SidebarRoot & {
86
131
  Item: typeof SidebarItem;
87
132
  Group: typeof SidebarGroup;
@@ -91,4 +136,4 @@ declare const Sidebar: typeof SidebarRoot & {
91
136
 
92
137
  declare function useSidebar(): SidebarContextValue;
93
138
 
94
- export { Sidebar, type SidebarCollapseMode, type SidebarContextValue, type SidebarGroupProps, type SidebarItemProps, type SidebarProps, type SidebarSubmenuProps, type SidebarToggleProps, useSidebar };
139
+ export { Sidebar, type SidebarCollapseMode, type SidebarContextValue, type SidebarDotColor, type SidebarGroupProps, type SidebarItemProps, type SidebarProps, type SidebarSubmenuProps, type SidebarToggleProps, useSidebar };
package/dist/sidebar.js CHANGED
@@ -1,10 +1,11 @@
1
- export { Sidebar, useSidebar } from './chunk-YJHP5FVA.js';
1
+ export { Sidebar, useSidebar } from './chunk-MTDOFZIB.js';
2
2
  import './chunk-2BXMMVQS.js';
3
3
  import './chunk-CPY7NHXM.js';
4
4
  import './chunk-ZQ3VXRUY.js';
5
5
  import './chunk-5U2DZ7AV.js';
6
6
  import './chunk-3K2CEAI7.js';
7
7
  import './chunk-MQ6VGG62.js';
8
+ import './chunk-S53A6JIE.js';
8
9
  import './chunk-RGANGU7X.js';
9
10
  import './chunk-YX6FTJ6N.js';
10
11
  import './chunk-EDYAXGUM.js';
package/dist/toast.cjs CHANGED
@@ -1,10 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var chunkH2YRZYKK_cjs = require('./chunk-H2YRZYKK.cjs');
3
+ var chunkKFA7B6WP_cjs = require('./chunk-KFA7B6WP.cjs');
4
4
  require('./chunk-MKHYENKR.cjs');
5
5
  require('./chunk-TI7D4QDM.cjs');
6
6
  require('./chunk-VBWRH4UW.cjs');
7
- require('./chunk-MOU6O324.cjs');
7
+ require('./chunk-OCHUZ7J3.cjs');
8
+ require('./chunk-X6LGRB4H.cjs');
8
9
  require('./chunk-SNHU2AI4.cjs');
9
10
  require('./chunk-ZU5Q77OT.cjs');
10
11
 
@@ -12,11 +13,11 @@ require('./chunk-ZU5Q77OT.cjs');
12
13
 
13
14
  Object.defineProperty(exports, "Toast", {
14
15
  enumerable: true,
15
- get: function () { return chunkH2YRZYKK_cjs.Toast; }
16
+ get: function () { return chunkKFA7B6WP_cjs.Toast; }
16
17
  });
17
18
  Object.defineProperty(exports, "useToast", {
18
19
  enumerable: true,
19
- get: function () { return chunkH2YRZYKK_cjs.useToast; }
20
+ get: function () { return chunkKFA7B6WP_cjs.useToast; }
20
21
  });
21
22
  //# sourceMappingURL=toast.cjs.map
22
23
  //# sourceMappingURL=toast.cjs.map
package/dist/toast.js CHANGED
@@ -1,8 +1,9 @@
1
- export { Toast, useToast } from './chunk-BQFPC5FL.js';
1
+ export { Toast, useToast } from './chunk-ESCIXKFT.js';
2
2
  import './chunk-5VMILVWD.js';
3
3
  import './chunk-RBCMKPBX.js';
4
4
  import './chunk-IQ4KQJAO.js';
5
- import './chunk-6FCQD2KQ.js';
5
+ import './chunk-OZ4QFJ7N.js';
6
+ import './chunk-S53A6JIE.js';
6
7
  import './chunk-EDYAXGUM.js';
7
8
  import './chunk-MMW2JGKZ.js';
8
9
  //# sourceMappingURL=toast.js.map
package/docs/Button.md CHANGED
@@ -44,6 +44,7 @@ import { Button } from "@particle-academy/react-fancy";
44
44
  | sort | `string` | `"eiab"` | Sort order of decorative elements: `e`=emoji, `i`=icon, `a`=avatar, `b`=badge |
45
45
  | loading | `boolean` | `false` | Show loading spinner (disables the button) |
46
46
  | disabled | `boolean` | - | Disable the button |
47
+ | type | `"button" \| "submit" \| "reset"` | `"button"` | Native button type. **Defaults to `"button"` since 6.0.0** (it was the HTML default, `submit`, before), so a Button inside a `<form>` does not submit it unless you pass `type="submit"`. Not applied in anchor mode. |
47
48
  | href | `string` | - | Render as an anchor tag instead of a button. Sanitized to a safe-protocol allow-list (since v2.5.0) — `javascript:`, `data:`, `vbscript:` are silently dropped and the component renders a `<button>` instead of an `<a>`. |
48
49
 
49
50
  Also extends all native `<button>` HTML attributes (except `color`).
@@ -75,6 +76,18 @@ Also extends all native `<button>` HTML attributes (except `color`).
75
76
  </Button>
76
77
  ```
77
78
 
79
+ ### In a form
80
+
81
+ A Button is `type="button"` unless you say otherwise, so only the one that
82
+ should submit says so:
83
+
84
+ ```tsx
85
+ <form onSubmit={save}>
86
+ <Button type="button" variant="ghost" onClick={cancel}>Cancel</Button>
87
+ <Button type="submit" color="blue">Save</Button>
88
+ </form>
89
+ ```
90
+
78
91
  ### Link button with trailing icon
79
92
 
80
93
  ```tsx
@@ -89,3 +102,11 @@ Also extends all native `<button>` HTML attributes (except `color`).
89
102
  <Button variant="ghost" color="red" icon="trash-2">Delete</Button>
90
103
  <Button variant="ghost" icon="download">Export</Button>
91
104
  ```
105
+
106
+ ## Focus ring
107
+
108
+ The ring shows on `:focus-visible` only, so it appears when someone reaches the
109
+ Button by keyboard and not after a mouse click. It uses the focus token
110
+ (`--fancy-focus`, blue-500 by default; `--fancy-focus-dark`, blue-400, in dark
111
+ mode) and is offset against the surface token, so dark mode gets no white gap.
112
+ Override it with `focus-visible:ring-*` classes in `className`.
package/docs/Sidebar.md CHANGED
@@ -34,6 +34,9 @@ import { Sidebar, Icon } from "@particle-academy/react-fancy";
34
34
  | defaultCollapsed | `boolean` | `false` | Default collapsed state (uncontrolled) |
35
35
  | onCollapsedChange | `(collapsed: boolean) => void` | - | Callback when collapsed state changes |
36
36
  | collapseMode | `"icons" \| "letters"` | `"icons"` | How items display when collapsed: icons only, or first 3 letters |
37
+ | embedded | `boolean` | `false` | Drop the app-shell chrome (right border, background, fixed `w-60`) for a sidebar inside a card, panel or drawer |
38
+ | navLabel | `string` | - | Wrap the children in `<nav aria-label={navLabel}>` so the items form a navigation landmark. Omitted, no `<nav>` is rendered |
39
+ | keyboardNav | `boolean` | `false` | ArrowUp / ArrowDown / Home / End between items, with a roving tabindex (the rail becomes one tab stop). See [Keyboard navigation](#keyboard-navigation) |
37
40
  | className | `string` | - | Additional CSS classes |
38
41
 
39
42
  ### Sidebar.Item
@@ -45,7 +48,10 @@ import { Sidebar, Icon } from "@particle-academy/react-fancy";
45
48
  | icon | `ReactNode` | - | Leading icon |
46
49
  | active | `boolean` | - | Active state highlight |
47
50
  | disabled | `boolean` | - | Disable the item |
48
- | badge | `ReactNode` | - | Trailing badge element |
51
+ | badge | `ReactNode` | - | Trailing badge element (expanded only, unless `collapsedBadge`) |
52
+ | collapsedBadge | `boolean` | `false` | Also show `badge` on a collapsed rail, as an overlay at the icon's corner. Best for short counts |
53
+ | dot | `boolean \| Color` | - | Attention dot at the icon's corner, shown expanded and collapsed. `true` is red; any Badge colour otherwise |
54
+ | dotLabel | `string` | - | Screen-reader text for the dot ("3 unread"), visually hidden and added to the item's accessible name |
49
55
  | onClick | `() => void` | - | Click handler |
50
56
  | className | `string` | - | Additional CSS classes |
51
57
 
@@ -94,6 +100,74 @@ const [collapsed, setCollapsed] = useState(false);
94
100
  - `"icons"` (default) — only the icon is shown when collapsed; falls back to the first 3 letters if no icon is provided
95
101
  - `"letters"` — the first 3 letters of the label are always shown
96
102
 
103
+ ## Attention marks on a compact rail
104
+
105
+ A collapsed rail shows only icons, so `badge` is hidden there by default. Use
106
+ `dot` for an unread, warning or "needs you" mark: it renders at the icon's
107
+ corner in both modes. A dot is only colour, so give it a `dotLabel` for screen
108
+ readers.
109
+
110
+ ```tsx
111
+ <Sidebar collapsed navLabel="Main">
112
+ <Sidebar.Item icon={<Icon name="inbox" size="sm" />} dot dotLabel="3 unread">
113
+ Inbox
114
+ </Sidebar.Item>
115
+ <Sidebar.Item icon={<Icon name="triangle-alert" size="sm" />} dot="amber" dotLabel="needs you">
116
+ Deploys
117
+ </Sidebar.Item>
118
+ <Sidebar.Item
119
+ icon={<Icon name="message-square" size="sm" />}
120
+ badge={<Badge size="sm" color="blue" variant="solid">12</Badge>}
121
+ collapsedBadge
122
+ >
123
+ Messages
124
+ </Sidebar.Item>
125
+ </Sidebar>
126
+ ```
127
+
128
+ - The collapsed item is still named by its label (`title` and a visually
129
+ hidden copy of the label), so the dot label or a badge count never replaces
130
+ the name: a screen reader hears "Inbox 3 unread".
131
+ - With both `dot` and `collapsedBadge` on a collapsed item, the badge takes the
132
+ top corner and the dot moves to the bottom one (`data-position="bottom"`).
133
+ - Handles: `data-react-fancy-sidebar-dot` (with `data-color` and
134
+ `data-position`), `data-react-fancy-sidebar-dot-label`,
135
+ `data-react-fancy-sidebar-badge` for the collapsed badge overlay.
136
+
137
+ ## Navigation landmark
138
+
139
+ `Sidebar` renders an `<aside>`. Pass `navLabel` to wrap its children in a
140
+ labelled `<nav>`, so the items appear in a screen reader's landmark list:
141
+
142
+ ```tsx
143
+ <Sidebar navLabel="Main">…</Sidebar>
144
+ ```
145
+
146
+ The `<nav>` (`data-react-fancy-sidebar-nav`) takes over the column layout and
147
+ fills the rail, so a footer pushed down with `mt-auto` still reaches the
148
+ bottom. Without `navLabel` the markup is unchanged.
149
+
150
+ ## Keyboard navigation
151
+
152
+ `keyboardNav` turns the rail into one tab stop with a roving tabindex:
153
+
154
+ - **Tab** lands on the active item (the one with `active`), or the first
155
+ enabled item when none is active. `Sidebar.Toggle` keeps its own tab stop.
156
+ - **ArrowDown / ArrowUp** move to the next / previous item; **Home / End** to
157
+ the first / last. No wrap at the ends.
158
+ - Disabled items are skipped. An open `Sidebar.Submenu`'s trigger and its items
159
+ are in the sequence; a closed submenu's items are skipped (its trigger gets
160
+ `aria-expanded`). Enter / Space on a trigger opens it as usual.
161
+ - Keys pressed in an input, textarea, select or contenteditable inside the
162
+ sidebar are never intercepted, nor are arrows with a modifier key.
163
+
164
+ It is opt-in because it changes Tab order: without it, every item is its own
165
+ tab stop, exactly as before.
166
+
167
+ ```tsx
168
+ <Sidebar keyboardNav navLabel="Main">…</Sidebar>
169
+ ```
170
+
97
171
  ## useSidebar Hook
98
172
 
99
173
  Access collapsed state from any child component:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/react-fancy",
3
- "version": "5.72.0",
3
+ "version": "6.1.0",
4
4
  "description": "React UI component library for Human+ UX — controlled, agent-bridgeable primitives",
5
5
  "repository": {
6
6
  "type": "git",