@flamingo-stack/openframe-frontend-core 0.0.661 → 0.0.662-snapshot.20260923194332

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 (133) hide show
  1. package/dist/{chunk-M23ZPKOK.js → chunk-3PSNWOAP.js} +4 -4
  2. package/dist/{chunk-D7QWYQBQ.cjs → chunk-4ZEHQXQ5.cjs} +75 -75
  3. package/dist/{chunk-D7QWYQBQ.cjs.map → chunk-4ZEHQXQ5.cjs.map} +1 -1
  4. package/dist/{chunk-YNW3DQFY.cjs → chunk-67FVIC5H.cjs} +81 -53
  5. package/dist/chunk-67FVIC5H.cjs.map +1 -0
  6. package/dist/{chunk-J5TAB64U.js → chunk-7I4DGWF5.js} +2 -2
  7. package/dist/{chunk-24T5HZPB.cjs → chunk-BASKR3Z4.cjs} +1 -1
  8. package/dist/chunk-BASKR3Z4.cjs.map +1 -0
  9. package/dist/{chunk-GXHZCGVJ.cjs → chunk-BSETJKSW.cjs} +25 -25
  10. package/dist/{chunk-GXHZCGVJ.cjs.map → chunk-BSETJKSW.cjs.map} +1 -1
  11. package/dist/{chunk-N4ORXOZK.cjs → chunk-DF6UYONR.cjs} +10 -10
  12. package/dist/{chunk-N4ORXOZK.cjs.map → chunk-DF6UYONR.cjs.map} +1 -1
  13. package/dist/{chunk-Z572FXXM.js → chunk-EX3YF5UR.js} +2 -2
  14. package/dist/{chunk-U4N65JUW.js → chunk-FXEOBJKX.js} +4 -4
  15. package/dist/{chunk-WDJT7NJ5.js → chunk-HZ3KIFUW.js} +5 -5
  16. package/dist/{chunk-PC5WWTDM.js → chunk-I5ZKHDT6.js} +3 -3
  17. package/dist/{chunk-5LS7KNAU.js → chunk-IHTDANFB.js} +7 -7
  18. package/dist/{chunk-F5LMTKQD.js → chunk-J3T2WNWC.js} +5 -5
  19. package/dist/{chunk-Q4XWYP5U.js → chunk-JVAG5CHS.js} +140 -112
  20. package/dist/chunk-JVAG5CHS.js.map +1 -0
  21. package/dist/{chunk-UA3V3KXX.js → chunk-KU7HL52F.js} +1 -1
  22. package/dist/chunk-KU7HL52F.js.map +1 -0
  23. package/dist/{chunk-7KNVRRI4.cjs → chunk-LPZHG75D.cjs} +25 -25
  24. package/dist/{chunk-7KNVRRI4.cjs.map → chunk-LPZHG75D.cjs.map} +1 -1
  25. package/dist/{chunk-ZASHVL45.cjs → chunk-MB5RK5WQ.cjs} +3 -3
  26. package/dist/{chunk-ZASHVL45.cjs.map → chunk-MB5RK5WQ.cjs.map} +1 -1
  27. package/dist/{chunk-4EY5JSMK.cjs → chunk-MEVV7FIR.cjs} +5 -5
  28. package/dist/{chunk-4EY5JSMK.cjs.map → chunk-MEVV7FIR.cjs.map} +1 -1
  29. package/dist/{chunk-IMDYBINC.js → chunk-N55XI4LH.js} +4 -4
  30. package/dist/{chunk-RFGXKRRL.js → chunk-NAML3TDW.js} +7 -7
  31. package/dist/{chunk-TRR6XUEP.js → chunk-OJR7KKCI.js} +3 -3
  32. package/dist/{chunk-LXBHYUIN.js → chunk-OZTH6T4W.js} +2 -2
  33. package/dist/{chunk-6VY6PXAN.cjs → chunk-P3IDYJE5.cjs} +33 -33
  34. package/dist/{chunk-6VY6PXAN.cjs.map → chunk-P3IDYJE5.cjs.map} +1 -1
  35. package/dist/{chunk-WGTKYVBK.cjs → chunk-PBEXPLFI.cjs} +12 -12
  36. package/dist/{chunk-WGTKYVBK.cjs.map → chunk-PBEXPLFI.cjs.map} +1 -1
  37. package/dist/{chunk-EUT6SQW7.js → chunk-Q3G5WOER.js} +3 -3
  38. package/dist/{chunk-4JITKV2S.cjs → chunk-REQ2AIEE.cjs} +51 -51
  39. package/dist/{chunk-4JITKV2S.cjs.map → chunk-REQ2AIEE.cjs.map} +1 -1
  40. package/dist/{chunk-4NKKPGDN.js → chunk-RP4TSHMY.js} +2 -2
  41. package/dist/{chunk-GLDXZK76.cjs → chunk-RYEMWKYE.cjs} +7 -7
  42. package/dist/{chunk-GLDXZK76.cjs.map → chunk-RYEMWKYE.cjs.map} +1 -1
  43. package/dist/{chunk-RPHRBZG6.cjs → chunk-TKASQOSM.cjs} +3 -3
  44. package/dist/{chunk-RPHRBZG6.cjs.map → chunk-TKASQOSM.cjs.map} +1 -1
  45. package/dist/{chunk-KCYGLC7Q.js → chunk-V54WTP2E.js} +5 -5
  46. package/dist/{chunk-H3DF7COI.cjs → chunk-VKKVWGFW.cjs} +44 -44
  47. package/dist/{chunk-H3DF7COI.cjs.map → chunk-VKKVWGFW.cjs.map} +1 -1
  48. package/dist/{chunk-XNJZ6A2S.cjs → chunk-WDE7ETA5.cjs} +5 -5
  49. package/dist/{chunk-XNJZ6A2S.cjs.map → chunk-WDE7ETA5.cjs.map} +1 -1
  50. package/dist/{chunk-XOA32PN3.cjs → chunk-WZ6OV7VU.cjs} +22 -22
  51. package/dist/{chunk-XOA32PN3.cjs.map → chunk-WZ6OV7VU.cjs.map} +1 -1
  52. package/dist/{chunk-QARWK4LN.cjs → chunk-XKQJDXDO.cjs} +10 -10
  53. package/dist/{chunk-QARWK4LN.cjs.map → chunk-XKQJDXDO.cjs.map} +1 -1
  54. package/dist/{chunk-FC6I2NWF.js → chunk-XSQSTJ5D.js} +2 -2
  55. package/dist/{chunk-ZIT4TC5R.cjs → chunk-XVSA4565.cjs} +248 -248
  56. package/dist/{chunk-ZIT4TC5R.cjs.map → chunk-XVSA4565.cjs.map} +1 -1
  57. package/dist/components/case-studies/index.cjs +20 -20
  58. package/dist/components/case-studies/index.js +5 -5
  59. package/dist/components/chat/index.cjs +3 -3
  60. package/dist/components/chat/index.js +2 -2
  61. package/dist/components/contact/index.cjs +6 -6
  62. package/dist/components/contact/index.js +5 -5
  63. package/dist/components/docs/index.cjs +9 -9
  64. package/dist/components/docs/index.js +8 -8
  65. package/dist/components/embeds/index.cjs +6 -6
  66. package/dist/components/embeds/index.js +5 -5
  67. package/dist/components/faq/index.cjs +6 -6
  68. package/dist/components/faq/index.js +5 -5
  69. package/dist/components/features/index.cjs +5 -5
  70. package/dist/components/features/index.js +4 -4
  71. package/dist/components/help-center-pages/index.cjs +25 -25
  72. package/dist/components/help-center-pages/index.js +16 -16
  73. package/dist/components/icons/elestio-logo.d.ts +4 -1
  74. package/dist/components/icons/elestio-logo.d.ts.map +1 -1
  75. package/dist/components/icons/index.cjs +2 -2
  76. package/dist/components/icons/index.js +1 -1
  77. package/dist/components/index.cjs +44 -42
  78. package/dist/components/index.cjs.map +1 -1
  79. package/dist/components/index.js +17 -15
  80. package/dist/components/index.js.map +1 -1
  81. package/dist/components/meeting-scheduler/index.cjs +28 -28
  82. package/dist/components/meeting-scheduler/index.js +4 -4
  83. package/dist/components/navigation/index.cjs +10 -8
  84. package/dist/components/navigation/index.cjs.map +1 -1
  85. package/dist/components/navigation/index.d.ts +2 -0
  86. package/dist/components/navigation/index.d.ts.map +1 -1
  87. package/dist/components/navigation/index.js +9 -7
  88. package/dist/components/navigation/mobile-burger-menu.d.ts.map +1 -1
  89. package/dist/components/navigation/navigation-item-badge.d.ts +22 -0
  90. package/dist/components/navigation/navigation-item-badge.d.ts.map +1 -0
  91. package/dist/components/navigation/navigation-sidebar-item.d.ts.map +1 -1
  92. package/dist/components/onboarding-guides/index.cjs +8 -8
  93. package/dist/components/onboarding-guides/index.js +7 -7
  94. package/dist/components/tickets/index.cjs +9 -9
  95. package/dist/components/tickets/index.js +8 -8
  96. package/dist/components/ui/index.cjs +5 -5
  97. package/dist/components/ui/index.js +4 -4
  98. package/dist/hooks/index.cjs +3 -3
  99. package/dist/hooks/index.js +2 -2
  100. package/dist/index.cjs +11 -9
  101. package/dist/index.cjs.map +1 -1
  102. package/dist/index.js +10 -8
  103. package/dist/index.js.map +1 -1
  104. package/dist/types/navigation.d.ts +8 -0
  105. package/dist/types/navigation.d.ts.map +1 -1
  106. package/package.json +1 -1
  107. package/src/components/icons/elestio-logo.tsx +4 -1
  108. package/src/components/navigation/index.ts +2 -0
  109. package/src/components/navigation/mobile-burger-menu.tsx +16 -8
  110. package/src/components/navigation/navigation-item-badge.tsx +40 -0
  111. package/src/components/navigation/navigation-sidebar-item.tsx +15 -4
  112. package/src/stories/AppLayout.stories.tsx +1 -0
  113. package/src/types/navigation.ts +8 -0
  114. package/dist/chunk-24T5HZPB.cjs.map +0 -1
  115. package/dist/chunk-Q4XWYP5U.js.map +0 -1
  116. package/dist/chunk-UA3V3KXX.js.map +0 -1
  117. package/dist/chunk-YNW3DQFY.cjs.map +0 -1
  118. /package/dist/{chunk-M23ZPKOK.js.map → chunk-3PSNWOAP.js.map} +0 -0
  119. /package/dist/{chunk-J5TAB64U.js.map → chunk-7I4DGWF5.js.map} +0 -0
  120. /package/dist/{chunk-Z572FXXM.js.map → chunk-EX3YF5UR.js.map} +0 -0
  121. /package/dist/{chunk-U4N65JUW.js.map → chunk-FXEOBJKX.js.map} +0 -0
  122. /package/dist/{chunk-WDJT7NJ5.js.map → chunk-HZ3KIFUW.js.map} +0 -0
  123. /package/dist/{chunk-PC5WWTDM.js.map → chunk-I5ZKHDT6.js.map} +0 -0
  124. /package/dist/{chunk-5LS7KNAU.js.map → chunk-IHTDANFB.js.map} +0 -0
  125. /package/dist/{chunk-F5LMTKQD.js.map → chunk-J3T2WNWC.js.map} +0 -0
  126. /package/dist/{chunk-IMDYBINC.js.map → chunk-N55XI4LH.js.map} +0 -0
  127. /package/dist/{chunk-RFGXKRRL.js.map → chunk-NAML3TDW.js.map} +0 -0
  128. /package/dist/{chunk-TRR6XUEP.js.map → chunk-OJR7KKCI.js.map} +0 -0
  129. /package/dist/{chunk-LXBHYUIN.js.map → chunk-OZTH6T4W.js.map} +0 -0
  130. /package/dist/{chunk-EUT6SQW7.js.map → chunk-Q3G5WOER.js.map} +0 -0
  131. /package/dist/{chunk-4NKKPGDN.js.map → chunk-RP4TSHMY.js.map} +0 -0
  132. /package/dist/{chunk-KCYGLC7Q.js.map → chunk-V54WTP2E.js.map} +0 -0
  133. /package/dist/{chunk-FC6I2NWF.js.map → chunk-XSQSTJ5D.js.map} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flamingo-stack/openframe-frontend-core",
3
- "version": "0.0.661",
3
+ "version": "0.0.662-snapshot.20260923194332",
4
4
  "description": "Shared design system and components for all Flamingo platforms",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -4,7 +4,10 @@ import React from 'react';
4
4
  * Official Elestio logo with unique IDs to prevent gradient/clip-path collisions
5
5
  * when the same SVG is rendered multiple times on the page.
6
6
  */
7
- /** @deprecated Use icons from icons-v2-generated instead. */
7
+ /**
8
+ * @deprecated Use icons from icons-v2-generated instead. This component is retained
9
+ * only for existing usages; do not add new usages or new icons to this deprecated set.
10
+ */
8
11
  export const ElestioLogo = ({ className, ...props }: { className?: string } & React.SVGProps<SVGSVGElement>) => {
9
12
  // Generate unique ID suffix to avoid ID collisions between instances
10
13
  const uniqueId = React.useId();
@@ -51,6 +51,8 @@ export { HeaderButton } from './header-button';
51
51
  export type { HeaderButtonProps } from './header-button';
52
52
  export { UnreadDot, UnreadCountBadge } from './unread-dot';
53
53
  export type { UnreadDotProps, UnreadCountBadgeProps } from './unread-dot';
54
+ export { NavigationItemBadge } from './navigation-item-badge';
55
+ export type { NavigationItemBadgeProps } from './navigation-item-badge';
54
56
  export { TicketAlertsButton } from './ticket-alerts-button';
55
57
  export type { TicketAlertsButtonProps } from './ticket-alerts-button';
56
58
 
@@ -8,6 +8,7 @@ import { cn } from '../../utils';
8
8
  import { Logout02Icon, PenEditIcon, UserSearchIcon } from '../icons-v2-generated';
9
9
  import { Button, SquareAvatar } from '../ui';
10
10
  import { OVERLAY_BACKDROP_CLASS } from '../ui/drawer';
11
+ import { NavigationItemBadge } from './navigation-item-badge';
11
12
 
12
13
  // Header height constant — the unified top-navigation `small` bar (56px on all screens)
13
14
  const HEADER_HEIGHT = 56;
@@ -93,6 +94,9 @@ export const MobileBurgerMenu = React.memo(function MobileBurgerMenuImpl({
93
94
  disabled && 'cursor-not-allowed opacity-50',
94
95
  )}
95
96
  aria-current={isActive ? 'page' : undefined}
97
+ // The same name the sidebar row announces — "Scripts (Beta)" — rather than
98
+ // the content read raw, which Chrome hands over as "Scripts BETA".
99
+ aria-label={item.badge ? `${item.label} (${item.badge})` : undefined}
96
100
  >
97
101
  {/* Icon */}
98
102
  {item.icon && (
@@ -104,14 +108,18 @@ export const MobileBurgerMenu = React.memo(function MobileBurgerMenuImpl({
104
108
  </div>
105
109
  )}
106
110
 
107
- {/* Label */}
108
- <span
109
- className={cn(
110
- 'flex-1 truncate text-left text-h6',
111
- isActive && !disabled ? 'text-ods-accent' : 'text-ods-text-primary',
112
- )}
113
- >
114
- {item.label}
111
+ {/* Label, with its stamp when the entry carries one. The button's
112
+ accessible name is its content, so the stamp reads as part of it. */}
113
+ <span className="flex min-w-0 flex-1 items-center gap-[var(--spacing-system-xxs)]">
114
+ <span
115
+ className={cn(
116
+ 'min-w-0 truncate text-left text-h6',
117
+ isActive && !disabled ? 'text-ods-accent' : 'text-ods-text-primary',
118
+ )}
119
+ >
120
+ {item.label}
121
+ </span>
122
+ {item.badge && <NavigationItemBadge compact label={item.badge} />}
115
123
  </span>
116
124
  </button>
117
125
  );
@@ -0,0 +1,40 @@
1
+ 'use client';
2
+
3
+ import { cn } from '../../utils/cn';
4
+ import { Tag } from '../ui/tag';
5
+
6
+ export interface NavigationItemBadgeProps {
7
+ label: string;
8
+ /**
9
+ * The chip at the badge scale — `h-5`, the word at `text-badge` — for the
10
+ * mobile burger card. The card is a 40px `text-h6` row in a two-column grid,
11
+ * and the default 32px chip stretches its grid row 16px past its neighbours.
12
+ * The sidebar row is 56px and takes the default chip, the same one Settings
13
+ * stamps "Beta" with.
14
+ */
15
+ compact?: boolean;
16
+ className?: string;
17
+ 'aria-hidden'?: boolean;
18
+ }
19
+
20
+ /**
21
+ * The stamp a navigation entry carries after its label
22
+ * (`NavigationSidebarItem.badge`): the `warning` `Tag`, the same chip Settings
23
+ * stamps "Beta" with, on the two surfaces that draw an entry with its label —
24
+ * the expanded sidebar row and the mobile burger card. The minimized rail draws
25
+ * none; there the row's tooltip and accessible name carry the word.
26
+ */
27
+ export function NavigationItemBadge({ label, compact = false, className, ...rest }: NavigationItemBadgeProps) {
28
+ // `pointer-events-none`: the chip's hover shade is for chips you act on. In a
29
+ // nav row the row is the target, and the cursor passes through to it.
30
+ return (
31
+ <Tag
32
+ as="span"
33
+ label={label}
34
+ variant="warning"
35
+ className={cn('pointer-events-none shrink-0', compact && 'h-5 px-[var(--spacing-system-xxs)]', className)}
36
+ labelClassName={compact ? 'text-badge' : undefined}
37
+ {...rest}
38
+ />
39
+ );
40
+ }
@@ -4,6 +4,7 @@ import { cloneElement, memo, type ReactElement, type ReactNode, type MouseEvent
4
4
  import Link from '../../embed-shims/next-link';
5
5
  import type { NavigationSidebarItem } from '../../types/navigation';
6
6
  import { cn } from '../../utils';
7
+ import { NavigationItemBadge } from './navigation-item-badge';
7
8
  import { UnreadDot } from './unread-dot';
8
9
 
9
10
  interface IconProps {
@@ -50,6 +51,9 @@ export const NavigationSidebarItemButton = memo(function NavigationSidebarItemBu
50
51
  }: NavigationSidebarItemButtonProps) {
51
52
  const unreadCount = item.unreadCount ?? 0;
52
53
  const hasUnread = unreadCount > 0;
54
+ // The accessible name carries the stamp — "Devices (Beta)" — because `aria-label`
55
+ // replaces the content; the rail's tooltip is the same string.
56
+ const name = item.badge ? `${item.label} (${item.badge})` : item.label;
53
57
 
54
58
  const className = cn(
55
59
  // `isolate` scopes the hover layer's negative z-index to this row, so it
@@ -97,14 +101,21 @@ export const NavigationSidebarItemButton = memo(function NavigationSidebarItemBu
97
101
  {hasUnread && !showLabel && <UnreadDot size="fixed" />}
98
102
  </div>
99
103
 
104
+ {/* The label column: the label and its stamp, fading together on collapse.
105
+ The wrapper clips — a `shrink-0` stamp beside a zero-width label would
106
+ otherwise overflow the rail and hand the sidebar a horizontal scrollbar.
107
+ The rail draws no stamp of its own: a word under one glyph read as a
108
+ caption the other rows lack, so there the row's tooltip and accessible
109
+ name carry it. */}
100
110
  <span
101
111
  className={cn(
102
- 'flex-1 truncate text-left transition-[opacity,margin-left] duration-300 text-h4',
112
+ 'flex min-w-0 flex-1 items-center overflow-hidden text-left transition-[opacity,margin-left] duration-300',
103
113
  showLabel ? 'ml-[var(--spacing-system-xs)] opacity-100' : 'ml-0 opacity-0',
104
114
  )}
105
115
  aria-hidden={!showLabel}
106
116
  >
107
- {item.label}
117
+ <span className="min-w-0 truncate text-h4">{item.label}</span>
118
+ {item.badge && <NavigationItemBadge label={item.badge} className="ml-[var(--spacing-system-xs)] shrink-0" />}
108
119
  </span>
109
120
 
110
121
  {hasUnread && showLabel && (
@@ -117,8 +128,8 @@ export const NavigationSidebarItemButton = memo(function NavigationSidebarItemBu
117
128
 
118
129
  const shared = {
119
130
  className,
120
- title: !showLabel ? item.label : undefined,
121
- 'aria-label': item.label,
131
+ title: !showLabel ? name : undefined,
132
+ 'aria-label': name,
122
133
  'aria-current': isActive ? ('page' as const) : undefined,
123
134
  };
124
135
 
@@ -37,6 +37,7 @@ const defaultNavigationItems: NavigationSidebarConfig['items'] = [
37
37
  label: 'Scripts',
38
38
  icon: <BracketCurlyIcon size={24} />,
39
39
  path: '/scripts',
40
+ badge: 'Beta',
40
41
  },
41
42
  ];
42
43
 
@@ -165,6 +165,14 @@ export interface NavigationSidebarItem {
165
165
  icon: React.ReactNode;
166
166
  path?: string;
167
167
  unreadCount?: number;
168
+ /**
169
+ * A stamp after the label — "Beta" on a module still behind a flag. One short
170
+ * word, drawn as a chip beside the label in the expanded sidebar and the mobile
171
+ * menu; the minimized rail carries it only in the row's tooltip and accessible
172
+ * name. Cased as it should be read ("Beta"): the surfaces upper-case it
173
+ * themselves, and the accessible name becomes "Devices (Beta)".
174
+ */
175
+ badge?: string;
168
176
  isActive?: boolean;
169
177
  onClick?: () => void;
170
178
  children?: NavigationSidebarItem[];