Skip to main content

Install and check a Kit button

· 5 min read

This tutorial adds one Kit button to an existing React project. You will render the real component, press it, and check the same behavior with a keyboard.

Before you start

Use Node 24 and a React 18 or 19 project. The setup needs Tailwind CSS 4 and a shadcn components.json file. The file tells the CLI where to write UI components and the shared cn helper.

The published registry item contains the Button source and declares the cn registry dependency. The CLI copies the Button source, so your app does not load a Kit component runtime. The Button styles do use the published @n3wth/ui compatibility stylesheet.

Load the Kit theme

A default Tailwind and shadcn setup does not include the tokens used by this Button. The current source reads Kit variables such as --color-bg and --color-white. It also uses the shared focus-ring utility.

Install the existing shared UI package, which owns these styles:

npm install @n3wth/ui

Then load the documented compatibility stylesheet and Tailwind token bridge from your global CSS file. The compatibility entry includes the complete site foundation:

@import 'tailwindcss';
@import '@n3wth/ui/styles';
@import '@n3wth/ui/tailwind-theme.css';

This provides the Button tokens, its legacy glow-white utility, and its visible focus-ring behavior without copied local CSS.

Install the button

Run this command from the project root:

npx shadcn add https://kit.n3wth.com/r/button.json

Read the CLI summary before you accept an overwrite. In a standard shadcn setup, the component lands at components/ui/button.tsx. A custom UI alias can place it elsewhere.

Render the result

Add this client component. Change the import only if your components.json uses another UI alias.

'use client'
import { useState } from 'react'
import { Button } from '@/components/ui/button'
export function ButtonExample() {
const [pressCount, setPressCount] = useState(0)
return (
<div className="rounded-lg border border-rail bg-bg-soft p-6">
<div className="flex flex-wrap items-center gap-4">
<Button
type="button"
variant="primary"
size="md"
touchTarget
onClick={() => setPressCount((count) => count + 1)}
>
Check button
</Button>
<p className="text-sm text-ink-dim" role="status" aria-live="polite">
{pressCount === 0
? 'Not pressed yet.'
: `Pressed ${pressCount} ${pressCount === 1 ? 'time' : 'times'}.`}
</p>
</div>
</div>
)
}

The visible result is a medium primary button with a minimum 44-pixel touch target. Pressing it updates nearby status text. This live example uses the same published Button API:

Not pressed yet.

Check pointer and keyboard input

  1. Click or tap the button. The count must increase once.
  2. Press Tab until the button has a visible focus indicator.
  3. Press Enter. The count must increase once.
  4. Focus the button again and press Space. The count must increase once.
  5. Press Shift+Tab. Focus must move away from the button.

These checks use native button behavior. Do not replace the button with a clickable div.

Fix common failures

  • The CLI cannot find components.json: initialize shadcn in the app, then run the install command again.
  • The import cannot resolve: use the UI alias and output path shown by your CLI.
  • The cn helper cannot resolve: check the utils alias in components.json. The Button item declares this registry dependency.
  • The button works but looks wrong: confirm that your global CSS imports both documented n3wth styles after Tailwind. Default shadcn variables do not replace the Kit names used by this source.
  • The CLI asks to overwrite a file: stop and compare your local edits before you continue.

If you need to choose between source-owned components and package-owned components, read the Garden comparison of Astryx, shadcn, and Angular Material.