Skip to content

Commit 039c76c

Browse files
committed
feat: allow className props to be passed for custom tailwind class styling on widget
1 parent 82e5a07 commit 039c76c

File tree

8 files changed

+35
-7
lines changed

8 files changed

+35
-7
lines changed

packages/shadcn/src/AddButton/AddButton.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,25 @@ import { FormContextType, IconButtonProps, RJSFSchema, StrictRJSFSchema, Transla
22
import { PlusCircle } from 'lucide-react';
33

44
import { Button } from '../components/ui/button';
5+
import { cn } from '../lib/utils';
56

67
/**
78
* A button component for adding new items in a form
9+
* @param uiSchema - The UI schema for the form, which can include custom properties
10+
* @param registry - The registry object containing the form's configuration and utilities
11+
* @param className - Allow custom class names to be passed for Tailwind CSS styling
812
* @param props - The component properties
913
*/
1014
export default function AddButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>({
1115
uiSchema,
1216
registry,
17+
className,
1318
...props
1419
}: IconButtonProps<T, S, F>) {
1520
const { translateString } = registry;
1621
return (
1722
<div className='p-0 m-0'>
18-
<Button {...props} className='w-fit gap-2' variant='outline' type='button'>
23+
<Button {...props} className={cn('w-fit gap-2', className)} variant='outline' type='button'>
1924
<PlusCircle size={16} /> {translateString(TranslatableString.AddItemButton)}
2025
</Button>
2126
</div>

packages/shadcn/src/BaseInputTemplate/BaseInputTemplate.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export default function BaseInputTemplate<
4040
rawErrors = [],
4141
children,
4242
extraProps,
43+
className,
4344
}: BaseInputTemplateProps<T, S, F>) {
4445
const inputProps = {
4546
...extraProps,
@@ -61,7 +62,7 @@ export default function BaseInputTemplate<
6162
required={required}
6263
disabled={disabled}
6364
readOnly={readonly}
64-
className={cn({ 'border-destructive focus-visible:ring-0': rawErrors.length > 0 })}
65+
className={cn({ 'border-destructive focus-visible:ring-0': rawErrors.length > 0 }, className)}
6566
list={schema.examples ? examplesId<T>(id) : undefined}
6667
{...inputProps}
6768
value={value || value === 0 ? value : ''}

packages/shadcn/src/CheckboxWidget/CheckboxWidget.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export default function CheckboxWidget<
3737
onFocus,
3838
registry,
3939
uiSchema,
40+
className,
4041
} = props;
4142
// Because an unchecked checkbox will cause html5 validation to fail, only add
4243
// the "required" attribute if the field value must be "true", due to the
@@ -78,6 +79,7 @@ export default function CheckboxWidget<
7879
onCheckedChange={_onChange}
7980
onBlur={_onBlur}
8081
onFocus={_onFocus}
82+
className={className}
8183
/>
8284
<Label className='leading-tight' htmlFor={id}>
8385
{labelValue(label, hideLabel || !label)}

packages/shadcn/src/CheckboxesWidget/CheckboxesWidget.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,19 @@ export default function CheckboxesWidget<
2525
T = any,
2626
S extends StrictRJSFSchema = RJSFSchema,
2727
F extends FormContextType = any,
28-
>({ id, disabled, options, value, autofocus, readonly, required, onChange, onBlur, onFocus }: WidgetProps<T, S, F>) {
28+
>({
29+
id,
30+
disabled,
31+
options,
32+
value,
33+
autofocus,
34+
readonly,
35+
required,
36+
onChange,
37+
onBlur,
38+
onFocus,
39+
className,
40+
}: WidgetProps<T, S, F>) {
2941
const { enumOptions, enumDisabled, inline, emptyValue } = options;
3042
const checkboxesValues = Array.isArray(value) ? value : [value];
3143

@@ -56,6 +68,7 @@ export default function CheckboxesWidget<
5668
onChange(enumOptionsDeselectValue<S>(index, checkboxesValues, enumOptions));
5769
}
5870
}}
71+
className={className}
5972
checked={checked}
6073
autoFocus={autofocus && index === 0}
6174
onBlur={_onBlur}

packages/shadcn/src/RadioWidget/RadioWidget.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export default function RadioWidget<T = any, S extends StrictRJSFSchema = RJSFSc
2929
onChange,
3030
onBlur,
3131
onFocus,
32+
className,
3233
}: WidgetProps<T, S, F>) {
3334
const { enumOptions, enumDisabled, emptyValue } = options;
3435

@@ -53,7 +54,7 @@ export default function RadioWidget<T = any, S extends StrictRJSFSchema = RJSFSc
5354
onFocus={_onFocus}
5455
aria-describedby={ariaDescribedByIds<T>(id)}
5556
orientation={inline ? 'horizontal' : 'vertical'}
56-
className={cn('flex flex-wrap', { 'flex-col': !inline })}
57+
className={cn('flex flex-wrap', { 'flex-col': !inline }, className)}
5758
>
5859
{Array.isArray(enumOptions) &&
5960
enumOptions.map((option, index) => {

packages/shadcn/src/SelectWidget/SelectWidget.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export default function SelectWidget<
3636
defaultValue,
3737
placeholder,
3838
rawErrors = [],
39+
className,
3940
}: WidgetProps<T, S, F>) {
4041
const { enumOptions, enumDisabled, emptyValue: optEmptyValue } = options;
4142

@@ -54,6 +55,8 @@ export default function SelectWidget<
5455
disabled: Array.isArray(enumDisabled) && enumDisabled.includes(value),
5556
}));
5657

58+
const cnClassName = cn({ 'border-destructive': rawErrors.length > 0 }, className);
59+
5760
return (
5861
<div className='p-0.5'>
5962
{!multiple ? (
@@ -67,7 +70,7 @@ export default function SelectWidget<
6770
disabled={disabled || readonly}
6871
required={required}
6972
placeholder={placeholder}
70-
className={cn({ 'border-destructive': rawErrors.length > 0 })}
73+
className={cnClassName}
7174
onFocus={_onFancyFocus}
7275
onBlur={_onFancyBlur}
7376
ariaDescribedby={ariaDescribedByIds<T>(id)}
@@ -78,7 +81,7 @@ export default function SelectWidget<
7881
autoFocus={autofocus}
7982
disabled={disabled || readonly}
8083
multiple
81-
className={rawErrors.length > 0 ? 'border-destructive' : ''}
84+
className={cnClassName}
8285
items={items}
8386
selected={value}
8487
onValueChange={(values) => {

packages/shadcn/src/SubmitButton/SubmitButton.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { FormContextType, getSubmitButtonOptions, RJSFSchema, StrictRJSFSchema, SubmitButtonProps } from '@rjsf/utils';
22

33
import { Button } from '../components/ui/button';
4+
import { cn } from '../lib/utils';
45

56
/** The `SubmitButton` renders a button that represent the `Submit` action on a form
67
*/
@@ -13,7 +14,7 @@ export default function SubmitButton<T = any, S extends StrictRJSFSchema = RJSFS
1314
}
1415
return (
1516
<div>
16-
<Button type='submit' {...submitButtonProps} className='my-2'>
17+
<Button type='submit' {...submitButtonProps} className={cn('my-2', submitButtonProps?.className)}>
1718
{submitText}
1819
</Button>
1920
</div>

packages/shadcn/src/TextareaWidget/TextareaWidget.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export default function TextareaWidget<
3131
onFocus,
3232
onChange,
3333
options,
34+
className,
3435
}: CustomWidgetProps<T, S, F>) {
3536
const _onChange = ({ target: { value } }: ChangeEvent<HTMLTextAreaElement>) =>
3637
onChange(value === '' ? options.emptyValue : value);
@@ -53,6 +54,7 @@ export default function TextareaWidget<
5354
onBlur={_onBlur}
5455
onFocus={_onFocus}
5556
aria-describedby={ariaDescribedByIds<T>(id)}
57+
className={className}
5658
/>
5759
</div>
5860
);

0 commit comments

Comments
 (0)