@upstep/react-native 0.7.0 → 0.7.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.1
4
+
5
+ - Restore the original accent and use the configured accent for all chat actions.
6
+ - Compact text and action cards pinned near the composer, with two-step contact collection and expandable optional details.
7
+
3
8
  ## 0.7.0
4
9
 
5
10
  - Native support chat in the existing feedback sheet, with signed customer identities and anonymous session persistence.
package/README.md CHANGED
@@ -5,7 +5,7 @@ The [Upstep](https://upstep.dev) feedback SDK for React Native: a launcher butto
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- npm install @upstep/react-native@^0.7.0 react-native-safe-area-context @react-native-async-storage/async-storage
8
+ npm install @upstep/react-native@^0.7.1 react-native-safe-area-context @react-native-async-storage/async-storage
9
9
  ```
10
10
 
11
11
  `react-native-safe-area-context` is a required peer dependency (the sheet needs it for safe-area insets). Get an API key by creating a free project at [upstep.dev](https://upstep.dev).
@@ -56,7 +56,7 @@ If `expo-sensors` isn't installed, the hook is a no-op — safe to call uncondit
56
56
  | `apiKey` | `string` | — | **Required.** Your project's API key. |
57
57
  | `userId` | `string` | — | End-user id from your app, used to deduplicate votes per user. Call `identify(userId)` if it's only known after login. |
58
58
  | `baseUrl` | `string` | `https://upstep.dev` | Only needed for self-hosted or staging setups. |
59
- | `accentColor` | `string` | `#5B7168` | Any CSS color, used for the launcher button and highlights. |
59
+ | `accentColor` | `string` | `#D97757` | Any CSS color, used for the launcher button and highlights. |
60
60
  | `theme` | `"light" \| "dark" \| "auto"` | `"auto"` | `"auto"` follows the device color scheme. |
61
61
 
62
62
  ## API
@@ -75,7 +75,7 @@ If `expo-sensors` isn't installed, the hook is a no-op — safe to call uncondit
75
75
 
76
76
  ## Native AI and team support
77
77
 
78
- Version 0.7.0 adds a native Support tab to the existing feedback sheet. Enable Customer support for a paid project in UpStep, then use the existing provider and launcher. No WebView or separate chat package is needed. Set `chat={false}` on `FeedbackProvider` to hide support.
78
+ Version 0.7.1 adds a native Support tab to the existing feedback sheet. Enable Customer support for a paid project in UpStep, then use the existing provider and launcher. No WebView or separate chat package is needed. Set `chat={false}` on `FeedbackProvider` to hide support.
79
79
 
80
80
  ```tsx
81
81
  <FeedbackProvider apiKey="YOUR_PROJECT_KEY" chat={true} supportIdentityToken={signedToken}>
@@ -86,4 +86,4 @@ Version 0.7.0 adds a native Support tab to the existing feedback sheet. Enable C
86
86
 
87
87
  `supportIdentityToken` is optional: generate a short-lived project-scoped JWT on your authenticated backend using the signing secret from Support settings. Never put that secret in the app. Pass a new token on login and `undefined` on logout. `userId` is for feedback voting and does not authenticate private chat. Anonymous chat sessions persist using AsyncStorage.
88
88
 
89
- Chat includes large text, soft message bubbles, quick replies, issue detail cards and resolution confirmations. The team contact form appears after AI understands an unresolved issue, and requires name/email before handoff. Tickets include a reference and the business contact email.
89
+ Chat includes compact text, neutral message bubbles, quick replies, issue detail cards and resolution confirmations. Active actions stay near the composer, and contact details use two short steps. The team contact form appears after AI understands an unresolved issue, and requires name/email before handoff. Tickets include a reference and the business contact email.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upstep/react-native",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "Native UpStep feedback and AI support chat for React Native",
5
5
  "homepage": "https://upstep.dev",
6
6
  "repository": {
@@ -19,8 +19,8 @@
19
19
  }
20
20
  },
21
21
  "dependencies": {
22
- "@upstep/types": "0.7.0",
23
- "@upstep/js": "0.7.0"
22
+ "@upstep/types": "0.7.1",
23
+ "@upstep/js": "0.7.1"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "@react-native-async-storage/async-storage": ">=1.18",
@@ -25,7 +25,7 @@ if (Platform.OS === "android") {
25
25
  um.setLayoutAnimationEnabledExperimental?.(true);
26
26
  }
27
27
 
28
- const DEFAULT_ACCENT = "#5B7168";
28
+ const DEFAULT_ACCENT = "#D97757";
29
29
 
30
30
  interface UpstepContextValue {
31
31
  client: UpstepApiClient;
@@ -38,7 +38,7 @@ interface Palette {
38
38
 
39
39
  const LIGHT: Palette = {
40
40
  bg: "#ffffff",
41
- bgSoft: "#f4f6f4",
41
+ bgSoft: "#f5f5f5",
42
42
  text: "#1a1915",
43
43
  textSoft: "#56544d",
44
44
  textFaint: "#9b9890",
@@ -48,7 +48,7 @@ const LIGHT: Palette = {
48
48
 
49
49
  const DARK: Palette = {
50
50
  bg: "#000000",
51
- bgSoft: "#191d1b",
51
+ bgSoft: "#171717",
52
52
  text: "#f5f4f0",
53
53
  textSoft: "#b4b1a8",
54
54
  textFaint: "#7d7a72",
@@ -209,6 +209,7 @@ export function FeedbackSheet() {
209
209
  key={supportRevision}
210
210
  client={client.support}
211
211
  config={supportConfig}
212
+ accentColor={accentColor}
212
213
  dark={isDark}
213
214
  />
214
215
  )}
@@ -9,6 +9,7 @@ import {
9
9
  TextInput,
10
10
  TouchableOpacity,
11
11
  View,
12
+ useWindowDimensions,
12
13
  } from "react-native";
13
14
  import { SupportClient, supportMessageId } from "@upstep/js/support";
14
15
  import type {
@@ -20,11 +21,14 @@ export function SupportView({
20
21
  client,
21
22
  config,
22
23
  dark = false,
24
+ accentColor = "#D97757",
23
25
  }: {
24
26
  client: SupportClient;
25
27
  config: SupportConfiguration;
26
28
  dark?: boolean;
29
+ accentColor?: string;
27
30
  }) {
31
+ const { height } = useWindowDimensions();
28
32
  const [chat, setChat] = useState<SupportConversation | null>(null);
29
33
  const [text, setText] = useState("");
30
34
  const [busy, setBusy] = useState(false);
@@ -34,10 +38,10 @@ export function SupportView({
34
38
  const pending = useRef<{ text: string; id: string } | null>(null);
35
39
  const colors = {
36
40
  bg: dark ? "#000000" : "#ffffff",
37
- soft: dark ? "#191d1b" : "#f4f6f4",
38
- text: dark ? "#e5e7e5" : "#37413c",
39
- muted: dark ? "#a2aaa5" : "#69756d",
40
- line: dark ? "#303833" : "#dde4de",
41
+ soft: dark ? "#171717" : "#f5f5f5",
42
+ text: dark ? "#e5e5e5" : "#404040",
43
+ muted: dark ? "#a3a3a3" : "#737373",
44
+ line: dark ? "#404040" : "#e5e5e5",
41
45
  };
42
46
  async function refresh(id: string) {
43
47
  const next = await client.conversation(id);
@@ -95,6 +99,21 @@ export function SupportView({
95
99
  await refresh(c.id);
96
100
  });
97
101
  }
102
+ const widgets: SupportWidget[] = chat?.activeWidgetMessageId
103
+ ? (
104
+ chat.messages.find((m) => m.id === chat.activeWidgetMessageId)?.metadata
105
+ ?.widgets || []
106
+ ).filter((w) => w.type !== "contact_form" || chat.canEscalate)
107
+ : chat?.canEscalate
108
+ ? [
109
+ {
110
+ id: `contact:${chat.id}`,
111
+ type: "contact_form",
112
+ title: "Let the team follow up",
113
+ summary: chat.escalationSummary || "",
114
+ },
115
+ ]
116
+ : [];
98
117
  return (
99
118
  <View style={[styles.root, { backgroundColor: colors.bg }]}>
100
119
  <View style={[styles.heading, { borderColor: colors.line }]}>
@@ -203,45 +222,33 @@ export function SupportView({
203
222
  </TouchableOpacity>
204
223
  ))}
205
224
  </View>
206
- {m.id === chat.activeWidgetMessageId &&
207
- m.metadata?.widgets
208
- ?.filter((w) => w.type !== "contact_form" || chat.canEscalate)
209
- .map((w) => (
210
- <NativeSupportWidget
211
- key={w.id}
212
- widget={w}
213
- busy={busy}
214
- color={colors}
215
- name={chat.customer.name || ""}
216
- email={chat.customer.email || ""}
217
- verified={chat.customer.verified}
218
- onReply={send}
219
- onContact={(name, email) =>
220
- perform(async () => {
221
- await client.handoff(chat.id, name, email);
222
- await refresh(chat.id);
223
- })
224
- }
225
- onDetails={(values) =>
226
- perform(async () => {
227
- await client.details(chat.id, values);
228
- await refresh(chat.id);
229
- })
230
- }
231
- />
232
- ))}
233
225
  </View>
234
226
  ))}
235
- {chat?.canEscalate && !chat.activeWidgetMessageId && (
236
- <NativeSupportWidget
237
- widget={{
238
- id: `contact:${chat.id}`,
239
- type: "contact_form",
240
- title: "Let the team follow up",
241
- summary: chat.escalationSummary || "",
242
- }}
227
+ {chat?.aiPending && (
228
+ <View style={{ flexDirection: "row", gap: 10, alignItems: "center" }}>
229
+ <ActivityIndicator color={accentColor} />
230
+ <Text style={[styles.meta, { color: colors.muted }]}>
231
+ Thinking…
232
+ </Text>
233
+ </View>
234
+ )}
235
+ </ScrollView>
236
+ {chat && widgets.length > 0 && (
237
+ <ScrollView
238
+ keyboardShouldPersistTaps="handled"
239
+ style={{
240
+ maxHeight: height * 0.38,
241
+ flexGrow: 0,
242
+ marginHorizontal: 12,
243
+ }}
244
+ >
245
+ <NativeSupportActions
246
+ key={chat.activeWidgetMessageId || chat.id}
247
+ widgets={widgets}
248
+ online={config.online.length > 0}
243
249
  busy={busy}
244
250
  color={colors}
251
+ accentColor={accentColor}
245
252
  name={chat.customer.name || ""}
246
253
  email={chat.customer.email || ""}
247
254
  verified={chat.customer.verified}
@@ -259,16 +266,8 @@ export function SupportView({
259
266
  })
260
267
  }
261
268
  />
262
- )}
263
- {chat?.aiPending && (
264
- <View style={{ flexDirection: "row", gap: 10, alignItems: "center" }}>
265
- <ActivityIndicator color="#7c9386" />
266
- <Text style={[styles.meta, { color: colors.muted }]}>
267
- Thinking…
268
- </Text>
269
- </View>
270
- )}
271
- </ScrollView>
269
+ </ScrollView>
270
+ )}
272
271
  {error.length > 0 && (
273
272
  <Text
274
273
  accessibilityRole="alert"
@@ -283,7 +282,10 @@ export function SupportView({
283
282
  </Text>
284
283
  )}
285
284
  {chat?.state === "RESOLVED" ? (
286
- <TouchableOpacity style={styles.send} onPress={() => setChat(null)}>
285
+ <TouchableOpacity
286
+ style={[styles.send, { backgroundColor: accentColor }]}
287
+ onPress={() => setChat(null)}
288
+ >
287
289
  <Text style={styles.sendText}>Start a new conversation</Text>
288
290
  </TouchableOpacity>
289
291
  ) : (
@@ -303,7 +305,13 @@ export function SupportView({
303
305
  accessibilityLabel="Send message"
304
306
  disabled={busy || !text.trim()}
305
307
  onPress={() => void send()}
306
- style={[styles.send, { opacity: busy || !text.trim() ? 0.45 : 1 }]}
308
+ style={[
309
+ styles.send,
310
+ {
311
+ backgroundColor: accentColor,
312
+ opacity: busy || !text.trim() ? 0.45 : 1,
313
+ },
314
+ ]}
307
315
  >
308
316
  <Text style={styles.sendText}>Send</Text>
309
317
  </TouchableOpacity>
@@ -322,20 +330,11 @@ export function SupportView({
322
330
  </View>
323
331
  );
324
332
  }
325
- function NativeSupportWidget({
326
- widget,
327
- busy,
328
- color,
329
- name,
330
- email,
331
- verified,
332
- onReply,
333
- onContact,
334
- onDetails,
335
- }: {
336
- widget: SupportWidget;
333
+ type ActionProps = {
334
+ online: boolean;
337
335
  busy: boolean;
338
336
  color: { soft: string; text: string; muted: string; line: string };
337
+ accentColor: string;
339
338
  name: string;
340
339
  email: string;
341
340
  verified: boolean;
@@ -348,48 +347,113 @@ function NativeSupportWidget({
348
347
  reference: string;
349
348
  clientMessageId: string;
350
349
  }) => Promise<boolean>;
351
- }) {
352
- const [open, setOpen] = useState(false);
353
- const [fullName, setName] = useState(name);
354
- const [address, setEmail] = useState(email);
355
- const [summary, setSummary] = useState("");
356
- const [details, setDetails] = useState("");
357
- const [reference, setReference] = useState("");
350
+ };
351
+ function NativeSupportActions({
352
+ widgets,
353
+ ...props
354
+ }: ActionProps & { widgets: SupportWidget[] }) {
355
+ const [selected, setSelected] = useState(
356
+ widgets.find((w) => w.type === "quick_replies")?.id || widgets[0]?.id,
357
+ );
358
+ const widget = widgets.find((w) => w.id === selected) || widgets[0];
359
+ return (
360
+ <View style={{ gap: 8, paddingBottom: 4 }}>
361
+ {widgets.length > 1 && (
362
+ <View style={{ flexDirection: "row", gap: 8 }}>
363
+ {widgets.map((w) => (
364
+ <TouchableOpacity
365
+ key={w.id}
366
+ onPress={() => setSelected(w.id)}
367
+ style={[
368
+ styles.option,
369
+ { borderColor: props.color.line, padding: 8 },
370
+ ]}
371
+ >
372
+ <Text style={{ fontSize: 13, color: props.color.text }}>
373
+ {w.type === "quick_replies" ? "Quick replies" : "Issue details"}
374
+ </Text>
375
+ </TouchableOpacity>
376
+ ))}
377
+ </View>
378
+ )}
379
+ {widget && (
380
+ <NativeSupportWidget key={widget.id} {...props} widget={widget} />
381
+ )}
382
+ </View>
383
+ );
384
+ }
385
+ function NativeSupportWidget({
386
+ widget,
387
+ busy,
388
+ color,
389
+ accentColor,
390
+ name,
391
+ email,
392
+ verified,
393
+ online,
394
+ onReply,
395
+ onContact,
396
+ onDetails,
397
+ }: ActionProps & { widget: SupportWidget }) {
398
+ const [step, setStep] = useState(0),
399
+ [issueOpen, setIssueOpen] = useState(false),
400
+ [more, setMore] = useState(false);
401
+ const [fullName, setName] = useState(name),
402
+ [address, setEmail] = useState(email),
403
+ [summary, setSummary] = useState(""),
404
+ [details, setDetails] = useState(""),
405
+ [reference, setReference] = useState("");
358
406
  const id = useRef(supportMessageId());
407
+ const action = (title: string, press: () => void, disabled = false) => (
408
+ <TouchableOpacity
409
+ disabled={disabled || busy}
410
+ style={[
411
+ styles.send,
412
+ { backgroundColor: accentColor, opacity: disabled || busy ? 0.5 : 1 },
413
+ ]}
414
+ onPress={press}
415
+ >
416
+ <Text style={styles.sendText}>{title}</Text>
417
+ </TouchableOpacity>
418
+ );
359
419
  if (widget.type === "quick_replies" || widget.type === "confirmation")
360
420
  return (
361
- <View style={{ gap: 8, marginTop: 12 }}>
362
- <Text style={[styles.label, { color: color.text }]}>
421
+ <View style={{ gap: 8 }}>
422
+ <Text style={[styles.meta, { color: color.muted }]}>
363
423
  {widget.title}
364
424
  </Text>
365
- {widget.options.map((option) => (
366
- <TouchableOpacity
367
- key={option}
368
- disabled={busy}
369
- style={[styles.option, { borderColor: color.line }]}
370
- onPress={() => void onReply(option)}
371
- >
372
- <Text style={[styles.body, { color: color.text }]}>{option}</Text>
373
- </TouchableOpacity>
374
- ))}
425
+ <View style={{ flexDirection: "row", flexWrap: "wrap", gap: 8 }}>
426
+ {widget.options.map((option) => (
427
+ <TouchableOpacity
428
+ key={option}
429
+ disabled={busy}
430
+ style={[styles.option, { borderColor: color.line }]}
431
+ onPress={() => void onReply(option)}
432
+ >
433
+ <Text style={{ fontSize: 13, color: color.text }}>{option}</Text>
434
+ </TouchableOpacity>
435
+ ))}
436
+ </View>
375
437
  </View>
376
438
  );
377
439
  const field = (
378
440
  label: string,
379
441
  value: string,
380
- set: (s: string) => void,
381
- kind: "email-address" | "default" = "default",
442
+ set: (v: string) => void,
443
+ emailField = false,
382
444
  readOnly = false,
445
+ maxLength = 160,
383
446
  ) => (
384
- <View style={{ gap: 6 }}>
447
+ <View style={{ gap: 4 }}>
385
448
  <Text style={[styles.meta, { color: color.muted }]}>{label}</Text>
386
449
  <TextInput
387
450
  accessibilityLabel={label}
388
451
  value={value}
389
452
  onChangeText={set}
390
- editable={!readOnly && !busy}
391
- keyboardType={kind}
392
- autoCapitalize={kind === "email-address" ? "none" : "sentences"}
453
+ editable={!busy && !readOnly}
454
+ maxLength={maxLength}
455
+ keyboardType={emailField ? "email-address" : "default"}
456
+ autoCapitalize={emailField ? "none" : "sentences"}
393
457
  style={[
394
458
  styles.formInput,
395
459
  { color: color.text, borderColor: color.line },
@@ -404,73 +468,119 @@ function NativeSupportWidget({
404
468
  { backgroundColor: color.soft, borderColor: color.line },
405
469
  ]}
406
470
  >
407
- <Text style={[styles.title, { color: color.text }]}>{widget.title}</Text>
471
+ <View
472
+ style={{
473
+ flexDirection: "row",
474
+ justifyContent: "space-between",
475
+ gap: 8,
476
+ }}
477
+ >
478
+ <Text style={[styles.label, { color: color.text }]}>
479
+ {widget.title}
480
+ </Text>
481
+ {widget.type === "contact_form" && step > 0 && (
482
+ <Text style={[styles.meta, { color: color.muted }]}>{step} of 2</Text>
483
+ )}
484
+ </View>
408
485
  {widget.type === "contact_form" ? (
409
- <>
410
- <Text style={[styles.body, { color: color.muted }]}>
411
- {widget.summary}
412
- </Text>
413
- {!open ? (
414
- <TouchableOpacity
415
- disabled={busy}
416
- style={styles.send}
417
- onPress={() => setOpen(true)}
486
+ step === 0 ? (
487
+ <>
488
+ <Text
489
+ numberOfLines={2}
490
+ style={[styles.meta, { color: color.muted }]}
491
+ >
492
+ {widget.summary}
493
+ </Text>
494
+ {action("Ask the team", () => setStep(1))}
495
+ </>
496
+ ) : (
497
+ <>
498
+ {step === 1
499
+ ? field("Your name", fullName, setName, false, false, 100)
500
+ : field(
501
+ "Email for support follow-up",
502
+ address,
503
+ setEmail,
504
+ true,
505
+ verified && !!email,
506
+ 254,
507
+ )}
508
+ <View
509
+ style={{ flexDirection: "row", gap: 8, alignItems: "center" }}
418
510
  >
419
- <Text style={styles.sendText}>Ask the team</Text>
420
- </TouchableOpacity>
421
- ) : (
422
- <>
423
- {field("Your name", fullName, setName)}
424
- {field(
425
- "Email address",
426
- address,
427
- setEmail,
428
- "email-address",
429
- verified && !!email,
430
- )}
431
- <Text style={[styles.meta, { color: color.muted }]}>
432
- The team will use these details to follow up.
433
- </Text>
434
511
  <TouchableOpacity
435
- disabled={busy || !fullName.trim() || !address.trim()}
436
- style={[
437
- styles.send,
438
- {
439
- opacity:
440
- busy || !fullName.trim() || !address.trim() ? 0.5 : 1,
441
- },
442
- ]}
443
- onPress={() => void onContact(fullName, address)}
512
+ style={styles.option}
513
+ disabled={busy}
514
+ onPress={() => setStep(step - 1)}
444
515
  >
445
- <Text style={styles.sendText}>Send to the team</Text>
516
+ <Text style={{ color: color.text, fontSize: 13 }}>Back</Text>
446
517
  </TouchableOpacity>
447
- </>
448
- )}
449
- </>
518
+ <View style={{ flex: 1 }}>
519
+ {action(
520
+ step === 1
521
+ ? "Continue"
522
+ : online
523
+ ? "Request transfer"
524
+ : "Send to the team",
525
+ () => {
526
+ if (step === 1) setStep(2);
527
+ else void onContact(fullName, address);
528
+ },
529
+ !fullName.trim() || (step === 2 && !address.trim()),
530
+ )}
531
+ </View>
532
+ </View>
533
+ </>
534
+ )
535
+ ) : !issueOpen ? (
536
+ action("Add issue details", () => setIssueOpen(true))
450
537
  ) : (
451
538
  <>
452
539
  {field("What is happening?", summary, setSummary)}
453
- {field("What have you tried? (optional)", details, setDetails)}
454
- {field(
455
- "Order or issue reference (optional)",
456
- reference,
457
- setReference,
540
+ <TouchableOpacity onPress={() => setMore(!more)}>
541
+ <Text
542
+ style={[
543
+ styles.meta,
544
+ { color: color.muted, textDecorationLine: "underline" },
545
+ ]}
546
+ >
547
+ {more
548
+ ? "Hide optional details"
549
+ : "Add notes or a reference (optional)"}
550
+ </Text>
551
+ </TouchableOpacity>
552
+ {more && (
553
+ <>
554
+ {field(
555
+ "What have you tried?",
556
+ details,
557
+ setDetails,
558
+ false,
559
+ false,
560
+ 2000,
561
+ )}
562
+ {field(
563
+ "Order or issue reference",
564
+ reference,
565
+ setReference,
566
+ false,
567
+ false,
568
+ 100,
569
+ )}
570
+ </>
458
571
  )}
459
- <TouchableOpacity
460
- disabled={busy || !summary.trim()}
461
- style={styles.send}
462
- onPress={() =>
572
+ {action(
573
+ "Send details",
574
+ () =>
463
575
  void onDetails({
464
576
  widgetId: widget.id,
465
577
  summary,
466
578
  details,
467
579
  reference,
468
580
  clientMessageId: id.current,
469
- })
470
- }
471
- >
472
- <Text style={styles.sendText}>Send details</Text>
473
- </TouchableOpacity>
581
+ }),
582
+ !summary.trim(),
583
+ )}
474
584
  </>
475
585
  )}
476
586
  </View>
@@ -481,10 +591,10 @@ const styles = StyleSheet.create({
481
591
  heading: { padding: 16, borderBottomWidth: StyleSheet.hairlineWidth },
482
592
  title: { fontSize: 18, fontWeight: "600" },
483
593
  hero: { fontSize: 28, fontWeight: "600" },
484
- body: { fontSize: 16, lineHeight: 25 },
485
- meta: { fontSize: 14, lineHeight: 21 },
594
+ body: { fontSize: 15, lineHeight: 23 },
595
+ meta: { fontSize: 13, lineHeight: 19 },
486
596
  label: { fontSize: 15, fontWeight: "600" },
487
- bubble: { padding: 14, borderRadius: 16 },
597
+ bubble: { padding: 12, borderRadius: 16 },
488
598
  ticket: { padding: 12, gap: 4 },
489
599
  composer: {
490
600
  margin: 12,
@@ -505,21 +615,21 @@ const styles = StyleSheet.create({
505
615
  },
506
616
  send: {
507
617
  minHeight: 44,
508
- backgroundColor: "#5b7168",
618
+
509
619
  borderRadius: 12,
510
620
  paddingHorizontal: 16,
511
- paddingVertical: 12,
621
+ paddingVertical: 10,
512
622
  alignItems: "center",
513
623
  justifyContent: "center",
514
624
  },
515
- sendText: { fontSize: 16, fontWeight: "600", color: "white" },
625
+ sendText: { fontSize: 14, fontWeight: "600", color: "white" },
516
626
  option: { minHeight: 44, borderWidth: 1, borderRadius: 12, padding: 12 },
517
627
  form: {
518
- marginTop: 12,
628
+ marginTop: 0,
519
629
  borderWidth: 1,
520
630
  borderRadius: 16,
521
- padding: 14,
522
- gap: 12,
631
+ padding: 12,
632
+ gap: 8,
523
633
  },
524
634
  formInput: {
525
635
  borderWidth: 1,