rjsf-team / react-jsonschema-form

A React component for building Web forms from JSON Schema.
https://rjsf-team.github.io/react-jsonschema-form/
Apache License 2.0
14.09k stars 2.18k forks source link

Tailwind support #3199

Open c0ncentus opened 1 year ago

c0ncentus commented 1 year ago

Prerequisites

What theme are you using?

other

Is your feature request related to a problem? Please describe.

Tailwind is yeat an another css libraries but have such flexibility, popularity for dark mode or other things more simple to do with tailwind. It will be nice to have this library for having such flexibility to design inputs.

Describe the solution you'd like

tailwind implemented and dark mode with "dark:bg-blue-600" for exemple.

Describe alternatives you've considered

Get components on https://tailwindcomponents.com/ and FlowBite for integrate them directly (will be dirctly the className string).

heath-freenome commented 1 year ago

@c0ncentus We are open to contributions of new themes assuming those themes support the current features provided in other themes

tonyxiao commented 1 year ago

Would love this! Also related one would be shadcn or other component libs that are built on top of tailwind.

tonyxiao commented 1 year ago

For those looking, I ended up adding the following snippet into my global.css and it worked like a charm. Not a full integration, just hacking the css classes that came with bootstrap3.


@layer components {
  .schema-form {
    /* Left side is not needed due to fieldset left margin */
    @apply mr-2;
  }
  /* Aka sections */
  .schema-form fieldset > legend {
    /* Display block doesn't work for some reason. Does not fill parent width which is still a div, not sure why */
    @apply mb-3 pb-1 w-full border-b pt-4 text-xl font-semibold;
  }
  .schema-form fieldset > div {
    /* Offset to indicate hierarchy */
    @apply ml-3;
  }
  /* Label + component = group */
  .schema-form .form-group {
    @apply mb-2;
  }
  .schema-form label.control-label {
    @apply block mb-1 font-bold;
  }
  .schema-form p.field-description {
    @apply mb-1;
  }
  /* Select component, and maybe other .form-control too */
  .schema-form .form-control {
    @apply block w-full rounded-md border border-input p-2;
  }
  /* Input component */
  .schema-form input {
    @apply flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium 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;
  }

  /* Array elements */
  .schema-form .array-item {
    /* @apply grid grid-cols-12; */
    @apply flex flex-row items-end gap-4;
  }
  .schema-form .array-item .col-xs-9 {
    /* @apply col-span-9; */
    @apply grow;
  }
  .schema-form .array-item .col-xs-3 {
    /* @apply col-span-3; */
    @apply shrink-0;
  }
  .schema-form .array-item .array-item-toolbox {
    /* mb-4 to match .form-group */
    @apply mb-4 flex items-center justify-end;
  }
  /* Icons */
  .schema-form .glyphicon {
    @apply font-normal not-italic;
  }
  .schema-form .glyphicon-remove::before {
    content: 'Remove';
  }
  .schema-form .glyphicon-arrow-up::before {
    content: 'Up';
  }
  .schema-form .glyphicon-arrow-down::before {
    content: 'Down';
  }
  .schema-form .glyphicon-plus::before {
    content: 'Add';
  }
  /* Buttons (tends to be icon buttons */
  .schema-form .btn {
    @apply rounded-md p-2 border mx-1;
  }
  .schema-form .btn-danger {
    @apply border-red-200;
  }
  .schema-form .btn-add {
    @apply border-blue-200;
  }
  .schema-form button[type='submit'] {
    @apply bg-primary text-primary-foreground hover:bg-primary/90;
  }
}
phaux commented 9 months ago

For proper tailwind support all that would be needed is an easy way to override className for every widget (without the need for reimplementing the whole widget)

NixBiks commented 3 months ago

For proper tailwind support all that would be needed is an easy way to override className for every widget (without the need for reimplementing the whole widget)

So basically we'd need a utility function similar to cn from shadcn/ui? See usage here e.g.

Interested in a PR?

phaux commented 3 months ago

So basically we'd need a utility function similar to cn

That shouldn't be necessary.

My idea was to just:

- className='form-control'
+ className={'form-control ' + customClassName}

For example in https://github.com/rjsf-team/react-jsonschema-form/blob/ec932db942dd046640303056c89e3501b16ec469/packages/core/src/components/templates/BaseInputTemplate.tsx#L79

and allow specifying that custom className somewhere for every component. Similar to how there's a component registry that you can override by specifying your own component implementations, there should be something like a className registry.

burakakca commented 3 months ago

Hi, integrating rizzui library is the great option to support tailwindcss

NixBiks commented 3 months ago

Hi, integrating rizzui library is the best option to support tailwindcss

Using tailwindcss to support rizzui doesn't mean it supports tailwindcss

tonyxiao commented 3 months ago

what about shadcn?

burakakca commented 3 months ago

@tonyxiao thanks, shadcn also great

kevinschaich commented 2 months ago

My solution to pull in all your default components & customize them for shadcn/ui (+ maybe others):

'use client'

import {Checkbox} from '@/components/ui/checkbox'
import {Input} from '@/components/ui/input'
import Form from '@rjsf/core'
import {RegistryWidgetsType, WidgetProps} from '@rjsf/utils'
import validator from '@rjsf/validator-ajv8'

const widgets: RegistryWidgetsType = {
    CheckboxWidget: function (props: WidgetProps) {
        return <Checkbox checked={props.value} onChange={props.onChange} />
    },
    TextWidget: function (props: WidgetProps) {
        return <Input onChange={e => props.onChange(e.target.value)} value={props.value} className='text-red-500'/>
    },

    // add the rest of your desired components here
}

export const MyComponent = () => {
    return (
        <Form
            schema={{type: 'object'}}
            validator={validator}
            widgets={widgets}
        />
    )
}

result (note the red text specified via Tailwind in widgets above):

image
osseonews commented 1 month ago

Tailwind support is critical as it seems to be the preferred styling solution now for all new Next/React websites. I noticed this repo: https://github.com/m6io/rjsf-tailwind - can this be integrated?

heath-freenome commented 1 month ago

@osseonews You can either do it yourself or reach out to the author and ask them to do it