untitledui 0.1.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.
Files changed (121) hide show
  1. package/dist/commands/add.js +339 -0
  2. package/dist/commands/init.js +436 -0
  3. package/dist/helper/download-tar-api.js +129 -0
  4. package/dist/helper/download-tar.js +81 -0
  5. package/dist/helper/find-css-file.js +19 -0
  6. package/dist/helper/formatText.js +37 -0
  7. package/dist/helper/get-components-api.js +47 -0
  8. package/dist/helper/get-components-list.js +62 -0
  9. package/dist/helper/get-components.js +19 -0
  10. package/dist/helper/get-config.js +163 -0
  11. package/dist/helper/get-package-info.js +99 -0
  12. package/dist/helper/get-pkg-manager.js +16 -0
  13. package/dist/helper/get-project.js +176 -0
  14. package/dist/helper/install-template.js +29 -0
  15. package/dist/helper/match-color-css.js +82 -0
  16. package/dist/helper/update-color-css.js +134 -0
  17. package/dist/index.js +25 -0
  18. package/dist/package.json +50 -0
  19. package/dist/res/components.json +520 -0
  20. package/dist/res/config.json +3 -0
  21. package/package.json +61 -0
  22. package/templates/default/.prettierrc +10 -0
  23. package/templates/default/README.md +36 -0
  24. package/templates/default/eslint.config.mjs +58 -0
  25. package/templates/default/next.config.ts +6 -0
  26. package/templates/default/package.json +57 -0
  27. package/templates/default/postcss.config.js +5 -0
  28. package/templates/default/public/favicon.ico +0 -0
  29. package/templates/default/public/marketing/smiling-girl.png +0 -0
  30. package/templates/default/public/marketing/spirals.webp +0 -0
  31. package/templates/default/src/app/home-screen.tsx +109 -0
  32. package/templates/default/src/app/layout.tsx +42 -0
  33. package/templates/default/src/app/not-found.tsx +40 -0
  34. package/templates/default/src/app/page.tsx +3 -0
  35. package/templates/default/src/components/foundations/dot-icon.tsx +27 -0
  36. package/templates/default/src/components/foundations/featured-icon/featured-icons.tsx +153 -0
  37. package/templates/default/src/components/foundations/logo/UntitledLogo.tsx +63 -0
  38. package/templates/default/src/components/foundations/logo/UntitledLogoMinimal.tsx +164 -0
  39. package/templates/default/src/components/foundations/payment-icons/amex-icon.tsx +19 -0
  40. package/templates/default/src/components/foundations/payment-icons/apple-pay-icon.tsx +27 -0
  41. package/templates/default/src/components/foundations/payment-icons/discover-icon.tsx +34 -0
  42. package/templates/default/src/components/foundations/payment-icons/index.tsx +10 -0
  43. package/templates/default/src/components/foundations/payment-icons/mastercard-icon.tsx +39 -0
  44. package/templates/default/src/components/foundations/payment-icons/paypal-icon.tsx +45 -0
  45. package/templates/default/src/components/foundations/payment-icons/stripe-icon.tsx +27 -0
  46. package/templates/default/src/components/foundations/payment-icons/union-pay-icon.tsx +37 -0
  47. package/templates/default/src/components/foundations/payment-icons/visa-icon.tsx +27 -0
  48. package/templates/default/src/components/marketing/header-navigation/base-components/nav-menu-item.tsx +41 -0
  49. package/templates/default/src/components/marketing/header-navigation/components/header.tsx +245 -0
  50. package/templates/default/src/components/marketing/header-navigation/dropdown-header-navigation.tsx +53 -0
  51. package/templates/default/src/components/shared/avatar/avatar-label-group.tsx +32 -0
  52. package/templates/default/src/components/shared/avatar/avatar-profile-photo.tsx +84 -0
  53. package/templates/default/src/components/shared/avatar/avatar.tsx +131 -0
  54. package/templates/default/src/components/shared/avatar/base-components/avatar-add-button.tsx +33 -0
  55. package/templates/default/src/components/shared/avatar/base-components/avatar-company-icon.tsx +26 -0
  56. package/templates/default/src/components/shared/avatar/base-components/avatar-online-indicator.tsx +31 -0
  57. package/templates/default/src/components/shared/avatar/base-components/index.ts +4 -0
  58. package/templates/default/src/components/shared/avatar/base-components/verified-tick.tsx +34 -0
  59. package/templates/default/src/components/shared/avatar/utils.ts +12 -0
  60. package/templates/default/src/components/shared/badges/badge-groups.tsx +176 -0
  61. package/templates/default/src/components/shared/badges/badge-types.ts +264 -0
  62. package/templates/default/src/components/shared/badges/badges.tsx +479 -0
  63. package/templates/default/src/components/shared/button-group/button-group.tsx +97 -0
  64. package/templates/default/src/components/shared/buttons/app-store-buttons-outline.tsx +454 -0
  65. package/templates/default/src/components/shared/buttons/app-store-buttons.tsx +806 -0
  66. package/templates/default/src/components/shared/buttons/button-utility.tsx +87 -0
  67. package/templates/default/src/components/shared/buttons/button.tsx +284 -0
  68. package/templates/default/src/components/shared/buttons/close-button.tsx +39 -0
  69. package/templates/default/src/components/shared/buttons/social-button.tsx +135 -0
  70. package/templates/default/src/components/shared/buttons/social-logos.tsx +115 -0
  71. package/templates/default/src/components/shared/checkbox/checkbox.tsx +120 -0
  72. package/templates/default/src/components/shared/dropdown/dropdown.tsx +138 -0
  73. package/templates/default/src/components/shared/input-dropdown/combobox.tsx +161 -0
  74. package/templates/default/src/components/shared/input-dropdown/dropdown-item.tsx +98 -0
  75. package/templates/default/src/components/shared/input-dropdown/input-dropdown.tsx +172 -0
  76. package/templates/default/src/components/shared/input-dropdown/multi-select.tsx +373 -0
  77. package/templates/default/src/components/shared/input-dropdown/popover.tsx +36 -0
  78. package/templates/default/src/components/shared/input-dropdown/select.tsx +63 -0
  79. package/templates/default/src/components/shared/inputs/file-upload-trigger.tsx +74 -0
  80. package/templates/default/src/components/shared/inputs/form/form.tsx +10 -0
  81. package/templates/default/src/components/shared/inputs/hint-text.tsx +34 -0
  82. package/templates/default/src/components/shared/inputs/input/index.tsx +189 -0
  83. package/templates/default/src/components/shared/inputs/input/input-payment.tsx +134 -0
  84. package/templates/default/src/components/shared/inputs/input/input-with-button.tsx +69 -0
  85. package/templates/default/src/components/shared/inputs/input/input-with-dropdown.tsx +178 -0
  86. package/templates/default/src/components/shared/inputs/input/input-with-prefix.tsx +74 -0
  87. package/templates/default/src/components/shared/inputs/label.tsx +46 -0
  88. package/templates/default/src/components/shared/inputs/textarea/textarea.tsx +82 -0
  89. package/templates/default/src/components/shared/progress-indicators/progress-circles.tsx +176 -0
  90. package/templates/default/src/components/shared/progress-indicators/progress-indicators.tsx +86 -0
  91. package/templates/default/src/components/shared/progress-indicators/simple-circle.tsx +29 -0
  92. package/templates/default/src/components/shared/radio-buttons/radio-buttons.tsx +125 -0
  93. package/templates/default/src/components/shared/radio-groups/radio-group-avatar.tsx +62 -0
  94. package/templates/default/src/components/shared/radio-groups/radio-group-checkbox.tsx +72 -0
  95. package/templates/default/src/components/shared/radio-groups/radio-group-icon-card.tsx +95 -0
  96. package/templates/default/src/components/shared/radio-groups/radio-group-icon-simple.tsx +70 -0
  97. package/templates/default/src/components/shared/radio-groups/radio-group-payment-icon.tsx +71 -0
  98. package/templates/default/src/components/shared/radio-groups/radio-group-radio-button.tsx +76 -0
  99. package/templates/default/src/components/shared/radio-groups/radio-groups.tsx +8 -0
  100. package/templates/default/src/components/shared/slider/slider.tsx +76 -0
  101. package/templates/default/src/components/shared/tags/base-components/tag-checkbox.tsx +47 -0
  102. package/templates/default/src/components/shared/tags/base-components/tag-close-x.tsx +34 -0
  103. package/templates/default/src/components/shared/tags/tags.tsx +162 -0
  104. package/templates/default/src/components/shared/toggle/toggle.tsx +140 -0
  105. package/templates/default/src/components/shared/tooltips/tooltips.tsx +140 -0
  106. package/templates/default/src/components/utils/index.ts +48 -0
  107. package/templates/default/src/components/utils/isDeepEqual.ts +31 -0
  108. package/templates/default/src/components/utils/isReactComponent.ts +22 -0
  109. package/templates/default/src/components/utils/mergeRefs.ts +19 -0
  110. package/templates/default/src/components/utils/useBreakpoint.ts +36 -0
  111. package/templates/default/src/components/utils/uuid.ts +9 -0
  112. package/templates/default/src/fonts/GeistMonoVF.woff +0 -0
  113. package/templates/default/src/fonts/GeistVF.woff +0 -0
  114. package/templates/default/src/hooks/use-resize-observer.tsx +55 -0
  115. package/templates/default/src/providers/theme.tsx +11 -0
  116. package/templates/default/src/styles/colors.css +805 -0
  117. package/templates/default/src/styles/globals.css +86 -0
  118. package/templates/default/src/styles/text-styles.css +177 -0
  119. package/templates/default/src/styles/theme.css +1310 -0
  120. package/templates/default/src/styles/typography.css +428 -0
  121. package/templates/default/tsconfig.json +27 -0
@@ -0,0 +1,87 @@
1
+ "use client";
2
+
3
+ import type { DetailedHTMLProps, FC, HTMLAttributes, ReactNode } from "react";
4
+ import React, { isValidElement } from "react";
5
+ import type { ButtonProps as AriaButtonProps } from "react-aria-components";
6
+ import { Button as AriaButton } from "react-aria-components";
7
+ import { cx, sortCx } from "@/components/utils";
8
+ import { isReactComponent } from "@/components/utils/isReactComponent";
9
+ import { Tooltip } from "../tooltips/tooltips";
10
+
11
+ export const styles = sortCx({
12
+ common: {
13
+ root: "group relative inline-flex h-max cursor-pointer items-center justify-center transition duration-100 ease-linear focus:outline-2 focus:outline-offset-2 focus:outline-brand disabled:cursor-not-allowed disabled:text-fg-disabled_subtle",
14
+ icon: "pointer-events-none shrink-0 text-current transition-inherit-all",
15
+ },
16
+
17
+ sizes: {
18
+ xs: {
19
+ root: "rounded-md p-1.5",
20
+ icon: "size-4",
21
+ },
22
+ sm: {
23
+ root: "rounded-md p-1.5",
24
+ icon: "size-5",
25
+ },
26
+ },
27
+
28
+ colors: {
29
+ secondary: {
30
+ root: "bg-primary text-fg-quaternary shadow-xs-skeumorphic ring-1 ring-border-primary ring-inset hover:bg-primary_hover hover:text-fg-quaternary_hover disabled:shadow-xs disabled:ring-border-disabled_subtle",
31
+ },
32
+ tertiary: {
33
+ root: "text-fg-quaternary hover:bg-primary_hover hover:text-fg-quaternary_hover",
34
+ },
35
+ },
36
+ });
37
+
38
+ export interface ButtonUtilityProps extends DetailedHTMLProps<Omit<HTMLAttributes<HTMLButtonElement>, "color" | "slot">, HTMLButtonElement> {
39
+ disabled?: boolean;
40
+ color?: keyof typeof styles.colors;
41
+ size?: keyof typeof styles.sizes;
42
+ icon?: FC<{ className?: string }> | ReactNode;
43
+ slot?: AriaButtonProps["slot"];
44
+ tooltip?: string;
45
+ }
46
+
47
+ const ButtonUtility = ({ size = "sm", color = "secondary", className, icon: Icon, children, onClick, disabled, tooltip, ...rest }: ButtonUtilityProps) => {
48
+ const Component = "href" in rest ? "a" : AriaButton;
49
+
50
+ const content = (
51
+ <Component
52
+ isDisabled={disabled}
53
+ type="button"
54
+ // Remove `any` type assertion after splitting
55
+ // Component into Link and Button.
56
+ {...(rest as any)}
57
+ onPress={(event) => {
58
+ // @ts-expect-error FIX ME
59
+ rest.onPress?.(event);
60
+ onClick?.(event as any);
61
+ }}
62
+ className={cx(
63
+ styles.common.root,
64
+ styles.sizes[size].root,
65
+ styles.colors[color].root,
66
+
67
+ color === "tertiary" && size === "xs" && "p-2",
68
+ className,
69
+ )}
70
+ >
71
+ {isReactComponent(Icon) && <Icon data-icon="leading" className={cx(styles.common.icon, styles.sizes[size].icon)} />}
72
+ {isValidElement(Icon) && Icon}
73
+ </Component>
74
+ );
75
+
76
+ if (tooltip) {
77
+ return (
78
+ <Tooltip title={tooltip} offset={size === "xs" ? 4 : 6}>
79
+ {content}
80
+ </Tooltip>
81
+ );
82
+ }
83
+
84
+ return content;
85
+ };
86
+
87
+ export default ButtonUtility;
@@ -0,0 +1,284 @@
1
+ "use client";
2
+
3
+ import type { AnchorHTMLAttributes, ButtonHTMLAttributes, DetailedHTMLProps, FC, ReactNode } from "react";
4
+ import React, { isValidElement } from "react";
5
+ import Link from "next/link";
6
+ import type { ButtonProps as AriaButtonProps, PressEvent } from "react-aria-components";
7
+ import { Button as AriaButton } from "react-aria-components";
8
+ import { cx, sortCx } from "@/components/utils";
9
+ import { isReactComponent } from "@/components/utils/isReactComponent";
10
+
11
+ export const styles = sortCx({
12
+ common: {
13
+ root: [
14
+ "group relative inline-flex h-max cursor-pointer items-center justify-center whitespace-nowrap outline-brand transition duration-100 ease-linear before:absolute focus:outline-2 focus:outline-offset-2",
15
+ // Disabled styles
16
+ "disabled:cursor-not-allowed disabled:text-fg-disabled",
17
+ // Icon styles
18
+ "disabled:*:data-icon:text-fg-disabled_subtle",
19
+ ].join(" "),
20
+ icon: "pointer-events-none shrink-0 transition-inherit-all",
21
+ },
22
+
23
+ sizes: {
24
+ sm: {
25
+ root: "gap-1 rounded-lg px-3 py-2 tt-sm-semi before:rounded-[7px] data-icon-only:p-2",
26
+ linkRoot: "gap-1",
27
+ icon: "size-5",
28
+ },
29
+ md: {
30
+ root: "gap-1 rounded-lg px-3.5 py-2.5 tt-sm-semi before:rounded-[7px] data-icon-only:p-2.5",
31
+ linkRoot: "gap-1",
32
+ icon: "size-5",
33
+ },
34
+ lg: {
35
+ root: "gap-1.5 rounded-lg px-4 py-2.5 tt-md-semi before:rounded-[7px] data-icon-only:p-3",
36
+ linkRoot: "gap-1.5",
37
+ icon: "size-5",
38
+ },
39
+ xl: {
40
+ root: "gap-1.5 rounded-lg px-4.5 py-3 tt-md-semi before:rounded-[7px] data-icon-only:p-3.5",
41
+ linkRoot: "gap-1.5",
42
+ icon: "size-5",
43
+ },
44
+ "2xl": {
45
+ root: "gap-2 rounded-[10px] px-5.5 py-4 tt-lg-semi before:rounded-[9px] data-icon-only:p-4",
46
+ linkRoot: "gap-2",
47
+ icon: "size-6",
48
+ },
49
+ },
50
+
51
+ colors: {
52
+ primary: {
53
+ root: [
54
+ "bg-brand-solid text-white shadow-xs-skeumorphic ring-1 ring-transparent ring-inset hover:bg-brand-solid_hover data-loading:bg-brand-solid_hover",
55
+ // Inner border gradient
56
+ "before:absolute before:inset-px before:border before:border-white/12 before:mask-image-b",
57
+ // Disabled styles
58
+ "disabled:bg-disabled disabled:shadow-xs disabled:ring-border-disabled_subtle",
59
+ // Icon styles
60
+ "*:data-icon:text-button-primary-icon hover:*:data-icon:text-button-primary-icon_hover",
61
+ ].join(" "),
62
+ },
63
+ secondary: {
64
+ root: [
65
+ "bg-primary text-secondary shadow-xs-skeumorphic ring-1 ring-border-primary ring-inset hover:bg-primary_hover hover:text-secondary_hover data-loading:bg-primary_hover",
66
+ // Disabled styles
67
+ "disabled:shadow-xs disabled:ring-border-disabled_subtle",
68
+ // Icon styles
69
+ "*:data-icon:text-fg-quaternary hover:*:data-icon:text-fg-quaternary_hover",
70
+ ].join(" "),
71
+ },
72
+ tertiary: {
73
+ root: [
74
+ "text-tertiary hover:bg-primary_hover hover:text-tertiary_hover data-loading:bg-primary_hover",
75
+ // Icon styles
76
+ "*:data-icon:text-fg-quaternary hover:*:data-icon:text-fg-quaternary_hover",
77
+ ].join(" "),
78
+ },
79
+ "link-gray": {
80
+ root: [
81
+ "justify-normal rounded-xs p-0! text-tertiary hover:text-tertiary_hover hover:underline hover:underline-offset-2",
82
+ // Icon styles
83
+ "*:data-icon:text-fg-quaternary hover:*:data-icon:text-fg-quaternary_hover",
84
+ ].join(" "),
85
+ },
86
+ "link-color": {
87
+ root: [
88
+ "justify-normal rounded-xs p-0! text-brand-secondary hover:text-brand-secondary_hover hover:underline hover:underline-offset-2",
89
+ // Icon styles
90
+ "*:data-icon:text-fg-brand-secondary_alt hover:*:data-icon:text-fg-brand-secondary_hover",
91
+ ].join(" "),
92
+ },
93
+ "primary-destructive": {
94
+ root: [
95
+ "bg-error-solid text-white shadow-xs-skeumorphic ring-1 ring-transparent outline-error ring-inset",
96
+ // Inner border gradient
97
+ "before:absolute before:inset-px before:border before:border-white/12 before:mask-image-b",
98
+ // Disabled styles
99
+ "disabled:bg-disabled disabled:shadow-xs disabled:ring-border-disabled_subtle",
100
+ // Icon styles
101
+ "*:data-icon:text-button-destructive-primary-icon hover:*:data-icon:text-button-destructive-primary-icon_hover",
102
+ ].join(" "),
103
+ },
104
+ "secondary-destructive": {
105
+ root: [
106
+ "bg-primary text-error-primary shadow-xs-skeumorphic ring-1 ring-border-error_subtle outline-error ring-inset hover:bg-error-primary hover:text-error-primary_hover data-loading:bg-error-primary",
107
+ // Disabled styles
108
+ "disabled:bg-primary disabled:shadow-xs disabled:ring-border-disabled_subtle",
109
+ // Icon styles
110
+ "*:data-icon:text-fg-error-secondary hover:*:data-icon:text-fg-error-primary",
111
+ ].join(" "),
112
+ },
113
+ "tertiary-destructive": {
114
+ root: [
115
+ "text-error-primary outline-error hover:bg-error-primary hover:text-error-primary_hover data-loading:bg-error-primary",
116
+ // Icon styles
117
+ "*:data-icon:text-fg-error-secondary hover:*:data-icon:text-fg-error-primary",
118
+ ].join(" "),
119
+ },
120
+ "link-destructive": {
121
+ root: [
122
+ "justify-normal rounded-xs p-0! text-error-primary outline-error hover:text-error-primary_hover hover:underline hover:underline-offset-2",
123
+ // Icon styles
124
+ "*:data-icon:text-fg-error-secondary hover:*:data-icon:text-fg-error-primary",
125
+ ].join(" "),
126
+ },
127
+ },
128
+ });
129
+
130
+ /**
131
+ * Common props shared between button and anchor variants
132
+ */
133
+ export interface CommonProps {
134
+ /** Whether the link should open in a new tab */
135
+ isExternal?: boolean;
136
+ /** Disables the button and shows a disabled state */
137
+ isDisabled?: boolean;
138
+ /** Shows a loading spinner and disables the button */
139
+ isLoading?: boolean;
140
+ /** The size variant of the button */
141
+ size?: keyof typeof styles.sizes;
142
+ /** The color variant of the button */
143
+ color?: keyof typeof styles.colors;
144
+ /** Icon component or element to show before the text */
145
+ iconLeading?: FC<{ className?: string }> | ReactNode;
146
+ /** Icon component or element to show after the text */
147
+ iconTrailing?: FC<{ className?: string }> | ReactNode;
148
+ /** Removes horizontal padding from the text content */
149
+ noTextPadding?: boolean;
150
+ /** When true, keeps the text visible during loading state */
151
+ showTextWhileLoading?: boolean;
152
+ }
153
+
154
+ /**
155
+ * Props for the button variant (non-link)
156
+ */
157
+ export interface ButtonProps extends CommonProps, DetailedHTMLProps<Omit<ButtonHTMLAttributes<HTMLButtonElement>, "color" | "slot">, HTMLButtonElement> {
158
+ /** Slot name for react-aria component */
159
+ slot?: AriaButtonProps["slot"];
160
+ }
161
+
162
+ /**
163
+ * Props for the link variant (anchor tag)
164
+ */
165
+ interface LinkProps extends CommonProps, DetailedHTMLProps<Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "color">, HTMLAnchorElement> {}
166
+
167
+ /** Union type of button and link props */
168
+ export type Props = ButtonProps | LinkProps;
169
+
170
+ const Button = ({
171
+ size = "sm",
172
+ color = "primary",
173
+ className,
174
+ noTextPadding,
175
+ iconLeading: IconLeading,
176
+ iconTrailing: IconTrailing,
177
+ children,
178
+ onClick,
179
+ isDisabled: disabled,
180
+ isExternal: external,
181
+ isLoading: loading,
182
+ showTextWhileLoading,
183
+ ...rest
184
+ }: Props) => {
185
+ const href = "href" in rest ? rest.href : undefined;
186
+ // Feel free to replace `a` with `Link`
187
+ const Component = href ? (external ? "a" : Link) : AriaButton;
188
+
189
+ const isIcon = (IconLeading || IconTrailing) && !children;
190
+ const isLinkType = ["link-gray", "link-color", "link-destructive"].includes(color);
191
+
192
+ noTextPadding = isLinkType || noTextPadding;
193
+
194
+ let props = {};
195
+
196
+ if (href) {
197
+ props = {
198
+ onClick,
199
+
200
+ href: disabled ? undefined : href,
201
+ target: external ? "_blank" : undefined,
202
+ rel: external ? "noopener noreferrer" : undefined,
203
+
204
+ // Since anchor elements do not support the `disabled` attirbute and state,
205
+ // we need to spefiify `data-rac` and `data-disabled` in order to be able
206
+ // to use the `disabled:` selector in classes.
207
+ ...(disabled ? { "data-rac": true, "data-disabled": true } : {}),
208
+ };
209
+ } else {
210
+ props = {
211
+ type: rest.type || "button",
212
+ isDisabled: disabled,
213
+ onPress: (event: PressEvent) => {
214
+ // @ts-expect-error FIX ME
215
+ rest.onPress?.(event);
216
+ onClick?.(event as any);
217
+ },
218
+ };
219
+ }
220
+
221
+ return (
222
+ <Component
223
+ data-loading={loading ? true : undefined}
224
+ data-icon-only={isIcon ? true : undefined}
225
+ // Remove `any` type assertion after splitting
226
+ // Component into Link and Button.
227
+ {...(rest as any)}
228
+ {...props}
229
+ className={cx(
230
+ styles.common.root,
231
+ styles.sizes[size].root,
232
+ styles.colors[color].root,
233
+ isLinkType && styles.sizes[size].linkRoot,
234
+ (loading || (href && (disabled || loading))) && "pointer-events-none",
235
+ // If in `loading` state, hide everything except the loading icon (and text if `showTextWhileLoading` is true).
236
+ loading && (showTextWhileLoading ? "[&>*:not([data-icon=loading]):not([data-text])]:hidden" : "[&>*:not([data-icon=loading])]:invisible"),
237
+ className,
238
+ )}
239
+ >
240
+ {/* Leading icon */}
241
+ {isValidElement(IconLeading) && IconLeading}
242
+ {isReactComponent(IconLeading) && <IconLeading data-icon="leading" className={cx(styles.common.icon, styles.sizes[size].icon)} />}
243
+
244
+ {loading && (
245
+ <svg
246
+ data-icon="loading"
247
+ viewBox="0 0 20 20"
248
+ fill="none"
249
+ className={cx(
250
+ styles.common.icon,
251
+ styles.sizes[size].icon,
252
+ !showTextWhileLoading && "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2",
253
+ )}
254
+ >
255
+ {/* Background circle */}
256
+ <circle className="stroke-current opacity-30" cx="10" cy="10" r="8" fill="none" strokeWidth="2" />
257
+ {/* Spinning circle */}
258
+ <circle
259
+ className="origin-center animate-spin stroke-current"
260
+ cx="10"
261
+ cy="10"
262
+ r="8"
263
+ fill="none"
264
+ strokeWidth="2"
265
+ strokeDasharray="12.5 50"
266
+ strokeLinecap="round"
267
+ />
268
+ </svg>
269
+ )}
270
+
271
+ {children && (
272
+ <span data-text className={cx(!noTextPadding && "px-0.5")}>
273
+ {children}
274
+ </span>
275
+ )}
276
+
277
+ {/* Trailing icon */}
278
+ {isValidElement(IconTrailing) && IconTrailing}
279
+ {isReactComponent(IconTrailing) && <IconTrailing data-icon="trailing" className={cx(styles.common.icon, styles.sizes[size].icon)} />}
280
+ </Component>
281
+ );
282
+ };
283
+
284
+ export default Button;
@@ -0,0 +1,39 @@
1
+ "use client";
2
+
3
+ import type { HTMLAttributes } from "react";
4
+ import { X as CloseIcon } from "@untitledui/icons";
5
+ import { cx } from "@/components/utils";
6
+
7
+ const sizes = {
8
+ sm: { root: "size-9", icon: "size-5" },
9
+ md: { root: "size-10", icon: "size-5" },
10
+ lg: { root: "size-11", icon: "size-6" },
11
+ };
12
+
13
+ const themes = {
14
+ light: "text-fg-quaternary hover:bg-primary_hover hover:text-fg-quaternary_hover focus:outline-2 focus:outline-offset-2 outline-focus-ring",
15
+ dark: "text-fg-white/70 hover:text-fg-white hover:bg-white/20 focus:outline-2 focus:outline-offset-2 outline-focus-ring",
16
+ };
17
+
18
+ interface CloseButtonProps extends HTMLAttributes<HTMLButtonElement> {
19
+ theme?: "light" | "dark";
20
+ size?: "sm" | "md" | "lg";
21
+ label?: string;
22
+ }
23
+
24
+ export const CloseButton = ({ label, onClick, className, size = "sm", theme = "light" }: CloseButtonProps) => {
25
+ return (
26
+ <button
27
+ onClick={onClick}
28
+ aria-label={label || "Close"}
29
+ className={cx(
30
+ "flex cursor-pointer items-center justify-center rounded-lg p-2 transition duration-100 ease-linear focus:outline-hidden",
31
+ sizes[size].root,
32
+ themes[theme],
33
+ className,
34
+ )}
35
+ >
36
+ <CloseIcon aria-hidden="true" className={cx("shrink-0 transition-inherit-all", sizes[size].icon)} />
37
+ </button>
38
+ );
39
+ };
@@ -0,0 +1,135 @@
1
+ "use client";
2
+
3
+ import type { AnchorHTMLAttributes, ButtonHTMLAttributes, DetailedHTMLProps } from "react";
4
+ import React from "react";
5
+ import type { ButtonProps as AriaButtonProps } from "react-aria-components";
6
+ import { Button as AriaButton } from "react-aria-components";
7
+ import { cx, sortCx } from "@/components/utils";
8
+ import { AppleLogo, DribbleLogo, FacebookLogo, FigmaLogo, FigmaLogoOutlined, GoogleLogo, TwitterLogo } from "./social-logos";
9
+
10
+ export const styles = sortCx({
11
+ common: {
12
+ root: "group relative inline-flex h-max cursor-pointer items-center justify-center font-semibold whitespace-nowrap outline-focus-ring transition duration-100 ease-linear before:absolute focus:outline-2 focus:outline-offset-2 disabled:cursor-not-allowed disabled:stroke-fg-disabled disabled:text-fg-disabled disabled:*:text-fg-disabled",
13
+ icon: "pointer-events-none shrink-0 transition-inherit-all",
14
+ },
15
+
16
+ sizes: {
17
+ sm: {
18
+ root: "gap-2 rounded-lg px-3 py-2 text-sm leading-sm before:rounded-[7px] data-icon-only:p-2",
19
+ },
20
+ md: {
21
+ root: "gap-2.5 rounded-lg px-3.5 py-2.5 text-sm leading-sm before:rounded-[7px] data-icon-only:p-2.5",
22
+ },
23
+ lg: {
24
+ root: "gap-3 rounded-lg px-4 py-2.5 text-md leading-md before:rounded-[7px] data-icon-only:p-2.5",
25
+ },
26
+ xl: {
27
+ root: "gap-3.5 rounded-lg px-4.5 py-3 text-md leading-md before:rounded-[7px] data-icon-only:p-3.5",
28
+ },
29
+ "2xl": {
30
+ root: "gap-4 rounded-[10px] px-5.5 py-4 text-lg leading-lg before:rounded-[9px] data-icon-only:p-4",
31
+ },
32
+ },
33
+
34
+ colors: {
35
+ gray: {
36
+ root: "bg-primary text-secondary shadow-xs-skeumorphic ring-1 ring-border-primary ring-inset hover:bg-primary_hover hover:text-secondary_hover",
37
+ icon: "text-fg-quaternary group-hover:text-fg-quaternary_hover",
38
+ },
39
+ black: {
40
+ root: "bg-black text-white shadow-xs-skeumorphic ring-1 ring-transparent ring-inset before:absolute before:inset-px before:border before:border-white/12 before:mask-image-b",
41
+ icon: "",
42
+ },
43
+
44
+ facebook: {
45
+ root: "bg-[#1877F2] text-white shadow-xs-skeumorphic ring-1 ring-transparent ring-inset before:absolute before:inset-px before:border before:border-white/12 before:mask-image-b hover:bg-[#0C63D4]",
46
+ icon: "",
47
+ },
48
+
49
+ dribble: {
50
+ root: "bg-[#EA4C89] text-white shadow-xs-skeumorphic ring-1 ring-transparent ring-inset before:absolute before:inset-px before:border before:border-white/12 before:mask-image-b hover:bg-[#E62872]",
51
+ icon: "",
52
+ },
53
+ },
54
+ });
55
+
56
+ interface CommonProps {
57
+ social: "google" | "facebook" | "apple" | "twitter" | "figma" | "dribble";
58
+ disabled?: boolean;
59
+ theme?: "brand" | "color" | "gray";
60
+ size?: keyof typeof styles.sizes;
61
+ }
62
+
63
+ interface ButtonProps extends CommonProps, DetailedHTMLProps<Omit<ButtonHTMLAttributes<HTMLButtonElement>, "color" | "slot">, HTMLButtonElement> {
64
+ slot?: AriaButtonProps["slot"];
65
+ }
66
+
67
+ interface LinkProps extends CommonProps, DetailedHTMLProps<Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "color">, HTMLAnchorElement> {}
68
+
69
+ export type SocialButtonProps = ButtonProps | LinkProps;
70
+
71
+ const SocialButton = ({ size = "lg", theme = "brand", social, className, children, onClick, disabled, ...rest }: SocialButtonProps) => {
72
+ const Component = "href" in rest ? "a" : AriaButton;
73
+
74
+ const isIconOnly = !children;
75
+
76
+ const socialToColor = {
77
+ google: "gray",
78
+ facebook: "facebook",
79
+ apple: "black",
80
+ twitter: "black",
81
+ figma: "black",
82
+ dribble: "dribble",
83
+ } as const;
84
+
85
+ const colorStyles = theme === "brand" ? styles.colors[socialToColor[social]] : styles.colors.gray;
86
+
87
+ const logos = {
88
+ google: GoogleLogo,
89
+ facebook: FacebookLogo,
90
+ apple: AppleLogo,
91
+ twitter: TwitterLogo,
92
+ figma: theme === "gray" ? FigmaLogoOutlined : FigmaLogo,
93
+ dribble: DribbleLogo,
94
+ };
95
+
96
+ const Logo = logos[social];
97
+
98
+ return (
99
+ <Component
100
+ isDisabled={disabled}
101
+ type="button"
102
+ // Remove `any` type assertion after splitting
103
+ // Component into Link and Button.
104
+ {...(rest as any)}
105
+ onPress={(event) => {
106
+ // @ts-expect-error FIX ME
107
+ rest.onPress?.(event);
108
+ onClick?.(event as any);
109
+ }}
110
+ data-icon-only={isIconOnly ? true : undefined}
111
+ className={cx(styles.common.root, styles.sizes[size].root, colorStyles.root, className)}
112
+ >
113
+ <Logo
114
+ className={cx(
115
+ styles.common.icon,
116
+ theme === "gray"
117
+ ? colorStyles.icon
118
+ : theme === "brand" && (social === "facebook" || social === "apple" || social === "twitter")
119
+ ? "text-white"
120
+ : theme === "color" && (social === "apple" || social === "twitter")
121
+ ? "text-alpha-black"
122
+ : "",
123
+ )}
124
+ colorful={
125
+ (theme === "brand" && (social === "google" || social === "figma")) ||
126
+ (theme === "color" && (social === "google" || social === "facebook" || social === "figma" || social === "dribble"))
127
+ }
128
+ />
129
+
130
+ {children}
131
+ </Component>
132
+ );
133
+ };
134
+
135
+ export default SocialButton;
@@ -0,0 +1,115 @@
1
+ "use client";
2
+
3
+ import type { SVGProps } from "react";
4
+
5
+ export const GoogleLogo = ({ colorful = true, ...props }: SVGProps<SVGSVGElement> & { colorful?: boolean }) => {
6
+ return (
7
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" {...props}>
8
+ <path
9
+ d="M23.766 12.2764C23.766 11.4607 23.6999 10.6406 23.5588 9.83807H12.24V14.4591H18.7217C18.4528 15.9494 17.5885 17.2678 16.323 18.1056V21.1039H20.19C22.4608 19.0139 23.766 15.9274 23.766 12.2764Z"
10
+ fill={colorful ? "#4285F4" : "currentColor"}
11
+ />
12
+ <path
13
+ d="M12.24 24.0008C15.4764 24.0008 18.2058 22.9382 20.1944 21.1039L16.3274 18.1055C15.2516 18.8375 13.8626 19.252 12.2444 19.252C9.11376 19.252 6.45934 17.1399 5.50693 14.3003H1.51648V17.3912C3.55359 21.4434 7.70278 24.0008 12.24 24.0008Z"
14
+ fill={colorful ? "#34A853" : "currentColor"}
15
+ />
16
+ <path
17
+ d="M5.50253 14.3003C4.99987 12.8099 4.99987 11.1961 5.50253 9.70575V6.61481H1.51649C-0.18551 10.0056 -0.18551 14.0004 1.51649 17.3912L5.50253 14.3003Z"
18
+ fill={colorful ? "#FBBC04" : "currentColor"}
19
+ />
20
+ <path
21
+ d="M12.24 4.74966C13.9508 4.7232 15.6043 5.36697 16.8433 6.54867L20.2694 3.12262C18.1 1.0855 15.2207 -0.034466 12.24 0.000808666C7.70277 0.000808666 3.55359 2.55822 1.51648 6.61481L5.50252 9.70575C6.45052 6.86173 9.10935 4.74966 12.24 4.74966Z"
22
+ fill={colorful ? "#EA4335" : "currentColor"}
23
+ />
24
+ </svg>
25
+ );
26
+ };
27
+
28
+ export const FigmaLogo = ({ colorful = true, ...props }: SVGProps<SVGSVGElement> & { colorful?: boolean }) => {
29
+ return (
30
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" {...props}>
31
+ <path
32
+ d="M8.00006 24.0001C10.2081 24.0001 12.0001 22.208 12.0001 20V16H8.00006C5.79205 16 4 17.792 4 20C4 22.208 5.79205 24.0001 8.00006 24.0001Z"
33
+ fill={colorful ? "#24CB71" : "currentColor"}
34
+ />
35
+ <path d="M4 12C4 9.79203 5.79205 8 8.00006 8H12.0001V16H8.00006C5.79205 16.0001 4 14.208 4 12Z" fill={colorful ? "#874FFF" : "currentColor"} />
36
+ <path
37
+ d="M4 4.00003C4 1.79203 5.79205 0 8.00006 0H12.0001V7.99997H8.00006C5.79205 7.99997 4 6.20803 4 4.00003Z"
38
+ fill={colorful ? "#FF3737" : "currentColor"}
39
+ />
40
+ <path
41
+ d="M12 0H16.0001C18.2081 0 20.0001 1.79203 20.0001 4.00003C20.0001 6.20803 18.2081 7.99997 16.0001 7.99997H12V0Z"
42
+ fill={colorful ? "#FF7237" : "currentColor"}
43
+ />
44
+ <path
45
+ d="M20.0001 12C20.0001 14.208 18.2081 16.0001 16.0001 16.0001C13.792 16.0001 12 14.208 12 12C12 9.79203 13.792 8 16.0001 8C18.2081 8 20.0001 9.79203 20.0001 12Z"
46
+ fill={colorful ? "#00B6FF" : "currentColor"}
47
+ />
48
+ </svg>
49
+ );
50
+ };
51
+
52
+ export const FigmaLogoOutlined = (props: SVGProps<SVGSVGElement>) => {
53
+ return (
54
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" {...props}>
55
+ <path
56
+ fillRule="evenodd"
57
+ clipRule="evenodd"
58
+ d="M8.25 2C7.51349 2 6.81155 2.28629 6.29747 2.78895C5.78414 3.29087 5.5 3.96677 5.5 4.66667C5.5 5.36657 5.78414 6.04247 6.29747 6.54438C6.81155 7.04705 7.51349 7.33333 8.25 7.33333H11V2H8.25ZM13 2V7.33333H15.75C16.1142 7.33333 16.4744 7.26316 16.8097 7.12736C17.145 6.99157 17.4482 6.79311 17.7025 6.54438C17.9569 6.29571 18.1574 6.00171 18.2938 5.67977C18.4301 5.35788 18.5 5.0137 18.5 4.66667C18.5 4.31964 18.4301 3.97545 18.2938 3.65356C18.1574 3.33162 17.9569 3.03763 17.7025 2.78895C17.4482 2.54022 17.145 2.34177 16.8097 2.20598C16.4744 2.07017 16.1142 2 15.75 2H13ZM18.6884 8.33334C18.8324 8.22191 18.9702 8.10211 19.1008 7.9744C19.5429 7.54211 19.8948 7.02769 20.1353 6.45991C20.3759 5.89208 20.5 5.28266 20.5 4.66667C20.5 4.05067 20.3759 3.44126 20.1353 2.87342C19.8948 2.30564 19.5429 1.79122 19.1008 1.35894C18.6587 0.926696 18.1351 0.584984 17.5605 0.352241C16.9858 0.119512 16.3707 0 15.75 0H8.25C6.99738 0 5.79167 0.486331 4.89923 1.35894C4.00603 2.23228 3.5 3.42165 3.5 4.66667C3.5 5.91169 4.00603 7.10105 4.89923 7.9744C5.03021 8.10247 5.16794 8.22222 5.31158 8.33333C5.16794 8.44445 5.03021 8.5642 4.89923 8.69227C4.00603 9.56562 3.5 10.755 3.5 12C3.5 13.245 4.00603 14.4344 4.89923 15.3077C5.03022 15.4358 5.16795 15.5556 5.31159 15.6667C5.16795 15.7778 5.03022 15.8975 4.89923 16.0256C4.00603 16.899 3.5 18.0883 3.5 19.3333C3.5 20.5784 4.00603 21.7677 4.89923 22.6411C5.79167 23.5137 6.99738 24 8.25 24C9.5026 24 10.7083 23.5137 11.6008 22.6411C12.494 21.7677 13 20.5784 13 19.3333V15.8051C13.2922 16.0089 13.6073 16.1799 13.9395 16.3144C14.5142 16.5472 15.1293 16.6667 15.75 16.6667C16.3707 16.6667 16.9858 16.5472 17.5605 16.3144C18.1351 16.0817 18.6587 15.74 19.1008 15.3077C19.5429 14.8754 19.8948 14.361 20.1353 13.7932C20.3759 13.2254 20.5 12.616 20.5 12C20.5 11.384 20.3759 10.7746 20.1353 10.2068C19.8948 9.63898 19.5429 9.12456 19.1008 8.69227C18.9702 8.56456 18.8324 8.44476 18.6884 8.33334ZM11 14.6667V9.33333H8.25C7.51349 9.33333 6.81155 9.61962 6.29747 10.1223C5.78414 10.6242 5.5 11.3001 5.5 12C5.5 12.6999 5.78414 13.3758 6.29747 13.8777C6.81155 14.3804 7.51349 14.6667 8.25 14.6667H11ZM11 16.6667H8.25C7.51349 16.6667 6.81155 16.953 6.29747 17.4556C5.78414 17.9575 5.5 18.6334 5.5 19.3333C5.5 20.0332 5.78414 20.7091 6.29747 21.2111C6.81155 21.7137 7.51349 22 8.25 22C8.98651 22 9.6884 21.7137 10.2025 21.2111C10.7159 20.7091 11 20.0332 11 19.3333V16.6667ZM15.75 9.33333C15.3858 9.33333 15.0256 9.4035 14.6903 9.53931C14.355 9.6751 14.0518 9.87356 13.7975 10.1223C13.5431 10.371 13.3426 10.665 13.2062 10.9869C13.0699 11.3088 13 11.653 13 12C13 12.347 13.0699 12.6912 13.2062 13.0131C13.3426 13.335 13.5431 13.629 13.7975 13.8777C14.0518 14.1264 14.355 14.3249 14.6903 14.4607C15.0256 14.5965 15.3858 14.6667 15.75 14.6667C16.1142 14.6667 16.4744 14.5965 16.8097 14.4607C17.145 14.3249 17.4482 14.1264 17.7025 13.8777C17.9569 13.629 18.1574 13.335 18.2938 13.0131C18.4301 12.6912 18.5 12.347 18.5 12C18.5 11.653 18.4301 11.3088 18.2938 10.9869C18.1574 10.665 17.9569 10.371 17.7025 10.1223C17.4482 9.87356 17.145 9.6751 16.8097 9.53931C16.4744 9.4035 16.1142 9.33333 15.75 9.33333Z"
59
+ fill="currentColor"
60
+ />
61
+ </svg>
62
+ );
63
+ };
64
+
65
+ export const DribbleLogo = ({ colorful = true, ...props }: SVGProps<SVGSVGElement> & { colorful?: boolean }) => {
66
+ return (
67
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" {...props}>
68
+ <path
69
+ d="M12 23.625C18.4203 23.625 23.625 18.4203 23.625 12C23.625 5.57969 18.4203 0.375 12 0.375C5.57969 0.375 0.375 5.57969 0.375 12C0.375 18.4203 5.57969 23.625 12 23.625Z"
70
+ fill={colorful ? "#EA4C89" : "none"}
71
+ />
72
+ <path
73
+ fillRule="evenodd"
74
+ clipRule="evenodd"
75
+ d="M12 0C5.37527 0 0 5.37527 0 12C0 18.6248 5.37527 24 12 24C18.6117 24 24 18.6248 24 12C24 5.37527 18.6117 0 12 0ZM19.9262 5.53145C21.3579 7.27549 22.217 9.50107 22.243 11.9089C21.9046 11.8439 18.5206 11.154 15.1106 11.5835C15.0325 11.4143 14.9675 11.2321 14.8894 11.0499C14.6811 10.5554 14.4469 10.0477 14.2126 9.56618C17.9869 8.0304 19.705 5.81779 19.9262 5.53145ZM12 1.77007C14.603 1.77007 16.9848 2.74621 18.7939 4.34707C18.6117 4.60738 17.0629 6.67679 13.4186 8.04338C11.7397 4.95878 9.87855 2.43384 9.5922 2.04338C10.3601 1.86117 11.1671 1.77007 12 1.77007ZM7.63995 2.73319C7.91325 3.09761 9.73538 5.63558 11.4404 8.65508C6.65076 9.9306 2.42083 9.90458 1.96529 9.90458C2.62907 6.72885 4.77657 4.08676 7.63995 2.73319ZM1.74404 12.0131C1.74404 11.9089 1.74404 11.8048 1.74404 11.7007C2.18655 11.7136 7.15835 11.7787 12.2733 10.243C12.5727 10.8156 12.846 11.4013 13.1063 11.9869C12.9761 12.026 12.8329 12.0651 12.7028 12.1041C7.41865 13.8091 4.60738 18.4685 4.3731 18.859C2.7462 17.0499 1.74404 14.6421 1.74404 12.0131ZM12 22.256C9.6312 22.256 7.44469 21.449 5.71367 20.0954C5.89588 19.718 7.97827 15.7094 13.757 13.692C13.783 13.679 13.7961 13.679 13.8221 13.666C15.2668 17.4013 15.8525 20.5379 16.0087 21.436C14.7722 21.9696 13.4186 22.256 12 22.256ZM17.7136 20.4989C17.6096 19.8742 17.0629 16.8807 15.7223 13.1974C18.9371 12.6898 21.7484 13.5228 22.0998 13.6399C21.6573 16.4902 20.0173 18.9501 17.7136 20.4989Z"
76
+ fill={colorful ? "#C32361" : "currentColor"}
77
+ />
78
+ </svg>
79
+ );
80
+ };
81
+
82
+ export const FacebookLogo = ({ colorful = true, ...props }: SVGProps<SVGSVGElement> & { colorful?: boolean }) => {
83
+ return (
84
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" {...props}>
85
+ <path
86
+ d="M24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 17.9895 4.3882 22.954 10.125 23.8542V15.4688H7.07812V12H10.125V9.35625C10.125 6.34875 11.9166 4.6875 14.6576 4.6875C15.9701 4.6875 17.3438 4.92188 17.3438 4.92188V7.875H15.8306C14.34 7.875 13.875 8.80008 13.875 9.75V12H17.2031L16.6711 15.4688H13.875V23.8542C19.6118 22.954 24 17.9895 24 12Z"
87
+ fill={colorful ? "#1877F2" : "currentColor"}
88
+ />
89
+ </svg>
90
+ );
91
+ };
92
+
93
+ export const AppleLogo = (props: SVGProps<SVGSVGElement>) => {
94
+ return (
95
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" {...props}>
96
+ <path
97
+ d="M20.8426 17.1449C20.5099 17.9135 20.1161 18.6211 19.6598 19.2715C19.0379 20.1583 18.5286 20.7721 18.1362 21.113C17.5278 21.6724 16.876 21.959 16.178 21.9753C15.6769 21.9753 15.0726 21.8327 14.3691 21.5434C13.6634 21.2555 13.0148 21.113 12.4218 21.113C11.7998 21.113 11.1328 21.2555 10.4193 21.5434C9.70475 21.8327 9.1291 21.9834 8.68898 21.9984C8.01963 22.0269 7.35246 21.7322 6.6865 21.113C6.26145 20.7422 5.7298 20.1067 5.09291 19.2063C4.40957 18.2449 3.84778 17.13 3.40766 15.8589C2.9363 14.486 2.70001 13.1565 2.70001 11.8694C2.70001 10.3951 3.01859 9.12345 3.65671 8.05784C4.15821 7.20191 4.82539 6.52672 5.66041 6.03105C6.49543 5.53539 7.39768 5.2828 8.36931 5.26664C8.90096 5.26664 9.59815 5.43109 10.4645 5.75429C11.3285 6.07858 11.8832 6.24303 12.1264 6.24303C12.3083 6.24303 12.9245 6.05074 13.9692 5.66738C14.9571 5.31186 15.7909 5.16466 16.474 5.22264C18.3249 5.37202 19.7155 6.10167 20.6403 7.41619C18.9849 8.4192 18.1661 9.82403 18.1824 11.6262C18.1973 13.03 18.7065 14.1981 19.7074 15.1256C20.1609 15.5561 20.6675 15.8888 21.231 16.1251C21.1088 16.4795 20.9798 16.819 20.8426 17.1449ZM16.5976 0.440369C16.5976 1.54062 16.1956 2.56792 15.3944 3.51878C14.4275 4.64917 13.258 5.30236 11.9898 5.19929C11.9737 5.06729 11.9643 4.92837 11.9643 4.78239C11.9643 3.72615 12.4241 2.59576 13.2407 1.67152C13.6483 1.20356 14.1668 0.814453 14.7955 0.504058C15.4229 0.198295 16.0164 0.0292007 16.5745 0.000244141C16.5908 0.147331 16.5976 0.294426 16.5976 0.440355V0.440369Z"
98
+ fill="currentColor"
99
+ />
100
+ </svg>
101
+ );
102
+ };
103
+
104
+ export const TwitterLogo = (props: SVGProps<SVGSVGElement>) => {
105
+ return (
106
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" {...props}>
107
+ <path
108
+ fillRule="evenodd"
109
+ clipRule="evenodd"
110
+ d="M15.9455 23L10.396 15.0901L3.44886 23H0.509766L9.09209 13.2311L0.509766 1H8.05571L13.286 8.45502L19.8393 1H22.7784L14.5943 10.3165L23.4914 23H15.9455ZM19.2185 20.77H17.2398L4.71811 3.23H6.6971L11.7121 10.2532L12.5793 11.4719L19.2185 20.77Z"
111
+ fill="currentColor"
112
+ />
113
+ </svg>
114
+ );
115
+ };