@marimo-team/frontend 0.24.1-dev53 → 0.24.1-dev55

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 (80) hide show
  1. package/dist/assets/{CellStatus-B6CWKORY.js → CellStatus-D6_pLs0B.js} +1 -1
  2. package/dist/assets/JsonOutput-D0JlHn1Z.js +50 -0
  3. package/dist/assets/{MarimoErrorOutput-BXh29HCp.js → MarimoErrorOutput-CYOWXi9k.js} +2 -2
  4. package/dist/assets/{RenderHTML-COTZYPO7.js → RenderHTML-qnAqp9Q0.js} +1 -1
  5. package/dist/assets/{RunButton-DTUzITFm.js → RunButton-BDkLTxbY.js} +1 -1
  6. package/dist/assets/add-cell-with-ai-0dqk0f7O.js +77 -0
  7. package/dist/assets/{add-connection-dialog-CcnJ2LkX.js → add-connection-dialog-CnRoNzHS.js} +1 -1
  8. package/dist/assets/{agent-panel-B9BFcufg.js → agent-panel-D7mo8YLQ.js} +3 -3
  9. package/dist/assets/{ai-model-dropdown-a4n3JDbf.js → ai-model-dropdown-D2q0Cm0R.js} +1 -1
  10. package/dist/assets/{app-config-button-BQAVAUpN.js → app-config-button-CB6s4qUy.js} +1 -1
  11. package/dist/assets/{blob-BBiZd3vX.js → blob-Dza7uUlT.js} +1 -1
  12. package/dist/assets/cell-editor-e7_o4mEh.js +24 -0
  13. package/dist/assets/cell-link-DqJmxVu3.js +1 -0
  14. package/dist/assets/{cells-B1S_6FG3.js → cells-DfJw5iuV.js} +1 -1
  15. package/dist/assets/{chat-display-C7EsuQmC.js → chat-display-Cgg0xLir.js} +1 -1
  16. package/dist/assets/{chat-panel-DCSD5g-j.js → chat-panel-BaG-5LiN.js} +4 -4
  17. package/dist/assets/{chat-ui-C3ay3Rdi.js → chat-ui-DYLpA8l4.js} +4 -4
  18. package/dist/assets/{column-preview-DKbMmEB5.js → column-preview-BdNXfBsJ.js} +1 -1
  19. package/dist/assets/{command-palette-D1IoMI0F.js → command-palette-DiT0E_K7.js} +1 -1
  20. package/dist/assets/{common-BGLbVHCS.js → common-D_BAMDHd.js} +1 -1
  21. package/dist/assets/{components-BAvTsivu.js → components-D3x9DfK0.js} +1 -1
  22. package/dist/assets/{datasource-BrSYgi6C.js → datasource-B9lSU_L0.js} +1 -1
  23. package/dist/assets/{dependency-graph-panel-C13q-nga.js → dependency-graph-panel-3-8ygeBR.js} +1 -1
  24. package/dist/assets/{documentation-panel-CtQqNEQw.js → documentation-panel-BzJcTCN3.js} +1 -1
  25. package/dist/assets/{download-CIdXYNHv.js → download-4OuOU5F0.js} +1 -1
  26. package/dist/assets/{edit-page-B1g7AdLD.js → edit-page-DAC4cNKe.js} +6 -6
  27. package/dist/assets/{error-entries-DEjvzkum.js → error-entries-BCuZmxgk.js} +1 -1
  28. package/dist/assets/{error-panel-BvrDwUv8.js → error-panel-Dk-wFymb.js} +1 -1
  29. package/dist/assets/{file-explorer-panel-z-rke195.js → file-explorer-panel-Bprnrp3k.js} +1 -1
  30. package/dist/assets/{file-icons-Bo1Ewf1W.js → file-icons-BnE-lUIr.js} +1 -1
  31. package/dist/assets/{file-name-input-BeYyD2dj.js → file-name-input-B-KJyr-U.js} +1 -1
  32. package/dist/assets/{floating-outline-CNsG18LK.js → floating-outline-BebYvSvL.js} +1 -1
  33. package/dist/assets/{home-page-P1nAvpLK.js → home-page-zNwFmOPQ.js} +1 -1
  34. package/dist/assets/{index-Bn9RxQAN.css → index-BrmH4-pI.css} +1 -1
  35. package/dist/assets/index-DTQ4RS9q.js +29 -0
  36. package/dist/assets/{layout-vg4c6imf.js → layout-D3zwsTvR.js} +4 -4
  37. package/dist/assets/{logs-panel-BSD1GETR.js → logs-panel-CXu4QQwD.js} +1 -1
  38. package/dist/assets/{markdown-renderer-DIXiKP4m.js → markdown-renderer-BUBFaUWx.js} +1 -1
  39. package/dist/assets/{name-cell-input-zqypwqoZ.js → name-cell-input-DbRrAlCe.js} +1 -1
  40. package/dist/assets/{outline-panel-C5GAyqII.js → outline-panel-16ugwsMh.js} +1 -1
  41. package/dist/assets/{packages-panel-DMZtOQYl.js → packages-panel-8OASpr5S.js} +1 -1
  42. package/dist/assets/{panel-accordion-state-DmV3OgfX.js → panel-accordion-state-786YBa3I.js} +1 -1
  43. package/dist/assets/panels-ChFSBlsU.js +4 -0
  44. package/dist/assets/{process-output-DNhz9LLW.js → process-output-NwNkpkfY.js} +1 -1
  45. package/dist/assets/{readonly-code-display-CKT-gv1m.js → readonly-code-display-Ce9Vb5Wf.js} +1 -1
  46. package/dist/assets/{readonly-python-code-De0vvuWh.js → readonly-python-code-CQd3Bopx.js} +1 -1
  47. package/dist/assets/{reveal-component-D9uCWzLS.js → reveal-component-BFRmOcQr.js} +1 -1
  48. package/dist/assets/{run-page-ah4ptdoG.js → run-page-MZCCEXct.js} +1 -1
  49. package/dist/assets/{scratchpad-panel-YOarJKLy.js → scratchpad-panel-BqYT2vj3.js} +1 -1
  50. package/dist/assets/{session-panel-1RH7Zh0c.js → session-panel-BdXUO63q.js} +1 -1
  51. package/dist/assets/{skeleton-BX017Wzj.js → skeleton-gmxAkHfa.js} +1 -1
  52. package/dist/assets/{snippets-panel-BZ254lxN.js → snippets-panel-BI6SMTkf.js} +1 -1
  53. package/dist/assets/{state-llVv0lIh.js → state-CZxxcsV7.js} +1 -1
  54. package/dist/assets/{state-MlBpc9qi.js → state-DmlDv6kf.js} +3 -3
  55. package/dist/assets/{tracing-C0FGWieO.js → tracing-Bs9V1VRy.js} +1 -1
  56. package/dist/assets/{tracing-panel-LeIOi1Tv.js → tracing-panel-CMnYFlDr.js} +2 -2
  57. package/dist/assets/{tree-actions-CrWpuExP.js → tree-actions-A2eVufTn.js} +1 -1
  58. package/dist/assets/{useAddCell-DIdbaU70.js → useAddCell-BBv-60Hs.js} +1 -1
  59. package/dist/assets/{useCellActionButton-DXyUqFdJ.js → useCellActionButton-DgA6C9_m.js} +1 -1
  60. package/dist/assets/{useDeleteCell-CSCMg7Up.js → useDeleteCell-CqYCNkza.js} +1 -1
  61. package/dist/assets/{useDependencyPanelTab-Bt7aBDpS.js → useDependencyPanelTab-DhGw5Y2R.js} +1 -1
  62. package/dist/assets/{useNotebookActions-DKMS8mUE.js → useNotebookActions-BoFJmccb.js} +3 -3
  63. package/dist/assets/{useRunCells-DHnbXALT.js → useRunCells-BwYUZxV6.js} +1 -1
  64. package/dist/assets/{useSplitCell-CxlsGCB_.js → useSplitCell-D0ws6n0g.js} +1 -1
  65. package/dist/index.html +20 -20
  66. package/package.json +1 -1
  67. package/src/components/editor/ai/ai-completion-editor.tsx +9 -15
  68. package/src/components/editor/ai/completion-handlers.tsx +30 -10
  69. package/src/components/editor/cell/StagedAICell.tsx +53 -15
  70. package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +6 -1
  71. package/src/components/editor/notebook-cell.tsx +2 -2
  72. package/src/core/ai/__tests__/staged-cells.test.ts +45 -2
  73. package/src/core/ai/staged-cells.ts +15 -1
  74. package/src/css/app/Cell.css +25 -26
  75. package/dist/assets/JsonOutput--lW6GQQ9.js +0 -50
  76. package/dist/assets/add-cell-with-ai-hxrzwECc.js +0 -77
  77. package/dist/assets/cell-editor-DfhJQCKm.js +0 -24
  78. package/dist/assets/cell-link-BbAJokoX.js +0 -1
  79. package/dist/assets/index-BMQJCzfh.js +0 -29
  80. package/dist/assets/panels-DllVd27E.js +0 -4
@@ -7,6 +7,11 @@ import { Button } from "@/components/ui/button";
7
7
  import { Tooltip } from "@/components/ui/tooltip";
8
8
  import { isPlatformMac } from "@/core/hotkeys/shortcuts";
9
9
 
10
+ export const AI_EDIT_ACTION_LABELS = {
11
+ accept: "Keep change",
12
+ decline: "Revert change",
13
+ } as const;
14
+
10
15
  /**
11
16
  * Common keyboard shortcut handlers for AI completions
12
17
  */
@@ -48,16 +53,31 @@ export const CompletionActionsCellFooter: React.FC<{
48
53
  size?: "xs" | "sm";
49
54
  multipleCompletions?: boolean;
50
55
  runCell?: () => void;
51
- }> = ({ isLoading, onAccept, onDecline, runCell }) => {
56
+ acceptLabel?: string;
57
+ declineLabel?: string;
58
+ }> = ({
59
+ isLoading,
60
+ onAccept,
61
+ onDecline,
62
+ runCell,
63
+ acceptLabel,
64
+ declineLabel,
65
+ size,
66
+ }) => {
52
67
  return (
53
68
  <>
54
69
  <AcceptCompletionButton
55
70
  isLoading={isLoading}
56
71
  onAccept={onAccept}
57
- size="xs"
72
+ size={size}
58
73
  runCell={runCell}
74
+ label={acceptLabel}
75
+ />
76
+ <RejectCompletionButton
77
+ onDecline={onDecline}
78
+ size={size}
79
+ label={declineLabel}
59
80
  />
60
- <RejectCompletionButton onDecline={onDecline} size="xs" />
61
81
  </>
62
82
  );
63
83
  };
@@ -72,6 +92,7 @@ export const AcceptCompletionButton: React.FC<{
72
92
  borderless?: boolean;
73
93
  acceptShortcut?: string;
74
94
  runCell?: () => void;
95
+ label?: string;
75
96
  }> = ({
76
97
  isLoading,
77
98
  onAccept,
@@ -82,6 +103,7 @@ export const AcceptCompletionButton: React.FC<{
82
103
  runCell,
83
104
  playButtonStyles,
84
105
  borderless = false,
106
+ label,
85
107
  }) => {
86
108
  const handleAcceptAndRun = () => {
87
109
  onAccept();
@@ -90,7 +112,7 @@ export const AcceptCompletionButton: React.FC<{
90
112
  }
91
113
  };
92
114
 
93
- const text = multipleCompletions ? "Accept all" : "Accept";
115
+ const text = label ?? (multipleCompletions ? "Accept all" : "Accept");
94
116
 
95
117
  const baseClasses = `h-6 text-(--grass-11) bg-(--grass-3)/60
96
118
  hover:bg-(--grass-3) dark:bg-(--grass-4)/80 dark:hover:bg-(--grass-3) font-semibold
@@ -113,11 +135,7 @@ export const AcceptCompletionButton: React.FC<{
113
135
  )}
114
136
  </Button>
115
137
  <Tooltip
116
- content={
117
- multipleCompletions
118
- ? "Accept and run all cells"
119
- : "Accept and run cell"
120
- }
138
+ content={`${text} and run ${multipleCompletions ? "all cells" : "cell"}`}
121
139
  >
122
140
  <Button
123
141
  variant="text"
@@ -156,6 +174,7 @@ export const RejectCompletionButton: React.FC<{
156
174
  className?: string;
157
175
  borderless?: boolean;
158
176
  declineShortcut?: string;
177
+ label?: string;
159
178
  }> = ({
160
179
  onDecline,
161
180
  multipleCompletions = false,
@@ -163,6 +182,7 @@ export const RejectCompletionButton: React.FC<{
163
182
  className,
164
183
  declineShortcut,
165
184
  borderless = false,
185
+ label,
166
186
  }) => {
167
187
  return (
168
188
  <Button
@@ -174,7 +194,7 @@ export const RejectCompletionButton: React.FC<{
174
194
  active:bg-(--red-5) dark:active:bg-(--red-4)
175
195
  border-(--red-6) border hover:shadow-xs ${borderless && "border-none rounded-md"} ${className}`}
176
196
  >
177
- Reject{multipleCompletions && " all"}
197
+ {label ?? `Reject${multipleCompletions ? " all" : ""}`}
178
198
  {declineShortcut && (
179
199
  <MinimalHotkeys className="ml-1 inline" shortcut={declineShortcut} />
180
200
  )}
@@ -1,9 +1,11 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import { useAtomValue, useStore } from "jotai";
3
+ import { useStore } from "jotai";
4
+ import { SparklesIcon } from "lucide-react";
5
+ import { Tooltip } from "@/components/ui/tooltip";
4
6
  import {
5
7
  type Edit,
6
- stagedAICellsAtom,
8
+ useStagedAICell,
7
9
  useStagedCells,
8
10
  } from "@/core/ai/staged-cells";
9
11
  import { getCellEditorView } from "@/core/cells/cells";
@@ -11,15 +13,24 @@ import type { CellId } from "@/core/cells/ids";
11
13
  import { updateEditorCodeFromPython } from "@/core/codemirror/language/utils";
12
14
  import { cn } from "@/utils/cn";
13
15
  import { Logger } from "@/utils/Logger";
14
- import { CompletionActionsCellFooter } from "../ai/completion-handlers";
16
+ import {
17
+ AI_EDIT_ACTION_LABELS,
18
+ CompletionActionsCellFooter,
19
+ } from "../ai/completion-handlers";
15
20
  import { useRunCell } from "./useRunCells";
16
21
 
22
+ const actionLabels: Record<Edit["type"], { accept: string; decline: string }> =
23
+ {
24
+ add_cell: { accept: "Keep cell", decline: "Discard cell" },
25
+ update_cell: AI_EDIT_ACTION_LABELS,
26
+ delete_cell: { accept: "Delete cell", decline: "Keep cell" },
27
+ };
28
+
17
29
  export const StagedAICellBackground: React.FC<{
18
30
  cellId: CellId;
19
31
  className?: string;
20
32
  }> = ({ cellId, className }) => {
21
- const stagedAICells = useAtomValue(stagedAICellsAtom);
22
- const stagedCell = stagedAICells.get(cellId);
33
+ const stagedCell = useStagedAICell(cellId);
23
34
 
24
35
  if (!stagedCell) {
25
36
  return null;
@@ -37,8 +48,7 @@ export const StagedAICellFooter: React.FC<{ cellId: CellId }> = ({
37
48
  cellId,
38
49
  }) => {
39
50
  const store = useStore();
40
- const stagedAICells = useAtomValue(stagedAICellsAtom);
41
- const stagedAiCell = stagedAICells.get(cellId);
51
+ const stagedAiCell = useStagedAICell(cellId);
42
52
  const runCell = useRunCell(cellId);
43
53
 
44
54
  const { deleteStagedCell, removeStagedCell } = useStagedCells(store);
@@ -47,21 +57,49 @@ export const StagedAICellFooter: React.FC<{ cellId: CellId }> = ({
47
57
  return null;
48
58
  }
49
59
 
60
+ const isDeletion = stagedAiCell.type === "delete_cell";
61
+ const labels = actionLabels[stagedAiCell.type];
62
+
50
63
  const handleCompletion = (type: "accept" | "reject") => {
51
64
  const completionFunc =
52
65
  type === "accept" ? acceptStagedCell : rejectStagedCell;
53
66
  completionFunc(cellId, stagedAiCell, removeStagedCell, deleteStagedCell);
54
67
  };
55
68
 
69
+ const tooltipContent =
70
+ stagedAiCell.type === "add_cell"
71
+ ? "AI-generated cell"
72
+ : isDeletion
73
+ ? "AI suggests deleting this cell"
74
+ : "AI changed this cell";
75
+
56
76
  return (
57
- <div className="flex items-center justify-end gap-1.5 w-full pb-1 pt-2">
58
- <CompletionActionsCellFooter
59
- isLoading={false}
60
- onAccept={() => handleCompletion("accept")}
61
- onDecline={() => handleCompletion("reject")}
62
- size="xs"
63
- runCell={runCell}
64
- />
77
+ <div className="mo-ai-cell-footer">
78
+ <div className="flex items-center gap-1.5 text-xs text-muted-foreground">
79
+ <Tooltip content={tooltipContent}>
80
+ <span
81
+ className="inline-flex items-center gap-1.5"
82
+ aria-label={tooltipContent}
83
+ >
84
+ <SparklesIcon
85
+ aria-hidden="true"
86
+ className="size-3.5 text-(--blue-11)"
87
+ />
88
+ <span>AI</span>
89
+ </span>
90
+ </Tooltip>
91
+ </div>
92
+ <div className="flex items-center gap-1.5">
93
+ <CompletionActionsCellFooter
94
+ isLoading={false}
95
+ onAccept={() => handleCompletion("accept")}
96
+ onDecline={() => handleCompletion("reject")}
97
+ size="xs"
98
+ runCell={isDeletion ? undefined : runCell}
99
+ acceptLabel={labels.accept}
100
+ declineLabel={labels.decline}
101
+ />
102
+ </div>
65
103
  </div>
66
104
  );
67
105
  };
@@ -56,7 +56,10 @@ export const PendingAICells: React.FC = () => {
56
56
  };
57
57
 
58
58
  const runAllCells = () => {
59
- runCell(listStagedCells);
59
+ const cellsToRun = listStagedCells.filter(
60
+ (cellId) => stagedAiCells.get(cellId)?.type !== "delete_cell",
61
+ );
62
+ runCell(cellsToRun);
60
63
  };
61
64
 
62
65
  const cyanShadow = "shadow-[0_0_6px_0_#00A2C733]";
@@ -91,6 +94,7 @@ export const PendingAICells: React.FC = () => {
91
94
  multipleCompletions={true}
92
95
  onAccept={acceptAllCompletions}
93
96
  isLoading={false}
97
+ label="Keep all"
94
98
  size="xs"
95
99
  buttonStyles="h-6.5"
96
100
  playButtonStyles="h-6.5"
@@ -100,6 +104,7 @@ export const PendingAICells: React.FC = () => {
100
104
  multipleCompletions={true}
101
105
  onDecline={rejectAllCompletions}
102
106
  size="xs"
107
+ label="Discard all"
103
108
  className="h-6.5"
104
109
  />
105
110
  </div>
@@ -839,8 +839,8 @@ const EditableCellComponent = ({
839
839
  />
840
840
  )}
841
841
  <PendingDeleteConfirmation cellId={cellId} />
842
+ {!isPresenting && <StagedAICellFooter cellId={cellId} />}
842
843
  </div>
843
- {!isPresenting && <StagedAICellFooter cellId={cellId} />}
844
844
  {isCollapsed && !isPresenting && (
845
845
  <CollapsedCellBanner
846
846
  onClick={() => actions.expandCell({ cellId })}
@@ -1327,8 +1327,8 @@ const SetupCellComponent = ({
1327
1327
  cellId={cellId}
1328
1328
  debuggerActive={cellRuntime.debuggerActive}
1329
1329
  />
1330
+ <StagedAICellFooter cellId={cellId} />
1330
1331
  </div>
1331
- <StagedAICellFooter cellId={cellId} />
1332
1332
  </div>
1333
1333
  </CellActionsContextMenu>
1334
1334
  </TooltipProvider>
@@ -1,7 +1,8 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import { renderHook } from "@testing-library/react";
4
- import { getDefaultStore } from "jotai";
3
+ import { act, renderHook } from "@testing-library/react";
4
+ import { getDefaultStore, Provider } from "jotai";
5
+ import { createElement, type ReactNode } from "react";
5
6
  import { beforeEach, describe, expect, it, vi } from "vitest";
6
7
  import { cellId } from "@/__tests__/branded";
7
8
  import { CellId } from "@/core/cells/ids";
@@ -9,6 +10,7 @@ import { updateEditorCodeFromPython } from "../../codemirror/language/utils";
9
10
  import {
10
11
  type StagedAICells,
11
12
  stagedAICellsAtom,
13
+ useStagedAICell,
12
14
  useStagedCells,
13
15
  visibleForTesting,
14
16
  } from "../staged-cells";
@@ -149,6 +151,16 @@ describe("staged-cells", () => {
149
151
  expect(newState.has(cellId2)).toBe(true);
150
152
  });
151
153
 
154
+ it("should preserve state when removing a cell that is not staged", () => {
155
+ const state = new Map([[cellId1, { type: "add_cell" as const }]]);
156
+ const newState = reducer(state, {
157
+ type: "removeStagedCell",
158
+ payload: cellId2,
159
+ });
160
+
161
+ expect(newState).toBe(state);
162
+ });
163
+
152
164
  it("should clear all cells", () => {
153
165
  const state = new Map([
154
166
  [cellId1, { type: "add_cell" as const }],
@@ -206,6 +218,37 @@ describe("staged-cells", () => {
206
218
  const state = store.get(stagedAICellsAtom);
207
219
  expect(state).toEqual(new Map());
208
220
  });
221
+
222
+ it("should not rerender a cell when another cell's staging changes", () => {
223
+ let renderCount = 0;
224
+ const wrapper = ({ children }: { children: ReactNode }) =>
225
+ createElement(Provider, { store }, children);
226
+
227
+ renderHook(
228
+ () => {
229
+ renderCount++;
230
+ return useStagedAICell(cellId2);
231
+ },
232
+ { wrapper },
233
+ );
234
+ const initialRenderCount = renderCount;
235
+
236
+ act(() => {
237
+ store.set(
238
+ stagedAICellsAtom,
239
+ new Map([[cellId1, { type: "add_cell" }]]),
240
+ );
241
+ });
242
+ expect(renderCount).toBe(initialRenderCount);
243
+
244
+ act(() => {
245
+ store.set(
246
+ stagedAICellsAtom,
247
+ new Map([[cellId2, { type: "add_cell" }]]),
248
+ );
249
+ });
250
+ expect(renderCount).toBeGreaterThan(initialRenderCount);
251
+ });
209
252
  });
210
253
 
211
254
  describe("useStagedCells hook", () => {
@@ -1,7 +1,9 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
3
  import type { UIMessageChunk } from "ai";
4
- import { useRef } from "react";
4
+ import { useAtomValue } from "jotai";
5
+ import { selectAtom } from "jotai/utils";
6
+ import { useMemo, useRef } from "react";
5
7
  import {
6
8
  type AiCompletion,
7
9
  codeToCells,
@@ -51,6 +53,9 @@ const {
51
53
  return new Map([...state, [cellId, edit]]);
52
54
  },
53
55
  removeStagedCell: (state, cellId: CellId) => {
56
+ if (!state.has(cellId)) {
57
+ return state;
58
+ }
54
59
  const newState = new Map(state);
55
60
  newState.delete(cellId);
56
61
  return newState;
@@ -66,6 +71,15 @@ export {
66
71
  reducer as stagedAICellsReducer,
67
72
  };
68
73
 
74
+ export function useStagedAICell(cellId: CellId): Edit | undefined {
75
+ const stagedCellAtom = useMemo(
76
+ () =>
77
+ selectAtom(stagedAICellsAtom, (cells) => cells.get(cellId), Object.is),
78
+ [cellId],
79
+ );
80
+ return useAtomValue(stagedCellAtom);
81
+ }
82
+
69
83
  interface UpdateStagedCellAction {
70
84
  cellId: CellId;
71
85
  code: string;
@@ -27,25 +27,14 @@
27
27
  outline: none;
28
28
  }
29
29
 
30
- &:has(.mo-ai-generated-cell)::before {
31
- content: "";
32
- position: absolute;
33
- inset: 0;
34
- border-radius: 10px;
35
- pointer-events: none;
36
- opacity: 0.5;
37
- box-shadow: 0px 0px 10px 0px var(--cyan-9);
38
- z-index: 1;
39
- }
40
-
41
- &:has(.mo-ai-generated-cell.mo-ai-setup-cell)::before {
42
- border-radius: 2px;
30
+ &:has(.mo-ai-generated-cell) {
31
+ border-color: var(--blue-7);
43
32
  }
44
33
 
45
34
  /* Styling for cells marked for deletion by AI */
46
35
  &:has(.mo-ai-deleted-cell) {
47
- opacity: 0.7;
48
36
  position: relative;
37
+ border-color: var(--red-7);
49
38
 
50
39
  .output-area,
51
40
  .cm-gutters,
@@ -53,18 +42,6 @@
53
42
  background-color: var(--red-2);
54
43
  }
55
44
 
56
- /* Add a red glow to indicate deletion */
57
- &::before {
58
- content: "";
59
- position: absolute;
60
- inset: 0;
61
- border-radius: 10px;
62
- pointer-events: none;
63
- opacity: 0.6;
64
- box-shadow: 0px 0px 10px 0px var(--red-9);
65
- z-index: 1;
66
- }
67
-
68
45
  /* Add strikethrough effect to the code */
69
46
  .cm-content {
70
47
  text-decoration: line-through;
@@ -326,6 +303,20 @@
326
303
  @apply bg-background;
327
304
  }
328
305
 
306
+ .mo-ai-cell-footer {
307
+ display: flex;
308
+ align-items: center;
309
+ justify-content: space-between;
310
+ gap: 0.75rem;
311
+ width: 100%;
312
+ padding: 0.375rem 0.5rem;
313
+ background: var(--gray-2);
314
+ }
315
+
316
+ .dark .mo-ai-cell-footer {
317
+ background: var(--gray-3);
318
+ }
319
+
329
320
  .dark .marimo-cell {
330
321
  @apply border-border;
331
322
 
@@ -364,6 +355,14 @@
364
355
  }
365
356
  }
366
357
 
358
+ .dark .marimo-cell:has(.mo-ai-generated-cell) {
359
+ border-color: var(--blue-8);
360
+ }
361
+
362
+ .dark .marimo-cell:has(.mo-ai-deleted-cell) {
363
+ border-color: var(--red-8);
364
+ }
365
+
367
366
  #cell-setup,
368
367
  #cell-setup .cm-editor,
369
368
  #cell-setup .cm-gutter {