Skip to content
Nerdfishui
Esc
navigateopen⌘Jpreview
On this page

Button

Buttons are used to trigger actions.

'use client'

import { Button } from '@nerdfish/react/button'

export default function ButtonExample() {
	return <Button>Button</Button>
}

Variants

'use client'

import { Button } from '@nerdfish/react/button'

export default function ButtonVariantsExample() {
	return (
		<div className="space-y-friends flex flex-col">
			<Button variant="default">Default</Button>
			<Button variant="accent">Nerdfish</Button>
			<Button variant="secondary">Secondary</Button>
			<Button variant="destructive" onClick={() => {}}>
				Danger
			</Button>
			<Button variant="success">Success</Button>
			<Button variant="ghost">Ghost</Button>
			<Button variant="outline">Outline</Button>
			<Button variant="link">Link</Button>
		</div>
	)
}

Disabled

'use client'

import { Button } from '@nerdfish/react/button'

export default function ButtonDisabledExample() {
	return (
		<div className="space-y-friends flex flex-col">
			<Button disabled variant="default">
				Default
			</Button>
			<Button disabled variant="accent">
				Nerdfish
			</Button>
			<Button disabled variant="secondary">
				Secondary
			</Button>
			<Button disabled variant="destructive">
				Danger
			</Button>
			<Button disabled variant="success">
				Success
			</Button>
			<Button disabled variant="ghost">
				Ghost
			</Button>
			<Button disabled variant="outline">
				Outline
			</Button>
			<Button disabled variant="link">
				Link
			</Button>
		</div>
	)
}

Sizes

'use client'

import { Button } from '@nerdfish/react/button'
import { ButtonGroup } from '@nerdfish/react/button-group'
import { Mail } from 'lucide-react'

export default function ButtonSizesExample() {
	return (
		<div className="gap-casual flex flex-col">
			<div className="gap-best-friends flex flex-col">
				<div>
					<Button variant="accent" size="xs">
						Extra Small
					</Button>
				</div>
				<div>
					<Button variant="accent" size="sm">
						Small
					</Button>
				</div>
				<div>
					<Button variant="accent" size="md">
						Medium
					</Button>
				</div>
				<div>
					<Button variant="accent" size="lg">
						Large
					</Button>
				</div>
				<div>
					<Button variant="accent" size="xl">
						Extra Large
					</Button>
				</div>
			</div>
			<div className="gap-best-friends flex flex-col">
				<ButtonGroup>
					<Button size="xs">Extra small</Button>
					<Button size="xs" icon>
						<Mail />
					</Button>
				</ButtonGroup>
				<ButtonGroup>
					<Button size="sm">Small</Button>
					<Button size="sm" icon>
						<Mail />
					</Button>
				</ButtonGroup>
				<ButtonGroup>
					<Button>Medium</Button>
					<Button icon>
						<Mail />
					</Button>
				</ButtonGroup>
				<ButtonGroup>
					<Button size="lg">Large</Button>
					<Button size="lg" icon>
						<Mail />
					</Button>
				</ButtonGroup>
				<ButtonGroup>
					<Button size="xl">Extra Large</Button>
					<Button size="xl" icon>
						<Mail />
					</Button>
				</ButtonGroup>
			</div>
			<div className="gap-best-friends flex flex-col">
				<Button variant="accent" size="xs" icon>
					<Mail />
				</Button>
				<Button variant="accent" size="sm" icon>
					<Mail />
				</Button>
				<Button variant="accent" size="md" icon>
					<Mail />
				</Button>
				<Button variant="accent" size="lg" icon>
					<Mail />
				</Button>
				<Button variant="accent" size="xl" icon>
					<Mail />
				</Button>
			</div>
		</div>
	)
}

With Icon

'use client'

import { Button } from '@nerdfish/react/button'
import { MailIcon } from 'lucide-react'

export default function ButtonWithIconExample() {
	return (
		<Button>
			<MailIcon className="mr-best-friends size-4" /> Login with Email
		</Button>
	)
}

Loading

'use client'

import { Button } from '@nerdfish/react/button'
import { Loader2 } from 'lucide-react'

export default function ButtonLoadingExample() {
	return (
		<Button disabled>
			<Loader2 className="mr-best-friends size-4 animate-spin" />
			Please wait
		</Button>
	)
}

Icon only

'use client'

import { Button } from '@nerdfish/react/button'
import { Mail } from 'lucide-react'

export default function ButtonIconOnlyExample() {
	return (
		<Button icon>
			<Mail className="size-4" />
			<span className="sr-only">Mail</span>
		</Button>
	)
}

Render

'use client'

import { Button } from '@nerdfish/react/button'

export default function ButtonRenderExample() {
	return <Button render={<a href="https://nerdfish.be">Nerdfish</a>} />
}

Button Group

'use client'

import { Button } from '@nerdfish/react/button'
import { ButtonGroup } from '@nerdfish/react/button-group'
import {
	DropdownMenu,
	DropdownMenuContent,
	DropdownMenuGroup,
	DropdownMenuItem,
	DropdownMenuRadioGroup,
	DropdownMenuRadioItem,
	DropdownMenuSeparator,
	DropdownMenuSub,
	DropdownMenuSubContent,
	DropdownMenuSubTrigger,
	DropdownMenuTrigger,
} from '@nerdfish/react/dropdown-menu'
import {
	ArchiveIcon,
	ArrowLeftIcon,
	CalendarPlusIcon,
	ClockIcon,
	ListFilterPlusIcon,
	MailCheckIcon,
	MoreHorizontalIcon,
	TagIcon,
	Trash2Icon,
} from 'lucide-react'
import { useState } from 'react'

export default function ButtonGroupExample() {
	const [label, setLabel] = useState('personal')

	return (
		<ButtonGroup className="gap-friends">
			<ButtonGroup>
				<Button variant="outline" icon aria-label="Go Back">
					<ArrowLeftIcon />
				</Button>
			</ButtonGroup>
			<ButtonGroup>
				<Button variant="outline">Archive</Button>
				<Button variant="outline">Report</Button>
			</ButtonGroup>
			<ButtonGroup>
				<Button variant="outline">Snooze</Button>
				<DropdownMenu>
					<DropdownMenuTrigger
						render={
							<Button variant="outline" icon aria-label="More Options">
								<MoreHorizontalIcon />
							</Button>
						}
					/>
					<DropdownMenuContent align="end" className="w-52">
						<DropdownMenuGroup>
							<DropdownMenuItem>
								<MailCheckIcon />
								Mark as Read
							</DropdownMenuItem>
							<DropdownMenuItem>
								<ArchiveIcon />
								Archive
							</DropdownMenuItem>
						</DropdownMenuGroup>
						<DropdownMenuSeparator />
						<DropdownMenuGroup>
							<DropdownMenuItem>
								<ClockIcon />
								Snooze
							</DropdownMenuItem>
							<DropdownMenuItem>
								<CalendarPlusIcon />
								Add to Calendar
							</DropdownMenuItem>
							<DropdownMenuItem>
								<ListFilterPlusIcon />
								Add to List
							</DropdownMenuItem>
							<DropdownMenuSub>
								<DropdownMenuSubTrigger>
									<TagIcon />
									Label As...
								</DropdownMenuSubTrigger>
								<DropdownMenuSubContent>
									<DropdownMenuRadioGroup
										value={label}
										onValueChange={setLabel}
									>
										<DropdownMenuRadioItem value="personal">
											Personal
										</DropdownMenuRadioItem>
										<DropdownMenuRadioItem value="work">
											Work
										</DropdownMenuRadioItem>
										<DropdownMenuRadioItem value="other">
											Other
										</DropdownMenuRadioItem>
									</DropdownMenuRadioGroup>
								</DropdownMenuSubContent>
							</DropdownMenuSub>
						</DropdownMenuGroup>
						<DropdownMenuSeparator />
						<DropdownMenuGroup>
							<DropdownMenuItem variant="destructive">
								<Trash2Icon />
								Trash
							</DropdownMenuItem>
						</DropdownMenuGroup>
					</DropdownMenuContent>
				</DropdownMenu>
			</ButtonGroup>
		</ButtonGroup>
	)
}

Button Group Use Case

'use client'

import { Button } from '@nerdfish/react/button'
import { ButtonGroup } from '@nerdfish/react/button-group'
import {
	DropdownMenuGroup,
	DropdownMenu,
	DropdownMenuContent,
	DropdownMenuItem,
	DropdownMenuTrigger,
} from '@nerdfish/react/dropdown-menu'
import { ChevronDownIcon } from 'lucide-react'
import { useState } from 'react'

const descriptionsMap = {
	merge:
		'All commits from the source branch are added to the destination branch via a merge commit.',
	squash:
		'All commits from the source branch are added to the destination branch as a single commit.',
	rebase:
		'All commits from the source branch are added to the destination branch individually.',
}

const labelsMap = {
	merge: 'Create a merge commit',
	squash: 'Squash and merge',
	rebase: 'Rebase and merge',
}

export default function ButtonGroupUseCase() {
	const [selectedOption, setSelectedOption] =
		useState<keyof typeof labelsMap>('merge')

	return (
		<ButtonGroup>
			<Button variant="success">{labelsMap[selectedOption]}</Button>

			<DropdownMenu>
				<DropdownMenuTrigger
					render={
						<Button variant="success" icon>
							<ChevronDownIcon className="size-4" />
						</Button>
					}
				/>
				<DropdownMenuContent className="max-w-75">
					<DropdownMenuGroup>
						{Object.entries(labelsMap).map(([key, label]) => {
							const option = key as keyof typeof labelsMap
							return (
								<DropdownMenuItem
									onSelect={() => setSelectedOption(option)}
									key={key}
								>
									<div className="gap-best-friends flex flex-col">
										<span className="font-bold">{label}</span>
										<p className="text-sm">{descriptionsMap[option]}</p>
									</div>
								</DropdownMenuItem>
							)
						})}
					</DropdownMenuGroup>
				</DropdownMenuContent>
			</DropdownMenu>
		</ButtonGroup>
	)
}