Handbook

Styling

Style blakeUI components with CSS, Tailwind, or CSS-in-JS

blakeUI components provide flexible styling options: Tailwind CSS utilities, CSS with BEM classes or data attributes, CSS-in-JS libraries, and render props for dynamic styling.

Basic Styling

Using className: All blakeUI components accept className props:

<Button className="bg-purple-500 hover:bg-purple-600">
  Custom Button
</Button>

<Accordion className="border-2 border-gray-200 rounded-xl">
  {/* content */}
</Accordion>

Using style: Components also accept inline styles:

<Button style={{ backgroundColor: '#8B5CF6' }}>
  Styled Button
</Button>

Scrollbars

blakeUI scroll slots use @apply scrollbar in component CSS. For your own overflow containers, use the utilities from @blakeui/styles:

<div className="scrollbar h-64 overflow-y-auto">
  {/* long content */}
</div>
UtilityEffect
scrollbarblakeUI thumb (reads theme --scrollbar-* variables)
scrollbar-thinblakeUI themed thin scrollbar
scrollbar-defaultOS / browser scrollbars
scrollbar-noneHidden scrollbar

Global and per-subtree control uses data-scrollbar on an ancestor. See Theming for tokens and modes.

State-Based Styling

blakeUI components expose their state through data attributes, similar to CSS pseudo-classes:

/* Target different states */
.button[data-hovered="true"], .button:hover {
  background: var(--accent-hover);
}

.button[data-pressed="true"], .button:active {
  transform: scale(0.97);
}

.button[data-focus-visible="true"], .button:focus-visible {
  outline: 2px solid var(--focus);
}

Render Props

Apply dynamic styling based on component state:

// Dynamic classes
<Button
  className={({ isPressed }) =>
    isPressed ? 'bg-blue-600' : 'bg-blue-500'
  }
>
  Press me
</Button>

// Dynamic content
<Button>
  {({ isHovered, isPressed }) => (
    <>
      <Icon
        icon="gravity-ui:heart"
        className={isPressed ? 'text-red-500' : 'text-neutral-400'}
      />
      <span className={isHovered ? 'underline' : ''}>
        Like
      </span>
    </>
  )}
</Button>

BEM Classes

blakeUI uses BEM methodology for consistent class naming:

/* Block */
.button { }
.accordion { }

/* Element */
.accordion__trigger { }
.accordion__panel { }

/* Modifier */
.button--primary { }
.button--lg { }
.accordion--outline { }

Customizing components globally:

/* global.css */

@layer components {
  /* Override button styles */
  .button {
    @apply font-semibold uppercase;
  }

  .button--primary {
    @apply bg-indigo-600 hover:bg-indigo-700;
  }

  /* Add custom variant */
  .button--gradient {
    @apply bg-gradient-to-r from-purple-500 to-pink-500;
  }
}

Creating Wrapper Components

Create reusable custom components using tailwind-variants—a Tailwind CSS first-class variant API:

import { Button as HeroButton, type ButtonProps } from '@blakeui/react';
import { buttonVariants, tv, type VariantProps } from '@blakeui/styles';

const customButtonVariants = tv({
  extend: buttonVariants,
  base: 'font-medium transition-all',
  variants: {
    intent: {
      primary: 'bg-blue-500 hover:bg-blue-600 text-white',
      secondary: 'bg-gray-200 hover:bg-gray-300',
      danger: 'bg-red-500 hover:bg-red-600 text-white',
    },
    size: {
      small: 'text-sm px-2 py-1',
      medium: 'text-base px-4 py-2',
      large: 'text-lg px-6 py-3',
    },
  },
  defaultVariants: {
    intent: 'primary',
    size: 'medium',
  },
});

type CustomButtonVariants = VariantProps<typeof customButtonVariants>;
interface CustomButtonProps
  extends Omit<ButtonProps, 'className'>,
  CustomButtonVariants {
  className?: string;
}

export function CustomButton({ intent, size, className, ...props }: CustomButtonProps) {
  return (
    <HeroButton
      className={customButtonVariants({ intent, size, className })}
      {...props}
    />
  );
}

CSS-in-JS Integration

Styled Components:

import styled from 'styled-components';
import { Button } from '@blakeui/react';

const StyledButton = styled(Button)`
  background: linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%);
  border-radius: 8px;
  color: white;
  padding: 12px 24px;

  &:hover {
    box-shadow: 0 3px 10px rgba(255, 105, 135, 0.3);
  }
`;

Emotion:

import { css } from '@emotion/css';
import { Button } from '@blakeui/react';

const buttonStyles = css`
  background: linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%);
  border-radius: 8px;
  color: white;
  padding: 12px 24px;

  &:hover {
    box-shadow: 0 3px 10px rgba(255, 105, 135, 0.3);
  }
`;

<Button className={buttonStyles}>
  Emotion Button
</Button>

Responsive Design

Using Tailwind utilities:

<Button className="text-sm md:text-base lg:text-lg px-3 md:px-4 lg:px-6">
  Responsive Button
</Button>

Or with CSS:

.button {
  font-size: 0.875rem;
  padding: 0.5rem 1rem;
}

@media (min-width: 768px) {
  .button {
    font-size: 1rem;
    padding: 0.75rem 1.5rem;
  }
}

CSS Modules

For scoped styles, use CSS Modules:

/* Button.module.css */
.button {
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: white;
  padding: 12px 24px;
  border-radius: 8px;
}

.button:hover {
  transform: translateY(-2px);
}

.button--primary {
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: white;
  padding: 12px 24px;
  border-radius: 8px;
}
import styles from './Button.module.css';
import { Button } from '@blakeui/react';

<Button className={styles.button}>
  Scoped Button
</Button>

Completeness

Every component page declares one of two verdicts. Components that need more than their CSS carry a Behavior required badge beside their source links; the rest carry nothing.

Behavior required means the stylesheet is half the component. The keyboard map, focus managed across more than one element, ARIA attributes that point at other nodes, and the [data-*] attributes the CSS keys on are all set by running code in @blakeui/react. Take the CSS on its own and you get something that renders correctly and responds to nothing — it looks finished, which is exactly why it is worth flagging.

Styles sufficient means the stylesheet is the whole component. There is no behaviour to re-implement.

Porting a component outside React? Ask the MCP server for the contract instead of inferring it from the source. get_component_behavior("Tabs") returns it framework-neutral: required roles and ARIA, the full keyboard map, focus rules, and every [data-*] the stylesheet depends on — what sets each one, and when it changes. For a behavior-required component, get_component_source_styles withholds the CSS until you pass behavior_source, declaring whether @blakeui/react drives the component or you are writing the interaction layer yourself.

Component Classes Reference

Button: .button, .button--{variant}, .button--{size}, .button--icon-only Accordion: .accordion, .accordion__item, .accordion__trigger, .accordion__panel, .accordion--outline

Note: See component docs for complete class references: Button, Accordion

Next Steps

On this page