Skip to content

Commit fc39f7e

Browse files
committed
feat: add new directives for breadcrumb, collapsible, scroll area, slider, and toggle group components
1 parent ea698ff commit fc39f7e

16 files changed

Lines changed: 262 additions & 10 deletions

src/packages/registry/badge/badge.directive.ts.template

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,24 @@ import { LuminaBadgeVariant } from './badge.types';
1111
},
1212
})
1313
export class LuminaBadgeDirective {
14-
variant = input<LuminaBadgeVariant>('default', { alias: 'lmBadge' });
14+
// Supports shorthand: <span lmBadge> or <span lmBadge="outline">
15+
variant = input<LuminaBadgeVariant, LuminaBadgeVariant | ''>('default', {
16+
alias: 'lmBadge',
17+
transform: (v) => (v === '' ? 'default' : v),
18+
});
19+
20+
// Supports shape change: <span lmBadge shape="square">
21+
shape = input<'pill' | 'square'>('pill');
1522

1623
userClass = input<string>('', { alias: 'class' });
1724

18-
computedClass = computed(() => cn(badgeVariants({ variant: this.variant() }), this.userClass()));
25+
computedClass = computed(() =>
26+
cn(
27+
badgeVariants({
28+
variant: this.variant() as LuminaBadgeVariant,
29+
shape: this.shape(),
30+
}),
31+
this.userClass(),
32+
),
33+
);
1934
}

src/packages/registry/badge/badge.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"destination": "ui/badge",
44
"primaryExport": "LuminaBadgeComponent",
55
"files": [
6-
"badge.component.ts.template",
76
"badge.variants.ts.template",
87
"badge.types.ts.template",
98
"badge.directive.ts.template"
Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
export type LuminaBadgeVariant =
2-
| "default"
3-
| "secondary"
4-
| "outline"
5-
| "destructive";
1+
export type LuminaBadgeVariant = 'default' | 'secondary' | 'destructive' | 'outline';
2+
export type LuminaBadgeShape = 'pill' | 'square'; // Added this
3+
4+
export interface LuminaBadgeProps {
5+
variant?: LuminaBadgeVariant;
6+
shape?: LuminaBadgeShape;
7+
class?: string;
8+
}

src/packages/registry/badge/badge.variants.ts.template

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { cva } from '../../../lib/cva';
2-
import type { LuminaBadgeVariant } from './badge.types';
2+
import { LuminaBadgeVariant } from './badge.types';
33

44
export const badgeVariants = cva(
5-
'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
5+
'inline-flex items-center border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
66
{
77
variants: {
88
variant: {
@@ -13,9 +13,15 @@ export const badgeVariants = cva(
1313
'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
1414
outline: 'text-foreground',
1515
} as Record<LuminaBadgeVariant, string>,
16+
// New: Add shape variants
17+
shape: {
18+
pill: 'rounded-full',
19+
square: 'rounded-md',
20+
},
1621
},
1722
defaultVariants: {
1823
variant: 'default',
24+
shape: 'pill',
1925
},
2026
},
2127
);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Directive, input, computed } from '@angular/core';
2+
import { cn } from '../../../lib/cn';
3+
4+
@Directive({
5+
selector: 'li[lmBreadcrumbItem]',
6+
standalone: true,
7+
host: { '[class]': 'computedClass()' },
8+
})
9+
export class LuminaBreadcrumbItemDirective {
10+
userClass = input('', { alias: 'class' });
11+
computedClass = computed(() => cn('inline-flex items-center gap-1.5', this.userClass()));
12+
}
13+
14+
@Directive({
15+
selector: 'a[lmBreadcrumbLink]',
16+
standalone: true,
17+
host: { '[class]': 'computedClass()' },
18+
})
19+
export class LuminaBreadcrumbLinkDirective {
20+
userClass = input('', { alias: 'class' });
21+
computedClass = computed(() => cn('transition-colors hover:text-foreground', this.userClass()));
22+
}
23+
24+
@Directive({
25+
selector: 'span[lmBreadcrumbPage]',
26+
standalone: true,
27+
host: {
28+
'[class]': 'computedClass()',
29+
role: 'link',
30+
'aria-disabled': 'true',
31+
'aria-current': 'page',
32+
},
33+
})
34+
export class LuminaBreadcrumbPageDirective {
35+
userClass = input('', { alias: 'class' });
36+
computedClass = computed(() => cn('font-normal text-foreground', this.userClass()));
37+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Directive, input, computed } from '@angular/core';
2+
import { cn } from '../../../lib/cn';
3+
4+
@Directive({
5+
selector: 'li[lmBreadcrumbSeparator]',
6+
standalone: true,
7+
host: {
8+
'[class]': 'computedClass()',
9+
role: 'presentation',
10+
'aria-hidden': 'true',
11+
},
12+
})
13+
export class LuminaBreadcrumbSeparatorDirective {
14+
userClass = input('', { alias: 'class' });
15+
computedClass = computed(() => cn('[&>svg]:size-3.5', this.userClass()));
16+
}
17+
18+
@Directive({
19+
selector: 'span[lmBreadcrumbEllipsis]',
20+
standalone: true,
21+
host: {
22+
'[class]': 'computedClass()',
23+
role: 'presentation',
24+
'aria-hidden': 'true',
25+
},
26+
})
27+
export class LuminaBreadcrumbEllipsisDirective {
28+
userClass = input('', { alias: 'class' });
29+
computedClass = computed(() => cn('flex h-9 w-9 items-center justify-center', this.userClass()));
30+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Directive, input, computed } from '@angular/core';
2+
import { cn } from '../../../lib/cn';
3+
4+
@Directive({
5+
selector: 'nav[lmBreadcrumb]',
6+
standalone: true,
7+
host: { 'aria-label': 'breadcrumb' },
8+
})
9+
export class LuminaBreadcrumbDirective {}
10+
11+
@Directive({
12+
selector: 'ol[lmBreadcrumbList]',
13+
standalone: true,
14+
host: { '[class]': 'computedClass()' },
15+
})
16+
export class LuminaBreadcrumbListDirective {
17+
userClass = input('', { alias: 'class' });
18+
computedClass = computed(() =>
19+
cn(
20+
'flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5',
21+
this.userClass(),
22+
),
23+
);
24+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "breadcrumb",
3+
"destination": "ui/breadcrumb",
4+
"primaryExport": "LuminaBreadcrumbDirective",
5+
"files": [
6+
"breadcrumb-item.directive.ts.template",
7+
"breadcrumb-shared.directive.ts.template",
8+
"breadcrumb.directive.ts.template"
9+
]
10+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Directive, model } from '@angular/core';
2+
3+
@Directive({
4+
selector: '[lmCollapsible]',
5+
exportAs: 'lmCollapsible',
6+
host: {
7+
'[attr.aria-expanded]': 'open()',
8+
'[attr.data-state]': 'open() ? "open" : "closed"',
9+
},
10+
})
11+
export class LuminaCollapsibleDirective {
12+
open = model(false);
13+
14+
toggle() {
15+
this.open.update((v) => !v);
16+
}
17+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "collapsible",
3+
"destination": "ui/collapsible",
4+
"primaryExport": "LuminaCollapsibleDirective",
5+
"files": ["collapsible.directive.ts.template"]
6+
}

0 commit comments

Comments
 (0)