# Consider Base UI for New Components

**SHOULD** · **ID:** `interactions-ibelick-base-ui` · **Category:** interactions
**Source:** [@Ibelick](https://www.ui-skills.com/)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/interactions-ibelick-base-ui

> SHOULD: Prefer Base UI for new primitives if compatible with the stack. It's unstyled, accessible, and doesn't impose styling opinions.

Prefer Base UI for new primitives, if it is compatible with the stack you already have

This is a SHOULD, and the conditional matters: it applies to *new* primitives, and only where Base UI fits the existing stack. Base UI ships fully accessible, unstyled primitives with strong TypeScript support that pair well with Tailwind. It is not a mandate to migrate primitives you already have.

## Bad — do not do this

`interactions-ibelick-base-ui-bad`

```tsx
import { useState } from 'react';

export function IbelickBaseUiBad() {
  const [value, setValue] = useState(50);

  return (
    <div className="space-y-4">
      <div className="space-y-2">
        <label className="text-sm font-medium">Custom slider:</label>
        <div
          className="relative h-2 bg-muted rounded-full cursor-pointer"
          onClick={(e) => {
            const rect = e.currentTarget.getBoundingClientRect();
            const percent = ((e.clientX - rect.left) / rect.width) * 100;
            setValue(Math.round(percent));
          }}
        >
          <div
            className="absolute h-full bg-primary rounded-full"
            style={{ width: `${value}%` }}
          />
          <div
            className="absolute top-1/2 -translate-y-1/2 size-4 bg-primary rounded-full"
            style={{ left: `calc(${value}% - 8px)` }}
          />
        </div>
        <p className="text-xs text-muted-foreground">Value: {value}</p>
      </div>
      <p className="text-xs text-destructive">
        Custom slider: no keyboard support, no ARIA, click-only interaction
      </p>
    </div>
  );
}
```

## Good — do this

`interactions-ibelick-base-ui-good`

```tsx
import { useState } from 'react';

export function IbelickBaseUiGood() {
  const [value, setValue] = useState(50);

  // Note: In production, use Base UI Slider:
  // import { Slider } from '@base_ui/react/Slider';
  // <Slider.Root value={value} onValueChange={setValue}>
  //   <Slider.Track><Slider.Indicator /><Slider.Thumb /></Slider.Track>
  // </Slider.Root>

  return (
    <div className="space-y-4">
      <div className="space-y-2">
        <label htmlFor="base-slider" className="text-sm font-medium">Base UI slider:</label>
        <input
          id="base-slider"
          type="range"
          min={0}
          max={100}
          value={value}
          onChange={(e) => setValue(Number(e.target.value))}
          className="w-full h-2 bg-muted rounded-full appearance-none cursor-pointer accent-primary"
        />
        <p className="text-xs text-muted-foreground">Value: {value}</p>
      </div>
      <p className="text-xs text-success">
        Base UI Slider: keyboard arrows, ARIA, touch support, RTL ready
      </p>
    </div>
  );
}
```

## References

- [ibelick/ui-skills — baseline-ui](https://github.com/ibelick/ui-skills)
- [Base UI Components](https://base-ui.com/react/components)
