Skip to content

Commit 7bcefd1

Browse files
add headless and unstyled component configs
1 parent ae060af commit 7bcefd1

File tree

2 files changed

+34
-9
lines changed

2 files changed

+34
-9
lines changed

packages/react/src/components/button.tsx

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,13 @@ export function UploadButton<
9999
> &
100100
UploadThingInternalProps;
101101

102-
const { mode = "auto", appendOnPaste = false } = $props.config ?? {};
102+
const {
103+
mode = "auto",
104+
appendOnPaste = false,
105+
headless = false,
106+
unstyled = false,
107+
} = $props.config ?? {};
108+
const applyDefaultStyling = !headless && !unstyled;
103109

104110
const useUploadThing = INTERNAL_uploadthingHookGen<TRouter>({
105111
url: resolveMaybeUrlArg($props.url),
@@ -202,6 +208,7 @@ export function UploadButton<
202208
styleFieldArg,
203209
);
204210
if (customContent) return customContent;
211+
if (headless) return null;
205212

206213
if (state === "readying") {
207214
return "Loading...";
@@ -231,7 +238,8 @@ export function UploadButton<
231238
}
232239
}}
233240
className={twMerge(
234-
"h-[1.25rem] cursor-pointer rounded border-none bg-transparent text-gray-500 transition-colors hover:bg-slate-200 hover:text-gray-600",
241+
applyDefaultStyling &&
242+
"h-[1.25rem] cursor-pointer rounded border-none bg-transparent text-gray-500 transition-colors hover:bg-slate-200 hover:text-gray-600",
235243
styleFieldToClassName($props.appearance?.clearBtn, styleFieldArg),
236244
)}
237245
style={styleFieldToCssObject($props.appearance?.clearBtn, styleFieldArg)}
@@ -246,7 +254,7 @@ export function UploadButton<
246254
const renderAllowedContent = () => (
247255
<div
248256
className={twMerge(
249-
"h-[1.25rem] text-xs leading-5 text-gray-600",
257+
applyDefaultStyling && "h-[1.25rem] text-xs leading-5 text-gray-600",
250258
styleFieldToClassName($props.appearance?.allowedContent, styleFieldArg),
251259
)}
252260
style={styleFieldToCssObject(
@@ -264,7 +272,8 @@ export function UploadButton<
264272
return (
265273
<div
266274
className={twMerge(
267-
"flex flex-col items-center justify-center gap-1",
275+
applyDefaultStyling &&
276+
"flex flex-col items-center justify-center gap-1",
268277
$props.className,
269278
styleFieldToClassName($props.appearance?.container, styleFieldArg),
270279
)}
@@ -273,11 +282,15 @@ export function UploadButton<
273282
>
274283
<label
275284
className={twMerge(
276-
"relative flex h-10 w-36 cursor-pointer items-center justify-center overflow-hidden rounded-md text-white after:transition-[width] after:duration-500 focus-within:ring-2 focus-within:ring-blue-600 focus-within:ring-offset-2",
277-
state === "readying" && "cursor-not-allowed bg-blue-400",
278-
state === "uploading" &&
279-
`bg-blue-400 after:absolute after:left-0 after:h-full after:bg-blue-600 after:content-[''] ${progressWidths[uploadProgress]}`,
280-
state === "ready" && "bg-blue-600",
285+
...(applyDefaultStyling
286+
? [
287+
"relative flex h-10 w-36 cursor-pointer items-center justify-center overflow-hidden rounded-md text-white after:transition-[width] after:duration-500 focus-within:ring-2 focus-within:ring-blue-600 focus-within:ring-offset-2",
288+
state === "readying" && "cursor-not-allowed bg-blue-400",
289+
state === "uploading" &&
290+
`bg-blue-400 after:absolute after:left-0 after:h-full after:bg-blue-600 after:content-[''] ${progressWidths[uploadProgress]}`,
291+
state === "ready" && "bg-blue-600",
292+
]
293+
: []),
281294
styleFieldToClassName($props.appearance?.button, styleFieldArg),
282295
)}
283296
style={styleFieldToCssObject($props.appearance?.button, styleFieldArg)}

packages/react/src/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,18 @@ export type UploadthingComponentProps<
9999
config?: {
100100
mode?: "auto" | "manual";
101101
appendOnPaste?: boolean;
102+
/**
103+
* Enabling this will disable all default rendering.
104+
* You'll have to render the different parts of the component yourself using the `content` prop
105+
* @default false
106+
*/
107+
headless?: boolean;
108+
/**
109+
* Enabling this will disable the default styling of the component.
110+
* Unlike `headless`, elements will still be rendered, but they will have no styling applied to them.
111+
* @default false
112+
*/
113+
unstyled?: boolean;
102114
};
103115
} & ExtendObjectIf<
104116
inferEndpointInput<TRouter[TEndpoint]>,

0 commit comments

Comments
 (0)