@sikka/hawa 0.2.4-beta → 0.2.6-beta

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/dist/styles.css CHANGED
@@ -388,7 +388,8 @@ video {
388
388
  :root {
389
389
  --background: 0 0% 100%;
390
390
  --foreground: 240 10% 3.9%;
391
- --card: 0 0% 100%;
391
+ /* --card: 0 0% 100%; */
392
+ --card: 210 50% 98%;
392
393
  --card-foreground: 240 10% 3.9%;
393
394
  --popover: 0 0% 100%;
394
395
  --popover-foreground: 240 10% 3.9%;
@@ -422,7 +423,7 @@ video {
422
423
  --border: 240 5.9% 90%;
423
424
  --input: 240 5.9% 90%;
424
425
  --ring: 240 5% 64.9%;
425
- --radius: 1rem;
426
+ --radius: 0.5rem;
426
427
  --radius-inner: calc(var(--radius) - calc(var(--radius) / 3));
427
428
 
428
429
  --layout-primary-700: #b7aff7;
@@ -445,7 +446,8 @@ video {
445
446
  --layout-primary-300: #4a4a4a;
446
447
  --background: 240 10% 3.9%;
447
448
  --foreground: 0 0% 98%;
448
- --card: 240 10% 3.9%;
449
+ /* --card: 240 10% 3.9%; */
450
+ --card: 0 0% 2%;
449
451
  --card-foreground: 0 0% 98%;
450
452
  --popover: 240 10% 3.9%;
451
453
  --popover-foreground: 0 0% 98%;
@@ -1170,6 +1172,9 @@ video {
1170
1172
  .h-\[150px\] {
1171
1173
  height: 150px;
1172
1174
  }
1175
+ .h-\[165px\] {
1176
+ height: 165px;
1177
+ }
1173
1178
  .h-\[16px\] {
1174
1179
  height: 16px;
1175
1180
  }
@@ -1197,6 +1202,9 @@ video {
1197
1202
  .h-\[400px\] {
1198
1203
  height: 400px;
1199
1204
  }
1205
+ .h-\[44px\] {
1206
+ height: 44px;
1207
+ }
1200
1208
  .h-\[80px\] {
1201
1209
  height: 80px;
1202
1210
  }
@@ -1438,6 +1446,9 @@ video {
1438
1446
  .max-w-\[200px\] {
1439
1447
  max-width: 200px;
1440
1448
  }
1449
+ .max-w-\[300px\] {
1450
+ max-width: 300px;
1451
+ }
1441
1452
  .max-w-\[52px\] {
1442
1453
  max-width: 52px;
1443
1454
  }
@@ -2563,6 +2574,10 @@ video {
2563
2574
  .tracking-widest {
2564
2575
  letter-spacing: 0.1em;
2565
2576
  }
2577
+ .text-\[\#666666\] {
2578
+ --tw-text-opacity: 1;
2579
+ color: rgb(102 102 102 / var(--tw-text-opacity));
2580
+ }
2566
2581
  .text-black {
2567
2582
  --tw-text-opacity: 1;
2568
2583
  color: rgb(0 0 0 / var(--tw-text-opacity));
@@ -2895,6 +2910,9 @@ video {
2895
2910
  .duration-500 {
2896
2911
  transition-duration: 500ms;
2897
2912
  }
2913
+ .ease-in-out {
2914
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2915
+ }
2898
2916
  .will-change-transform {
2899
2917
  will-change: transform;
2900
2918
  }
@@ -2951,6 +2969,9 @@ video {
2951
2969
  .delay-300 {
2952
2970
  animation-delay: 300ms;
2953
2971
  }
2972
+ .ease-in-out {
2973
+ animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2974
+ }
2954
2975
  .repeat-infinite {
2955
2976
  animation-iteration-count: infinite;
2956
2977
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sikka/hawa",
3
- "version": "0.2.4-beta",
3
+ "version": "0.2.6-beta",
4
4
  "description": "Modern UI Kit made with Tailwind & Radix Primitives",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -1,2 +1,2 @@
1
- export * from "./UserProfileForm";
2
- export * from "./UserSettingsForm";
1
+ export * from "./UserProfileForm"
2
+ export * from "./UserSettingsForm"
@@ -1,8 +1,9 @@
1
1
  import React, { useState, FC } from "react"
2
2
  import { Controller, useForm } from "react-hook-form"
3
- import { HawaPhoneInput } from "../../elements"
3
+ import { HawaPhoneInput, HawaPinInput } from "../../elements"
4
4
  import { Card, CardContent } from "../../elements/Card"
5
5
  import { Button } from "../../elements/Button"
6
+ import { cn } from "../../util"
6
7
 
7
8
  type SignInPhoneTypes = {
8
9
  value: any
@@ -12,45 +13,147 @@ type SignInPhoneTypes = {
12
13
  handlePhoneChange: any
13
14
  phoneRequiredText: any
14
15
  SignInButtonText: any
15
- handleSignIn: any
16
+ handleContinue: any
17
+ handleConfirm: any
18
+ loadingContinue?: boolean
19
+ loadingConfirm?: boolean
20
+ confirmationStage?: boolean
21
+ texts?: {
22
+ didntGetCode?: string
23
+ resendCode?: string
24
+ cancel?: string
25
+ confirm?: string
26
+ continue?: string
27
+ }
16
28
  }
17
29
 
18
30
  export const SignInPhone: FC<SignInPhoneTypes> = (props) => {
31
+ const [pins, setPins] = useState(null)
32
+
19
33
  const methods = useForm()
20
34
  const {
21
35
  formState: { errors },
22
36
  handleSubmit,
23
37
  control,
24
38
  } = methods
39
+ const [resendTimer, setResendTimer] = useState(null)
40
+ const [remainingTime, setRemainingTime] = useState(0)
41
+ const [showResendTimer, setShowResendTimer] = useState(false)
25
42
 
26
43
  const [userPhone, setUserPhone] = useState("")
44
+ const [phoneConfirm, setPhoneConfirm] = useState(props.confirmationStage)
45
+
46
+ const startResendTimer = () => {
47
+ // Clear any existing timer
48
+ clearTimeout(resendTimer)
49
+
50
+ // Set the timer duration (e.g., 60 seconds)
51
+ const timerDuration = 60
52
+ setRemainingTime(timerDuration)
53
+ setShowResendTimer(true)
54
+
55
+ const newTimer = setInterval(() => {
56
+ setRemainingTime((prevTime) => {
57
+ if (prevTime > 0) {
58
+ return prevTime - 1;
59
+ } else {
60
+ clearInterval(newTimer); // Stop the timer when it reaches zero
61
+ setShowResendTimer(false);
62
+ return 0;
63
+ }
64
+ });
65
+ }, 1000);
66
+
67
+ // Update the state with the new timer
68
+ setResendTimer(newTimer)
69
+
70
+ // Add logic to resend OTP here if needed
71
+ }
72
+
27
73
  return (
28
74
  <Card>
29
- <CardContent headless>
30
- <form
31
- onSubmit={(e) => {
32
- e.preventDefault()
33
- props.handleSignIn(userPhone)
34
- }}
35
- >
36
- <Controller
37
- control={control}
38
- name="phone"
39
- render={({ field }) => (
40
- <HawaPhoneInput
41
- country={props.country ?? ""}
42
- label={props.label ?? ""}
43
- handleChange={(e: any) => setUserPhone(e.target.value)}
44
- {...field}
45
- />
46
- )}
47
- rules={{
48
- required: props.phoneRequiredText,
75
+ <CardContent className="transition-all" headless>
76
+ {phoneConfirm ? (
77
+ <form
78
+ onSubmit={(e) => {
79
+ e.preventDefault()
80
+ if (pins) {
81
+ props.handleConfirm(pins)
82
+ }
83
+ }}
84
+ >
85
+ <HawaPinInput width="full" digits={6} getPins={(e) => setPins(e)} />
86
+ <div className=" py-2 text-center text-xs text-muted-foreground">
87
+ {showResendTimer ? (
88
+ <span>
89
+ Resend code in {remainingTime} seconds |{" "}
90
+ <span
91
+ className="clickable-link"
92
+ onClick={() => {
93
+ clearTimeout(resendTimer)
94
+ setShowResendTimer(false)
95
+ // Add logic to resend OTP here
96
+ }}
97
+ >
98
+ Cancel
99
+ </span>
100
+ </span>
101
+ ) : (
102
+ <span>
103
+ {props.texts?.didntGetCode ?? "Didn't get the code?"}{" "}
104
+ <span
105
+ className="clickable-link"
106
+ onClick={() => {
107
+ startResendTimer()
108
+ // Add logic to resend OTP here
109
+ }}
110
+ >
111
+ {props.texts?.resendCode ?? "Click to resend"}
112
+ </span>
113
+ </span>
114
+ )}
115
+ </div>
116
+
117
+ <div className="mt-4 grid grid-cols-2 gap-2">
118
+ <Button
119
+ variant="secondary"
120
+ onClick={() => setPhoneConfirm(false)}
121
+ >
122
+ {props.texts?.cancel ?? "Cancel"}
123
+ </Button>
124
+ <Button isLoading={props.loadingConfirm}>
125
+ {props.texts?.confirm ?? "Confirm"}
126
+ </Button>
127
+ </div>
128
+ </form>
129
+ ) : (
130
+ <form
131
+ onSubmit={(e) => {
132
+ e.preventDefault()
133
+ setPhoneConfirm(true)
134
+ props.handleContinue(userPhone)
49
135
  }}
50
- />
51
- <div className="mt-2"></div>
52
- <Button className="w-full">{props.SignInButtonText}</Button>
53
- </form>
136
+ >
137
+ <Controller
138
+ control={control}
139
+ name="phone"
140
+ render={({ field }) => (
141
+ <HawaPhoneInput
142
+ country={props.country ?? ""}
143
+ label={props.label ?? ""}
144
+ handleChange={(e: any) => setUserPhone(e.target.value)}
145
+ {...field}
146
+ />
147
+ )}
148
+ rules={{
149
+ required: props.phoneRequiredText,
150
+ }}
151
+ />
152
+ <Button isLoading={props.loadingContinue} className="w-full">
153
+ {props.texts?.continue ?? "Continue"}
154
+ </Button>
155
+ </form>
156
+ )}
54
157
  </CardContent>
55
158
  </Card>
56
159
  )
@@ -25,8 +25,8 @@ const buttonVariants = cva(
25
25
  size: {
26
26
  default: "h-10 px-4 py-2",
27
27
  heightless: "px-4 py-4",
28
- xs: "h-fit py-1 text-[10px] px-2",
29
- sm: "h-9 rounded-md px-3",
28
+ xs: "h-fit py-1 text-[10px] px-2 ",
29
+ sm: "h-9 text-[11px] rounded-md px-3",
30
30
  lg: "h-11 rounded-md px-8",
31
31
  xl: "h-14 rounded-md px-10",
32
32
  icon: "h-10 w-10",
@@ -78,7 +78,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
78
78
  <HawaLoading
79
79
  design="dots-pulse"
80
80
  color={loadingColor} // Apply the computed color here
81
- size="button"
81
+ size={size === "sm" ? "xs" : "normal"}
82
82
  />
83
83
  ) : (
84
84
  children
@@ -0,0 +1,220 @@
1
+ import React, { FC, useState } from "react"
2
+ import { Button } from "./Button"
3
+ import { Textarea } from "./Textarea"
4
+ import { cn } from "../util"
5
+ import { Popover } from "./Popover"
6
+
7
+ type ComponentTypes = {
8
+ handleSubmit: ({}) => void
9
+ showSuccess?: boolean
10
+ }
11
+ export const FeedbackByEmoji: FC<ComponentTypes> = (props) => {
12
+ const [selectedEmoji, setSelectedEmoji] = useState(null)
13
+ const [loadingSubmit, setLoadingSubmit] = useState(false)
14
+ const [feedbackText, setFeedbackText] = useState("")
15
+ const [helperText, setHelperText] = useState(false)
16
+
17
+ let emojis = [
18
+ { icon: <VeryGoodEmoji />, value: "very-good" },
19
+ { icon: <GoodEmoji />, value: "good" },
20
+ { icon: <BadEmoji />, value: "bad" },
21
+ { icon: <VeryBadEmoji />, value: "very-bad" },
22
+ ]
23
+
24
+ const onFeedbackSubmit = async () => {
25
+ console.log("submitting")
26
+ if (feedbackText) {
27
+ setLoadingSubmit(true)
28
+ try {
29
+ await props.handleSubmit({
30
+ choice: selectedEmoji,
31
+ feedback: feedbackText,
32
+ })
33
+ } catch (error) {
34
+ console.error("Error during submission:", error)
35
+ setLoadingSubmit(false)
36
+ }
37
+ await setLoadingSubmit(false)
38
+ } else {
39
+ setLoadingSubmit(false)
40
+ setHelperText(true)
41
+ }
42
+ }
43
+ return (
44
+ <div
45
+ className={cn(
46
+ "flex flex-col gap-2 rounded border p-2 transition-all",
47
+ selectedEmoji ? "h-[165px] min-w-fit" : "h-[44px] "
48
+ )}
49
+ >
50
+ <div className="flex flex-row items-center justify-center gap-2 ">
51
+ {/* <span className="whitespace-nowrap text-sm">
52
+ Was this helpful?
53
+ </span>*/}
54
+ <div className="flex flex-row justify-center gap-0.5 ">
55
+ {emojis.map((emoji, i) => (
56
+ <Button
57
+ key={i}
58
+ onClick={() => {
59
+ if (selectedEmoji === emoji.value) {
60
+ setSelectedEmoji("")
61
+ } else {
62
+ setSelectedEmoji(emoji.value)
63
+ }
64
+ }}
65
+ variant="ghost"
66
+ size="smallIcon"
67
+ className={cn(
68
+ selectedEmoji === emoji.value
69
+ ? "bg-primary/10 hover:bg-primary/10 "
70
+ : "text-[#666666]"
71
+ )}
72
+ >
73
+ {emoji.icon}
74
+ </Button>
75
+ ))}
76
+ </div>
77
+ </div>
78
+ <div
79
+ className={cn(
80
+ "flex flex-col overflow-clip transition-all duration-500 ease-in-out ",
81
+ selectedEmoji ? "visible opacity-100" : "invisible opacity-0 "
82
+ )}
83
+ >
84
+ {props.showSuccess ? (
85
+ <div className="flex h-full flex-col items-center justify-center gap-2 pt-4">
86
+ <div className="rounded bg-primary p-2 text-primary-foreground">
87
+ <svg
88
+ stroke="currentColor"
89
+ fill="currentColor"
90
+ strokeWidth="0"
91
+ viewBox="0 0 512 512"
92
+ height="0.5em"
93
+ width="0.5em"
94
+ >
95
+ <path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"></path>
96
+ </svg>
97
+ </div>
98
+ <div className="text-sm flex flex-col text-center">
99
+ <span>Your feedback has been received!</span>
100
+ <span>Thank you for your help</span>
101
+ </div>
102
+ </div>
103
+ ) : (
104
+ <>
105
+ <Popover
106
+ className="select-none p-1 text-xs "
107
+ open={helperText}
108
+ trigger={
109
+ <Textarea
110
+ className={cn("mb-2 h-full resize-none")}
111
+ placeholder="Your feedback"
112
+ onChange={(e) => {
113
+ if (e.target.value) {
114
+ setHelperText(false)
115
+ }
116
+ setFeedbackText(e.target.value)
117
+ console.log("changing to", e.target.value)
118
+ }}
119
+ />
120
+ }
121
+ >
122
+ <span>Please enter your feedback</span>{" "}
123
+ </Popover>
124
+ <Button
125
+ isLoading={loadingSubmit}
126
+ onClick={onFeedbackSubmit}
127
+ className="w-full"
128
+ size="sm"
129
+ >
130
+ Submit
131
+ </Button>
132
+ </>
133
+ )}
134
+ </div>
135
+ </div>
136
+ )
137
+ }
138
+
139
+ const VeryGoodEmoji = () => (
140
+ <svg
141
+ fill="none"
142
+ height="16"
143
+ viewBox="0 0 16 16"
144
+ width="16"
145
+ xmlns="http://www.w3.org/2000/svg"
146
+ >
147
+ <g clipPath="url(#clip0_53_166)">
148
+ <path
149
+ clipRule="evenodd"
150
+ d="M14.5 8C14.5 11.5899 11.5899 14.5 8 14.5C4.41015 14.5 1.5 11.5899 1.5 8C1.5 4.41015 4.41015 1.5 8 1.5C11.5899 1.5 14.5 4.41015 14.5 8ZM16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8ZM4.5 8.97498H3.875V9.59998C3.875 11.4747 5.81046 12.8637 7.99817 12.8637C10.1879 12.8637 12.125 11.4832 12.125 9.59998V8.97498H11.5H4.5ZM7.99817 11.6137C6.59406 11.6137 5.63842 10.9482 5.28118 10.225H10.7202C10.3641 10.9504 9.40797 11.6137 7.99817 11.6137Z"
151
+ fill="currentColor"
152
+ fillRule="evenodd"
153
+ ></path>
154
+ <path
155
+ clipRule="evenodd"
156
+ d="M6.15295 4.92093L5.375 3.5L4.59705 4.92093L3 5.21885L4.11625 6.39495L3.90717 8L5.375 7.30593L6.84283 8L6.63375 6.39495L7.75 5.21885L6.15295 4.92093ZM11.403 4.92093L10.625 3.5L9.84705 4.92093L8.25 5.21885L9.36625 6.39495L9.15717 8L10.625 7.30593L12.0928 8L11.8837 6.39495L13 5.21885L11.403 4.92093Z"
157
+ fill="#FF990A"
158
+ fillRule="evenodd"
159
+ ></path>
160
+ </g>
161
+ </svg>
162
+ )
163
+ const GoodEmoji = () => (
164
+ <svg
165
+ fill="none"
166
+ height="16"
167
+ viewBox="0 0 16 16"
168
+ width="16"
169
+ xmlns="http://www.w3.org/2000/svg"
170
+ >
171
+ <g clipPath="url(#clip0_53_167)">
172
+ <path
173
+ clipRule="evenodd"
174
+ d="M14.5 8C14.5 11.5899 11.5899 14.5 8 14.5C4.41015 14.5 1.5 11.5899 1.5 8C1.5 4.41015 4.41015 1.5 8 1.5C11.5899 1.5 14.5 4.41015 14.5 8ZM16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8ZM11.5249 10.8478L11.8727 10.3286L10.8342 9.6329L10.4863 10.1522C9.94904 10.9543 9.0363 11.4802 8.00098 11.4802C6.96759 11.4802 6.05634 10.9563 5.51863 10.1567L5.16986 9.63804L4.13259 10.3356L4.48137 10.8542C5.2414 11.9844 6.53398 12.7302 8.00098 12.7302C9.47073 12.7302 10.7654 11.9816 11.5249 10.8478ZM6.75 6.75C6.75 7.30228 6.30228 7.75 5.75 7.75C5.19772 7.75 4.75 7.30228 4.75 6.75C4.75 6.19772 5.19772 5.75 5.75 5.75C6.30228 5.75 6.75 6.19772 6.75 6.75ZM10.25 7.75C10.8023 7.75 11.25 7.30228 11.25 6.75C11.25 6.19772 10.8023 5.75 10.25 5.75C9.69771 5.75 9.25 6.19772 9.25 6.75C9.25 7.30228 9.69771 7.75 10.25 7.75Z"
175
+ fill="currentColor"
176
+ fillRule="evenodd"
177
+ ></path>
178
+ </g>
179
+ </svg>
180
+ )
181
+ const BadEmoji = () => (
182
+ <svg
183
+ fill="none"
184
+ height="16"
185
+ viewBox="0 0 16 16"
186
+ width="16"
187
+ xmlns="http://www.w3.org/2000/svg"
188
+ >
189
+ <g clipPath="url(#clip0_53_152)">
190
+ <path
191
+ clipRule="evenodd"
192
+ d="M14.5 8C14.5 11.5899 11.5899 14.5 8 14.5C4.41015 14.5 1.5 11.5899 1.5 8C1.5 4.41015 4.41015 1.5 8 1.5C11.5899 1.5 14.5 4.41015 14.5 8ZM16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8ZM5.75 7.75C6.30228 7.75 6.75 7.30228 6.75 6.75C6.75 6.19772 6.30228 5.75 5.75 5.75C5.19772 5.75 4.75 6.19772 4.75 6.75C4.75 7.30228 5.19772 7.75 5.75 7.75ZM11.25 6.75C11.25 7.30228 10.8023 7.75 10.25 7.75C9.69771 7.75 9.25 7.30228 9.25 6.75C9.25 6.19772 9.69771 5.75 10.25 5.75C10.8023 5.75 11.25 6.19772 11.25 6.75ZM11.5249 11.2622L11.8727 11.7814L10.8342 12.4771L10.4863 11.9578C9.94904 11.1557 9.0363 10.6298 8.00098 10.6298C6.96759 10.6298 6.05634 11.1537 5.51863 11.9533L5.16986 12.4719L4.13259 11.7744L4.48137 11.2558C5.2414 10.1256 6.53398 9.37982 8.00098 9.37982C9.47073 9.37982 10.7654 10.1284 11.5249 11.2622Z"
193
+ fill="currentColor"
194
+ fillRule="evenodd"
195
+ ></path>
196
+ </g>
197
+ </svg>
198
+ )
199
+ const VeryBadEmoji = () => (
200
+ <svg
201
+ fill="none"
202
+ height="16"
203
+ viewBox="0 0 16 16"
204
+ width="16"
205
+ xmlns="http://www.w3.org/2000/svg"
206
+ >
207
+ <g clipPath="url(#clip0_53_151)">
208
+ <path
209
+ d="M11.841 12.0225C12.7197 12.9324 12.7197 14.4077 11.841 15.3176C10.9623 16.2275 9.53769 16.2275 8.65901 15.3176C7.78033 14.4077 7.78033 12.9324 8.65901 12.0225L10.25 10.375L11.841 12.0225Z"
210
+ fill="#0070F3"
211
+ ></path>
212
+ <path
213
+ clipRule="evenodd"
214
+ d="M8 1.5C4.41015 1.5 1.5 4.41015 1.5 8C1.5 10.9668 3.48826 13.4711 6.20649 14.2496L5.79351 15.6916C2.44895 14.7338 0 11.6539 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8C16 9.4652 15.6054 10.8405 14.9162 12.023L13.6203 11.2677C14.1794 10.3083 14.5 9.19272 14.5 8C14.5 4.41015 11.5899 1.5 8 1.5ZM6.75 6.75C6.75 7.30228 6.30228 7.75 5.75 7.75C5.19772 7.75 4.75 7.30228 4.75 6.75C4.75 6.19772 5.19772 5.75 5.75 5.75C6.30228 5.75 6.75 6.19772 6.75 6.75ZM10.25 7.75C10.8023 7.75 11.25 7.30228 11.25 6.75C11.25 6.19772 10.8023 5.75 10.25 5.75C9.69771 5.75 9.25 6.19772 9.25 6.75C9.25 7.30228 9.69771 7.75 10.25 7.75Z"
215
+ fill="currentColor"
216
+ fillRule="evenodd"
217
+ ></path>
218
+ </g>
219
+ </svg>
220
+ )
@@ -13,7 +13,7 @@ type ComponentTypes = {
13
13
  position?: "bottom-right" | "bottom-left"
14
14
  onOptionClicked?: (option) => void
15
15
  }
16
- export const UserFeedback: FC<ComponentTypes> = ({
16
+ export const FeedbackRating: FC<ComponentTypes> = ({
17
17
  position = "bottom-right",
18
18
  ...props
19
19
  }) => {
@@ -2,7 +2,7 @@ import React, { FC } from "react"
2
2
  import clsx from "clsx"
3
3
 
4
4
  type LoadingTypes = {
5
- size?: "button" | "sm" | "normal" | "lg" | "xl"
5
+ size?: "button" | "xs" | "sm" | "normal" | "lg" | "xl"
6
6
  design?: "spinner" | "dots-bounce" | "dots-pulse" | "pulse" | "spinner-dots"
7
7
  color?: any
8
8
  }
@@ -15,6 +15,7 @@ export const HawaLoading: FC<LoadingTypes> = ({
15
15
  }) => {
16
16
  let sizeStyles = {
17
17
  button: "h-4 w-4",
18
+ xs: "h-1 w-1",
18
19
  sm: "h-6 w-6",
19
20
  normal: "h-8 w-8",
20
21
  lg: "h-14 w-14",
@@ -96,11 +96,11 @@ export const HawaTextField: FC<TextFieldTypes> = ({
96
96
  {props.iconInside}
97
97
  </div>
98
98
  )}
99
- {props.helpertext ? (
99
+ {props.helpertext && (
100
100
  <p className="mb-0 mt-0 text-xs text-red-600 dark:text-red-500">
101
101
  {props.helpertext}
102
102
  </p>
103
- ) : null}
103
+ )}
104
104
  </>
105
105
  </>
106
106
  )}
@@ -28,6 +28,7 @@ interface PopoverProps {
28
28
  children: React.ReactNode
29
29
  className?: string
30
30
  sideOffset?: number
31
+ open?: boolean
31
32
  }
32
33
 
33
34
  const Popover: React.FC<PopoverProps> = ({
@@ -37,8 +38,9 @@ const Popover: React.FC<PopoverProps> = ({
37
38
  align = "center",
38
39
  side,
39
40
  sideOffset = 4,
41
+ open,
40
42
  }) => (
41
- <PopoverPrimitive.Root>
43
+ <PopoverPrimitive.Root open={open}>
42
44
  <PopoverPrimitive.Trigger>{trigger}</PopoverPrimitive.Trigger>
43
45
  <PopoverContent
44
46
  side={side}
@@ -5,22 +5,29 @@ import { Label } from "./Label"
5
5
  export interface TextareaProps
6
6
  extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
7
7
  label?: string
8
+ helperText?: string
8
9
  }
9
10
 
10
11
  const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
11
- ({ className, label, ...props }, ref) => {
12
+ ({ className, label, helperText, ...props }, ref) => {
12
13
  return (
13
- <>
14
+ <div className="flex flex-col gap-2">
14
15
  {label && <Label htmlFor={props.id}>{label}</Label>}
15
16
  <textarea
16
17
  className={cn(
17
- "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
18
+ "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
19
+ // focus-visible:ring-offset-2
18
20
  className
19
21
  )}
20
22
  ref={ref}
21
23
  {...props}
22
24
  />
23
- </>
25
+ {helperText && (
26
+ <p className="mb-0 mt-0 text-xs text-red-600 dark:text-red-500">
27
+ {helperText}
28
+ </p>
29
+ )}
30
+ </div>
24
31
  )
25
32
  }
26
33
  )
@@ -52,7 +52,7 @@ export const UserReferralSource: FC<ComponentTypes> = ({
52
52
  return (
53
53
  <Card
54
54
  ref={popUpRef}
55
- className={clsx("fixed bottom-4 p-4 ", boxPosition[position])}
55
+ className={clsx("fixed bottom-4 p-0 ", boxPosition[position])}
56
56
  >
57
57
  <button
58
58
  type="button"
@@ -28,7 +28,8 @@ export * from "./Breadcrumb"
28
28
  export * from "./SubsectionList"
29
29
  export * from "./UsageCard"
30
30
  export * from "./InvoiceAccordion"
31
- export * from "./UserFeedback"
31
+ export * from "./FeedbackRating"
32
+ export * from "./FeedbackByEmoji"
32
33
  export * from "./ArrowCarousel"
33
34
  export * from "./FloatingComment"
34
35
  export * from "./FloatingCommentSlate"
@@ -2,6 +2,7 @@ import { BsInstagram, BsTwitter } from "react-icons/bs"
2
2
  import { FaSnapchatGhost, FaTiktok } from "react-icons/fa"
3
3
  import { Button } from "../elements"
4
4
  import { cn } from "../util"
5
+ import React from "react"
5
6
 
6
7
  type FooterTypes = {
7
8
  logoText?: string