Compare commits

...

2 Commits

Author SHA1 Message Date
wagonsoftware
e7624ab550 Merge remote-tracking branch 'origin/main' 2022-10-31 23:01:37 +03:00
wagonsoftware
1d2c28a370 popup component added 2022-10-31 23:00:55 +03:00
25 changed files with 419 additions and 26 deletions

View File

@ -1,3 +1,3 @@
<button> <button [attr.data-appearance]="appearance">
<ng-content></ng-content> <ng-content></ng-content>
</button> </button>

View File

@ -6,14 +6,34 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--sk-gap-m); gap: var(--sk-gap-m);
background-color: var(--sk-accent);
border: none;
border-radius: var(--sk-br-m); border-radius: var(--sk-br-m);
border: none;
cursor: pointer; cursor: pointer;
color: #fff; font-weight: 500;
&:hover { &:hover {
opacity: 0.9; opacity: 0.9;
} }
&[data-appearance="default"], &[data-appearance="primary"] {
background-color: var(--sk-primary);
color: #fff;
}
&[data-appearance="secondary"] {
background-color: var(--sk-secondary);
color: #fff;
}
&[data-appearance="outline"] {
color: #fff;
background-color: transparent;
box-shadow: 0px 0px 0px 1px rgba(255, 255, 255, 0.1);
}
&[data-appearance="flat"] {
color: #fff;
background-color: transparent;
}
} }
} }

View File

@ -1,15 +1,12 @@
import { Component, OnInit } from '@angular/core'; import { Component, Input, OnInit } from '@angular/core';
@Component({ @Component({
selector: 'skirda-button', selector: 'skirda-button',
templateUrl: './button.component.html', templateUrl: './button.component.html',
styleUrls: ['./button.component.scss'] styleUrls: ['./button.component.scss'],
}) })
export class ButtonComponent implements OnInit { export class ButtonComponent {
@Input() appearance: string = 'default';
constructor() { }
ngOnInit(): void {
}
constructor() {}
} }

View File

@ -6,5 +6,5 @@
</div> </div>
<skirda-text>description</skirda-text> <skirda-text>description</skirda-text>
</div> </div>
<skirda-icon name="play" size="16" (click)="run(game)" color="var(--sk-accent)"></skirda-icon> <skirda-icon name="play" size="16" (click)="run(game)" color="var(--sk-primary)"></skirda-icon>
</div> </div>

View File

@ -0,0 +1,21 @@
<div class="popup-overlay" [ngClass]="{'shown': loaded, 'hiding': hiding}">
<div class="popup-window-wrapper">
<div class="popup-window">
<div class="popup-head">
<div class="head-title">Notification</div>
<div class="head-close" (click)="cancel.emit()">
<skirda-icon name="sign-out" size="18"></skirda-icon>
</div>
</div>
<div class="popup-body">
<ng-template skirdaPopup></ng-template>
</div>
<div class="popup-actions">
<skirda-button appearance="flat" (click)="cancel.emit()">Cancel</skirda-button>
<skirda-button (click)="confirm.emit()">Confirm</skirda-button>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,121 @@
:host {
position: absolute;
@keyframes show {
from {
translate: 0px 20px;
opacity: 0;
}
to {
translate: 0px 0px;
opacity: 1;
}
}
@keyframes hide {
from {
translate: 0px 0px;
opacity: 1;
}
to {
translate: 0px 20px;
opacity: 0;
}
}
@keyframes showOverlay {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes hideOverlay {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.popup-overlay {
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: rgba(0,0,0,0.5);
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
&.shown {
animation: showOverlay 0.2s ease 0s 1 forwards;
.popup-window-wrapper {
animation: show 0.3s ease 0.1s 1 forwards;
}
}
&.hiding {
animation: hideOverlay 0.3s ease 0s 1 forwards;
.popup-window-wrapper {
animation: hide 0.3s ease 0s 1 forwards;
}
}
.popup-window-wrapper {
width: 500px;
background: linear-gradient(45deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.25));
padding: 1px;
border-radius: 8px;
overflow: hidden;
translate: 0px 20px;
opacity: 0;
.popup-window {
border-radius: 7px;
background-color: #222;
.popup-head {
padding: 1rem;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
.head-title {
font-size: 1rem;
color: #aaa;
}
.head-close {
width: 1.125rem;
height: 1.125rem;
cursor: pointer;
}
}
.popup-body {
padding: 2rem;
text-align: center;
line-height: 140%;
}
.popup-actions {
border-top: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
align-items: center;
padding: 1rem;
gap: 0.25rem;
justify-content: flex-end;
}
}
}
}
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PopupComponent } from './popup.component';
describe('PopupComponent', () => {
let component: PopupComponent;
let fixture: ComponentFixture<PopupComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PopupComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(PopupComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,55 @@
import {
AfterViewInit,
Component,
EventEmitter,
OnInit,
Output,
TemplateRef,
ViewChild,
ViewContainerRef,
} from '@angular/core';
import { PopupDirective } from './popup.directive';
@Component({
selector: 'skirda-popup',
templateUrl: './popup.component.html',
styleUrls: ['./popup.component.scss'],
})
export class PopupComponent implements OnInit, AfterViewInit {
loaded: boolean = false;
hiding: boolean = false;
contentQueue?: TemplateRef<any>;
@Output() cancel: EventEmitter<void> = new EventEmitter();
@Output() confirm: EventEmitter<void> = new EventEmitter();
@ViewChild(PopupDirective) private popupContent!: PopupDirective;
constructor(private viewContainerRef: ViewContainerRef) {}
ngOnInit(): void {}
ngAfterViewInit(): void {
if (this.contentQueue) {
this.load(this.contentQueue);
this.contentQueue = undefined;
}
}
load(template?: TemplateRef<any>) {
this.loaded = true;
if (!template) return;
if (!this.popupContent) {
this.contentQueue = template;
return;
}
this.popupContent.viewContainerRef.createEmbeddedView(template);
}
hide() {
this.loaded = false;
this.hiding = true;
}
}

View File

@ -0,0 +1,8 @@
import { PopupDirective } from './popup.directive';
describe('PopupDirective', () => {
it('should create an instance', () => {
const directive = new PopupDirective();
expect(directive).toBeTruthy();
});
});

View File

@ -0,0 +1,8 @@
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[skirdaPopup]',
})
export class PopupDirective {
constructor(public viewContainerRef: ViewContainerRef) {}
}

View File

@ -0,0 +1,13 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PopupComponent } from './popup.component';
import { PopupDirective } from './popup.directive';
import { ButtonModule } from '../button/button.module';
import { IconModule } from '../icon/icon.module';
@NgModule({
declarations: [PopupComponent, PopupDirective],
imports: [CommonModule, ButtonModule, IconModule],
exports: [PopupComponent, PopupDirective],
})
export class PopupModule {}

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { PopupService } from './popup.service';
describe('PopupService', () => {
let service: PopupService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(PopupService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,49 @@
import {
ComponentRef,
EventEmitter,
Injectable,
Output,
TemplateRef,
ViewChild,
} from '@angular/core';
import { first } from 'rxjs';
import { PopupComponent } from './popup.component';
import { PopupDirective } from './popup.directive';
@Injectable({
providedIn: 'root',
})
export class PopupService {
instance?: PopupComponent;
constructor() {}
open(portal: PopupDirective, template?: TemplateRef<any>) {
let container = portal.viewContainerRef;
container.clear();
let componentRef = container.createComponent(PopupComponent);
this.instance = componentRef.instance;
this.instance.confirm.pipe(first()).subscribe(() => {
this.hide(componentRef);
});
this.instance.cancel.pipe(first()).subscribe(() => {
this.hide(componentRef);
});
this.instance.load(template);
return this.instance;
}
hide(componentRef: ComponentRef<PopupComponent>) {
if (!this.instance) return;
this.instance.hide();
setTimeout(() => {
componentRef.destroy();
}, 300);
}
}

View File

@ -1,7 +1,7 @@
:host { :host {
&.filled .sk-tag { &.filled .sk-tag {
background-color: var(--sk-accent); background-color: var(--sk-primary);
} }
.sk-tag { .sk-tag {

View File

@ -10,6 +10,7 @@ import { ButtonModule } from './button/button.module';
import { TagModule } from './tag/tag.module'; import { TagModule } from './tag/tag.module';
import { PipesModule } from './pipes/pipes.module'; import { PipesModule } from './pipes/pipes.module';
import { GameModule } from './game/game.module'; import { GameModule } from './game/game.module';
import { PopupModule } from '../public-api';
@NgModule({ @NgModule({
declarations: [], declarations: [],
@ -25,6 +26,7 @@ import { GameModule } from './game/game.module';
TagModule, TagModule,
PipesModule, PipesModule,
GameModule, GameModule,
PopupModule,
], ],
exports: [ exports: [
IconModule, IconModule,
@ -34,9 +36,11 @@ import { GameModule } from './game/game.module';
TypographyModule, TypographyModule,
SectionLabelModule, SectionLabelModule,
ImageIconModule, ImageIconModule,
ButtonModule,
TagModule, TagModule,
PipesModule, PipesModule,
GameModule GameModule,
PopupModule,
], ],
}) })
export class UiModule {} export class UiModule {}

View File

@ -13,3 +13,4 @@ export * from './lib/image-icon/image-icon.module';
export * from './lib/tag/tag.module'; export * from './lib/tag/tag.module';
export * from './lib/pipes/pipes.module'; export * from './lib/pipes/pipes.module';
export * from './lib/game/game.module'; export * from './lib/game/game.module';
export * from './lib/popup/popup.module';

View File

@ -4,7 +4,7 @@
<skirda-icon name="search" size="16" role="left"></skirda-icon> <skirda-icon name="search" size="16" role="left"></skirda-icon>
</skirda-input> </skirda-input>
<button> <button>
<skirda-icon name="menu-panel" color="var(--sk-accent)"></skirda-icon> <skirda-icon name="menu-panel" color="var(--sk-primary)"></skirda-icon>
</button> </button>
</div> </div>
<div class="sk-sections"> <div class="sk-sections">

View File

@ -18,6 +18,7 @@
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
background-size: cover; background-size: cover;
position: inherit;
} }
.content { .content {

View File

@ -16,6 +16,7 @@ import { ButtonModule } from 'projects/ui/src/lib/button/button.module';
import { TypographyModule } from 'projects/ui/src/lib/typography/typography.module'; import { TypographyModule } from 'projects/ui/src/lib/typography/typography.module';
import { IconModule } from 'projects/ui/src/lib/icon/icon.module'; import { IconModule } from 'projects/ui/src/lib/icon/icon.module';
import { DownloadsPageComponent } from './sections/downloads-page/downloads-page.component'; import { DownloadsPageComponent } from './sections/downloads-page/downloads-page.component';
import { PopupModule } from 'projects/ui/src/public-api';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -39,6 +40,7 @@ import { DownloadsPageComponent } from './sections/downloads-page/downloads-page
TypographyModule, TypographyModule,
ButtonModule, ButtonModule,
IconModule, IconModule,
PopupModule,
], ],
exports: [ exports: [
MainRootComponent, MainRootComponent,

View File

@ -1,3 +1,9 @@
<ng-template [skirdaPopup]></ng-template>
<ng-template #popupContent>
<h1 style="font-size: 72px">😳🕶🤏</h1>
<p>Church-key listicle whatever hoodie hexagon pour-over ascot paleo tacos, organic aesthetic tbh meggings raclette.</p>
</ng-template>
<div class="section"> <div class="section">
<div class="section-head"> <div class="section-head">
<div class="head-title"> <div class="head-title">
@ -6,6 +12,10 @@
<div class="head-subtitle">Game page will be here</div> <div class="head-subtitle">Game page will be here</div>
</div> </div>
<div class="section-content"> <div class="section-content">
<!-- <skirda-button (click)="openPopup(popupContent)">
<skirda-icon name="play" size="16"></skirda-icon>
Run game
</skirda-button> -->
<skirda-button> <skirda-button>
<skirda-icon name="play" size="16"></skirda-icon> <skirda-icon name="play" size="16"></skirda-icon>
Run game Run game

View File

@ -1,15 +1,29 @@
import { TemplateRef, ViewChild } from '@angular/core';
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { PopupDirective } from 'projects/ui/src/lib/popup/popup.directive';
import { PopupService } from 'projects/ui/src/lib/popup/popup.service';
import { first } from 'rxjs';
@Component({ @Component({
selector: 'app-game-page', selector: 'app-game-page',
templateUrl: './game-page.component.html', templateUrl: './game-page.component.html',
styleUrls: ['./game-page.component.scss'] styleUrls: ['./game-page.component.scss'],
}) })
export class GamePageComponent implements OnInit { export class GamePageComponent implements OnInit {
@ViewChild(PopupDirective, { static: true }) popupPortal!: PopupDirective;
constructor() { } constructor(private popup: PopupService) {}
ngOnInit(): void { ngOnInit(): void {}
openPopup(template: TemplateRef<any>) {
let dialog = this.popup.open(this.popupPortal, template);
dialog.cancel.pipe(first()).subscribe(() => {
console.log('cancel clicked');
});
dialog.confirm.pipe(first()).subscribe(() => {
console.log('confirm clicked');
});
} }
} }

View File

@ -20,3 +20,12 @@
</form> </form>
<hr> <hr>
<h3>Dialog</h3>
<ng-template [skirdaPopup]></ng-template>
<ng-template #popupContent>
<h3>Warning</h3>
<p>Church-key listicle whatever hoodie hexagon pour-over ascot paleo tacos, organic aesthetic tbh meggings raclette.</p>
</ng-template>
<skirda-button (click)="openPopup(popupContent)">Call popup</skirda-button>

View File

@ -10,6 +10,11 @@
gap: 1rem; gap: 1rem;
} }
hr {
width: 100%;
border-color: rgba(255, 255, 255, 0.1);
}
form { form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -1,5 +1,8 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms'; import { FormControl, FormGroup } from '@angular/forms';
import { PopupDirective } from 'projects/ui/src/lib/popup/popup.directive';
import { PopupService } from 'projects/ui/src/lib/popup/popup.service';
import { first } from 'rxjs';
@Component({ @Component({
selector: 'app-sandbox', selector: 'app-sandbox',
@ -13,12 +16,24 @@ export class SandboxComponent implements OnInit {
name: new FormControl<string>(''), name: new FormControl<string>(''),
age: new FormControl<number>(0), age: new FormControl<number>(0),
}); });
@ViewChild(PopupDirective, { static: true }) popupPortal!: PopupDirective;
constructor() {} constructor(private popup: PopupService) {}
ngOnInit(): void {} ngOnInit(): void {}
print() { print() {
console.log(this.form); console.log(this.form);
} }
openPopup(template: TemplateRef<any>) {
let dialog = this.popup.open(this.popupPortal, template);
dialog.cancel.pipe(first()).subscribe(() => {
console.log('cancel clicked');
});
dialog.confirm.pipe(first()).subscribe(() => {
console.log('confirm clicked');
});
}
} }

View File

@ -22,8 +22,9 @@ button, input, textarea {
// colors // colors
--sk-input: rgba(18,18,18,0.5); --sk-input: rgba(18,18,18,0.5);
--sk-input-focus: rgba(18,18,18,0.9); --sk-input-focus: rgba(18,18,18,0.9);
--sk-accent: #67A69E; --sk-primary: #24927a;
--sk-accent-dark: #2A3B39; --sk-secondary: #1b557d;
--sk-primary-dark: #2A3B39;
// border-radius // border-radius
--sk-br-s: 0.25rem; --sk-br-s: 0.25rem;