Skip to content

ecklf/tailwindcss-base-ui

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Utilities and variants for styling Base UI state

tailwindcss v4 ready npm version npm downloads

Important

This is still a WIP, most of the code was ported with Cursor from tailwindcss-radix

What is this?

The main purpose of this library is adding classnames for accessing Base UI data attributes, which gains you the benefit of auto-completion compared to using data-* variants.

TL;DR It's @headlessui-tailwindcss for Base UI.

Installation

pnpm add tailwindcss-base-ui

Demo

Click on the banner to check out the demo components. You can find the code inside the demo folder.

Usage

With @plugin directive (recommended)

Default prefix

/* Generates `bui-*` utilities for data attributes */
@plugin "tailwindcss-base-ui";

Custom prefix

/* Generates `ui-*` utilities for data attributes */
@plugin "tailwindcss-base-ui" {
  variantPrefix: ui;
}

Default prefix

module.exports = {
  // --snip --
  plugins: [
    // Generates `bui-*` utilities for data attributes
    require("tailwindcss-base-ui")(),
  ],
};

Custom prefix

module.exports = {
  // --snip --
  plugins: [
    // Generates `ui-*` utilities for data attributes
    require("tailwindcss-base-ui")({
      variantPrefix: "ui",
    }),
  ],
};

Load configuration

@config "../../tailwind.config.js";

Styling state

Basic usage

This plugin works with CSS attribute selectors. Use the variants based on the data-* attribute added by Base UI.

import React from "react";
import * as DropdownMenuPrimitive from "@base-ui-ui/react-dropdown-menu";

const App = () => {
  return (
    <DropdownMenuPrimitive.Root>
      <DropdownMenuPrimitive.Trigger className="border-black bui-ui-state-open:border-2">
        Trigger
      </DropdownMenuPrimitive.Trigger>
      <DropdownMenuPrimitive.Content>
        <DropdownMenuPrimitive.Item>Item</DropdownMenuPrimitive.Item>
      </DropdownMenuPrimitive.Content>
    </DropdownMenuPrimitive.Root>
  );
};

export default App;

Accessing parent state

When you need to style an element based on the state of a parent element, mark the parent with the group class and style the target with group-bui-* modifiers.

Example usage of a conditional transform for a Base UI Accordion:

import React from "react";
import * as AccordionPrimitive from "@base-ui-ui/react-accordion";
import { ChevronDownIcon } from "@base-ui-ui/react-icons";

const Accordion = () => {
  return (
    <AccordionPrimitive.Root type="multiple">
      <AccordionPrimitive.Item value="item-1">
        <AccordionPrimitive.Header>
          <AccordionPrimitive.Trigger className="group">
            <div className="flex items-center">
              Item 1
              <ChevronDownIcon className="w-5 h-5 ml-2 transform group-bui-open:rotate-180" />
            </div>
          </AccordionPrimitive.Trigger>
        </AccordionPrimitive.Header>
        <AccordionPrimitive.Content>Content 1</AccordionPrimitive.Content>
      </AccordionPrimitive.Item>
      <AccordionPrimitive.Item value="item-2">
        <AccordionPrimitive.Header>
          <AccordionPrimitive.Trigger className="group">
            <div className="flex items-center">
              Item 2
              <ChevronDownIcon className="w-5 h-5 ml-2 transform group-bui-state-open:rotate-180" />
            </div>
          </AccordionPrimitive.Trigger>
        </AccordionPrimitive.Header>
        <AccordionPrimitive.Content>Content 2</AccordionPrimitive.Content>
      </AccordionPrimitive.Item>
    </AccordionPrimitive.Root>
  );
};

export default App;

Accessing sibling state

When you need to style an element based on the state of a sibling element, mark the sibling with the peer class and style the target with peer-bui-* modifiers.

Example usage of a conditional icon color for a sibling of a Base UI Checkbox:

import * as CheckboxPrimitive from "@base-ui-ui/react-checkbox";
import { CheckIcon, TargetIcon } from "@base-ui-ui/react-icons";
import React from "react";

interface Props {}

const App = (props: Props) => {
  return (
    <>
      <CheckboxPrimitive.Root id="c1" defaultChecked className="peer h-5 w-5">
        <CheckboxPrimitive.Indicator>
          <CheckIcon />
        </CheckboxPrimitive.Indicator>
      </CheckboxPrimitive.Root>

      <TargetIcon className="text-red-500 peer-bui-checked:text-green-500" />
    </>
  );
};

export default App;

Disabled state

Use the generated disabled variant.

import React from "react";
import * as ContextMenuPrimitive from "@base-ui-ui/react-context-menu";

const ContextMenu = () => {
  return (
    // --snip--
    <ContextMenuPrimitive.Item
      disabled
      className="bui-disabled:opacity-50 bui-disabled:cursor-not-allowed"
    >
      Item
    </ContextMenuPrimitive.Item>
    // --snip--
  );
};

MIT

About

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Sponsor this project

 

Packages

 
 
 

Contributors