@oneuptime/common 11.3.28 → 11.4.1

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 (244) hide show
  1. package/Models/DatabaseModels/AIRun.ts +50 -0
  2. package/Models/DatabaseModels/Project.ts +60 -0
  3. package/Server/API/AIAgentTaskAPI.ts +10 -24
  4. package/Server/API/AIInvestigationAPI.ts +148 -0
  5. package/Server/API/TelemetryAPI.ts +4 -3
  6. package/Server/Infrastructure/Postgres/SchemaMigrations/1783598145111-AddEnableAutomaticIncidentInvestigationToProject.ts +19 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/1783615884106-AddInvestigationSubjectToAIRun.ts +33 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1783632447975-AddEnableAutomaticAlertInvestigationToProject.ts +19 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  10. package/Server/Services/AIAgentTaskService.ts +62 -0
  11. package/Server/Services/AlertService.ts +25 -0
  12. package/Server/Services/AnalyticsDatabaseService.ts +27 -0
  13. package/Server/Services/IncidentService.ts +25 -0
  14. package/Server/Services/IncidentStateTimelineService.ts +19 -0
  15. package/Server/Services/LogAggregationService.ts +29 -11
  16. package/Server/Services/MetricService.ts +603 -13
  17. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +119 -11
  18. package/Server/Utils/AI/Sentinel/AlertInvestigationRunner.ts +141 -0
  19. package/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.ts +178 -0
  20. package/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.ts +105 -0
  21. package/Server/Utils/AI/Sentinel/README.md +10 -0
  22. package/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.ts +405 -0
  23. package/Server/Utils/AI/Sentinel/SentinelMemory.ts +167 -0
  24. package/Server/Utils/AI/Toolbox/Index.ts +11 -0
  25. package/Server/Utils/AI/Toolbox/SentinelActionTools.ts +577 -0
  26. package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +44 -0
  27. package/Server/Utils/Monitor/MonitorMetricUtil.ts +108 -2
  28. package/Tests/Server/API/BaseAPI.test.ts +1 -0
  29. package/Tests/Server/Services/AIAgentTaskServiceClaim.test.ts +146 -0
  30. package/Tests/Server/Services/LogAggregationService.test.ts +22 -0
  31. package/Tests/Server/Services/MetricServiceAggregate.test.ts +194 -0
  32. package/Tests/Types/AI/AIAgentTaskStatus.test.ts +86 -0
  33. package/Tests/Types/BaseDatabase/AggregationIntervalUtil.test.ts +127 -0
  34. package/Tests/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.test.ts +152 -0
  35. package/Tests/Types/OnCallDutyPolicy/ScheduleShiftUtil.test.ts +260 -0
  36. package/Tests/Types/Trace/TraceRecordingRuleDefinition.test.ts +308 -0
  37. package/Tests/UI/Components/Dropdown.test.tsx +17 -0
  38. package/Tests/UI/Components/EntityDropdown.test.tsx +130 -0
  39. package/Tests/UI/Components/Modal.test.tsx +144 -2
  40. package/Tests/UI/Components/TelemetrySearchBar.test.tsx +90 -0
  41. package/Tests/UI/Utils/Theme.test.ts +161 -0
  42. package/Types/BaseDatabase/AggregateBy.ts +12 -0
  43. package/Types/Dashboard/DashboardComponentType.ts +1 -0
  44. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
  45. package/Types/Dashboard/DashboardComponents/DashboardLogChartComponent.ts +19 -0
  46. package/Types/Dashboard/DashboardTemplates.ts +9 -1
  47. package/Types/Date.ts +46 -0
  48. package/Types/Monitor/CriteriaFilter.ts +4 -0
  49. package/Types/Monitor/HttpPhaseTimings.ts +16 -0
  50. package/Types/Monitor/MonitorMetricType.ts +17 -0
  51. package/Types/Monitor/PingMonitor/PingMonitorResponse.ts +20 -0
  52. package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +257 -0
  53. package/Types/Probe/ProbeMonitorResponse.ts +14 -0
  54. package/UI/Components/Calendar/Calendar.tsx +8 -2
  55. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +5 -5
  56. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +8 -5
  57. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +4 -1
  58. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +6 -3
  59. package/UI/Components/CodeBlock/CodeBlock.tsx +2 -1
  60. package/UI/Components/CodeEditor/CodeEditor.tsx +3 -0
  61. package/UI/Components/Divider/Divider.tsx +1 -1
  62. package/UI/Components/Dropdown/Dropdown.tsx +13 -4
  63. package/UI/Components/EntityDropdown/EntityDropdown.tsx +110 -2
  64. package/UI/Components/ErrorBoundary.tsx +2 -1
  65. package/UI/Components/EventItem/EventItem.tsx +2 -2
  66. package/UI/Components/GanttChart/Bar/Index.tsx +1 -1
  67. package/UI/Components/Graphs/UptimeBarTooltip.tsx +30 -23
  68. package/UI/Components/Header/Header.tsx +7 -0
  69. package/UI/Components/Header/HeaderIconDropdownButton.tsx +2 -0
  70. package/UI/Components/Label/Label.tsx +2 -2
  71. package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +22 -10
  72. package/UI/Components/LogsViewer/components/LogsHistogram.tsx +9 -3
  73. package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +8 -8
  74. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +44 -20
  75. package/UI/Components/Modal/ConfirmModal.tsx +1 -1
  76. package/UI/Components/Modal/Modal.tsx +213 -121
  77. package/UI/Components/Modal/ModalFooter.tsx +33 -22
  78. package/UI/Components/ModelTable/TableView.tsx +1 -1
  79. package/UI/Components/MonitorGraphs/UptimeBarDayModal.tsx +20 -12
  80. package/UI/Components/Pill/Pill.tsx +21 -13
  81. package/UI/Components/StatusBubble/StatusBubble.tsx +3 -3
  82. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +7 -1
  83. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +9 -3
  84. package/UI/Components/TelemetryViewer/components/TelemetrySearchBar.tsx +62 -4
  85. package/UI/Components/Workflow/Component.tsx +53 -33
  86. package/UI/Components/Workflow/ComponentPortViewer.tsx +6 -6
  87. package/UI/Components/Workflow/ComponentReturnValueViewer.tsx +8 -8
  88. package/UI/Components/Workflow/ComponentsModal.tsx +16 -9
  89. package/UI/Components/Workflow/Workflow.tsx +13 -11
  90. package/UI/Utils/Theme.ts +140 -0
  91. package/Utils/Dashboard/Components/DashboardLogChartComponent.ts +104 -0
  92. package/Utils/Dashboard/Components/Index.ts +7 -0
  93. package/Utils/Monitor/MonitorMetricType.ts +70 -2
  94. package/build/dist/Models/DatabaseModels/AIRun.js +52 -0
  95. package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
  96. package/build/dist/Models/DatabaseModels/Project.js +62 -0
  97. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  98. package/build/dist/Server/API/AIAgentTaskAPI.js +8 -23
  99. package/build/dist/Server/API/AIAgentTaskAPI.js.map +1 -1
  100. package/build/dist/Server/API/AIInvestigationAPI.js +107 -0
  101. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -0
  102. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  103. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783598145111-AddEnableAutomaticIncidentInvestigationToProject.js +12 -0
  104. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783598145111-AddEnableAutomaticIncidentInvestigationToProject.js.map +1 -0
  105. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783615884106-AddInvestigationSubjectToAIRun.js +18 -0
  106. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783615884106-AddInvestigationSubjectToAIRun.js.map +1 -0
  107. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783632447975-AddEnableAutomaticAlertInvestigationToProject.js +12 -0
  108. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783632447975-AddEnableAutomaticAlertInvestigationToProject.js.map +1 -0
  109. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  110. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  111. package/build/dist/Server/Services/AIAgentTaskService.js +59 -0
  112. package/build/dist/Server/Services/AIAgentTaskService.js.map +1 -1
  113. package/build/dist/Server/Services/AlertService.js +24 -0
  114. package/build/dist/Server/Services/AlertService.js.map +1 -1
  115. package/build/dist/Server/Services/AnalyticsDatabaseService.js +19 -0
  116. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  117. package/build/dist/Server/Services/IncidentService.js +24 -0
  118. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  119. package/build/dist/Server/Services/IncidentStateTimelineService.js +19 -0
  120. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  121. package/build/dist/Server/Services/LogAggregationService.js +21 -7
  122. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  123. package/build/dist/Server/Services/MetricService.js +449 -7
  124. package/build/dist/Server/Services/MetricService.js.map +1 -1
  125. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +59 -11
  126. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  127. package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js +119 -0
  128. package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js.map +1 -0
  129. package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js +147 -0
  130. package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js.map +1 -0
  131. package/build/dist/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.js +93 -0
  132. package/build/dist/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.js.map +1 -0
  133. package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js +311 -0
  134. package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js.map +1 -0
  135. package/build/dist/Server/Utils/AI/Sentinel/SentinelMemory.js +143 -0
  136. package/build/dist/Server/Utils/AI/Sentinel/SentinelMemory.js.map +1 -0
  137. package/build/dist/Server/Utils/AI/Toolbox/Index.js +6 -0
  138. package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
  139. package/build/dist/Server/Utils/AI/Toolbox/SentinelActionTools.js +451 -0
  140. package/build/dist/Server/Utils/AI/Toolbox/SentinelActionTools.js.map +1 -0
  141. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +29 -0
  142. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
  143. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +86 -2
  144. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  145. package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
  146. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  147. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
  148. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  149. package/build/dist/Types/Dashboard/DashboardComponents/DashboardLogChartComponent.js +2 -0
  150. package/build/dist/Types/Dashboard/DashboardComponents/DashboardLogChartComponent.js.map +1 -0
  151. package/build/dist/Types/Dashboard/DashboardTemplates.js +9 -1
  152. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  153. package/build/dist/Types/Date.js +32 -0
  154. package/build/dist/Types/Date.js.map +1 -1
  155. package/build/dist/Types/Monitor/CriteriaFilter.js +4 -0
  156. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  157. package/build/dist/Types/Monitor/HttpPhaseTimings.js +2 -0
  158. package/build/dist/Types/Monitor/HttpPhaseTimings.js.map +1 -0
  159. package/build/dist/Types/Monitor/MonitorMetricType.js +15 -0
  160. package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
  161. package/build/dist/Types/Monitor/PingMonitor/PingMonitorResponse.js +2 -0
  162. package/build/dist/Types/Monitor/PingMonitor/PingMonitorResponse.js.map +1 -0
  163. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +159 -0
  164. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -0
  165. package/build/dist/UI/Components/Calendar/Calendar.js +2 -2
  166. package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
  167. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +2 -2
  168. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  169. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +7 -4
  170. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  171. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +4 -1
  172. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  173. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +6 -3
  174. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  175. package/build/dist/UI/Components/CodeBlock/CodeBlock.js +1 -1
  176. package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
  177. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +3 -1
  178. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  179. package/build/dist/UI/Components/Divider/Divider.js +1 -1
  180. package/build/dist/UI/Components/Divider/Divider.js.map +1 -1
  181. package/build/dist/UI/Components/Dropdown/Dropdown.js +10 -4
  182. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  183. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +76 -3
  184. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  185. package/build/dist/UI/Components/ErrorBoundary.js +2 -1
  186. package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
  187. package/build/dist/UI/Components/EventItem/EventItem.js +2 -2
  188. package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
  189. package/build/dist/UI/Components/GanttChart/Bar/Index.js +1 -1
  190. package/build/dist/UI/Components/GanttChart/Bar/Index.js.map +1 -1
  191. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js +29 -23
  192. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js.map +1 -1
  193. package/build/dist/UI/Components/Header/Header.js +1 -0
  194. package/build/dist/UI/Components/Header/Header.js.map +1 -1
  195. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -1
  196. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
  197. package/build/dist/UI/Components/Label/Label.js +2 -2
  198. package/build/dist/UI/Components/Label/Label.js.map +1 -1
  199. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +20 -8
  200. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
  201. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +8 -2
  202. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
  203. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +8 -8
  204. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +40 -20
  205. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  206. package/build/dist/UI/Components/Modal/ConfirmModal.js +1 -1
  207. package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
  208. package/build/dist/UI/Components/Modal/Modal.js +109 -51
  209. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  210. package/build/dist/UI/Components/Modal/ModalFooter.js +13 -10
  211. package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
  212. package/build/dist/UI/Components/ModelTable/TableView.js +1 -1
  213. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  214. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js +17 -12
  215. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js.map +1 -1
  216. package/build/dist/UI/Components/Pill/Pill.js +12 -13
  217. package/build/dist/UI/Components/Pill/Pill.js.map +1 -1
  218. package/build/dist/UI/Components/StatusBubble/StatusBubble.js +3 -3
  219. package/build/dist/UI/Components/StatusBubble/StatusBubble.js.map +1 -1
  220. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +1 -1
  221. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  222. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +8 -2
  223. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  224. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js +36 -6
  225. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js.map +1 -1
  226. package/build/dist/UI/Components/Workflow/Component.js +43 -33
  227. package/build/dist/UI/Components/Workflow/Component.js.map +1 -1
  228. package/build/dist/UI/Components/Workflow/ComponentPortViewer.js +6 -6
  229. package/build/dist/UI/Components/Workflow/ComponentPortViewer.js.map +1 -1
  230. package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js +8 -8
  231. package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js.map +1 -1
  232. package/build/dist/UI/Components/Workflow/ComponentsModal.js +15 -9
  233. package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
  234. package/build/dist/UI/Components/Workflow/Workflow.js +13 -11
  235. package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
  236. package/build/dist/UI/Utils/Theme.js +106 -0
  237. package/build/dist/UI/Utils/Theme.js.map +1 -0
  238. package/build/dist/Utils/Dashboard/Components/DashboardLogChartComponent.js +92 -0
  239. package/build/dist/Utils/Dashboard/Components/DashboardLogChartComponent.js.map +1 -0
  240. package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
  241. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  242. package/build/dist/Utils/Monitor/MonitorMetricType.js +70 -3
  243. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  244. package/package.json +1 -1
@@ -10,6 +10,7 @@ import ObjectID from "../../../Types/ObjectID";
10
10
  import ModelAPI, { ListResult } from "../../Utils/ModelAPI/ModelAPI";
11
11
  import Icon from "../Icon/Icon";
12
12
  import {
13
+ DROPDOWN_MENU_Z_INDEX,
13
14
  DropdownOption,
14
15
  DropdownOptionGroup,
15
16
  DropdownOptionLabel,
@@ -20,6 +21,7 @@ import React, {
20
21
  ReactElement,
21
22
  useCallback,
22
23
  useEffect,
24
+ useLayoutEffect,
23
25
  useMemo,
24
26
  useRef,
25
27
  useState,
@@ -107,6 +109,18 @@ export interface EntityDropdownProps {
107
109
  const SEARCH_DEBOUNCE_MS: number = 250;
108
110
  const SEARCH_PAGE_SIZE: number = 50;
109
111
  const LABEL_PREVIEW_LIMIT: number = 50;
112
+ const MENU_GAP_PX: number = 4;
113
+ const MENU_MAX_HEIGHT_PX: number = 384;
114
+ const MENU_MIN_USEFUL_HEIGHT_PX: number = 160;
115
+ const MENU_VIEWPORT_PADDING_PX: number = 8;
116
+
117
+ interface EntityDropdownMenuPosition {
118
+ bottom?: number | undefined;
119
+ left: number;
120
+ maxHeight: number;
121
+ top?: number | undefined;
122
+ width: number;
123
+ }
110
124
 
111
125
  const flattenOptions: (
112
126
  options: Array<DropdownOption | DropdownOptionGroup> | undefined,
@@ -441,12 +455,91 @@ const EntityDropdown: FunctionComponent<EntityDropdownProps> = (
441
455
 
442
456
  const containerRef: React.MutableRefObject<HTMLDivElement | null> =
443
457
  useRef<HTMLDivElement | null>(null);
458
+ const controlRef: React.MutableRefObject<HTMLDivElement | null> =
459
+ useRef<HTMLDivElement | null>(null);
444
460
  const inputRef: React.MutableRefObject<HTMLInputElement | null> =
445
461
  useRef<HTMLInputElement | null>(null);
446
462
  const debounceRef: React.MutableRefObject<number | null> = useRef<
447
463
  number | null
448
464
  >(null);
449
465
  const searchSeqRef: React.MutableRefObject<number> = useRef<number>(0);
466
+ const [menuPosition, setMenuPosition] =
467
+ useState<EntityDropdownMenuPosition | null>(null);
468
+
469
+ const updateMenuPosition: () => void = useCallback((): void => {
470
+ if (!controlRef.current || typeof window === "undefined") {
471
+ return;
472
+ }
473
+
474
+ const controlRect: DOMRect = controlRef.current.getBoundingClientRect();
475
+ const availableWidth: number = Math.max(
476
+ 0,
477
+ window.innerWidth - MENU_VIEWPORT_PADDING_PX * 2,
478
+ );
479
+ const width: number = Math.min(controlRect.width, availableWidth);
480
+ const maximumLeft: number = Math.max(
481
+ MENU_VIEWPORT_PADDING_PX,
482
+ window.innerWidth - MENU_VIEWPORT_PADDING_PX - width,
483
+ );
484
+ const left: number = Math.min(
485
+ Math.max(controlRect.left, MENU_VIEWPORT_PADDING_PX),
486
+ maximumLeft,
487
+ );
488
+ const spaceBelow: number = Math.max(
489
+ 0,
490
+ window.innerHeight -
491
+ controlRect.bottom -
492
+ MENU_GAP_PX -
493
+ MENU_VIEWPORT_PADDING_PX,
494
+ );
495
+ const spaceAbove: number = Math.max(
496
+ 0,
497
+ controlRect.top - MENU_GAP_PX - MENU_VIEWPORT_PADDING_PX,
498
+ );
499
+ const shouldOpenAbove: boolean =
500
+ spaceBelow < MENU_MIN_USEFUL_HEIGHT_PX && spaceAbove > spaceBelow;
501
+ const availableHeight: number = shouldOpenAbove ? spaceAbove : spaceBelow;
502
+
503
+ setMenuPosition({
504
+ bottom: shouldOpenAbove
505
+ ? window.innerHeight - controlRect.top + MENU_GAP_PX
506
+ : undefined,
507
+ left,
508
+ maxHeight: Math.min(MENU_MAX_HEIGHT_PX, availableHeight),
509
+ top: shouldOpenAbove ? undefined : controlRect.bottom + MENU_GAP_PX,
510
+ width,
511
+ });
512
+ }, []);
513
+
514
+ useLayoutEffect(() => {
515
+ if (!isOpen) {
516
+ setMenuPosition(null);
517
+ return;
518
+ }
519
+
520
+ let animationFrame: number | null = null;
521
+ const schedulePositionUpdate: () => void = (): void => {
522
+ if (animationFrame !== null) {
523
+ return;
524
+ }
525
+ animationFrame = window.requestAnimationFrame((): void => {
526
+ animationFrame = null;
527
+ updateMenuPosition();
528
+ });
529
+ };
530
+
531
+ updateMenuPosition();
532
+ window.addEventListener("resize", schedulePositionUpdate);
533
+ document.addEventListener("scroll", schedulePositionUpdate, true);
534
+
535
+ return () => {
536
+ window.removeEventListener("resize", schedulePositionUpdate);
537
+ document.removeEventListener("scroll", schedulePositionUpdate, true);
538
+ if (animationFrame !== null) {
539
+ window.cancelAnimationFrame(animationFrame);
540
+ }
541
+ };
542
+ }, [isOpen, selectedKeys, updateMenuPosition]);
450
543
 
451
544
  // Click-outside closes the popover.
452
545
  useEffect(() => {
@@ -1106,7 +1199,7 @@ const EntityDropdown: FunctionComponent<EntityDropdownProps> = (
1106
1199
  </div>
1107
1200
  )}
1108
1201
 
1109
- <div className="relative">
1202
+ <div ref={controlRef} className="relative">
1110
1203
  {/*
1111
1204
  * Single-select shows the resolved label in-place when closed so the
1112
1205
  * chrome looks like a static value field. Click anywhere on the
@@ -1281,6 +1374,11 @@ const EntityDropdown: FunctionComponent<EntityDropdownProps> = (
1281
1374
  return;
1282
1375
  }
1283
1376
  if (event.key === "Escape") {
1377
+ /*
1378
+ * The modal also listens for Escape. Consume it here so the
1379
+ * first press closes the menu without dismissing the form.
1380
+ */
1381
+ event.preventDefault();
1284
1382
  setIsOpen(false);
1285
1383
  setHighlightedIndex(-1);
1286
1384
  return;
@@ -1329,8 +1427,18 @@ const EntityDropdown: FunctionComponent<EntityDropdownProps> = (
1329
1427
 
1330
1428
  {isOpen && !props.disabled && (
1331
1429
  <div
1332
- className="absolute z-20 mt-1 flex max-h-96 w-full flex-col overflow-hidden rounded-md border border-gray-200 bg-white text-sm shadow-lg"
1430
+ className="fixed flex flex-col overflow-hidden rounded-md border border-gray-200 bg-white text-sm shadow-lg"
1431
+ data-testid="entity-dropdown-menu"
1333
1432
  role="listbox"
1433
+ style={{
1434
+ bottom: menuPosition?.bottom,
1435
+ left: menuPosition?.left ?? 0,
1436
+ maxHeight: menuPosition?.maxHeight,
1437
+ top: menuPosition?.top,
1438
+ visibility: menuPosition ? "visible" : "hidden",
1439
+ width: menuPosition?.width ?? 0,
1440
+ zIndex: DROPDOWN_MENU_Z_INDEX,
1441
+ }}
1334
1442
  >
1335
1443
  {labelsTabEnabled && (
1336
1444
  <div className="flex flex-shrink-0 items-center gap-1 border-b border-gray-100 bg-gray-50 px-1.5 py-1">
@@ -15,7 +15,8 @@ const Fallback: FunctionComponent = () => {
15
15
  bottom: "0",
16
16
  left: "0",
17
17
  right: "0",
18
- backgroundColor: "#fdfdfd",
18
+ backgroundColor: "var(--ou-background-primary, #fdfdfd)",
19
+ color: "var(--ou-text-primary, #111827)",
19
20
  zIndex: "999",
20
21
  display: "flex",
21
22
  justifyContent: "center",
@@ -168,8 +168,8 @@ const EventItem: FunctionComponent<ComponentProps> = (
168
168
  text={item}
169
169
  color={VeryLightGray}
170
170
  style={{
171
- backgroundColor: "#f3f4f6",
172
- color: "#9ca3af",
171
+ backgroundColor: "var(--ou-surface-tertiary, #f3f4f6)",
172
+ color: "var(--ou-text-subtle, #9ca3af)",
173
173
  }}
174
174
  />
175
175
  );
@@ -137,7 +137,7 @@ const Bar: FunctionComponent<ComponentProps> = (
137
137
  marginLeft: `${barWidth + 15}px`,
138
138
  opacity: barOpacity,
139
139
  fontWeight: props.isHighlighted ? 600 : undefined,
140
- color: props.isHighlighted ? "#4338ca" : undefined,
140
+ color: props.isHighlighted ? "var(--ou-link, #4338ca)" : undefined,
141
141
  }}
142
142
  >
143
143
  <BarLabel label={props.bar.label} />
@@ -72,7 +72,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
72
72
  gap: "8px",
73
73
  paddingBottom: "10px",
74
74
  marginBottom: "10px",
75
- borderBottom: "1px solid #f0f0f0",
75
+ borderBottom: "1px solid var(--ou-border-subtle, #f0f0f0)",
76
76
  }}
77
77
  >
78
78
  <svg
@@ -80,7 +80,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
80
80
  height="14"
81
81
  viewBox="0 0 24 24"
82
82
  fill="none"
83
- stroke="#9ca3af"
83
+ stroke="var(--ou-text-subtle, #9ca3af)"
84
84
  strokeWidth="2"
85
85
  strokeLinecap="round"
86
86
  strokeLinejoin="round"
@@ -95,7 +95,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
95
95
  style={{
96
96
  fontWeight: 600,
97
97
  fontSize: "13px",
98
- color: "#111827",
98
+ color: "var(--ou-text-primary, #111827)",
99
99
  letterSpacing: "-0.01em",
100
100
  }}
101
101
  >
@@ -121,7 +121,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
121
121
  <span
122
122
  style={{
123
123
  fontSize: "11px",
124
- color: "#6b7280",
124
+ color: "var(--ou-text-muted, #6b7280)",
125
125
  fontWeight: 500,
126
126
  }}
127
127
  >
@@ -165,7 +165,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
165
165
  overflow: "hidden",
166
166
  display: "flex",
167
167
  gap: "1px",
168
- backgroundColor: "#e5e7eb",
168
+ backgroundColor: "var(--ou-border-default, #e5e7eb)",
169
169
  }}
170
170
  >
171
171
  {sortedDurations.map((status: StatusDuration, index: number) => {
@@ -191,7 +191,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
191
191
  style={{
192
192
  width: "100%",
193
193
  height: "4px",
194
- backgroundColor: "#e5e7eb",
194
+ backgroundColor: "var(--ou-border-default, #e5e7eb)",
195
195
  borderRadius: "100px",
196
196
  overflow: "hidden",
197
197
  }}
@@ -213,7 +213,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
213
213
  {!props.hasEvents && (
214
214
  <div
215
215
  style={{
216
- backgroundColor: "#f9fafb",
216
+ backgroundColor: "var(--ou-surface-secondary, #f9fafb)",
217
217
  borderRadius: "8px",
218
218
  padding: "16px",
219
219
  textAlign: "center",
@@ -224,7 +224,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
224
224
  height="18"
225
225
  viewBox="0 0 24 24"
226
226
  fill="none"
227
- stroke="#d1d5db"
227
+ stroke="var(--ou-border-strong, #d1d5db)"
228
228
  strokeWidth="1.5"
229
229
  strokeLinecap="round"
230
230
  strokeLinejoin="round"
@@ -237,7 +237,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
237
237
  <div
238
238
  style={{
239
239
  fontSize: "12px",
240
- color: "#9ca3af",
240
+ color: "var(--ou-text-subtle, #9ca3af)",
241
241
  fontWeight: 500,
242
242
  }}
243
243
  >
@@ -252,7 +252,9 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
252
252
  style={{
253
253
  paddingBottom: hasIncidents ? "10px" : "0",
254
254
  marginBottom: hasIncidents ? "10px" : "0",
255
- borderBottom: hasIncidents ? "1px solid #f0f0f0" : "none",
255
+ borderBottom: hasIncidents
256
+ ? "1px solid var(--ou-border-subtle, #f0f0f0)"
257
+ : "none",
256
258
  }}
257
259
  >
258
260
  {sortedDurations.map((status: StatusDuration, index: number) => {
@@ -291,7 +293,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
291
293
  <span
292
294
  style={{
293
295
  fontSize: "12px",
294
- color: "#374151",
296
+ color: "var(--ou-text-secondary, #374151)",
295
297
  fontWeight: 500,
296
298
  whiteSpace: "nowrap",
297
299
  overflow: "hidden",
@@ -306,7 +308,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
306
308
  style={{
307
309
  flex: 1,
308
310
  height: "4px",
309
- backgroundColor: "#f3f4f6",
311
+ backgroundColor: "var(--ou-surface-tertiary, #f3f4f6)",
310
312
  borderRadius: "100px",
311
313
  overflow: "hidden",
312
314
  }}
@@ -325,7 +327,9 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
325
327
  <span
326
328
  style={{
327
329
  fontSize: "11px",
328
- color: status.isDowntime ? "#dc2626" : "#6b7280",
330
+ color: status.isDowntime
331
+ ? "var(--ou-danger-text, #b91c1c)"
332
+ : "var(--ou-text-muted, #6b7280)",
329
333
  fontWeight: status.isDowntime ? 600 : 400,
330
334
  fontVariantNumeric: "tabular-nums",
331
335
  whiteSpace: "nowrap",
@@ -356,7 +360,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
356
360
  <span
357
361
  style={{
358
362
  fontSize: "11px",
359
- color: "#6b7280",
363
+ color: "var(--ou-text-muted, #6b7280)",
360
364
  fontWeight: 500,
361
365
  flex: 1,
362
366
  }}
@@ -367,8 +371,9 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
367
371
  style={{
368
372
  fontSize: "10px",
369
373
  fontWeight: 600,
370
- color: "#dc2626",
371
- backgroundColor: "#fef2f2",
374
+ color: "var(--ou-danger-text, #b91c1c)",
375
+ backgroundColor:
376
+ "color-mix(in srgb, #ef4444 14%, var(--ou-surface-primary, #ffffff))",
372
377
  padding: "1px 7px",
373
378
  borderRadius: "9999px",
374
379
  lineHeight: "1.6",
@@ -400,21 +405,23 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
400
405
  marginBottom: "6px",
401
406
  cursor: isClickable ? "pointer" : "default",
402
407
  transition: "background-color 0.12s ease",
403
- backgroundColor: "#fafafa",
408
+ backgroundColor: "var(--ou-surface-secondary, #fafafa)",
404
409
  borderRadius: "0 6px 6px 0",
405
410
  }}
406
411
  onMouseEnter={(e: React.MouseEvent<HTMLDivElement>) => {
407
412
  if (isClickable) {
408
413
  (
409
414
  e.currentTarget as HTMLDivElement
410
- ).style.backgroundColor = "#f3f4f6";
415
+ ).style.backgroundColor =
416
+ "var(--ou-surface-tertiary, #f3f4f6)";
411
417
  }
412
418
  }}
413
419
  onMouseLeave={(e: React.MouseEvent<HTMLDivElement>) => {
414
420
  if (isClickable) {
415
421
  (
416
422
  e.currentTarget as HTMLDivElement
417
- ).style.backgroundColor = "#fafafa";
423
+ ).style.backgroundColor =
424
+ "var(--ou-surface-secondary, #fafafa)";
418
425
  }
419
426
  }}
420
427
  >
@@ -431,7 +438,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
431
438
  flex: 1,
432
439
  minWidth: 0,
433
440
  fontSize: "12px",
434
- color: "#111827",
441
+ color: "var(--ou-text-primary, #111827)",
435
442
  fontWeight: 600,
436
443
  lineHeight: "1.3",
437
444
  overflow: "hidden",
@@ -451,7 +458,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
451
458
  >
452
459
  <path
453
460
  d="M6 3l5 5-5 5"
454
- stroke="#6b7280"
461
+ stroke="var(--ou-text-muted, #6b7280)"
455
462
  strokeWidth="1.5"
456
463
  strokeLinecap="round"
457
464
  strokeLinejoin="round"
@@ -509,7 +516,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
509
516
  <span
510
517
  style={{
511
518
  fontSize: "10px",
512
- color: "#b0b0b0",
519
+ color: "var(--ou-text-subtle, #b0b0b0)",
513
520
  marginLeft: "auto",
514
521
  whiteSpace: "nowrap",
515
522
  }}
@@ -528,7 +535,7 @@ const UptimeBarTooltip: FunctionComponent<ComponentProps> = (
528
535
  <div
529
536
  style={{
530
537
  fontSize: "11px",
531
- color: "#9ca3af",
538
+ color: "var(--ou-text-subtle, #9ca3af)",
532
539
  textAlign: "center",
533
540
  padding: "4px 0 0",
534
541
  fontWeight: 500,
@@ -3,6 +3,7 @@ import React, { FunctionComponent, ReactElement } from "react";
3
3
  export interface ComponentProps {
4
4
  leftComponents?: undefined | Array<ReactElement> | ReactElement;
5
5
  rightComponents?: undefined | Array<ReactElement> | ReactElement;
6
+ mobileRightComponents?: undefined | Array<ReactElement> | ReactElement;
6
7
  centerComponents?: undefined | Array<ReactElement> | ReactElement;
7
8
  className?: string | undefined;
8
9
  }
@@ -28,6 +29,12 @@ const Header: FunctionComponent<ComponentProps> = (
28
29
  </div>
29
30
  )}
30
31
 
32
+ {props.mobileRightComponents && (
33
+ <div className="relative z-20 flex items-center lg:hidden">
34
+ {props.mobileRightComponents}
35
+ </div>
36
+ )}
37
+
31
38
  <div className="hidden lg:relative lg:z-10 lg:ml-4 lg:flex lg:items-center lg:gap-2">
32
39
  {props.rightComponents}
33
40
  </div>
@@ -19,6 +19,7 @@ export interface ComponentProps {
19
19
  onClick?: (() => void) | undefined;
20
20
  name: string;
21
21
  showDropdown: boolean;
22
+ isPressed?: boolean | undefined;
22
23
  }
23
24
 
24
25
  const HeaderIconDropdownButton: FunctionComponent<ComponentProps> = (
@@ -53,6 +54,7 @@ const HeaderIconDropdownButton: FunctionComponent<ComponentProps> = (
53
54
  id={hasDropdown ? "user-menu-button" : undefined}
54
55
  aria-expanded={hasDropdown ? isDropdownVisible : undefined}
55
56
  aria-haspopup={hasDropdown ? "true" : undefined}
57
+ aria-pressed={props.isPressed}
56
58
  onClick={() => {
57
59
  props.onClick?.();
58
60
  setIsComponentVisible(!isDropdownVisible);
@@ -1,7 +1,7 @@
1
1
  import React, { CSSProperties, FunctionComponent, ReactElement } from "react";
2
2
  import LabelModel from "../../../Models/DatabaseModels/Label";
3
3
  import Pill, { ComponentProps as PillProps, PillSize } from "../Pill/Pill";
4
- import { Black } from "../../../Types/BrandColors";
4
+ import { Gray500 } from "../../../Types/BrandColors";
5
5
  import Color from "../../../Types/Color";
6
6
  import IconProp from "../../../Types/Icon/IconProp";
7
7
 
@@ -19,7 +19,7 @@ const LabelElement: FunctionComponent<ComponentProps> = (
19
19
 
20
20
  const resolveColor: Color = (() => {
21
21
  if (!label.color) {
22
- return Black;
22
+ return Gray500;
23
23
  }
24
24
 
25
25
  if (typeof label.color === "string") {
@@ -654,21 +654,27 @@ const LogsAnalyticsView: FunctionComponent<LogsAnalyticsViewProps> = (
654
654
  </defs>
655
655
  <CartesianGrid
656
656
  strokeDasharray="none"
657
- stroke="#f1f5f9"
657
+ stroke="var(--ou-chart-grid, #f1f5f9)"
658
658
  vertical={false}
659
659
  />
660
660
  <XAxis
661
661
  dataKey="time"
662
662
  tickFormatter={formatTickTime}
663
- tick={{ fontSize: 11, fill: "#94a3b8" }}
664
- axisLine={{ stroke: "#e2e8f0" }}
663
+ tick={{
664
+ fontSize: 11,
665
+ fill: "var(--ou-chart-tick, #94a3b8)",
666
+ }}
667
+ axisLine={{ stroke: "var(--ou-chart-grid, #e2e8f0)" }}
665
668
  tickLine={false}
666
669
  minTickGap={50}
667
670
  interval="preserveStartEnd"
668
671
  dy={8}
669
672
  />
670
673
  <YAxis
671
- tick={{ fontSize: 11, fill: "#94a3b8" }}
674
+ tick={{
675
+ fontSize: 11,
676
+ fill: "var(--ou-chart-tick, #94a3b8)",
677
+ }}
672
678
  axisLine={false}
673
679
  tickLine={false}
674
680
  width={52}
@@ -678,7 +684,7 @@ const LogsAnalyticsView: FunctionComponent<LogsAnalyticsViewProps> = (
678
684
  <Tooltip
679
685
  content={<AnalyticsTooltip />}
680
686
  cursor={{
681
- stroke: "#c7d2fe",
687
+ stroke: "var(--ou-accent-muted, #c7d2fe)",
682
688
  strokeWidth: 1,
683
689
  strokeDasharray: "4 4",
684
690
  }}
@@ -692,7 +698,7 @@ const LogsAnalyticsView: FunctionComponent<LogsAnalyticsViewProps> = (
692
698
  activeDot={{
693
699
  r: 4,
694
700
  fill: CHART_COLORS[0]!,
695
- stroke: "#fff",
701
+ stroke: "var(--ou-chart-marker-ring, #ffffff)",
696
702
  strokeWidth: 2,
697
703
  }}
698
704
  isAnimationActive={false}
@@ -707,21 +713,27 @@ const LogsAnalyticsView: FunctionComponent<LogsAnalyticsViewProps> = (
707
713
  >
708
714
  <CartesianGrid
709
715
  strokeDasharray="none"
710
- stroke="#f1f5f9"
716
+ stroke="var(--ou-chart-grid, #f1f5f9)"
711
717
  vertical={false}
712
718
  />
713
719
  <XAxis
714
720
  dataKey="time"
715
721
  tickFormatter={formatTickTime}
716
- tick={{ fontSize: 11, fill: "#94a3b8" }}
717
- axisLine={{ stroke: "#e2e8f0" }}
722
+ tick={{
723
+ fontSize: 11,
724
+ fill: "var(--ou-chart-tick, #94a3b8)",
725
+ }}
726
+ axisLine={{ stroke: "var(--ou-chart-grid, #e2e8f0)" }}
718
727
  tickLine={false}
719
728
  minTickGap={50}
720
729
  interval="preserveStartEnd"
721
730
  dy={8}
722
731
  />
723
732
  <YAxis
724
- tick={{ fontSize: 11, fill: "#94a3b8" }}
733
+ tick={{
734
+ fontSize: 11,
735
+ fill: "var(--ou-chart-tick, #94a3b8)",
736
+ }}
725
737
  axisLine={false}
726
738
  tickLine={false}
727
739
  width={52}
@@ -216,15 +216,21 @@ const LogsHistogram: FunctionComponent<LogsHistogramProps> = (
216
216
  <XAxis
217
217
  dataKey="time"
218
218
  tickFormatter={formatTickTime}
219
- tick={{ fontSize: 10, fill: "#9ca3af" }}
220
- axisLine={{ stroke: "#e5e7eb" }}
219
+ tick={{
220
+ fontSize: 10,
221
+ fill: "var(--ou-chart-tick, #9ca3af)",
222
+ }}
223
+ axisLine={{ stroke: "var(--ou-chart-grid, #e5e7eb)" }}
221
224
  tickLine={false}
222
225
  minTickGap={40}
223
226
  dy={4}
224
227
  interval="preserveStartEnd"
225
228
  />
226
229
  <YAxis
227
- tick={{ fontSize: 10, fill: "#9ca3af" }}
230
+ tick={{
231
+ fontSize: 10,
232
+ fill: "var(--ou-chart-tick, #9ca3af)",
233
+ }}
228
234
  axisLine={false}
229
235
  tickLine={false}
230
236
  width={48}
@@ -901,17 +901,17 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
901
901
  .oneuptime-wysiwyg ol { list-style-type: decimal; }
902
902
  .oneuptime-wysiwyg ul.task-list, .oneuptime-wysiwyg ul.task-list li { list-style: none; margin-left: 0; }
903
903
  .oneuptime-wysiwyg ul.task-list li { padding-left: 0; }
904
- .oneuptime-wysiwyg blockquote { border-left: 3px solid #d1d5db; padding-left: 0.75rem; color: #4b5563; margin: 0.5rem 0; }
905
- .oneuptime-wysiwyg pre { background: #f3f4f6; border-radius: 0.375rem; padding: 0.75rem; overflow-x: auto; margin: 0.5rem 0; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.85rem; }
906
- .oneuptime-wysiwyg code { background: #f3f4f6; padding: 0 0.25rem; border-radius: 0.25rem; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.85em; }
904
+ .oneuptime-wysiwyg blockquote { border-left: 3px solid var(--ou-border-strong, #d1d5db); padding-left: 0.75rem; color: var(--ou-text-secondary, #4b5563); margin: 0.5rem 0; }
905
+ .oneuptime-wysiwyg pre { background: var(--ou-surface-tertiary, #f3f4f6); border-radius: 0.375rem; padding: 0.75rem; overflow-x: auto; margin: 0.5rem 0; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.85rem; }
906
+ .oneuptime-wysiwyg code { background: var(--ou-surface-tertiary, #f3f4f6); padding: 0 0.25rem; border-radius: 0.25rem; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.85em; }
907
907
  .oneuptime-wysiwyg pre code { background: transparent; padding: 0; }
908
- .oneuptime-wysiwyg a { color: #4f46e5; text-decoration: underline; }
909
- .oneuptime-wysiwyg hr { margin: 1rem 0; border: 0; border-top: 1px solid #e5e7eb; }
908
+ .oneuptime-wysiwyg a { color: var(--ou-link, #4f46e5); text-decoration: underline; }
909
+ .oneuptime-wysiwyg hr { margin: 1rem 0; border: 0; border-top: 1px solid var(--ou-border-default, #e5e7eb); }
910
910
  .oneuptime-wysiwyg table { border-collapse: collapse; margin: 0.5rem 0; }
911
- .oneuptime-wysiwyg th, .oneuptime-wysiwyg td { border: 1px solid #e5e7eb; padding: 0.25rem 0.5rem; }
912
- .oneuptime-wysiwyg th { background: #f9fafb; font-weight: 600; }
911
+ .oneuptime-wysiwyg th, .oneuptime-wysiwyg td { border: 1px solid var(--ou-border-default, #e5e7eb); padding: 0.25rem 0.5rem; }
912
+ .oneuptime-wysiwyg th { background: var(--ou-surface-secondary, #f9fafb); font-weight: 600; }
913
913
  .oneuptime-wysiwyg img { max-width: 100%; height: auto; }
914
- .oneuptime-wysiwyg:empty::before { content: attr(data-placeholder); color: #9ca3af; pointer-events: none; }
914
+ .oneuptime-wysiwyg:empty::before { content: attr(data-placeholder); color: var(--ou-text-subtle, #9ca3af); pointer-events: none; }
915
915
  `}</style>
916
916
 
917
917
  {/* Toolbar */}