# Use Existing Components First

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

> MUST: Use the project's existing component primitives before introducing new libraries. Check for existing Button, Dialog, Popover components first.

Before building custom UI, check if an existing component library already solves the problem

Building UI components from scratch introduces accessibility bugs, inconsistent behavior, maintenance burden, and duplicated effort. The project's own primitives have already been tested, styled, and documented — reach for those before reaching for a new dependency or a hand-rolled component.

## Bad — do not do this

`interactions-ibelick-existing-components-bad`

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

export function IbelickExistingComponentsBad() {
  const [isOn, setIsOn] = useState(false);

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-3">
        <span className="text-sm">Custom toggle:</span>
        <div
          onClick={() => setIsOn(!isOn)}
          className={`relative w-12 h-6 rounded-full cursor-pointer transition-colors ${
            isOn ? 'bg-primary' : 'bg-muted'
          }`}
        >
          <div
            className={`absolute top-1 size-4 bg-white rounded-full transition-transform ${
              isOn ? 'translate-x-7' : 'translate-x-1'
            }`}
          />
        </div>
      </div>
      <p className="text-xs text-destructive">
        Custom toggle: no keyboard support, no ARIA, no focus indicator
      </p>
    </div>
  );
}
```

## Good — do this

`interactions-ibelick-existing-components-good`

```tsx
import { useState } from 'react';
import { Switch } from '@/components/ui/switch';

export function IbelickExistingComponentsGood() {
  const [isOn, setIsOn] = useState(false);

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-3">
        <label htmlFor="notifications" className="text-sm">
          Email notifications
        </label>
        {/* The actual Switch from the design system, built on Radix. */}
        <Switch id="notifications" checked={isOn} onCheckedChange={setIsOn} />
      </div>
      <p className="text-xs text-success">
        The existing <code>Switch</code> is imported from the design system, so keyboard support, ARIA state and the
        focus ring come with it rather than being reimplemented
      </p>
    </div>
  );
}
```

## References

- [ibelick/ui-skills — baseline-ui](https://github.com/ibelick/ui-skills)
- [shadcn/ui Components](https://ui.shadcn.com/)
