Documentation
Documentation
Introduction

Getting Started

Getting StartedInstallationQuick StartProject Structure

Architecture

Architecture OverviewTech StacktRPC MiddlewareDesign Principles

Patterns

Code Patterns & ConventionsFeature ModulesError HandlingType Safety

Database

DatabaseSchema DefinitionDatabase OperationsMigrationsCaching

API

tRPCProceduresRouterstRPC Proxy Setup
APIsOpenAPIREST Endpoints

Auth & Access

AuthenticationConfigurationOAuth ProvidersRolesSession Management
AuthorizationUser RolesPermissions

Routing & i18n

RoutingDeclarative RoutingNavigation
InternationalizationTranslationsLocale Routing

Components & UI

ComponentsButtonsFormsNavigationDialogs
StylesTailwind CSSThemingTypography

Storage

StorageConfigurationUsageBuckets

Configuration

ConfigurationEnvironment VariablesFeature Flags

Templates

Template GuidesCreate New FeatureCreate New PageCreate Database TableCreate tRPC RouterAdd Translations

Development

DevelopmentCommandsAI AgentsBest Practices

Buttons

Button and link components

The project provides Button and ButtonLink components with built-in support for icons, loading states, and internationalization.

Basic Usage

import { Button, ButtonLink } from "@/components/ui/button";

<Button onClick={handleClick}>
  Click Me
</Button>

<ButtonLink href="/about">
  About Us
</ButtonLink>

Button Variants

VariantUse Case
defaultStandard actions
destructiveDelete or dangerous actions
outlineSecondary actions
secondaryAlternative styling
ghostSubtle actions, toolbar buttons
linkText-style links
<Button variant="default">Save</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Cancel</Button>
<Button variant="ghost">Skip</Button>

With Icons

Use the icon prop to add an icon from the icon registry:

<Button icon="save" variant="primary">
  Save Changes
</Button>

<Button icon="trash" variant="destructive">
  Delete
</Button>

<Button icon="download" variant="outline">
  Export
</Button>

The icon is automatically positioned before the text content.

Loading State

Set loading={true} to show a spinner and disable the button:

<Button
  loading={isDeleting}
  variant="destructive"
  icon="trash"
>
  Delete
</Button>

When loading, the button:

  • Shows a spinner icon
  • Becomes disabled
  • Maintains its dimensions

Internationalized Button Text

Use i18nButtonKey to automatically load translated button text:

<Button
  i18nButtonKey="save"
  icon="save"
  onClick={handleSave}
/>

<Button
  i18nButtonKey="delete"
  icon="trash"
  variant="destructive"
/>

This loads text from messages/dictionaries/{locale}/buttons.json:

{
  "save": "Save Changes",
  "delete": "Delete",
  "cancel": "Cancel"
}

When using i18nButtonKey, you don't need to provide children content—the text is loaded automatically.

ButtonLink

For navigation, use ButtonLink with the same API:

import { PageAbout } from "@/routes";

<ButtonLink href={PageAbout()}>
  About Us
</ButtonLink>

<ButtonLink
  href={PageDashboard()}
  variant="primary"
  icon="arrowRight"
>
  Go to Dashboard
</ButtonLink>

Combined Example

<Button
  variant="primary"
  icon="save"
  i18nButtonKey="save"
  loading={isSaving}
  onClick={handleSave}
/>

This button will:

  1. Show "Save Changes" text (from translations)
  2. Display a save icon (when not loading)
  3. Show spinner when isSaving is true
  4. Call handleSave on click

Best Practices

  1. Use i18nButtonKey - Prefer i18nButtonKey over hardcoded text for consistency
  2. Add icons for clarity - Icons help users understand button actions quickly
  3. Use appropriate variants - Match the variant to the action severity (destructive for delete, etc.)
  4. Handle loading states - Always show loading state during async operations

On this page

Basic Usage
Button Variants
With Icons
Loading State
Internationalized Button Text
ButtonLink
Combined Example
Best Practices