Skip to content

Commit 7eacaf0

Browse files
Add settings modal to React example
- Create SettingsModal component with form validation - Add localStorage utilities for settings persistence - Implement SettingsContext for state management - Add first-visit detection to auto-open modal - Include navigation button to reopen settings - Display current settings in the UI - Add comprehensive CSS styling with dark mode support - Fix TypeScript configuration for Node.js types
1 parent 47ae799 commit 7eacaf0

File tree

9 files changed

+647
-3
lines changed

9 files changed

+647
-3
lines changed

example/src/App.css

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,69 @@
99
padding: 2rem;
1010
}
1111

12+
.app-header {
13+
display: flex;
14+
justify-content: space-between;
15+
align-items: center;
16+
margin-bottom: 2rem;
17+
}
18+
19+
.app-header h1 {
20+
margin: 0;
21+
}
22+
23+
.settings-button {
24+
background-color: #646cff;
25+
color: white;
26+
border: none;
27+
padding: 0.75rem 1rem;
28+
border-radius: 4px;
29+
cursor: pointer;
30+
font-size: 1rem;
31+
transition: background-color 0.2s;
32+
}
33+
34+
.settings-button:hover {
35+
background-color: #535bf2;
36+
}
37+
38+
.welcome-message {
39+
background-color: #e3f2fd;
40+
border: 1px solid #2196f3;
41+
border-radius: 4px;
42+
padding: 1rem;
43+
margin-bottom: 1rem;
44+
text-align: center;
45+
}
46+
47+
.welcome-message p {
48+
margin: 0;
49+
color: #1976d2;
50+
font-weight: 500;
51+
}
52+
53+
.settings-info {
54+
background-color: #f5f5f5;
55+
border-radius: 4px;
56+
padding: 1rem;
57+
margin-bottom: 1rem;
58+
}
59+
60+
.settings-info h3 {
61+
margin-top: 0;
62+
margin-bottom: 0.5rem;
63+
color: #333;
64+
}
65+
66+
.settings-info ul {
67+
margin: 0;
68+
padding-left: 1.5rem;
69+
}
70+
71+
.settings-info li {
72+
margin: 0.25rem 0;
73+
}
74+
1275
.card {
1376
padding: 2em;
1477
margin: 1em 0;
@@ -73,4 +136,21 @@
73136
border-top-color: #333;
74137
color: #ccc;
75138
}
139+
140+
.welcome-message {
141+
background-color: #1a237e;
142+
border-color: #3f51b5;
143+
}
144+
145+
.welcome-message p {
146+
color: #90caf9;
147+
}
148+
149+
.settings-info {
150+
background-color: #2a2a2a;
151+
}
152+
153+
.settings-info h3 {
154+
color: #fff;
155+
}
76156
}

example/src/App.tsx

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,16 @@ import {
1010
EventSortOrder
1111
} from '@openhands/agent-server-typescript-client'
1212

13+
// Import settings components
14+
import { SettingsModal } from './components/SettingsModal'
15+
import { useSettings } from './contexts/SettingsContext'
16+
1317
function App() {
1418
const [sdkStatus, setSdkStatus] = useState<string>('Loading...')
1519
const [sdkInfo, setSdkInfo] = useState<any>(null)
20+
21+
// Use settings context
22+
const { settings, updateSettings, isModalOpen, openModal, closeModal, isFirstVisit } = useSettings()
1623

1724
useEffect(() => {
1825
// Test that the SDK imports work correctly
@@ -48,7 +55,28 @@ function App() {
4855
return (
4956
<div className="App">
5057
<div>
51-
<h1>OpenHands SDK Example</h1>
58+
<div className="app-header">
59+
<h1>OpenHands SDK Example</h1>
60+
<button className="settings-button" onClick={openModal}>
61+
⚙️ Settings
62+
</button>
63+
</div>
64+
65+
{isFirstVisit && (
66+
<div className="welcome-message">
67+
<p>👋 Welcome! Please configure your settings to get started.</p>
68+
</div>
69+
)}
70+
71+
<div className="settings-info">
72+
<h3>Current Settings:</h3>
73+
<ul>
74+
<li><strong>Agent Server URL:</strong> {settings.agentServerUrl}</li>
75+
<li><strong>Model:</strong> {settings.modelName}</li>
76+
<li><strong>API Key:</strong> {settings.apiKey ? '***configured***' : 'not set'}</li>
77+
</ul>
78+
</div>
79+
5280
<div className="card">
5381
<h2>SDK Import Status</h2>
5482
<p className="status">{sdkStatus}</p>
@@ -102,6 +130,13 @@ function App() {
102130
that the build process works correctly.
103131
</p>
104132
</div>
133+
134+
<SettingsModal
135+
isOpen={isModalOpen}
136+
onClose={closeModal}
137+
onSave={updateSettings}
138+
initialSettings={settings}
139+
/>
105140
</div>
106141
</div>
107142
)
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
.modal-overlay {
2+
position: fixed;
3+
top: 0;
4+
left: 0;
5+
right: 0;
6+
bottom: 0;
7+
background-color: rgba(0, 0, 0, 0.5);
8+
display: flex;
9+
justify-content: center;
10+
align-items: center;
11+
z-index: 1000;
12+
}
13+
14+
.modal-content {
15+
background: white;
16+
border-radius: 8px;
17+
padding: 0;
18+
width: 90%;
19+
max-width: 500px;
20+
max-height: 90vh;
21+
overflow-y: auto;
22+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
23+
}
24+
25+
.modal-header {
26+
display: flex;
27+
justify-content: space-between;
28+
align-items: center;
29+
padding: 1.5rem;
30+
border-bottom: 1px solid #e0e0e0;
31+
}
32+
33+
.modal-header h2 {
34+
margin: 0;
35+
color: #333;
36+
font-size: 1.5rem;
37+
}
38+
39+
.close-button {
40+
background: none;
41+
border: none;
42+
font-size: 1.5rem;
43+
cursor: pointer;
44+
color: #666;
45+
padding: 0;
46+
width: 30px;
47+
height: 30px;
48+
display: flex;
49+
align-items: center;
50+
justify-content: center;
51+
border-radius: 50%;
52+
transition: background-color 0.2s;
53+
}
54+
55+
.close-button:hover {
56+
background-color: #f0f0f0;
57+
color: #333;
58+
}
59+
60+
.settings-form {
61+
padding: 1.5rem;
62+
}
63+
64+
.form-group {
65+
margin-bottom: 1.5rem;
66+
}
67+
68+
.form-group label {
69+
display: block;
70+
margin-bottom: 0.5rem;
71+
font-weight: 600;
72+
color: #333;
73+
font-size: 0.9rem;
74+
}
75+
76+
.form-group input {
77+
width: 100%;
78+
padding: 0.75rem;
79+
border: 1px solid #ddd;
80+
border-radius: 4px;
81+
font-size: 1rem;
82+
transition: border-color 0.2s, box-shadow 0.2s;
83+
box-sizing: border-box;
84+
}
85+
86+
.form-group input:focus {
87+
outline: none;
88+
border-color: #646cff;
89+
box-shadow: 0 0 0 2px rgba(100, 108, 255, 0.1);
90+
}
91+
92+
.form-group input.error {
93+
border-color: #e74c3c;
94+
box-shadow: 0 0 0 2px rgba(231, 76, 60, 0.1);
95+
}
96+
97+
.error-message {
98+
display: block;
99+
color: #e74c3c;
100+
font-size: 0.8rem;
101+
margin-top: 0.25rem;
102+
}
103+
104+
.form-actions {
105+
display: flex;
106+
gap: 1rem;
107+
justify-content: flex-end;
108+
margin-top: 2rem;
109+
padding-top: 1rem;
110+
border-top: 1px solid #e0e0e0;
111+
}
112+
113+
.cancel-button,
114+
.save-button {
115+
padding: 0.75rem 1.5rem;
116+
border: none;
117+
border-radius: 4px;
118+
font-size: 1rem;
119+
cursor: pointer;
120+
transition: background-color 0.2s, transform 0.1s;
121+
}
122+
123+
.cancel-button {
124+
background-color: #f8f9fa;
125+
color: #666;
126+
border: 1px solid #ddd;
127+
}
128+
129+
.cancel-button:hover {
130+
background-color: #e9ecef;
131+
color: #333;
132+
}
133+
134+
.save-button {
135+
background-color: #646cff;
136+
color: white;
137+
}
138+
139+
.save-button:hover {
140+
background-color: #535bf2;
141+
}
142+
143+
.cancel-button:active,
144+
.save-button:active {
145+
transform: translateY(1px);
146+
}
147+
148+
/* Dark mode support */
149+
@media (prefers-color-scheme: dark) {
150+
.modal-content {
151+
background: #1a1a1a;
152+
color: #fff;
153+
}
154+
155+
.modal-header {
156+
border-bottom-color: #333;
157+
}
158+
159+
.modal-header h2 {
160+
color: #fff;
161+
}
162+
163+
.close-button {
164+
color: #ccc;
165+
}
166+
167+
.close-button:hover {
168+
background-color: #333;
169+
color: #fff;
170+
}
171+
172+
.form-group label {
173+
color: #fff;
174+
}
175+
176+
.form-group input {
177+
background-color: #2a2a2a;
178+
border-color: #444;
179+
color: #fff;
180+
}
181+
182+
.form-group input:focus {
183+
border-color: #646cff;
184+
box-shadow: 0 0 0 2px rgba(100, 108, 255, 0.2);
185+
}
186+
187+
.form-group input.error {
188+
border-color: #e74c3c;
189+
box-shadow: 0 0 0 2px rgba(231, 76, 60, 0.2);
190+
}
191+
192+
.form-actions {
193+
border-top-color: #333;
194+
}
195+
196+
.cancel-button {
197+
background-color: #2a2a2a;
198+
color: #ccc;
199+
border-color: #444;
200+
}
201+
202+
.cancel-button:hover {
203+
background-color: #333;
204+
color: #fff;
205+
}
206+
}

0 commit comments

Comments
 (0)