FAB common component add

This commit is contained in:
leejh 2019-10-30 18:18:35 +09:00
parent 33e6566eff
commit 36a983a6fd
9 changed files with 214 additions and 3 deletions

View File

@ -44,4 +44,8 @@
<app-layout-chat-left-sidenav-call></app-layout-chat-left-sidenav-call> <app-layout-chat-left-sidenav-call></app-layout-chat-left-sidenav-call>
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>
<ucap-ui-float-action-button
[fabButtons]="fabButtons"
(buttonClick)="onClickFab($event)"
></ucap-ui-float-action-button>
</div> </div>

View File

@ -31,6 +31,9 @@ export class LeftSideComponent implements OnInit {
/** 조직도에서 부서원 선택 */ /** 조직도에서 부서원 선택 */
selectedUserList: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = []; selectedUserList: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = [];
/** FAB */
fabButtons: { icon: string }[];
constructor( constructor(
private store: Store<any>, private store: Store<any>,
private dialogService: DialogService, private dialogService: DialogService,
@ -41,6 +44,20 @@ export class LeftSideComponent implements OnInit {
this.badgeChatUnReadCount$ = this.store.pipe( this.badgeChatUnReadCount$ = this.store.pipe(
select(AppStore.MessengerSelector.SyncSelector.selectChatUnreadCount) select(AppStore.MessengerSelector.SyncSelector.selectChatUnreadCount)
); );
this.fabButtons = [
{
icon: 'timeline'
},
{
icon: 'view_headline'
},
{
icon: 'room'
},
{
icon: 'lock'
}
];
} }
async onClickNewChat() { async onClickNewChat() {
@ -106,4 +123,9 @@ export class LeftSideComponent implements OnInit {
); );
} }
} }
/** FAB */
onClickFab(params: { btn: { icon: string } }) {
this.logger.debug('FAB click', params.btn);
}
} }

View File

@ -10,7 +10,8 @@ import {
state, state,
animation, animation,
useAnimation, useAnimation,
stagger stagger,
keyframes
} from '@angular/animations'; } from '@angular/animations';
const customAnimation = animation( const customAnimation = animation(
@ -548,5 +549,52 @@ export const ucapAnimations = [
query('content > :leave', animateChild(), { optional: true }) query('content > :leave', animateChild(), { optional: true })
]) ])
) )
]),
/**
* Floating ACtion Button Animation.
*/
trigger('fabToggler', [
state(
'inactive',
style({
transform: 'rotate(0deg)'
})
),
state(
'active',
style({
transform: 'rotate(225deg)'
})
),
transition('* <=> *', animate('200ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
]),
trigger('speedDialStagger', [
transition('* => *', [
query(':enter', style({ opacity: 0 }), { optional: true }),
query(
':enter',
stagger('40ms', [
animate(
'200ms cubic-bezier(0.4, 0.0, 0.2, 1)',
keyframes([
style({ opacity: 0, transform: 'translateY(10px)' }),
style({ opacity: 1, transform: 'translateY(0)' })
])
)
]),
{ optional: true }
),
query(
':leave',
animate(
'200ms cubic-bezier(0.4, 0.0, 0.2, 1)',
keyframes([style({ opacity: 1 }), style({ opacity: 0 })])
),
{ optional: true }
)
])
]) ])
]; ];

View File

@ -0,0 +1,21 @@
<div
id="fab-dismiss"
*ngIf="fabTogglerState === 'active'"
(click)="onToggleFab()"
></div>
<div class="fab-container">
<button mat-fab class="fab-toggler" (click)="onToggleFab()">
<mat-icon [@fabToggler]="fabTogglerState">add</mat-icon>
</button>
<div [@speedDialStagger]="buttons.length">
<button
*ngFor="let btn of buttons"
mat-mini-fab
class="fab-secondary"
color="secondary"
(click)="onClickButton(btn)"
>
<mat-icon>{{ btn.icon }}</mat-icon>
</button>
</div>
</div>

View File

@ -0,0 +1,34 @@
.fab-container {
position: fixed;
bottom: 15px;
right: 15px;
z-index: 100;
display: flex;
flex-direction: column-reverse;
align-items: center;
> div {
display: flex;
flex-direction: column-reverse;
align-items: center;
margin-bottom: 5px;
button {
margin-bottom: 17px;
}
}
}
.fab-toggler {
float: right;
z-index: 100;
}
#fab-dismiss {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 99;
}

View File

@ -0,0 +1,27 @@
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { FloatActionButtonComponent } from './float-action-button.component';
describe('FloatActionButtonComponent', () => {
let component: FloatActionButtonComponent;
let fixture: ComponentFixture<FloatActionButtonComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [FloatActionButtonComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FloatActionButtonComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,48 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { ucapAnimations } from '@ucap-webmessenger/ui';
export interface FloatActionButton {
/** Meterial Icon type */
icon: string;
divisionType?: string;
}
@Component({
selector: 'ucap-ui-float-action-button',
templateUrl: './float-action-button.component.html',
styleUrls: ['./float-action-button.component.scss'],
animations: ucapAnimations
})
export class FloatActionButtonComponent implements OnInit {
@Input()
fabButtons: FloatActionButton[] = [];
buttons = [];
fabTogglerState = 'inactive';
@Output()
buttonClick = new EventEmitter<{
btn: FloatActionButton;
}>();
constructor() {}
ngOnInit() {}
showItems() {
this.fabTogglerState = 'active';
this.buttons = this.fabButtons;
}
hideItems() {
this.fabTogglerState = 'inactive';
this.buttons = [];
}
onToggleFab() {
this.buttons.length ? this.hideItems() : this.showItems();
}
onClickButton(btn: FloatActionButton) {
this.hideItems();
this.buttonClick.emit({ btn });
}
}

View File

@ -0,0 +1,7 @@
import { FileUploadQueueComponent } from './file-upload-queue.component';
import { FloatActionButtonComponent } from './float-action-button.component';
export const UI_COMMON_COMPONENTS = [
FileUploadQueueComponent,
FloatActionButtonComponent
];

View File

@ -12,7 +12,7 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
import { DragDropModule } from '@angular/cdk/drag-drop'; import { DragDropModule } from '@angular/cdk/drag-drop';
import { FileUploadQueueComponent } from './components/file-upload-queue.component'; import { UI_COMMON_COMPONENTS } from './components/index';
import { BottomSheetService } from './services/bottom-sheet.service'; import { BottomSheetService } from './services/bottom-sheet.service';
import { ClipboardService } from './services/clipboard.service'; import { ClipboardService } from './services/clipboard.service';
@ -30,7 +30,7 @@ import { BytesPipe } from './pipes/bytes.pipe';
import { LinefeedToHtmlPipe, HtmlToLinefeedPipe } from './pipes/linefeed.pipe'; import { LinefeedToHtmlPipe, HtmlToLinefeedPipe } from './pipes/linefeed.pipe';
import { DateToStringForChatRoomListPipe } from './pipes/dates.pipe'; import { DateToStringForChatRoomListPipe } from './pipes/dates.pipe';
const COMPONENTS = [FileUploadQueueComponent]; const COMPONENTS = [...UI_COMMON_COMPONENTS];
const DIALOGS = [AlertDialogComponent, ConfirmDialogComponent]; const DIALOGS = [AlertDialogComponent, ConfirmDialogComponent];
const DIRECTIVES = [ const DIRECTIVES = [
ClickOutsideDirective, ClickOutsideDirective,