Docs
Tabs
Tabs
A set of layered sections of content—known as tab panels—that are displayed one at a time.
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>
<h3 ubCardTitle>Account</h3>
<p ubCardDescription>Make changes to your account here. Click save when you're done.</p>
</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>
<h3 ubCardTitle>Account</h3>
<p ubCardDescription>Make changes to your account here. Click save when you're done.</p>
</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
npx shadcn-ng@latest add tabs
npm
yarn
pnpm
bun
Copy and paste the following code into your project.
import type { BooleanInput } from '@angular/cdk/coercion'
import { cn } from '@/lib/utils'
import { booleanAttribute, computed, Directive, 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 {
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(),
),
)
}
import { cn } from '@/lib/utils'
import { computed, Directive, 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 {
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-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(),
),
)
}
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>