@oxy.so/bloom 4.25.0 → 4.26.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 (69) hide show
  1. package/docs/media-header.mdx +1 -1
  2. package/lib/commonjs/ai-chat/AiChatCodePanel.js +2 -2
  3. package/lib/commonjs/ai-chat/AiChatCodePanel.js.map +1 -1
  4. package/lib/commonjs/ai-chat/AiChatShell.js +3 -3
  5. package/lib/commonjs/ai-chat/AiChatShell.js.map +1 -1
  6. package/lib/commonjs/composer-panel/ComposerPanelStatusTab.js +2 -2
  7. package/lib/commonjs/composer-panel/ComposerPanelStatusTab.js.map +1 -1
  8. package/lib/commonjs/composer-panel/ComposerPillBase.js +3 -1
  9. package/lib/commonjs/composer-panel/ComposerPillBase.js.map +1 -1
  10. package/lib/commonjs/composer-panel/ComposerStatusBarBase.js +3 -3
  11. package/lib/commonjs/composer-panel/ComposerStatusBarBase.js.map +1 -1
  12. package/lib/commonjs/composer-panel/ModelPickerBase.js +3 -2
  13. package/lib/commonjs/composer-panel/ModelPickerBase.js.map +1 -1
  14. package/lib/commonjs/composer-panel/PermissionMenu.js +19 -3
  15. package/lib/commonjs/composer-panel/PermissionMenu.js.map +1 -1
  16. package/lib/commonjs/media-header/MediaActionBar.js +4 -1
  17. package/lib/commonjs/media-header/MediaActionBar.js.map +1 -1
  18. package/lib/module/ai-chat/AiChatCodePanel.js +2 -2
  19. package/lib/module/ai-chat/AiChatCodePanel.js.map +1 -1
  20. package/lib/module/ai-chat/AiChatShell.js +3 -3
  21. package/lib/module/ai-chat/AiChatShell.js.map +1 -1
  22. package/lib/module/composer-panel/ComposerPanelStatusTab.js +2 -2
  23. package/lib/module/composer-panel/ComposerPanelStatusTab.js.map +1 -1
  24. package/lib/module/composer-panel/ComposerPillBase.js +3 -1
  25. package/lib/module/composer-panel/ComposerPillBase.js.map +1 -1
  26. package/lib/module/composer-panel/ComposerStatusBarBase.js +3 -3
  27. package/lib/module/composer-panel/ComposerStatusBarBase.js.map +1 -1
  28. package/lib/module/composer-panel/ModelPickerBase.js +3 -2
  29. package/lib/module/composer-panel/ModelPickerBase.js.map +1 -1
  30. package/lib/module/composer-panel/PermissionMenu.js +19 -3
  31. package/lib/module/composer-panel/PermissionMenu.js.map +1 -1
  32. package/lib/module/media-header/MediaActionBar.js +4 -1
  33. package/lib/module/media-header/MediaActionBar.js.map +1 -1
  34. package/lib/typescript/commonjs/ai-chat/AiChatCodePanel.d.ts +1 -1
  35. package/lib/typescript/commonjs/ai-chat/AiChatShell.d.ts +1 -1
  36. package/lib/typescript/commonjs/composer-panel/ComposerPanelStatusTab.d.ts +1 -1
  37. package/lib/typescript/commonjs/composer-panel/ComposerPillBase.d.ts.map +1 -1
  38. package/lib/typescript/commonjs/composer-panel/ComposerStatusBarBase.d.ts +2 -2
  39. package/lib/typescript/commonjs/composer-panel/ModelPickerBase.d.ts +1 -1
  40. package/lib/typescript/commonjs/composer-panel/ModelPickerBase.d.ts.map +1 -1
  41. package/lib/typescript/commonjs/composer-panel/PermissionMenu.d.ts +3 -1
  42. package/lib/typescript/commonjs/composer-panel/PermissionMenu.d.ts.map +1 -1
  43. package/lib/typescript/commonjs/media-header/MediaActionBar.d.ts +1 -1
  44. package/lib/typescript/commonjs/media-header/MediaActionBar.d.ts.map +1 -1
  45. package/lib/typescript/commonjs/media-header/types.d.ts +10 -0
  46. package/lib/typescript/commonjs/media-header/types.d.ts.map +1 -1
  47. package/lib/typescript/module/ai-chat/AiChatCodePanel.d.ts +1 -1
  48. package/lib/typescript/module/ai-chat/AiChatShell.d.ts +1 -1
  49. package/lib/typescript/module/composer-panel/ComposerPanelStatusTab.d.ts +1 -1
  50. package/lib/typescript/module/composer-panel/ComposerPillBase.d.ts.map +1 -1
  51. package/lib/typescript/module/composer-panel/ComposerStatusBarBase.d.ts +2 -2
  52. package/lib/typescript/module/composer-panel/ModelPickerBase.d.ts +1 -1
  53. package/lib/typescript/module/composer-panel/ModelPickerBase.d.ts.map +1 -1
  54. package/lib/typescript/module/composer-panel/PermissionMenu.d.ts +3 -1
  55. package/lib/typescript/module/composer-panel/PermissionMenu.d.ts.map +1 -1
  56. package/lib/typescript/module/media-header/MediaActionBar.d.ts +1 -1
  57. package/lib/typescript/module/media-header/MediaActionBar.d.ts.map +1 -1
  58. package/lib/typescript/module/media-header/types.d.ts +10 -0
  59. package/lib/typescript/module/media-header/types.d.ts.map +1 -1
  60. package/package.json +1 -1
  61. package/src/ai-chat/AiChatCodePanel.tsx +2 -2
  62. package/src/ai-chat/AiChatShell.tsx +3 -3
  63. package/src/composer-panel/ComposerPanelStatusTab.tsx +2 -2
  64. package/src/composer-panel/ComposerPillBase.tsx +3 -1
  65. package/src/composer-panel/ComposerStatusBarBase.tsx +3 -3
  66. package/src/composer-panel/ModelPickerBase.tsx +3 -2
  67. package/src/composer-panel/PermissionMenu.tsx +17 -4
  68. package/src/media-header/MediaActionBar.tsx +4 -1
  69. package/src/media-header/types.ts +10 -0
@@ -236,7 +236,7 @@ export function AiChatResizeHandle({
236
236
  // ---------------------------------------------------------------------------
237
237
 
238
238
  /**
239
- * The in-container header below `xl`: 48 tall, px 12 / pt 11. The menu
239
+ * The in-container header below `xl`: at least 48 tall, px 12 / pt 11. The menu
240
240
  * button (below `lg`, where the sidebar is a drawer) and the chat's name in
241
241
  * headline-medium on the left; the button opening the panel drawer on the right.
242
242
  * Both are 36px secondary icon buttons. Renders nothing outside an
@@ -251,7 +251,7 @@ export function AiChatMobileHeader({ title, style, testID }: AiChatMobileHeaderP
251
251
  testID={testID}
252
252
  style={[
253
253
  {
254
- height: 48,
254
+ minHeight: 48,
255
255
  flexShrink: 0,
256
256
  flexDirection: 'row',
257
257
  alignItems: 'center',
@@ -738,7 +738,7 @@ export function AiChatShell({
738
738
  ]}>
739
739
  <View
740
740
  style={{
741
- height: 40,
741
+ minHeight: 40,
742
742
  flexShrink: 0,
743
743
  flexDirection: 'row',
744
744
  alignItems: 'center',
@@ -44,7 +44,7 @@ function StatusItem({ icon, label, palette }: { icon: React.ReactNode; label: st
44
44
 
45
45
  /**
46
46
  * The status tab: the grey tab hanging off the Composer Panel's
47
- * top edge — 34 tall, inset 28 each side, radius 16 on the top corners only,
47
+ * top edge — at least 34 tall, inset 28 each side, radius 16 on the top corners only,
48
48
  * px 8 / py 4. Branch (mirrored merge glyph) and project folder on the left, 12
49
49
  * apart; the context meter on the right (py 4, pl 6 / pr 8, gap 4).
50
50
  */
@@ -58,7 +58,7 @@ function ComposerPanelStatusTabComponent({ branch, project, context, style, test
58
58
  {
59
59
  marginLeft: TAB_INSET,
60
60
  marginRight: TAB_INSET,
61
- height: TAB_HEIGHT,
61
+ minHeight: TAB_HEIGHT,
62
62
  flexDirection: 'row',
63
63
  alignItems: 'center',
64
64
  justifyContent: 'space-between',
@@ -251,7 +251,9 @@ function ModelMenu({
251
251
  const modelName = models.find((entry) => entry.id === modelId)?.name ?? modelId;
252
252
  const hasEffort = levels.length > 0;
253
253
  const triggerStyle: WebCssStyle = {
254
- height: 32,
254
+ // At least 32, never exactly: a fixed height clips the name at the largest
255
+ // system font.
256
+ minHeight: 32,
255
257
  flexShrink: 0,
256
258
  flexDirection: 'row',
257
259
  alignItems: 'center',
@@ -142,8 +142,8 @@ function FolderRow({
142
142
  }
143
143
 
144
144
  /**
145
- * The line under the AI chat's pill composer (the reference's `StatusBar`): 26
146
- * tall, space-between.
145
+ * The line under the AI chat's pill composer (the reference's `StatusBar`): at
146
+ * least 26 tall (it grows with the system font), space-between.
147
147
  *
148
148
  * left gap 12: the branch (mirrored merge glyph) and the project folder —
149
149
  * its caret turns over while the "Local Folders" panel is open
@@ -188,7 +188,7 @@ export function ComposerStatusBarBase({
188
188
  return (
189
189
  <View
190
190
  testID={testID}
191
- style={[{ width: '100%', height: 26, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }, style]}>
191
+ style={[{ width: '100%', minHeight: 26, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }, style]}>
192
192
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>
193
193
  {branch !== undefined ? (
194
194
  <StatusItem
@@ -369,7 +369,8 @@ function ModelRow({
369
369
  <View
370
370
  style={{
371
371
  position: 'relative',
372
- height: ROW_HEIGHT,
372
+ // A floor, not a height: the name grows with the system font.
373
+ minHeight: ROW_HEIGHT,
373
374
  width: '100%',
374
375
  flexShrink: 0,
375
376
  flexDirection: 'row',
@@ -424,7 +425,7 @@ function ModelRow({
424
425
  * mark in view (instantly on open, smoothly after)
425
426
  * column top 8 / right 8 / left 52: a 20px header ("Models" + a 50%-opacity
426
427
  * "Quick Search" hint, or the search field), then the list 4 below
427
- * rows 36 tall, radius 10, px 8: 16px mark, 6, name (+ provider while
428
+ * rows min 36 tall, radius 10, px 8: 16px mark, 6, name (+ provider while
428
429
  * searching), the effort chip on the selected row, 12, 14px radio;
429
430
  * 4 apart, pb 4, soft top edge once scrolled
430
431
  *
@@ -10,6 +10,8 @@ import type { ComposerPanelLabels, ComposerPanelPermissionOption } from './types
10
10
  import { dataHook } from './web-hooks';
11
11
 
12
12
  const FLIP: ViewStyle = { transform: [{ scaleY: -1 }] };
13
+ /** The permission chip's widest: past this a mode's name truncates. */
14
+ const PERMISSION_TRIGGER_MAX_WIDTH = 160;
13
15
 
14
16
  interface PermissionMenuProps {
15
17
  palette: ComposerPalette;
@@ -27,7 +29,9 @@ interface PermissionMenuProps {
27
29
  * press or while its menu is open, and a 323px panel of radio rows that opens
28
30
  * upward.
29
31
  *
30
- * trigger h 30, pl 8 / pr 10, gap 4, icon 16, body-medium secondary
32
+ * trigger min-h 30 (grows with the system font), max-w 160 then the
33
+ * label ellipsizes, pl 8 / pr 10, gap 4, icon 16, body-medium
34
+ * secondary
31
35
  * panel w 323, radius 20, border, p 6, shadow-dropdown
32
36
  * body pt 4, header→rows 6; header px 8 gap 10, body-medium tertiary
33
37
  * row p 8, radius 14, gap 8, icon 20, label body-medium secondary,
@@ -82,7 +86,12 @@ export function PermissionMenu({
82
86
  onHoverOut={() => setHovered(false)}
83
87
  style={({ pressed }) => {
84
88
  const trigger: WebCssStyle = {
85
- height: 30,
89
+ // At least 30, never exactly: at the largest system font the label
90
+ // is taller than 30 and a fixed height clipped it top and bottom.
91
+ // A long mode name truncates at a width that still reads as a chip.
92
+ minHeight: 30,
93
+ minWidth: 0,
94
+ maxWidth: PERMISSION_TRIGGER_MAX_WIDTH,
86
95
  flexShrink: 0,
87
96
  flexDirection: 'row',
88
97
  alignItems: 'center',
@@ -98,10 +107,14 @@ export function PermissionMenu({
98
107
  };
99
108
  return trigger;
100
109
  }}>
101
- <View style={current.flip ? FLIP : undefined}>
110
+ <View style={current.flip ? [FLIP, { flexShrink: 0 }] : { flexShrink: 0 }}>
102
111
  <CurrentIcon width={16} height={16} fill={palette.iconSecondary} />
103
112
  </View>
104
- <Text variant="body-medium" numberOfLines={1} style={{ color: palette.textSecondary }}>
113
+ <Text
114
+ variant="body-medium"
115
+ numberOfLines={1}
116
+ ellipsizeMode="tail"
117
+ style={{ flexShrink: 1, minWidth: 0, color: palette.textSecondary }}>
105
118
  {current.label}
106
119
  </Text>
107
120
  </Pressable>
@@ -279,6 +279,8 @@ function FollowButtonComponent({
279
279
  onFollowChange,
280
280
  label = 'Follow',
281
281
  followingLabel = 'Following',
282
+ accessibilityLabel,
283
+ accessibilityHint,
282
284
  color,
283
285
  tone = 'support',
284
286
  iconOnly = false,
@@ -319,7 +321,8 @@ function FollowButtonComponent({
319
321
  );
320
322
  return (
321
323
  <Button appearance="subtle" tone={tone} size={size} iconOnly={iconOnly}
322
- pressed={following} stopPropagation accessibilityLabel={label} disabled={disabled} loading={loading}
324
+ pressed={following} stopPropagation accessibilityLabel={accessibilityLabel ?? label}
325
+ accessibilityHint={accessibilityHint} disabled={disabled} loading={loading}
323
326
  onPress={() => onFollowChange(!following)} trailing={visual}
324
327
  style={style} testID={testID} />
325
328
  );
@@ -160,6 +160,16 @@ export interface FollowButtonProps extends ToggleBase {
160
160
  label?: string;
161
161
  /** Default `"Following"`. */
162
162
  followingLabel?: string;
163
+ /**
164
+ * Accessible name, instead of `label`. Pass one that follows the state when
165
+ * the caller knows more than the visible text does — "Following @nate"
166
+ * rather than "Follow" — so a screen reader hears who and whether without
167
+ * relying on the pressed state alone (Android TalkBack reads a pressed
168
+ * toggle as "selected", which says nothing about following).
169
+ */
170
+ accessibilityLabel?: string;
171
+ /** What pressing does, read after the name ("Unfollows @nate"). */
172
+ accessibilityHint?: string;
163
173
  /** Draw on a band: the pill takes the band's text colour. */
164
174
  color?: string;
165
175
  /** Shared Button sizes; small by default. */