Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 0 additions & 4 deletions packages/components/navbar-ic/navbar-ic-header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@
&.kbq-navbar-ic-header_interactive {
cursor: pointer;
}

&.kbq-collapsed .kbq-navbar-ic-title {
display: none;
}
}

a.kbq-navbar-ic-header {
Expand Down
16 changes: 15 additions & 1 deletion packages/components/navbar-ic/navbar-ic-header.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
AfterContentInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ContentChild,
DestroyRef,
Expand All @@ -10,15 +11,22 @@ import {
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { kbqInjectNativeElement, PopUpPlacements, PopUpTriggers } from '@koobiq/components/core';
import { KbqTooltipTrigger } from '@koobiq/components/tooltip';
import { distinctUntilChanged } from 'rxjs/operators';
import { KbqNavbarIc } from './navbar-ic';
import { KbqNavbarIcLogo, KbqNavbarIcTitle } from './navbar-ic-item';
import { toggleNavbarIcItemAnimation } from './navbar-ic.animation';

@Component({
standalone: true,
selector: 'kbq-navbar-ic-header, [kbq-navbar-ic-header]',
exportAs: 'kbqNavbarIcHeader',
template: `
<div class="kbq-navbar-ic-header__inner">
<ng-content select="[kbqNavbarIcLogo]" />

<div [@toggle]="navbar.state.value">
<ng-content select="[kbqNavbarIcTitle]" />
</div>
<ng-content />
</div>
`,
Expand All @@ -28,12 +36,14 @@ import { KbqNavbarIcLogo, KbqNavbarIcTitle } from './navbar-ic-item';
'[class.kbq-navbar-ic-header_interactive]': 'isLink'
},
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None
encapsulation: ViewEncapsulation.None,
animations: [toggleNavbarIcItemAnimation()]
})
export class KbqNavbarIcHeader extends KbqTooltipTrigger implements AfterContentInit {
protected readonly navbar = inject(KbqNavbarIc);
protected readonly nativeElement = kbqInjectNativeElement();
protected readonly destroyRef = inject(DestroyRef);
protected readonly changeDetectorRef = inject(ChangeDetectorRef);

@ContentChild(KbqNavbarIcLogo) logo: KbqNavbarIcLogo;
@ContentChild(KbqNavbarIcTitle) title: KbqNavbarIcTitle;
Expand Down Expand Up @@ -61,6 +71,10 @@ export class KbqNavbarIcHeader extends KbqTooltipTrigger implements AfterContent
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(() => this.title?.checkTextOverflown());

this.navbar.state.pipe(distinctUntilChanged(), takeUntilDestroyed(this.destroyRef)).subscribe(() => {
this.changeDetectorRef.detectChanges();
});

this.title?.checkTextOverflown();

if (this.title?.isTextOverflown) {
Expand Down
2 changes: 1 addition & 1 deletion packages/components/navbar-ic/navbar-ic-item.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<ng-content select="[kbq-icon]" />

@if (title && !collapsed) {
<div class="kbq-navbar-ic-item__title-container">
<div class="kbq-navbar-ic-item__title-container" [@toggle]="navbar.state.value">
<ng-content select="[kbqNavbarIcTitle]" />

@if (showDropDownAngle) {
Expand Down
4 changes: 0 additions & 4 deletions packages/components/navbar-ic/navbar-ic-item.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@
top: 0;
right: 0;
}

& .kbq-navbar-ic-item__title-container {
display: none;
}
}

& > .kbq-icon {
Expand Down
13 changes: 6 additions & 7 deletions packages/components/navbar-ic/navbar-ic-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { KbqTooltipTrigger, TooltipModifier } from '@koobiq/components/tooltip';
import { Subject } from 'rxjs';
import { take } from 'rxjs/operators';
import { KbqNavbarIc } from './navbar-ic';
import { toggleNavbarIcItemAnimation } from './navbar-ic.animation';

/**
* The maximum number of characters that can be placed in a title without being wrapped.
Expand Down Expand Up @@ -261,10 +262,12 @@ export class KbqNavbarIcFocusableItem implements AfterContentInit, AfterViewInit
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
hostDirectives: [KbqRectangleItem],
imports: [KbqIcon]
imports: [KbqIcon],
animations: [toggleNavbarIcItemAnimation()]
})
export class KbqNavbarIcItem extends KbqTooltipTrigger implements AfterContentInit {
readonly rectangleElement = inject(KbqRectangleItem);
readonly navbar = inject(KbqNavbarIc);
readonly navbarFocusableItem = inject(KbqNavbarIcFocusableItem);

private changeDetectorRef = inject(ChangeDetectorRef);
Expand Down Expand Up @@ -310,11 +313,7 @@ export class KbqNavbarIcItem extends KbqTooltipTrigger implements AfterContentIn
}

get disabled(): boolean {
if (this._disabled !== undefined) {
return this._disabled;
}

return !this.collapsed && !this.hasCroppedText;
return this.collapsed || !this.hasCroppedText || this._disabled;
}

set disabled(value) {
Expand All @@ -341,7 +340,7 @@ export class KbqNavbarIcItem extends KbqTooltipTrigger implements AfterContentIn
}

this.rectangleElement.state.subscribe(() => {
this.collapsed = this.rectangleElement.collapsed;
this.disabled = this.collapsed = this.rectangleElement.collapsed;

this.changeDetectorRef.markForCheck();
});
Expand Down
10 changes: 9 additions & 1 deletion packages/components/navbar-ic/navbar-ic.animation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,13 @@ export function toggleNavbarIcAnimation(): AnimationTriggerMetadata {
return trigger('toggle', [
state('0', style({ width: '64px' })),
state('1', style({ width: '240px' })),
transition('0 <=> 1', animate('150ms ease-out'))]);
transition('0 <=> 1', animate('200ms cubic-bezier(0.4, 0, 0.2, 1)'))]);
}

export function toggleNavbarIcItemAnimation(): AnimationTriggerMetadata {
return trigger('toggle', [
state('expanded', style({ opacity: 1, marginLeft: 0 })),
state('collapsed', style({ opacity: 0, marginLeft: '-8px' })),
transition('collapsed => expanded', animate('200ms 150ms cubic-bezier(0.4, 0, 0.2, 1)')),
transition('expanded => collapsed', animate('200ms cubic-bezier(0.4, 0, 0.2, 1)'))]);
}
63 changes: 54 additions & 9 deletions packages/components/navbar-ic/navbar-ic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ import { KBQ_LOCALE_SERVICE, KbqRectangleItem, ruRULocaleData } from '@koobiq/co
import { KbqDropdownTrigger } from '@koobiq/components/dropdown';
import { KbqNotificationCenterTrigger } from '@koobiq/components/notification-center';
import { KbqPopoverTrigger } from '@koobiq/components/popover';
import { BehaviorSubject, combineLatest, merge, Observable, Subject, Subscription } from 'rxjs';
import { startWith } from 'rxjs/operators';
import { BehaviorSubject, EMPTY, filter, merge, Observable, Subject, Subscription, timer } from 'rxjs';
import { delay, startWith, switchMap, takeUntil, tap } from 'rxjs/operators';
import {
KbqNavbarFocusableItemEvent,
KbqNavbarIcFocusableItem,
Expand All @@ -43,6 +43,12 @@ export enum KbqExpandEvents {
hoverOrFocus
}

/** minimum timeout to use KBQ_ENTER_DELAY */
export const KBQ_MIN_TIMEOUT_FOR_ENTER_DELAY = 2000;

/** delay before open navbar-ic */
export const KBQ_ENTER_DELAY = 400;

/** default configuration of navbar-ic */
/** @docs-private */
export const KBQ_NAVBAR_IC_DEFAULT_CONFIGURATION = ruRULocaleData.navbarIc;
Expand Down Expand Up @@ -218,6 +224,8 @@ export class KbqNavbarIc extends KbqFocusable implements AfterContentInit {

readonly externalConfiguration = inject(KBQ_NAVBAR_IC_CONFIGURATION, { optional: true });

readonly state = new BehaviorSubject<'expanded' | 'collapsed' | null>(null);

configuration;

/** @docs-private */
Expand Down Expand Up @@ -276,6 +284,8 @@ export class KbqNavbarIc extends KbqFocusable implements AfterContentInit {
set expanded(value: boolean) {
this._expanded = value;

this.state.next(value || this.pinned || this.hasOpenedPopUp ? 'expanded' : 'collapsed');

this.updateExpandedStateForItems();
}

Expand All @@ -299,24 +309,55 @@ export class KbqNavbarIc extends KbqFocusable implements AfterContentInit {
return this.expanded ? this.expandedWidth : this.collapsedWidth;
}

private lastOpeningTime: number;

constructor() {
super();

this.animationDone.pipe(takeUntilDestroyed()).subscribe(this.updateTooltipForItems);

effect(this.updateExpandedStateForItems);

combineLatest([this.hovered, this.focused])
.pipe(takeUntilDestroyed())
.subscribe(([hovered, focused]) => {
if (this.pinned) return;
this.focused
.pipe(
delay(0),
filter(() => !this.pinned || !this.hasOpenedPopUp),
takeUntilDestroyed()
)
.subscribe((focused) => {
if (this.hovered.value) return;

this.expandEvent = KbqExpandEvents.hoverOrFocus;
this.expanded = hovered || focused;
this.expanded = focused;

this.changeDetectorRef.markForCheck();
});

this.hovered
.pipe(
filter(() => !this.pinned),
switchMap((hovered) => {
if (!hovered) {
if (this.expanded) {
this.lastOpeningTime = Date.now();
}

this.expanded = false;

return EMPTY;
}

return timer(this.getExpandDelay()).pipe(
tap(() => {
this.expandEvent = KbqExpandEvents.hoverOrFocus;
this.expanded = true;
this.changeDetectorRef.markForCheck();
}),
takeUntil(this.hovered.pipe(filter((h) => !h)))
);
}),
takeUntilDestroyed()
)
.subscribe();

this.focusMonitor.monitor(this.elementRef, true).subscribe((focusOrigin) => {
this.focused.next(focusOrigin === 'keyboard');
});
Expand Down Expand Up @@ -366,6 +407,10 @@ export class KbqNavbarIc extends KbqFocusable implements AfterContentInit {
}
}

private getExpandDelay() {
return Date.now() - this.lastOpeningTime < KBQ_MIN_TIMEOUT_FOR_ENTER_DELAY ? 0 : KBQ_ENTER_DELAY;
}

protected updateTooltipForItems = () => this.items().forEach((item) => item.updateTooltip());

protected updateExpandedStateForItems = () => this.rectangleElements().forEach(this.updateItemExpandedState);
Expand Down
14 changes: 13 additions & 1 deletion tools/public_api_guard/components/navbar-ic.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ import { Signal } from '@angular/core';
import { Subject } from 'rxjs';
import { TooltipModifier } from '@koobiq/components/tooltip';

// @public
export const KBQ_ENTER_DELAY = 400;

// @public
export const KBQ_MIN_TIMEOUT_FOR_ENTER_DELAY = 2000;

// @public
export const KBQ_NAVBAR_IC_CONFIGURATION: InjectionToken<unknown>;

Expand Down Expand Up @@ -162,6 +168,8 @@ export class KbqNavbarIc extends KbqFocusable implements AfterContentInit {
popoverTrigger: Signal<readonly any[]>;
rectangleElements: Signal<readonly any[]>;
// (undocumented)
readonly state: BehaviorSubject<"expanded" | "collapsed" | null>;
// (undocumented)
toggle(): void;
toggleElement: Signal<readonly any[]>;
// (undocumented)
Expand Down Expand Up @@ -242,6 +250,8 @@ export class KbqNavbarIcFocusableItem implements AfterContentInit, AfterViewInit
export class KbqNavbarIcHeader extends KbqTooltipTrigger implements AfterContentInit {
constructor();
// (undocumented)
protected readonly changeDetectorRef: ChangeDetectorRef;
// (undocumented)
protected readonly destroyRef: DestroyRef;
// (undocumented)
get isLink(): boolean;
Expand All @@ -258,7 +268,7 @@ export class KbqNavbarIcHeader extends KbqTooltipTrigger implements AfterContent
// (undocumented)
get titleText(): string;
// (undocumented)
static ɵcmp: i0.ɵɵComponentDeclaration<KbqNavbarIcHeader, "kbq-navbar-ic-header, [kbq-navbar-ic-header]", ["kbqNavbarIcHeader"], {}, {}, ["logo", "title"], ["*"], true, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<KbqNavbarIcHeader, "kbq-navbar-ic-header, [kbq-navbar-ic-header]", ["kbqNavbarIcHeader"], {}, {}, ["logo", "title"], ["[kbqNavbarIcLogo]", "[kbqNavbarIcTitle]", "*"], true, never>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<KbqNavbarIcHeader, never>;
}
Expand All @@ -280,6 +290,8 @@ export class KbqNavbarIcItem extends KbqTooltipTrigger implements AfterContentIn
get hasDropDownTrigger(): boolean;
icon: KbqIcon;
// (undocumented)
readonly navbar: KbqNavbarIc;
// (undocumented)
readonly navbarFocusableItem: KbqNavbarIcFocusableItem;
// (undocumented)
ngAfterContentInit(): void;
Expand Down