Security News
The Push to Ban Ransom Payments Is Gaining Momentum
Ransomware costs victims an estimated $30 billion per year and has gotten so out of control that global support for banning payments is gaining momentum.
tailwindcss-radix
Advanced tools
Readme
Utilities and variants for styling Radix state
The main purpose of this library is adding classnames for accessing Radix data attributes, which gains you the benefit of auto-completion compared to using data-*
variants.
TL;DR It's @headlessui-tailwindcss for Radix.
pnpm add tailwindcss-radix
Click on the banner to check out the demo components. You can find the code inside the demo folder.
Add the plugin to your plugins array:
module.exports = {
theme: {
// --snip--
},
variants: {
// --snip--
},
plugins: [
// Initialize with default values (see options below)
require("tailwindcss-radix")(),
],
};
require("tailwindcss-radix")({
// Default: `radix`
variantPrefix: "rdx",
});
// Example 1: Generates `rdx-[state/side/orientation]-*` utilities for `data-[state/side/orientation]="*"`
variantPrefix: "rdx",
// Example 2: Generates `[state/side/orientation]-*` utilities for `data-[state/side/orientation]="*"`
variantPrefix: false,
This plugin works with CSS attribute selectors. Use the variants based on the data-*
attribute added by Radix.
import React from "react";
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
const App = () => {
return (
<DropdownMenuPrimitive.Root>
<DropdownMenuPrimitive.Trigger className="border-black radix-state-open:border-2">
Trigger
</DropdownMenuPrimitive.Trigger>
<DropdownMenuPrimitive.Content>
<DropdownMenuPrimitive.Item>Item</DropdownMenuPrimitive.Item>
</DropdownMenuPrimitive.Content>
</DropdownMenuPrimitive.Root>
);
};
export default App;
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-radix-*
modifiers.
Example usage of a conditional transform for a Radix Accordion
:
import React from "react";
import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { ChevronDownIcon } from "@radix-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-radix-state-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-radix-state-open:rotate-180" />
</div>
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
<AccordionPrimitive.Content>Content 2</AccordionPrimitive.Content>
</AccordionPrimitive.Item>
</AccordionPrimitive.Root>
);
};
export default App;
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-radix-*
modifiers.
Example usage of a conditional icon color for a sibling of a Radix Checkbox
:
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import { CheckIcon, TargetIcon } from "@radix-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-radix-state-checked:text-green-500" />
</>
);
};
export default App;
Use the generated disabled
variant.
import React from "react";
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
const ContextMenu = () => {
return (
// --snip--
<ContextMenuPrimitive.Item
disabled
className="radix-disabled:opacity-50 radix-disabled:cursor-not-allowed"
>
Item
</ContextMenuPrimitive.Item>
// --snip--
);
};
.origin-radix-context-menu {
transform-origin: var(--radix-context-menu-content-transform-origin);
}
.origin-radix-dropdown-menu {
transform-origin: var(--radix-dropdown-menu-content-transform-origin);
}
.origin-radix-hover-card {
transform-origin: var(--radix-hover-card-content-transform-origin);
}
.origin-radix-menubar {
transform-origin: var(--radix-menubar-content-transform-origin);
}
.origin-radix-popover {
transform-origin: var(--radix-popover-content-transform-origin);
}
.origin-radix-select {
transform-origin: var(--radix-select-content-transform-origin);
}
.origin-radix-tooltip {
transform-origin: var(--radix-tooltip-content-transform-origin);
}
.w-radix-accordion-content {
width: var(--radix-accordion-content-width);
}
.h-radix-accordion-content {
height: var(--radix-accordion-content-height);
}
.w-radix-collapsible-content {
width: var(--radix-collapsible-content-width);
}
.h-radix-collapsible-content {
height: var(--radix-collapsible-content-height);
}
.w-radix-navigation-menu-viewport {
width: var(--radix-navigation-menu-viewport-width);
}
.h-radix-navigation-menu-viewport {
height: var(--radix-navigation-menu-viewport-height);
}
.w-radix-context-menu-content-available {
width: var(--radix-context-menu-content-available-width);
}
.max-w-radix-context-menu-content-available {
max-width: var(--radix-context-menu-content-available-width);
}
.h-radix-context-menu-content-available {
height: var(--radix-context-menu-content-available-height);
}
.max-h-radix-context-menu-content-available {
max-height: var(--radix-context-menu-content-available-height);
}
.w-radix-dropdown-menu-content-available {
width: var(--radix-dropdown-menu-content-available-width);
}
.max-w-radix-dropdown-menu-content-available {
max-width: var(--radix-dropdown-menu-content-available-width);
}
.h-radix-dropdown-menu-content-available {
height: var(--radix-dropdown-menu-content-available-height);
}
.max-h-radix-dropdown-menu-content-available {
max-height: var(--radix-dropdown-menu-content-available-height);
}
.w-radix-hover-card-content-available {
width: var(--radix-hover-card-content-available-width);
}
.max-w-radix-hover-card-content-available {
max-width: var(--radix-hover-card-content-available-width);
}
.h-radix-hover-card-content-available {
height: var(--radix-hover-card-content-available-height);
}
.max-h-radix-hover-card-content-available {
max-height: var(--radix-hover-card-content-available-height);
}
.w-radix-menubar-content-available {
width: var(--radix-menubar-content-available-width);
}
.max-w-radix-menubar-content-available {
max-width: var(--radix-menubar-content-available-width);
}
.h-radix-menubar-content-available {
height: var(--radix-menubar-content-available-height);
}
.max-h-radix-menubar-content-available {
max-height: var(--radix-menubar-content-available-height);
}
.w-radix-popover-content-available {
width: var(--radix-popover-content-available-width);
}
.max-w-radix-popover-content-available {
max-width: var(--radix-popover-content-available-width);
}
.h-radix-popover-content-available {
height: var(--radix-popover-content-available-height);
}
.max-h-radix-popover-content-available {
max-height: var(--radix-popover-content-available-height);
}
.w-radix-select-content-available {
width: var(--radix-select-content-available-width);
}
.max-w-radix-select-content-available {
max-width: var(--radix-select-content-available-width);
}
.h-radix-select-content-available {
height: var(--radix-select-content-available-height);
}
.max-h-radix-select-content-available {
max-height: var(--radix-select-content-available-height);
}
.w-radix-tooltip-content-available {
width: var(--radix-tooltip-content-available-width);
}
.max-w-radix-tooltip-content-available {
max-width: var(--radix-tooltip-content-available-width);
}
.h-radix-tooltip-content-available {
height: var(--radix-tooltip-content-available-height);
}
.max-h-radix-tooltip-content-available {
max-height: var(--radix-tooltip-content-available-height);
}
.w-radix-context-menu-trigger {
width: var(--radix-context-menu-trigger-width);
}
.h-radix-context-menu-trigger {
height: var(--radix-context-menu-trigger-height);
}
.w-radix-dropdown-menu-trigger {
width: var(--radix-dropdown-menu-trigger-width);
}
.h-radix-dropdown-menu-trigger {
height: var(--radix-dropdown-menu-trigger-height);
}
.w-radix-hover-card-trigger {
width: var(--radix-hover-card-trigger-width);
}
.h-radix-hover-card-trigger {
height: var(--radix-hover-card-trigger-height);
}
.w-radix-menubar-trigger {
width: var(--radix-menubar-trigger-width);
}
.h-radix-menubar-trigger {
height: var(--radix-menubar-trigger-height);
}
.w-radix-popover-trigger {
width: var(--radix-popover-trigger-width);
}
.h-radix-popover-trigger {
height: var(--radix-popover-trigger-height);
}
.w-radix-select-trigger {
width: var(--radix-select-trigger-width);
}
.h-radix-select-trigger {
height: var(--radix-select-trigger-height);
}
.w-radix-tooltip-trigger {
width: var(--radix-tooltip-trigger-width);
}
.h-radix-tooltip-trigger {
height: var(--radix-tooltip-trigger-height);
}
.translate-x-radix-toast-swipe-end-x {
transform: translateX(var(--radix-toast-swipe-end-x));
}
.translate-y-radix-toast-swipe-end-y {
transform: translateY(var(--radix-toast-swipe-end-y));
}
.translate-x-radix-toast-swipe-move-x {
transform: translateX(var(--radix-toast-swipe-move-x));
}
.translate-y-radix-toast-swipe-move-y {
transform: translateY(var(--radix-toast-swipe-move-y));
}
To prevent a possible future name clashing the skipAttributeNames
option has been removed. In case you used this option, please update the class names accordingly.
In case you use content-available
utilities:
-content-available
to the width-based classnameswidth
and height
from content-available-[width|height]
-w-radix-context-menu
+w-radix-context-menu-content-available
-h-radix-context-menu-content-available-height
+h-radix-context-menu-content-available
-max-w-radix-context-menu-content-available-width
+max-w-radix-context-menu-content-available
-max-h-radix-context-menu-content-available-height
+max-h-radix-context-menu-content-available
-w-radix-dropdown-menu
+w-radix-dropdown-menu-content-available
-h-radix-dropdown-menu-content-available-height
+h-radix-dropdown-menu-content-available
-max-w-radix-dropdown-menu-content-available-width
+max-w-radix-dropdown-menu-content-available
-max-h-radix-dropdown-menu-content-available-height
+max-h-radix-dropdown-menu-content-available
-w-radix-hover-card
+w-radix-hover-card-content-available
-h-radix-hover-card-content-available-height
+h-radix-hover-card-content-available
-max-w-radix-hover-card-content-available-width
+max-w-radix-hover-card-content-available
-max-h-radix-hover-card-content-available-height
+max-h-radix-hover-card-content-available
-w-radix-menubar
+w-radix-menubar-content-available
-h-radix-menubar-content-available-height
+h-radix-menubar-content-available
-max-w-radix-menubar-content-available-width
+max-w-radix-menubar-content-available
-max-h-radix-menubar-content-available-height
+max-h-radix-menubar-content-available
-w-radix-popover
+w-radix-popover-content-available
-h-radix-popover-content-available-height
+h-radix-popover-content-available
-max-w-radix-popover-content-available-width
+max-w-radix-popover-content-available
-max-h-radix-popover-content-available-height
+max-h-radix-popover-content-available
-w-radix-select
+w-radix-select-content-available
-h-radix-select
+h-radix-select-content-available
-max-w-radix-select-content-available-width
+max-w-radix-select-content-available
-max-h-radix-select-content-available-height
+max-h-radix-select-content-available
-w-radix-tooltip
+w-radix-tooltip-content-available
-h-radix-tooltip
+h-radix-tooltip-content-available
-max-w-radix-tooltip-content-available-width
+max-w-radix-tooltip-content-available
-max-h-radix-tooltip-content-available-height
+max-h-radix-tooltip-content-available
FAQs
Utilities and variants for styling Radix state
We found that tailwindcss-radix demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Ransomware costs victims an estimated $30 billion per year and has gotten so out of control that global support for banning payments is gaining momentum.
Application Security
New SEC disclosure rules aim to enforce timely cyber incident reporting, but fear of job loss and inadequate resources lead to significant underreporting.
Security News
The Python Software Foundation has secured a 5-year sponsorship from Fastly that supports PSF's activities and events, most notably the security and reliability of the Python Package Index (PyPI).