@marimo-team/islands 0.25.3-dev222 → 0.25.3-dev223

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 (23) hide show
  1. package/dist/{ErrorBoundary-Cg9q4kUW.js → ErrorBoundary-BToheQV2.js} +1 -1
  2. package/dist/{code-visibility-Dp-DkL1e.js → code-visibility-CO0hOr56.js} +1 -1
  3. package/dist/{common-DHr2MXY3.js → common-CV0669k1.js} +1 -1
  4. package/dist/{data-grid-overlay-editor-B-OJHxuO.js → data-grid-overlay-editor-CwDPMtXI.js} +1 -1
  5. package/dist/{feedback-button-DGAcA9xH.js → feedback-button-RB_OfVUt.js} +2 -2
  6. package/dist/{glide-data-editor-09FJOvJw.js → glide-data-editor-B2h5fYfH.js} +3 -3
  7. package/dist/{globals-2eTRp9qC.js → globals-YR9OeOwq.js} +1 -1
  8. package/dist/main.js +6 -6
  9. package/dist/{number-overlay-editor-XJ1jA8Jv.js → number-overlay-editor-BY4yYxfZ.js} +1 -1
  10. package/dist/{reveal-component-DxdLWQiq.js → reveal-component-GiGQpBMz.js} +2 -2
  11. package/dist/style.css +1 -1
  12. package/package.json +1 -1
  13. package/src/components/app-config/ai-config.tsx +148 -147
  14. package/src/components/app-config/app-config-button.tsx +6 -5
  15. package/src/components/app-config/common.tsx +7 -9
  16. package/src/components/app-config/data-form.tsx +112 -113
  17. package/src/components/app-config/mcp-config.tsx +30 -53
  18. package/src/components/app-config/user-config-form.css +91 -0
  19. package/src/components/app-config/user-config-form.tsx +236 -298
  20. package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +9 -5
  21. package/src/components/editor/actions/__tests__/pair-with-agent.test.tsx +3 -3
  22. package/src/components/editor/actions/pair-with-agent-modal.tsx +5 -5
  23. package/src/components/editor/actions/pair-with-agent.tsx +10 -7
@@ -75,113 +75,113 @@ export const DataForm = ({
75
75
 
76
76
  return (
77
77
  <>
78
- <OverriddenFormField
79
- control={form.control}
80
- name="display.dataframes"
81
- render={({ field, override }) => (
82
- <div className="flex flex-col space-y-1">
83
- <FormItem className={formItemClasses}>
84
- <FormLabel>Dataframe viewer</FormLabel>
85
- <FormControl>
86
- <NativeSelect
87
- data-testid="display-dataframes-select"
88
- onChange={(e) => field.onChange(e.target.value)}
89
- value={override.value}
90
- disabled={field.disabled || override.isOverridden}
91
- className="inline-flex mr-2"
92
- >
93
- {["rich", "plain"].map((option) => (
94
- <option value={option} key={option}>
95
- {option}
96
- </option>
97
- ))}
98
- </NativeSelect>
99
- </FormControl>
100
- <FormMessage />
101
- <IsOverridden override={override} />
102
- </FormItem>
103
-
104
- <FormDescription>
105
- Whether to use marimo's rich dataframe viewer or a plain HTML
106
- table. This requires restarting your notebook to take effect.
107
- </FormDescription>
108
- </div>
109
- )}
110
- />
111
- <OverriddenFormField
112
- control={form.control}
113
- name="display.default_table_page_size"
114
- render={({ field, override }) => (
115
- <div className="flex flex-col space-y-1">
116
- <FormItem className={formItemClasses}>
117
- <FormLabel>Default table page size</FormLabel>
118
- <FormControl>
119
- <NumberField
120
- aria-label="Default table page size"
121
- data-testid="default-table-page-size-input"
122
- className="m-0 w-24"
123
- {...field}
124
- value={override.value}
125
- isDisabled={override.isOverridden}
126
- minValue={1}
127
- step={1}
128
- onChange={(value) => {
129
- field.onChange(value);
130
- if (!Number.isNaN(value)) {
131
- onSubmit(form.getValues());
132
- }
133
- }}
134
- />
135
- </FormControl>
136
- <FormMessage />
137
- <IsOverridden override={override} />
138
- </FormItem>
139
- <FormDescription>
140
- The default number of rows displayed in dataframes and SQL
141
- results.
142
- </FormDescription>
143
- </div>
144
- )}
145
- />
146
- <OverriddenFormField
147
- control={form.control}
148
- name="display.default_table_max_columns"
149
- render={({ field, override }) => (
150
- <div className="flex flex-col space-y-1">
151
- <FormItem className={formItemClasses}>
152
- <FormLabel>Default table max columns</FormLabel>
153
- <FormControl>
154
- <NumberField
155
- aria-label="Default table max columns"
156
- data-testid="default-table-max-columns-input"
157
- className="m-0 w-24"
158
- {...field}
159
- value={override.value}
160
- isDisabled={override.isOverridden}
161
- minValue={1}
162
- step={1}
163
- onChange={(value) => {
164
- field.onChange(value);
165
- if (!Number.isNaN(value)) {
166
- onSubmit(form.getValues());
167
- }
168
- }}
169
- />
170
- </FormControl>
171
- <FormMessage />
172
- <IsOverridden override={override} />
173
- </FormItem>
174
- <FormDescription>
175
- The default maximum number of columns displayed in dataframes and
176
- SQL results.
177
- </FormDescription>
178
- </div>
179
- )}
180
- />
181
-
78
+ <SettingGroup title="Data">
79
+ <OverriddenFormField
80
+ control={form.control}
81
+ name="display.dataframes"
82
+ render={({ field, override }) => (
83
+ <div className="settings-field flex flex-col space-y-1">
84
+ <FormItem className={formItemClasses}>
85
+ <FormLabel>Dataframe viewer</FormLabel>
86
+ <FormDescription>
87
+ Whether to use marimo's rich dataframe viewer or a plain HTML
88
+ table. This requires restarting your notebook to take effect.
89
+ </FormDescription>
90
+ <FormControl>
91
+ <NativeSelect
92
+ data-testid="display-dataframes-select"
93
+ onChange={(e) => field.onChange(e.target.value)}
94
+ value={override.value}
95
+ disabled={field.disabled || override.isOverridden}
96
+ className="inline-flex mr-2"
97
+ >
98
+ {["rich", "plain"].map((option) => (
99
+ <option value={option} key={option}>
100
+ {option}
101
+ </option>
102
+ ))}
103
+ </NativeSelect>
104
+ </FormControl>
105
+ <FormMessage />
106
+ <IsOverridden override={override} />
107
+ </FormItem>
108
+ </div>
109
+ )}
110
+ />
111
+ <OverriddenFormField
112
+ control={form.control}
113
+ name="display.default_table_page_size"
114
+ render={({ field, override }) => (
115
+ <div className="settings-field flex flex-col space-y-1">
116
+ <FormItem className={formItemClasses}>
117
+ <FormLabel>Default table page size</FormLabel>
118
+ <FormDescription>
119
+ The default number of rows displayed in dataframes and SQL
120
+ results.
121
+ </FormDescription>
122
+ <FormControl>
123
+ <NumberField
124
+ aria-label="Default table page size"
125
+ data-testid="default-table-page-size-input"
126
+ className="m-0 w-24"
127
+ {...field}
128
+ value={override.value}
129
+ isDisabled={override.isOverridden}
130
+ minValue={1}
131
+ step={1}
132
+ onChange={(value) => {
133
+ field.onChange(value);
134
+ if (!Number.isNaN(value)) {
135
+ onSubmit(form.getValues());
136
+ }
137
+ }}
138
+ />
139
+ </FormControl>
140
+ <FormMessage />
141
+ <IsOverridden override={override} />
142
+ </FormItem>
143
+ </div>
144
+ )}
145
+ />
146
+ <OverriddenFormField
147
+ control={form.control}
148
+ name="display.default_table_max_columns"
149
+ render={({ field, override }) => (
150
+ <div className="settings-field flex flex-col space-y-1">
151
+ <FormItem className={formItemClasses}>
152
+ <FormLabel>Default table max columns</FormLabel>
153
+ <FormDescription>
154
+ The default maximum number of columns displayed in dataframes
155
+ and SQL results.
156
+ </FormDescription>
157
+ <FormControl>
158
+ <NumberField
159
+ aria-label="Default table max columns"
160
+ data-testid="default-table-max-columns-input"
161
+ className="m-0 w-24"
162
+ {...field}
163
+ value={override.value}
164
+ isDisabled={override.isOverridden}
165
+ minValue={1}
166
+ step={1}
167
+ onChange={(value) => {
168
+ field.onChange(value);
169
+ if (!Number.isNaN(value)) {
170
+ onSubmit(form.getValues());
171
+ }
172
+ }}
173
+ />
174
+ </FormControl>
175
+ <FormMessage />
176
+ <IsOverridden override={override} />
177
+ </FormItem>
178
+ </div>
179
+ )}
180
+ />
181
+ </SettingGroup>
182
182
  <SettingGroup title="SQL">
183
- <div className="flex flex-col gap-1">
184
- <div className="text-sm text-foreground">
183
+ <div className="settings-field flex flex-col gap-1">
184
+ <div className="text-sm font-semibold text-muted-foreground">
185
185
  Database Schema Discovery
186
186
  </div>
187
187
  <div className="text-sm text-muted-foreground mb-2">
@@ -212,7 +212,7 @@ export const DataForm = ({
212
212
  control={form.control}
213
213
  name="diagnostics.sql_linter"
214
214
  render={({ field, override }) => (
215
- <div className="flex flex-col space-y-1">
215
+ <div className="settings-field flex flex-col space-y-1">
216
216
  <FormItem className={formItemClasses}>
217
217
  <FormLabel>SQL Linter</FormLabel>
218
218
  <FormControl>
@@ -237,9 +237,13 @@ export const DataForm = ({
237
237
  control={form.control}
238
238
  name="runtime.default_sql_output"
239
239
  render={({ field, override }) => (
240
- <div className="flex flex-col space-y-1">
240
+ <div className="settings-field flex flex-col space-y-1">
241
241
  <FormItem className={formItemClasses}>
242
242
  <FormLabel>Default SQL output</FormLabel>
243
+ <FormDescription>
244
+ The default SQL output type for new notebooks; overridden by
245
+ "sql_output" in the application config.
246
+ </FormDescription>
243
247
  <FormControl>
244
248
  <NativeSelect
245
249
  data-testid="user-config-sql-output-select"
@@ -258,11 +262,6 @@ export const DataForm = ({
258
262
  <FormMessage />
259
263
  <IsOverridden override={override} />
260
264
  </FormItem>
261
-
262
- <FormDescription>
263
- The default SQL output type for new notebooks; overridden by
264
- "sql_output" in the application config.
265
- </FormDescription>
266
265
  </div>
267
266
  )}
268
267
  />
@@ -1,22 +1,22 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import { CheckSquareIcon, Loader2, RefreshCwIcon } from "lucide-react";
3
+ import { Loader2, RefreshCwIcon } from "lucide-react";
4
4
  import React from "react";
5
5
  import type { UseFormReturn } from "react-hook-form";
6
+ import { Checkbox } from "@/components/ui/checkbox";
6
7
  import {
7
- Card,
8
- CardContent,
9
- CardDescription,
10
- CardHeader,
11
- CardTitle,
12
- } from "@/components/ui/card";
13
- import { FormField, FormItem } from "@/components/ui/form";
8
+ FormControl,
9
+ FormDescription,
10
+ FormField,
11
+ FormItem,
12
+ FormLabel,
13
+ } from "@/components/ui/form";
14
14
  import type { UserConfig } from "@/core/config/config-schema";
15
15
  import { useMCPRefresh, useMCPStatus } from "../mcp/hooks";
16
16
  import { McpStatusText } from "../mcp/mcp-status-indicator";
17
17
  import { Button } from "../ui/button";
18
18
  import { Kbd } from "../ui/kbd";
19
- import { SettingSubtitle } from "./common";
19
+ import { formItemClasses, SettingSubtitle } from "./common";
20
20
  import { useOpenSettingsToTab } from "./state";
21
21
 
22
22
  interface MCPConfigProps {
@@ -35,13 +35,14 @@ interface PresetConfig {
35
35
  const PRESET_CONFIGS: PresetConfig[] = [
36
36
  {
37
37
  id: "marimo",
38
- title: "marimo (docs)",
39
- description: "Access marimo documentation",
38
+ title: "marimo documentation",
39
+ description: "Let the AI assistant look up marimo documentation.",
40
40
  },
41
41
  {
42
42
  id: "context7",
43
43
  title: "Context7",
44
- description: "Connect to Context7 MCP server",
44
+ description:
45
+ "Let the AI assistant look up current documentation and code examples for third-party libraries using Context7.",
45
46
  },
46
47
  ];
47
48
 
@@ -58,12 +59,13 @@ export const MCPConfig: React.FC<MCPConfigProps> = ({ form, onSubmit }) => {
58
59
  return (
59
60
  <div className="flex flex-col gap-4">
60
61
  <div className="flex items-center justify-between">
61
- <SettingSubtitle>MCP Servers</SettingSubtitle>
62
+ <SettingSubtitle>MCP servers</SettingSubtitle>
62
63
  <div className="flex items-center gap-2">
63
64
  {status && <McpStatusText status={status.status} />}
64
65
  <Button
65
66
  variant="outline"
66
67
  size="xs"
68
+ aria-label="Refresh MCP servers"
67
69
  onClick={handleRefresh}
68
70
  disabled={isRefreshing || isFetching}
69
71
  >
@@ -101,7 +103,7 @@ export const MCPConfig: React.FC<MCPConfigProps> = ({ form, onSubmit }) => {
101
103
  onClick={() => handleClick("optionalDeps")}
102
104
  size="xs"
103
105
  >
104
- Optional Features
106
+ Optional features
105
107
  </Button>{" "}
106
108
  for more details.
107
109
  </p>
@@ -121,45 +123,20 @@ export const MCPConfig: React.FC<MCPConfigProps> = ({ form, onSubmit }) => {
121
123
  };
122
124
 
123
125
  return (
124
- <FormItem>
125
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
126
- {PRESET_CONFIGS.map((config) => {
127
- const isChecked = presets.includes(config.id);
128
-
129
- return (
130
- <Card
131
- key={config.id}
132
- className={`cursor-pointer transition-all ${
133
- isChecked
134
- ? "border-(--blue-9) bg-(--blue-2)"
135
- : "hover:border-(--blue-7)"
136
- }`}
137
- onClick={() => togglePreset(config.id)}
138
- >
139
- <CardHeader>
140
- <div className="flex items-start justify-between">
141
- <CardTitle className="text-base">
142
- {config.title}
143
- </CardTitle>
144
- <span
145
- className={`h-5 w-5 flex items-center justify-center rounded border ${
146
- isChecked
147
- ? "border-(--blue-7) bg-(--blue-7) text-foreground"
148
- : "border-muted bg-background text-muted-foreground"
149
- }`}
150
- >
151
- {isChecked ? <CheckSquareIcon /> : null}
152
- </span>
153
- </div>
154
- </CardHeader>
155
- <CardContent>
156
- <CardDescription>{config.description}</CardDescription>
157
- </CardContent>
158
- </Card>
159
- );
160
- })}
161
- </div>
162
- </FormItem>
126
+ <div className="flex flex-col gap-6">
127
+ {PRESET_CONFIGS.map((config) => (
128
+ <FormItem key={config.id} className={formItemClasses}>
129
+ <FormLabel>{config.title}</FormLabel>
130
+ <FormControl>
131
+ <Checkbox
132
+ checked={presets.includes(config.id)}
133
+ onCheckedChange={() => togglePreset(config.id)}
134
+ />
135
+ </FormControl>
136
+ <FormDescription>{config.description}</FormDescription>
137
+ </FormItem>
138
+ ))}
139
+ </div>
163
140
  );
164
141
  }}
165
142
  />
@@ -0,0 +1,91 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ .user-config-form .settings-group {
4
+ gap: 1.5rem;
5
+ }
6
+
7
+ .user-config-form .settings-group > h3 {
8
+ margin-bottom: -0.75rem;
9
+ }
10
+
11
+ .user-config-form .settings-group + .settings-group {
12
+ border-top: 1px solid var(--border);
13
+ padding-top: 1.5rem;
14
+ }
15
+
16
+ .user-config-form .settings-row {
17
+ display: flex;
18
+ flex-direction: column;
19
+ align-items: flex-start;
20
+ gap: 0.25rem;
21
+ }
22
+
23
+ .user-config-form .settings-row > * {
24
+ min-width: 0;
25
+ max-width: 100%;
26
+ margin: 0;
27
+ }
28
+
29
+ .user-config-form label {
30
+ font-weight: 600;
31
+ }
32
+
33
+ .user-config-form label:not(.text-destructive) {
34
+ color: var(--muted-foreground);
35
+ }
36
+
37
+ .user-config-form .settings-row > label {
38
+ width: auto;
39
+ line-height: 1.5;
40
+ }
41
+
42
+ .user-config-form .settings-row > label + p {
43
+ margin-bottom: 0.25rem;
44
+ }
45
+
46
+ .user-config-form .settings-row > select {
47
+ width: auto;
48
+ min-width: min(100%, 8rem);
49
+ height: 1.75rem;
50
+ }
51
+
52
+ .user-config-form .settings-row:has(> [role="checkbox"]) {
53
+ display: grid;
54
+ grid-template-columns: auto minmax(0, 1fr);
55
+ align-items: center;
56
+ column-gap: 0.5rem;
57
+ }
58
+
59
+ .user-config-form .settings-row > [role="checkbox"] {
60
+ grid-column: 1;
61
+ grid-row: 1;
62
+ }
63
+
64
+ .user-config-form .settings-row:has(> [role="checkbox"]) > label {
65
+ grid-column: 2;
66
+ grid-row: 1;
67
+ }
68
+
69
+ .user-config-form .settings-row:has(> [role="checkbox"]) > :nth-child(n + 3) {
70
+ grid-column: 1 / -1;
71
+ justify-self: start;
72
+ }
73
+
74
+ .user-config-form p {
75
+ line-height: 1.5;
76
+ }
77
+
78
+ .user-config-form :is(.settings-field, .settings-row) {
79
+ border-radius: 0.375rem;
80
+ }
81
+
82
+ .user-config-form
83
+ :is(.settings-field, .settings-row):is(:hover, :focus-within) {
84
+ background-color: color-mix(in srgb, var(--muted) 50%, transparent);
85
+ box-shadow: 0 0 0 0.5rem color-mix(in srgb, var(--muted) 50%, transparent);
86
+ }
87
+
88
+ .user-config-form .settings-field .settings-row:is(:hover, :focus-within) {
89
+ background-color: transparent;
90
+ box-shadow: none;
91
+ }