Docs
Tabs

Tabs

A set of layered sections of content—known as tab panels—that are displayed one at a time.

Preview Code
Loading...
Loading...
import { UbButtonDirective } from '@/components/ui/button'

import { UbCardContentDirective, UbCardDescriptionDirective, UbCardDirective, UbCardFooterDirective, UbCardHeaderDirective, UbCardTitleDirective } from '@/components/ui/card'
import { UbInputDirective } from '@/components/ui/input'
import { UbLabelDirective } from '@/components/ui/label'
import { UbTabsContentDirective, UbTabsDirective, UbTabsListDirective, UbTabsTriggerDirective } from '@/components/ui/tabs'
import { Component } from '@angular/core'

@Component({
  standalone: true,
  selector: 'tabs-demo-new-york',
  imports: [
    UbTabsDirective,
    UbTabsListDirective,
    UbTabsTriggerDirective,
    UbTabsContentDirective,

    UbCardDirective,
    UbCardHeaderDirective,
    UbCardTitleDirective,
    UbCardDescriptionDirective,
    UbCardContentDirective,
    UbCardFooterDirective,

    UbButtonDirective,

    UbLabelDirective,
    UbInputDirective,
  ],
  template: `
    <div ubTabs defaultValue="account" class="w-[400px]">
        <div ubTabsList class="grid w-full grid-cols-2">
            <button ubTabsTrigger value="account">Account</button>
            <button ubTabsTrigger value="password">Password</button>
        </div>

        <section ubTabsContent value="account">
            <div ubCard>
                <div ubCardHeader>
                    <h5 ubCardTitle>Account</h5>
                    <div ubCardDescription>Make changes to your account here. Click save when you're done.</div>
                </div>

                <div ubCardContent class="space-y-2">
                    <div class="space-y-1">
                        <label ubLabel htmlFor="name">Name</label>
                        <input ubInput type="text" id="name" value="Pedro Duarte" />
                    </div>
                    <div class="space-y-1">
                        <label ubLabel htmlFor="username">Username</label>
                        <input ubInput type="text" id="username" value="@peduarte" />
                    </div>
                </div>

                <div ubCardFooter>
                    <button ubButton>Save changes</button>
                </div>
            </div>
        </section>

        <section ubTabsContent value="password">
            <div ubCard>
                <div ubCardHeader>
                    <h5 ubCardTitle>Password</h5>
                    <div ubCardDescription>Change your password here. After saving, you'll be logged out.</div>
                </div>

                <div ubCardContent class="space-y-2">
                    <div class="space-y-1">
                        <label ubLabel htmlFor="current">Current password</label>
                        <input ubInput type="password" id="current" />
                    </div>
                    <div class="space-y-1">
                        <label ubLabel htmlFor="new">New password</label>
                        <input ubInput type="password" id="new" />
                    </div>
                </div>

                <div ubCardFooter>
                    <button ubButton>Save changes</button>
                </div>
            </div>
        </section>
    </div>
    `,
})
export class TabsDemoNewYork { }

import { UbButtonDirective } from '@/components/ui/button'

import { UbCardContentDirective, UbCardDescriptionDirective, UbCardDirective, UbCardFooterDirective, UbCardHeaderDirective, UbCardTitleDirective } from '@/components/ui/card'
import { UbInputDirective } from '@/components/ui/input'
import { UbLabelDirective } from '@/components/ui/label'
import { UbTabsContentDirective, UbTabsDirective, UbTabsListDirective, UbTabsTriggerDirective } from '@/components/ui/tabs'
import { Component } from '@angular/core'

@Component({
  standalone: true,
  selector: 'tabs-demo-default',
  imports: [
    UbTabsDirective,
    UbTabsListDirective,
    UbTabsTriggerDirective,
    UbTabsContentDirective,

    UbCardDirective,
    UbCardHeaderDirective,
    UbCardTitleDirective,
    UbCardDescriptionDirective,
    UbCardContentDirective,
    UbCardFooterDirective,

    UbButtonDirective,

    UbLabelDirective,
    UbInputDirective,
  ],
  template: `
    <div ubTabs defaultValue="account" class="w-[400px]">
        <div ubTabsList class="grid w-full grid-cols-2">
            <button ubTabsTrigger value="account">Account</button>
            <button ubTabsTrigger value="password">Password</button>
        </div>

        <section ubTabsContent value="account">
            <div ubCard>
                <div ubCardHeader>
                    <h5 ubCardTitle>Account</h5>
                    <div ubCardDescription>Make changes to your account here. Click save when you're done.</div>
                </div>

                <div ubCardContent class="space-y-2">
                    <div class="space-y-1">
                        <label ubLabel htmlFor="name">Name</label>
                        <input ubInput type="text" id="name" value="Pedro Duarte" />
                    </div>
                    <div class="space-y-1">
                        <label ubLabel htmlFor="username">Username</label>
                        <input ubInput type="text" id="username" value="@peduarte" />
                    </div>
                </div>

                <div ubCardFooter>
                    <button ubButton>Save changes</button>
                </div>
            </div>
        </section>

        <section ubTabsContent value="password">
            <div ubCard>
                <div ubCardHeader>
                    <h5 ubCardTitle>Password</h5>
                    <div ubCardDescription>Change your password here. After saving, you'll be logged out.</div>
                </div>

                <div ubCardContent class="space-y-2">
                    <div class="space-y-1">
                        <label ubLabel htmlFor="current">Current password</label>
                        <input ubInput type="password" id="current" />
                    </div>
                    <div class="space-y-1">
                        <label ubLabel htmlFor="new">New password</label>
                        <input ubInput type="password" id="new" />
                    </div>
                </div>

                <div ubCardFooter>
                    <button ubButton>Save changes</button>
                </div>
            </div>
        </section>
    </div>
    `,
})
export class TabsDemoDefault { }

Installation

CLI Manual
npx shadcn-ng@latest add tabs

Copy and paste the following code into your project.

import { cn } from '@/lib/utils'

import { computed, Directive, Input, input } from '@angular/core'

import {
  RdxTabsContentDirective,
  RdxTabsListDirective,
  RdxTabsRootDirective,
  RdxTabsTriggerDirective,
} from '@radix-ng/primitives/tabs'

@Directive({
  selector: '[ubTabs]',
  standalone: true,
  hostDirectives: [
    {
      directive: RdxTabsRootDirective,
      inputs: ['defaultValue: defaultValue'],
    },
  ],
})
export class UbTabsDirective {
  @Input() defaultValue?: string
}

@Directive({
  selector: '[ubTabsList]',
  standalone: true,
  hostDirectives: [RdxTabsListDirective],
  host: {
    '[class]': 'computedClass()',
  },
})
export class UbTabsListDirective {
  readonly class = input<string>()
  protected computedClass = computed(() =>
    cn(
      'inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',
      this.class(),
    ),
  )
}

@Directive({
  selector: '[ubTabsTrigger]',
  standalone: true,
  hostDirectives: [
    { directive: RdxTabsTriggerDirective, inputs: ['value: value'] },
  ],
  host: {
    '[class]': 'computedClass()',
  },
})
export class UbTabsTriggerDirective {
  readonly value = input.required<string>()

  readonly class = input<string>()
  protected computedClass = computed(() =>
    cn(
      'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm',
      this.class(),
    ),
  )
}

@Directive({
  selector: '[ubTabsContent]',
  standalone: true,
  hostDirectives: [
    { directive: RdxTabsContentDirective, inputs: ['value: value'] },
  ],
  host: {
    '[class]': 'computedClass()',
  },
})
export class UbTabsContentDirective {
  readonly value = input.required<string>()

  readonly class = input<string>()
  protected computedClass = computed(() =>
    cn(
      'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
      this.class(),
    ),
  )
}
import { cn } from '@/lib/utils'

import { booleanAttribute, computed, Directive, input } from '@angular/core'
import {
  RdxTabsContentDirective,
  RdxTabsListDirective,
  RdxTabsRootDirective,
  RdxTabsTriggerDirective,
} from '@radix-ng/primitives/tabs'
import type { BooleanInput } from '@angular/cdk/coercion'

@Directive({
  selector: '[ubTabs]',
  standalone: true,
  hostDirectives: [
    {
      directive: RdxTabsRootDirective,
      inputs: ['defaultValue: defaultValue'],
    },
  ],
})
export class UbTabsDirective {
  defaultValue = input<string>()
}

@Directive({
  selector: '[ubTabsList]',
  standalone: true,
  hostDirectives: [RdxTabsListDirective],
  host: {
    '[class]': 'computedClass()',
  },
})
export class UbTabsListDirective {
  readonly class = input<string>()
  protected computedClass = computed(() =>
    cn(
      'inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground',
      this.class(),
    ),
  )
}

@Directive({
  selector: '[ubTabsTrigger]',
  standalone: true,
  hostDirectives: [
    { directive: RdxTabsTriggerDirective, inputs: ['value: value', 'disabled: disabled'] },
  ],
  host: {
    '[class]': 'computedClass()',
  },
})
export class UbTabsTriggerDirective {
  readonly value = input.required<string>()
  readonly disabled = input<boolean, BooleanInput>(false, {
    transform: booleanAttribute,
  })

  readonly class = input<string>()
  protected computedClass = computed(() =>
    cn(
      'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow',
      this.class(),
    ),
  )
}

@Directive({
  selector: '[ubTabsContent]',
  standalone: true,
  hostDirectives: [
    { directive: RdxTabsContentDirective, inputs: ['value: value'] },
  ],
  host: {
    '[class]': 'computedClass()',
  },
})
export class UbTabsContentDirective {
  readonly value = input.required<string>()

  readonly class = input<string>()
  protected computedClass = computed(() =>
    cn(
      'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
      this.class(),
    ),
  )
}

Update the import paths to match your project setup.

Usage

import {
    UbTabsContentDirective,
    UbTabsDirective,
    UbTabsListDirective,
    UbTabsTriggerDirective
} from '@/components/ui/tabs.directive';
<div ubTabs defaultValue="account" class="w-[400px]">
    <div ubTabsList>
        <button ubTabsTrigger value="account">Account</button>
        <button ubTabsTrigger value="password">Password</button>
    </div>

    <section ubTabsContent value="account">Make changes to your account here.</section>
    <section ubTabsContent value="password">Change your password here.</section>
</div>