Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e5d85aa
feat(sonner): add brain sonner entry
marcjulian Mar 5, 2026
87019e1
feat(sonner): remove ngx-sonner and use @spartan-ng/brain/sonner
marcjulian Mar 5, 2026
ea400e2
docs(sonner): add brain api section
marcjulian Mar 5, 2026
745a1e7
fix(sonner): vanishing of custom icons
marcjulian Mar 5, 2026
e11e6be
feat(sonner): add toaster spec and update snapshot
marcjulian Mar 5, 2026
b7f6421
fix(sonner): filter toasts/heights by position in toast to expand toa…
marcjulian Mar 5, 2026
e1904b5
feat(sonner): add sonner toaster config
marcjulian Mar 5, 2026
b3b6433
feat(sonner): use Directionality for dir, use afterNextRender and DOC…
marcjulian Mar 5, 2026
05c8539
feat(sonner): update modifiers and type imports
marcjulian Mar 5, 2026
612ffef
feat(sonner): update snapshot
marcjulian Mar 5, 2026
4133a9f
feat(sonner): add sonner healthcheck and migration to migrate ngx-sonner
marcjulian Mar 5, 2026
3b68cd6
fix(sonner): update healthcheck guard
marcjulian Mar 5, 2026
d6e2fb5
feat(sonner): copy to helm
marcjulian Mar 5, 2026
42080b2
fix(sonner): update comment
marcjulian Mar 5, 2026
c755159
fix(sonner): replace comment
marcjulian Mar 5, 2026
9e0c443
fix(sonner): update migration test message
marcjulian Mar 5, 2026
bc7ed2a
feat(sonner): replace all in migration
marcjulian Mar 5, 2026
6e8bdc7
feat(sonner): use injected document, update comments
marcjulian Mar 5, 2026
58d2f7e
feat(sonner): use clsx
marcjulian Mar 6, 2026
e22c6e0
feat(sonner): use computed for classes
marcjulian Mar 6, 2026
78ced54
docs(sonner): update about
marcjulian Mar 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { afterNextRender, Component, computed, inject, type OnDestroy, signal } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { BrnInputOtp } from '@spartan-ng/brain/input-otp';
import { toast } from '@spartan-ng/brain/sonner';
import { HlmButton } from '@spartan-ng/helm/button';
import { HlmInputOtp, HlmInputOtpGroup, HlmInputOtpSlot } from '@spartan-ng/helm/input-otp';
import { HlmToaster } from '@spartan-ng/helm/sonner';
import { toast } from 'ngx-sonner';

@Component({
selector: 'spartan-input-otp-form',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ import {
lucideMap,
lucidePlus,
} from '@ng-icons/lucide';
import { toast } from 'ngx-sonner';
import { toast } from '@spartan-ng/brain/sonner';
import { HlmToasterImports } from '@spartan-ng/helm/sonner';

@Component({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { toast } from '@spartan-ng/brain/sonner';
import { HlmButtonImports } from '@spartan-ng/helm/button';
import { toast } from 'ngx-sonner';

@Component({
selector: 'spartan-sonner-description-example',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { toast } from '@spartan-ng/brain/sonner';
import { HlmButtonImports } from '@spartan-ng/helm/button';
import { toast } from 'ngx-sonner';

@Component({
selector: 'spartan-sonner-position-example',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { toast } from '@spartan-ng/brain/sonner';
import { HlmButtonImports } from '@spartan-ng/helm/button';
import { toast } from 'ngx-sonner';

@Component({
selector: 'spartan-sonner-types-example',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ export const routeMeta: RouteMeta = {
<spartan-code secondTab [code]="_positionCode()" />
</spartan-tabs>
<spartan-section-sub-heading id="brn-api">Brain API</spartan-section-sub-heading>
<spartan-ui-api-docs docType="brain" />
<spartan-section-sub-heading id="hlm-api">Helm API</spartan-section-sub-heading>
<spartan-ui-api-docs docType="helm" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component } from '@angular/core';
import { toast } from '@spartan-ng/brain/sonner';
import { HlmButtonImports } from '@spartan-ng/helm/button';
import { HlmToasterImports } from '@spartan-ng/helm/sonner';
import { toast } from 'ngx-sonner';

@Component({
selector: 'spartan-sonner-preview',
Expand All @@ -24,7 +24,7 @@ export class SonnerPreview {
}

export const defaultImports = `
import { toast } from 'ngx-sonner';
import { toast } from '@spartan-ng/brain/sonner';
`;
export const defaultSkeleton = `
toast('Event has been created.');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Component, ViewEncapsulation } from '@angular/core';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideChartPie, lucideFrame, lucideMap, lucidePlus } from '@ng-icons/lucide';
import { toast } from '@spartan-ng/brain/sonner';
import { HlmIcon } from '@spartan-ng/helm/icon';
import { HlmSidebarImports } from '@spartan-ng/helm/sidebar';
import { HlmToasterImports } from '@spartan-ng/helm/sonner';
import { toast } from 'ngx-sonner';

@Component({
selector: 'spartan-sidebar-group-action',
Expand Down
1 change: 0 additions & 1 deletion apps/app/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export default defineConfig(({ mode }) => {
'marked-gfm-heading-id',
'marked-highlight',
'prismjs/**/*',
'ngx-sonner',
'@ng-icons/remixicon',
'luxon',
'@angular/cdk/portal',
Expand Down
2 changes: 1 addition & 1 deletion apps/ui-storybook/stories/sonner.stories.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Component } from '@angular/core';
import { toast } from '@spartan-ng/brain/sonner';
import { HlmButton } from '@spartan-ng/helm/button';
import { HlmToaster } from '@spartan-ng/helm/sonner';
import type { Meta, StoryObj } from '@storybook/angular';
import { moduleMetadata } from '@storybook/angular';
import { toast } from 'ngx-sonner';

const meta: Meta<HlmToaster> = {
title: 'Sonner',
Expand Down
3 changes: 3 additions & 0 deletions libs/brain/sonner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# @spartan-ng/brain/sonner

Secondary entry point of `@spartan-ng/brain`. It can be used by importing from `@spartan-ng/brain/sonner`.
5 changes: 5 additions & 0 deletions libs/brain/sonner/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"lib": {
"entryFile": "src/index.ts"
}
}
8 changes: 8 additions & 0 deletions libs/brain/sonner/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { BrnSonnerToaster } from './lib/brn-toaster';

export * from './lib/brn-toaster';
export * from './lib/brn-toaster.token';
export * from './lib/state';
export * from './lib/types';

export const BrnSonnerImports = [BrnSonnerToaster] as const;
51 changes: 51 additions & 0 deletions libs/brain/sonner/src/lib/brn-icon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
import type { ToastTypes } from './types';

@Component({
selector: 'brn-sonner-icon',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
@switch (type()) {
@case ('success') {
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20">
<path
fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
clip-rule="evenodd"
/>
</svg>
}
@case ('error') {
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20">
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z"
clip-rule="evenodd"
/>
</svg>
}
@case ('info') {
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20">
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z"
clip-rule="evenodd"
/>
</svg>
}
@case ('warning') {
<svg viewBox="0 0 64 64" fill="currentColor" height="20" width="20" xmlns="http://www.w3.org/2000/svg">
<path
d="M32.427,7.987c2.183,0.124 4,1.165 5.096,3.281l17.936,36.208c1.739,3.66 -0.954,8.585 -5.373,8.656l-36.119,0c-4.022,-0.064 -7.322,-4.631 -5.352,-8.696l18.271,-36.207c0.342,-0.65 0.498,-0.838 0.793,-1.179c1.186,-1.375 2.483,-2.111 4.748,-2.063Zm-0.295,3.997c-0.687,0.034 -1.316,0.419 -1.659,1.017c-6.312,11.979 -12.397,24.081 -18.301,36.267c-0.546,1.225 0.391,2.797 1.762,2.863c12.06,0.195 24.125,0.195 36.185,0c1.325,-0.064 2.321,-1.584 1.769,-2.85c-5.793,-12.184 -11.765,-24.286 -17.966,-36.267c-0.366,-0.651 -0.903,-1.042 -1.79,-1.03Z"
/>
<path
d="M33.631,40.581l-3.348,0l-0.368,-16.449l4.1,0l-0.384,16.449Zm-3.828,5.03c0,-0.609 0.197,-1.113 0.592,-1.514c0.396,-0.4 0.935,-0.601 1.618,-0.601c0.684,0 1.223,0.201 1.618,0.601c0.395,0.401 0.593,0.905 0.593,1.514c0,0.587 -0.193,1.078 -0.577,1.473c-0.385,0.395 -0.929,0.593 -1.634,0.593c-0.705,0 -1.249,-0.198 -1.634,-0.593c-0.384,-0.395 -0.576,-0.886 -0.576,-1.473Z"
/>
</svg>
}
}
`,
})
export class BrnSonnerIcon {
public readonly type = input<ToastTypes>('default');
}
20 changes: 20 additions & 0 deletions libs/brain/sonner/src/lib/brn-loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { BooleanInput } from '@angular/cdk/coercion';
import { booleanAttribute, ChangeDetectionStrategy, Component, input } from '@angular/core';

@Component({
selector: 'brn-sonner-loader',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="sonner-loading-wrapper" [attr.data-visible]="isVisible()">
<div class="sonner-spinner">
@for (_ of _bars; track $index) {
<div class="sonner-loading-bar"></div>
}
</div>
</div>
`,
})
export class BrnSonnerLoader {
public readonly isVisible = input.required<boolean, BooleanInput>({ transform: booleanAttribute });
protected readonly _bars = Array(12).fill(0);
}
Loading