-
-
Notifications
You must be signed in to change notification settings - Fork 242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Shadcn / Tailwind example #672
Comments
I've never used shadcn before, but for tailwind you can add the utility classes to each component with the I don't have an example specifically for tailwind but the Tremor example uses tailwind internally: https://github.com/react-querybuilder/react-querybuilder/tree/main/examples/tremor |
I was going to close this but I think I'll keep it open as a request for a pure Tailwind example. |
Yeah, when I was looking into it I couldn't figure out how that was a benefit. That said, you could theoretically replace all the components with custom components. A lot of the default logic is in hooks so it might not actually be a huge amount of work. |
Well that's the selling point of shadcn/ui, you own the ui library, so customizing it is as easy as editing files directly. It has its upsides and downsides, but for example if I wanted to customize @react-querybuilder/chakra, I would have to fork it or override classes, which may not cover all my needs. On the other hand, with creating a react-querybuilder-shadcn-ui component, since I would import ui components from my own codebase, it will use my very own ui components that are already custom. Not everyone likes it, but it's a cool approach. That said, making a react-querybuilder-shadcn-ui library would imply making copy-pastable code instead of a npm module, which is what I'm planning to do and share. Another approach would be using dependency injection to inject custom components, but it would be overwhelming. |
For what it's worth, I'm not knocking this approach. I guess I don't understand the difference between copy/pasting code and forking a library. You lose the upgrade path either way, and while I can see the benefits of "owning" your components, you're also taking on responsibility for compatibility, testing, etc.
This is not correct. You can copy/paste the components from the
I would be happy to add something like this to the examples folder, foregoing an npm package. Feel free to submit a PR to that effect!
Again, |
Honestly this is a whole debate by itself, and I can totally understand it's not obvious, but after years using Chakra and fighting it to customize components (in particular the theming API is complex with components made of multiple parts) VS editing shadcn/ui components by hand in my components folder I'm sold, but I was very skeptical at first. And forking Chakra is a lot more effort than copy pasting some JSX.
Yes of course, but what I meant is that in the end if you want to customize freely and use your very own components you end up copy pasting basically :) Which is kind of the point of the copy-pasting approach of shadcn/ui.
I will !
What I meant is that to publish a module that would allow using your own shadcn/ui components, since the paths are local to your project, it's impossible to reference them from the module code. |
I feel your pain with Chakra. I nearly gave up on building that compatibility package several times. Chakra and Ant Design have been the most painful so far, although MUI also took a long time to get right because of the way they handle the context provider.
Ok I think I understand now. You're saying that it doesn't make sense to publish a compatibility package for shadcn à la For what it's worth—and for future reference, I guess—here's an example using the shadcn import { Button } from "@/components/ui/button";
const MyActionElement = (props: ActionPropsWithRulesAndAdders) => (
<Button
type="button"
className={props.className}
title={props.disabledTranslation && disabled ? props.disabledTranslation.title : props.title}
disabled={props.disabled && !props.disabledTranslation}
onClick={e => props.handleOnClick(e)}
>
{props.disabledTranslation && props.disabled ? props.disabledTranslation.label : props.label}
</Button>
);
export const App = () => {
return <QueryBuilder controlElements={{ actionElement: MyActionElement }} />
} ( |
Absolutely !
That's pretty much what I did, although I used different variations for addRule, addGroup etc. |
Do you already have a working example you could share? I need it and I don't know whether to start implementing Shadcn integration from scratch. |
Unless @jide has created something, my example in #672 (comment) is all we have for now. The problem with Shadcn is there is you can't really do "integration." Since components are local to each project and not common to all Shadcn implementations, you'd have to reimplement RQB components using your own Shadcn components. You shouldn't have to reimplement |
Hey, I took the time to extract the ui into a clean project. It's still very rough, but I thought it may be useful at this stage. |
In the end, I think my "component injection" idea may not be that bad... This way, it will be distributable as a standalone npm module while still allowing using shadcn/ui components from your project. This is how the implementation looks like : import { getQueryBuilderShadcnUi } from "@react-querybuilder/shadcn-ui";
// Import needed shadcn/ui components.
import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Textarea } from "@/components/ui/textarea";
import {
Select,
SelectContent,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
// Pass them to getQueryBuilderShadcnUi()
const components = {
Button,
Switch,
Checkbox,
Input,
Label,
RadioGroup,
RadioGroupItem,
Textarea,
Select,
SelectContent,
SelectTrigger,
SelectValue,
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
};
const QueryBuilderShadcnUi = getQueryBuilderShadcnUi(components); @jakeboone02 What do you think of this approach ? |
@jide this is looking really great. Kudos! After looking at the code in full, I'm going to politely rescind my offer to host the example code in the However, I would be more than happy to link to this example from somewhere in the repo or the website. It's coming together as a great showcase of the modularity of RQB. My only condition would be that the example repo makes clear what RQB version the component code was copied from, in addition to a pinned ...I was just about to submit that when your last comment came through. The method you've proposed is similar to what we do with MUI components in |
Damn, how did not I see this from the mui package. Indeed that's the same approach. Let me know. |
Do a PR and we'll see where it goes. |
Description of the feature
Are there any plans to add a new theme based on the growing popularity of shadcn or pure Tailwind?
Maybe someone already has a demo?
The text was updated successfully, but these errors were encountered: