• Skip to main content
  • Skip to primary sidebar

Web Development Archive

  • Archive
You are here: Home / Other / Card Toggle Menu

Card Toggle Menu

<div class="card ad-card" [ngClass]="data.isMobile ? 'mobile' : 'desktop'" (click)="closeMenu()">
<div class="card-header">
<div class="card-header-title">{{ data.cardTitle }}</div>
<div class="card-header-icon">
<app-card-button (click)="menuToggle($event)" />
@if (isMenuOpened) {
<ng-container *ngTemplateOutlet="menu" />
}
</div>
</div>
<div class="card-body">
<div class="stats-wrapper">
<app-stats [type]="StatType.CLICKS" [statLabel]="'Kattintások'" [statValue]="50" />
<app-stats [type]="StatType.BUDGET" [statLabel]="'Keret'" [statValue]="30000" />
<app-stats [type]="StatType.CTR" [statLabel]="'CTR'" [statValue]="0.023" />
<app-stats [type]="StatType.CPC" [statLabel]="'CPC'" [statValue]="133" />
</div>
<div class="bar-wrapper">
<app-progress-bar-2
[type]="BarType.APPEARANCE"
[currentNum]="data.currentNum ?? 0"
[allNum]="data.allNum ?? 0"
[isLabelRight]="true"
/>
<app-progress-bar-2
[type]="BarType.BUDGET"
[currentMoney]="data.currentMoney ?? 0"
[allMoney]="data.allMoney ?? 0"
[isLabelRight]="true"
/>
</div>
</div>
<div class="card-footer">
<div class="card-footer-wrapper">
<app-status [icon]="'icon-play-circle'" [text]="'Fut'" [statusType]="StatusType.RUNNING" />
<div class="card-footer-label">
<span class="card-footer-label-text">{{ data.footerLabelText }}</span>
<span class="card-footer-label-date">{{ data.footerLabelDate | date: 'yyyy.MM.dd. HH:mm' }}</span>
</div>
</div>
<div class="card-footer-warning" *ngIf="data.isLowerThanExpected">{{ data.lowerThanExpectedText }}</div>
</div>
</div>
<ng-template #menu>
<div class="menu" [ngClass]="isMobile ? 'mobile' : 'desktop'">
<button class="menu-item" (click)="onView()">{{ 'ADS.VIEW' | transloco }}</button>
<button class="menu-item" (click)="onChange()">{{ 'ADS.CHANGE' | transloco }}</button>
<button class="menu-item" (click)="onRestart()">{{ 'ADS.RESTART' | transloco }}</button>
<span class="menu-item-divider"></span>
<button class="menu-item" (click)="onDelete()">{{ 'ADS.DELETE' | transloco }}</button>
</div>
</ng-template>
.menu {
position: absolute;
right: 0;
border-radius: 8px;
box-shadow: 0px 16px 16px 0px rgba(217, 218, 243, 0.3);
background: var(--color-white);
&.desktop {
border: 1px solid var(--color-grey-300);
position: absolute;
top: 20px;
width: 200px;
z-index: 9;
.menu-item {
padding: 12px 30px;
}
}
&-item {
padding: 12px 0;
color: var(--color-primary-950);
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 120%;
display: block;
width: 100%;
text-align: left;
&:hover {
background: var(--color-grey-100);
}
&-divider {
background: var(--color-grey-300);
display: block;
width: 100%;
height: 1px;
}
}
}
export class AdCardComponent implements OnInit, OnDestroy {
private readonly _eref = inject(ElementRef);
private readonly _deviceService = inject(DeviceService);
private readonly _cdr = inject(ChangeDetectorRef);
private readonly _destroy$ = new Subject();

@Input() public data: AdCard;
@Input() public isMobile: boolean = false;
public isMenuOpened: boolean = false;

public StatusType = StatusType;
public StatType = StatType;
public BarType = BarType;

@Output() public viewEvent = new EventEmitter<CardMember>();
@Output() public changeEvent = new EventEmitter<CardMember>();
@Output() public duplicateEvent = new EventEmitter<CardMember>();
@Output() public archiveEvent = new EventEmitter<CardMember>();
@Output() public startEvent = new EventEmitter<CardMember>();
@Output() public stopEvent = new EventEmitter<CardMember>();
@Output() public restartEvent = new EventEmitter<CardMember>();
@Output() public deleteEvent = new EventEmitter<CardMember>();

public get classes(): string[] {
const deviceType = this.isMobile ? 'mobile' : 'desktop';
return [deviceType];
}

public ngOnInit(): void {
this._deviceService.isMobileObs$.pipe(takeUntil(this._destroy$)).subscribe((isMobile) => {
this.isMobile = isMobile;
this._cdr.markForCheck();
});
}

public ngOnDestroy(): void {
this._destroy$.next(null);
this._destroy$.complete();
}

@HostListener('document:click', ['$event.target'])
public clickOutside(targetElement: HTMLElement): void {
const clickedInside = this._eref.nativeElement.contains(targetElement);
if (!clickedInside) {
this.isMenuOpened = false;
}
}

public menuToggle($event: MouseEvent): void {
$event.stopPropagation();
this.isMenuOpened = !this.isMenuOpened;
}

public closeMenu(): void {
this.isMenuOpened = false;
}

public onView(): void {
this.viewEvent.emit();
}

public onChange(): void {
this.changeEvent.emit();
}

public onStart(): void {
this.startEvent.emit();
}

public onDelete(): void {
this.deleteEvent.emit();
}
}

Filed Under: Other

About Gabor Flamich

I'm a web developer and designer based in Budapest, Hungary. In recent years, I've documented hundreds of solutions I came across during development. This site is an archive for useful code snippets on WordPress, Genesis Framework and WooCommerce. If You have any questions related to WordPress development, get in touch!

Primary Sidebar

  • angular.io
© 2026 WP Flames - All Right Reserved