diff --git a/package-lock.json b/package-lock.json
index a22ecdc..897d7e2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -30,8 +30,7 @@
"rxjs": "~7.8.0",
"tailwind-variants": "^1.0.0",
"tailwindcss": "^4.1.11",
- "tslib": "^2.3.0",
- "tw-animate-css": "^1.3.7"
+ "tslib": "^2.3.0"
},
"devDependencies": {
"@angular/build": "^20.1.3",
@@ -48,6 +47,7 @@
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"ng-packagr": "^20.1.0",
+ "tw-animate-css": "^1.3.8",
"typescript": "~5.8.2"
}
},
@@ -10516,9 +10516,10 @@
}
},
"node_modules/tw-animate-css": {
- "version": "1.3.7",
- "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.7.tgz",
- "integrity": "sha512-lvLb3hTIpB5oGsk8JmLoAjeCHV58nKa2zHYn8yWOoG5JJusH3bhJlF2DLAZ/5NmJ+jyH3ssiAx/2KmbhavJy/A==",
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.8.tgz",
+ "integrity": "sha512-Qrk3PZ7l7wUcGYhwZloqfkWCmaXZAoqjkdbIDvzfGshwGtexa/DAs9koXxIkrpEasyevandomzCBAV1Yyop5rw==",
+ "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/Wombosvideo"
diff --git a/package.json b/package.json
index 5e56e45..ed3b4fc 100644
--- a/package.json
+++ b/package.json
@@ -45,8 +45,7 @@
"rxjs": "~7.8.0",
"tailwind-variants": "^1.0.0",
"tailwindcss": "^4.1.11",
- "tslib": "^2.3.0",
- "tw-animate-css": "^1.3.7"
+ "tslib": "^2.3.0"
},
"devDependencies": {
"@angular/build": "^20.1.3",
@@ -63,6 +62,7 @@
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"ng-packagr": "^20.1.0",
+ "tw-animate-css": "^1.3.8",
"typescript": "~5.8.2"
}
}
diff --git a/projects/docs/src/app/pages/docs/components/components.routes.ts b/projects/docs/src/app/pages/docs/components/components.routes.ts
index c3b4902..6f75b4a 100644
--- a/projects/docs/src/app/pages/docs/components/components.routes.ts
+++ b/projects/docs/src/app/pages/docs/components/components.routes.ts
@@ -88,6 +88,14 @@ export const routes: Routes = [
path: 'toggle',
loadComponent: () => import('./toggle/toggle').then(m => m.Toggle)
},
+ {
+ path: 'toggle-group',
+ loadComponent: () => import('./toggle-group/toggle-group').then(m => m.ToggleGroup)
+ },
+ {
+ path: 'skeleton',
+ loadComponent: () => import('./skeleton/skeleton').then(m => m.Skeleton)
+ },
{
path: '',
redirectTo: 'alert',
diff --git a/projects/docs/src/app/pages/docs/components/skeleton/skeleton.ts b/projects/docs/src/app/pages/docs/components/skeleton/skeleton.ts
new file mode 100644
index 0000000..3458597
--- /dev/null
+++ b/projects/docs/src/app/pages/docs/components/skeleton/skeleton.ts
@@ -0,0 +1,18 @@
+import { Component } from '@angular/core';
+import { ComponentPreview } from '@components/component-preview/component-preview';
+import { skeletonVariants, skeletonMeta } from './skeleton.variants';
+
+@Component({
+ selector: 'docs-skeleton',
+ imports: [ComponentPreview],
+ template: `
+
+
+ `
+})
+export class Skeleton {
+ skeletonMeta = skeletonMeta;
+ skeletonVariants = skeletonVariants;
+}
diff --git a/projects/docs/src/app/pages/docs/components/skeleton/skeleton.variants.ts b/projects/docs/src/app/pages/docs/components/skeleton/skeleton.variants.ts
new file mode 100644
index 0000000..e2a06b8
--- /dev/null
+++ b/projects/docs/src/app/pages/docs/components/skeleton/skeleton.variants.ts
@@ -0,0 +1,161 @@
+import { Component } from '@angular/core';
+import { UiSkeleton } from 'ui';
+import { IVariant, IComponentMeta } from '@components/component-preview/component-preview';
+
+@Component({
+ selector: 'skeleton-default-example',
+ template: `
+
+ `,
+ imports: [UiSkeleton]
+})
+export class SkeletonDefaultExample {}
+
+@Component({
+ selector: 'skeleton-card-example',
+ template: `
+
+ `,
+ imports: [UiSkeleton]
+})
+export class SkeletonCardExample {}
+
+@Component({
+ selector: 'skeleton-list-example',
+ template: `
+
+ `,
+ imports: [UiSkeleton]
+})
+export class SkeletonListExample {}
+
+export const skeletonMeta: IComponentMeta = {
+ title: 'Skeleton',
+ description: 'Use to show a placeholder while content is loading.',
+ installation: {
+ package: 'skeleton',
+ import: `import { UiSkeleton } from '@workspace/ui/directives/skeleton';`,
+ usage: ``
+ },
+ api: {
+ props: [
+ { name: 'class', type: 'string', description: 'Additional CSS classes to apply to the skeleton element.' }
+ ]
+ }
+};
+
+export const skeletonVariants: IVariant[] = [
+ {
+ title: 'Default',
+ description: 'A basic skeleton with avatar and text placeholders.',
+ code: `import { UiSkeleton } from '@workspace/ui/directives/skeleton';
+
+@Component({
+ selector: 'skeleton-default-example',
+ template: \`
+
+ \`,
+ imports: [UiSkeleton]
+})
+export class SkeletonDefaultExample {}`,
+ component: SkeletonDefaultExample
+ },
+ {
+ title: 'Card',
+ description: 'A skeleton for card layouts with image and text placeholders.',
+ code: `import { UiSkeleton } from '@workspace/ui/directives/skeleton';
+
+@Component({
+ selector: 'skeleton-card-example',
+ template: \`
+
+ \`,
+ imports: [UiSkeleton]
+})
+export class SkeletonCardExample {}`,
+ component: SkeletonCardExample
+ },
+ {
+ title: 'List',
+ description: 'A skeleton for list layouts with multiple items.',
+ code: `import { UiSkeleton } from '@workspace/ui/directives/skeleton';
+
+@Component({
+ selector: 'skeleton-list-example',
+ template: \`
+
+ \`,
+ imports: [UiSkeleton]
+})
+export class SkeletonListExample {}`,
+ component: SkeletonListExample
+ }
+];
diff --git a/projects/docs/src/app/pages/docs/components/toggle-group/toggle-group.ts b/projects/docs/src/app/pages/docs/components/toggle-group/toggle-group.ts
new file mode 100644
index 0000000..e2d1246
--- /dev/null
+++ b/projects/docs/src/app/pages/docs/components/toggle-group/toggle-group.ts
@@ -0,0 +1,19 @@
+import { Component } from '@angular/core';
+import { ComponentPreview } from '@components/component-preview/component-preview';
+import { toggleGroupVariants, toggleGroupMeta } from './toggle-group.variants';
+
+@Component({
+ selector: 'docs-toggle-group',
+ imports: [ComponentPreview],
+ template: `
+
+
+ `
+})
+export class ToggleGroup {
+ toggleGroupMeta = toggleGroupMeta;
+ toggleGroupVariants = toggleGroupVariants;
+}
+
diff --git a/projects/docs/src/app/pages/docs/components/toggle-group/toggle-group.variants.ts b/projects/docs/src/app/pages/docs/components/toggle-group/toggle-group.variants.ts
new file mode 100644
index 0000000..965c059
--- /dev/null
+++ b/projects/docs/src/app/pages/docs/components/toggle-group/toggle-group.variants.ts
@@ -0,0 +1,422 @@
+import { Component, effect, model } from '@angular/core';
+import { UiToggleGroup, UiToggleGroupItem } from 'ui';
+import { IVariant, IComponentMeta } from '@components/component-preview/component-preview';
+import { NgIcon, provideIcons } from '@ng-icons/core';
+import { lucideBold, lucideItalic, lucideUnderline, lucideAlignLeft, lucideAlignCenter, lucideAlignRight } from '@ng-icons/lucide';
+
+// Toggle Group example components for dynamic rendering
+@Component({
+ selector: 'toggle-group-default-example',
+ template: `
+
+
+
+
+
+ `,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })]
+})
+export class ToggleGroupDefaultExample {}
+
+@Component({
+ selector: 'toggle-group-outline-example',
+ template: `
+
+
+
+
+
+ `,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })]
+})
+export class ToggleGroupOutlineExample {}
+
+@Component({
+ selector: 'toggle-group-single-example',
+ template: `
+
+
+
+
+
+ `,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })]
+})
+export class ToggleGroupSingleExample {}
+
+@Component({
+ selector: 'toggle-group-small-example',
+ template: `
+
+
+
+
+
+ `,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })]
+})
+export class ToggleGroupSmallExample {}
+
+@Component({
+ selector: 'toggle-group-large-example',
+ template: `
+
+
+
+
+
+ `,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })]
+})
+export class ToggleGroupLargeExample {}
+
+@Component({
+ selector: 'toggle-group-disabled-example',
+ template: `
+
+
+
+
+
+ `,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })]
+})
+export class ToggleGroupDisabledExample {}
+
+@Component({
+ selector: 'toggle-group-text-example',
+ template: `
+
+
+
+
+
+ `,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideAlignLeft, lucideAlignCenter, lucideAlignRight })]
+})
+export class ToggleGroupTextExample {}
+
+export const toggleGroupMeta: IComponentMeta = {
+ title: 'Toggle Group',
+ description: 'A set of two-state buttons that can be toggled on or off.',
+ installation: {
+ package: 'toggle-group',
+ import: `import { UiToggleGroup, UiToggleGroupItem } from '@workspace/ui/directives/toggle-group';`,
+ usage: `
+
+
+
+
`
+ },
+ api: {
+ props: [
+ {
+ name: 'variant',
+ type: '"default" | "outline"',
+ default: '"default"',
+ description: 'The visual variant of the toggle group. Applied to both the group container and all items.'
+ },
+ {
+ name: 'size',
+ type: '"default" | "sm" | "lg"',
+ default: '"default"',
+ description: 'The size of the toggle group. Applied to both the group container and all items.'
+ },
+ {
+ name: 'type',
+ type: '"single" | "multiple"',
+ default: '"single"',
+ description: 'Whether to allow single or multiple selections.'
+ },
+ {
+ name: 'disabled',
+ type: 'boolean',
+ default: 'false',
+ description: 'Whether the toggle group is disabled.'
+ },
+ {
+ name: 'groupValue',
+ type: 'string | string[]',
+ description: 'The current value(s) of the toggle group.'
+ },
+ {
+ name: 'value',
+ type: 'string',
+ description: 'The value of the toggle group item. Items inherit variant and size from parent.'
+ },
+ {
+ name: 'disabled',
+ type: 'boolean',
+ default: 'false',
+ description: 'Whether the toggle group item is disabled.'
+ },
+ {
+ name: 'class',
+ type: 'string',
+ description: 'Additional CSS classes to apply to the toggle group or item.'
+ }
+ ],
+ outputs: [
+ {
+ name: 'groupValueChange',
+ type: 'EventEmitter',
+ description: 'Event emitted when the toggle group value changes.'
+ }
+ ]
+ }
+};
+
+export const toggleGroupVariants: IVariant[] = [
+ {
+ title: 'Default',
+ description: 'The default toggle group with multiple selection.',
+ code: `import { UiToggleGroup, UiToggleGroupItem } from '@workspace/ui/directives/toggle-group';
+import { NgIcon, provideIcons } from '@ng-icons/core';
+import { lucideBold, lucideItalic, lucideUnderline } from '@ng-icons/lucide';
+
+@Component({
+ selector: 'toggle-group-default-example',
+ template: \`
+
+
+
+
+
+ \`,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })]
+})
+export class ToggleGroupDefaultExample {}`,
+ component: ToggleGroupDefaultExample
+ },
+ {
+ title: 'Outline',
+ description: 'A toggle group with an outlined appearance.',
+ code: `import { UiToggleGroup, UiToggleGroupItem } from '@workspace/ui/directives/toggle-group';
+import { NgIcon, provideIcons } from '@ng-icons/core';
+import { lucideBold, lucideItalic, lucideUnderline } from '@ng-icons/lucide';
+
+@Component({
+ selector: 'toggle-group-outline-example',
+ template: \`
+
+
+
+
+
+ \`,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })]
+})
+export class ToggleGroupOutlineExample {}`,
+ component: ToggleGroupOutlineExample
+ },
+ {
+ title: 'Single Selection',
+ description: 'A toggle group that allows only single selection.',
+ code: `import { UiToggleGroup, UiToggleGroupItem } from '@workspace/ui/directives/toggle-group';
+import { NgIcon, provideIcons } from '@ng-icons/core';
+import { lucideBold, lucideItalic, lucideUnderline } from '@ng-icons/lucide';
+
+@Component({
+ selector: 'toggle-group-single-example',
+ template: \`
+
+
+
+
+
+ \`,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })]
+})
+export class ToggleGroupSingleExample {}`,
+ component: ToggleGroupSingleExample
+ },
+ {
+ title: 'Small Size',
+ description: 'A toggle group in small size.',
+ code: `import { UiToggleGroup, UiToggleGroupItem } from '@workspace/ui/directives/toggle-group';
+import { NgIcon, provideIcons } from '@ng-icons/core';
+import { lucideBold, lucideItalic, lucideUnderline } from '@ng-icons/lucide';
+
+@Component({
+ selector: 'toggle-group-small-example',
+ template: \`
+
+
+
+
+
+ \`,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })]
+})
+export class ToggleGroupSmallExample {}`,
+ component: ToggleGroupSmallExample
+ },
+ {
+ title: 'Large Size',
+ description: 'A toggle group in large size.',
+ code: `import { UiToggleGroup, UiToggleGroupItem } from '@workspace/ui/directives/toggle-group';
+import { NgIcon, provideIcons } from '@ng-icons/core';
+import { lucideBold, lucideItalic, lucideUnderline } from '@ng-icons/lucide';
+
+@Component({
+ selector: 'toggle-group-large-example',
+ template: \`
+
+
+
+
+
+ \`,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })]
+})
+export class ToggleGroupLargeExample {}`,
+ component: ToggleGroupLargeExample
+ },
+ {
+ title: 'Disabled',
+ description: 'A disabled toggle group.',
+ code: `import { UiToggleGroup, UiToggleGroupItem } from '@workspace/ui/directives/toggle-group';
+import { NgIcon, provideIcons } from '@ng-icons/core';
+import { lucideBold, lucideItalic, lucideUnderline } from '@ng-icons/lucide';
+
+@Component({
+ selector: 'toggle-group-disabled-example',
+ template: \`
+
+
+
+
+
+ \`,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })]
+})
+export class ToggleGroupDisabledExample {}`,
+ component: ToggleGroupDisabledExample
+ },
+ {
+ title: 'With Text',
+ description: 'A toggle group with text labels.',
+ code: `import { UiToggleGroup, UiToggleGroupItem } from '@workspace/ui/directives/toggle-group';
+import { NgIcon, provideIcons } from '@ng-icons/core';
+import { lucideAlignLeft, lucideAlignCenter, lucideAlignRight } from '@ng-icons/lucide';
+
+@Component({
+ selector: 'toggle-group-text-example',
+ template: \`
+
+
+
+
+
+ \`,
+ imports: [UiToggleGroup, UiToggleGroupItem, NgIcon],
+ providers: [provideIcons({ lucideAlignLeft, lucideAlignCenter, lucideAlignRight })]
+})
+export class ToggleGroupTextExample {}`,
+ component: ToggleGroupTextExample
+ }
+];
+
diff --git a/projects/docs/src/app/shared/components/sidebar/sidebar.ts b/projects/docs/src/app/shared/components/sidebar/sidebar.ts
index 53b9362..87bee02 100644
--- a/projects/docs/src/app/shared/components/sidebar/sidebar.ts
+++ b/projects/docs/src/app/shared/components/sidebar/sidebar.ts
@@ -28,6 +28,11 @@ export class Sidebar {
// Two-way binding model signal for menu state
readonly menuOpen = model(false);
+ // Sort method for components
+ private sortComponents(components: NavLink[]): NavLink[] {
+ return components.sort((a, b) => a.name.localeCompare(b.name));
+ }
+
// Clean navigation structure
readonly sections = signal([
{
@@ -43,7 +48,7 @@ export class Sidebar {
{
title: 'Components',
link: 'components',
- links: [
+ links: this.sortComponents([
{ name: 'Accordion', path: 'accordion' },
{ name: 'Alert', path: 'alert' },
{ name: 'Alert Dialog', path: 'alert-dialog' },
@@ -67,8 +72,10 @@ export class Sidebar {
// { name: 'Toast', path: 'toast' },
{ name: 'Tooltip', path: 'tooltip' },
{ name: 'Table', path: 'table' },
- { name: 'Toggle', path: 'toggle' }
- ]
+ { name: 'Toggle', path: 'toggle' },
+ { name: 'Toggle Group', path: 'toggle-group' },
+ { name: 'Skeleton', path: 'skeleton' }
+ ])
}
]);
diff --git a/projects/ui/src/directives/button.ts b/projects/ui/src/directives/button.ts
index 43a321f..441079e 100644
--- a/projects/ui/src/directives/button.ts
+++ b/projects/ui/src/directives/button.ts
@@ -45,5 +45,5 @@ export class UiButton {
inputClass = input('', { alias: 'class' });
variant = input('default');
size = input('default');
- computedClass = computed(() => buttonVariants({ variant: this.variant(), size: this.size(), class: this.inputClass(), }));
+ computedClass = computed(() => buttonVariants({ variant: this.variant(), size: this.size(), class: this.inputClass() }));
}
diff --git a/projects/ui/src/directives/skeleton.ts b/projects/ui/src/directives/skeleton.ts
new file mode 100644
index 0000000..3d05ad5
--- /dev/null
+++ b/projects/ui/src/directives/skeleton.ts
@@ -0,0 +1,22 @@
+import { computed, Directive, input } from "@angular/core";
+import { tv } from "tailwind-variants";
+
+const skeletonVariants = tv({
+ slots: {
+ skeleton: 'bg-accent animate-pulse rounded-md'
+ }
+});
+
+const { skeleton } = skeletonVariants();
+
+@Directive({
+ selector: '[uiSkeleton]',
+ exportAs: 'uiSkeleton',
+ host: {
+ '[class]': 'computedClass()'
+ }
+})
+export class UiSkeleton {
+ inputClass = input('', { alias: 'class' });
+ computedClass = computed(() => skeleton({ class: this.inputClass() }));
+}
\ No newline at end of file
diff --git a/projects/ui/src/directives/toggle-group.ts b/projects/ui/src/directives/toggle-group.ts
new file mode 100644
index 0000000..a840ef3
--- /dev/null
+++ b/projects/ui/src/directives/toggle-group.ts
@@ -0,0 +1,129 @@
+import { computed, Directive, input, output, inject } from '@angular/core';
+import { tv, VariantProps } from 'tailwind-variants';
+import { NgpToggleGroup, NgpToggleGroupItem } from 'ng-primitives/toggle-group';
+
+const toggleGroupVariants = tv({
+ slots: {
+ root: 'group/toggle-group flex w-fit items-center rounded-md data-[disabled]:pointer-events-none data-[disabled]:opacity-50 ',
+ item: "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium data-[hover]:bg-muted data-[hover]:text-muted-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[selected]:bg-accent data-[selected]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 data-[focus-visible]:border-ring data-[focus-visible]:ring-ring/50 data-[focus-visible]:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap min-w-0 flex-1 shrink-0 rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10"
+ },
+ variants: {
+ variant: {
+ default: {
+ root: 'bg-transparent',
+ item: 'bg-transparent'
+ },
+ outline: {
+ root: 'shadow-xs',
+ item: 'border border-input bg-transparent shadow-xs data-[hover]:bg-accent data-[hover]:text-accent-foreground border-l-0 first:border-l'
+ }
+ },
+ size: {
+ default: {
+ root: 'h-9',
+ item: 'h-9 px-3'
+ },
+ sm: {
+ root: 'h-8',
+ item: 'h-8 px-2.5'
+ },
+ lg: {
+ root: 'h-10',
+ item: 'h-10 px-3.5'
+ }
+ }
+ },
+ compoundVariants: [
+ {
+ variant: 'outline',
+ size: 'sm',
+ class: {
+ root: 'h-8',
+ item: 'h-8 px-2.5'
+ }
+ },
+ {
+ variant: 'outline',
+ size: 'lg',
+ class: {
+ root: 'h-10',
+ item: 'h-10 px-3.5'
+ }
+ }
+ ],
+ defaultVariants: {
+ variant: 'default',
+ size: 'default'
+ }
+});
+
+type ToggleGroupVariants = VariantProps;
+
+@Directive({
+ selector: '[uiToggleGroup]',
+ exportAs: 'uiToggleGroup',
+ hostDirectives: [
+ {
+ directive: NgpToggleGroup,
+ inputs: [
+ 'ngpToggleGroupDisabled: disabled',
+ 'ngpToggleGroupType: type',
+ 'ngpToggleGroupValue: groupValue',
+ ],
+ outputs: [
+ 'ngpToggleGroupValueChange: groupValueChange',
+ ],
+ }
+ ],
+ host: {
+ '[class]': 'computedClass()'
+ }
+})
+export class UiToggleGroup {
+ inputClass = input('', { alias: 'class' });
+ variant = input('default');
+ size = input('default');
+ groupValue = input();
+ groupValueChange = output();
+
+ computedClass = computed(() => {
+ const { root } = toggleGroupVariants({
+ variant: this.variant(),
+ size: this.size()
+ });
+ return root({ class: this.inputClass() });
+ });
+}
+@Directive({
+ selector: '[uiToggleGroupItem]',
+ exportAs: 'uiToggleGroupItem',
+ hostDirectives: [
+ {
+ directive: NgpToggleGroupItem,
+ inputs: [
+ 'ngpToggleGroupItemValue: value',
+ 'ngpToggleGroupItemDisabled: disabled',
+ ],
+ }
+ ],
+ host: {
+ '[class]': 'computedClass()'
+ }
+})
+export class UiToggleGroupItem {
+ private parentToggleGroup = inject(UiToggleGroup, { optional: true, skipSelf: true });
+ inputClass = input('', { alias: 'class' });
+
+ computedClass = computed(() => {
+ if (!this.parentToggleGroup) {
+ const { item } = toggleGroupVariants();
+ return item({ class: this.inputClass() });
+ }
+
+ const { item } = toggleGroupVariants({
+ variant: this.parentToggleGroup.variant(),
+ size: this.parentToggleGroup.size()
+ });
+ return item({ class: this.inputClass() });
+ });
+}
diff --git a/projects/ui/src/directives/toggle.ts b/projects/ui/src/directives/toggle.ts
index 33c0d59..e40a860 100644
--- a/projects/ui/src/directives/toggle.ts
+++ b/projects/ui/src/directives/toggle.ts
@@ -1,5 +1,5 @@
import { computed, Directive, input } from "@angular/core";
-import { tv } from "tailwind-variants";
+import { tv, VariantProps } from "tailwind-variants";
import { NgpToggle } from "ng-primitives/toggle";
import { NgpButton } from "ng-primitives/button";
@@ -23,6 +23,7 @@ const toggleVariants = tv({
},
});
+type ToggleVariants = VariantProps;
@Directive({
selector: '[uiToggle]',
@@ -49,8 +50,8 @@ const toggleVariants = tv({
}],
})
export class UiToggle {
- variant = input<'default' | 'outline'>('default', { alias: 'variant' });
- size = input<'default' | 'sm' | 'lg'>('default', { alias: 'size' });
+ variant = input('default', { alias: 'variant' });
+ size = input('default', { alias: 'size' });
inputClass = input('', { alias: 'class' });
computedClass = computed(() => toggleVariants({ variant: this.variant(), size: this.size(), class: this.inputClass() }));
}
diff --git a/projects/ui/src/public-api.ts b/projects/ui/src/public-api.ts
index acafdfc..17cc14a 100644
--- a/projects/ui/src/public-api.ts
+++ b/projects/ui/src/public-api.ts
@@ -19,4 +19,6 @@ export * from './directives/table';
export * from './directives/breadcrumb';
export * from './directives/form-field';
export * from './directives/checkbox';
-export * from './directives/toggle';
\ No newline at end of file
+export * from './directives/toggle';
+export * from './directives/toggle-group';
+export * from './directives/skeleton';
\ No newline at end of file