Skip to content

Commit

Permalink
feat(addon-mobile): SwipeActions add new component
Browse files Browse the repository at this point in the history
  • Loading branch information
vladimirpotekhin committed Feb 1, 2024
1 parent 05eb2cd commit 363c532
Show file tree
Hide file tree
Showing 35 changed files with 825 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import {
TUI_DOC_MENU_TEXT,
TuiDocIcons,
} from '@taiga-ui/addon-doc/tokens';
import {ALWAYS_FALSE_HANDLER, TuiSwipeService} from '@taiga-ui/cdk';
import {ALWAYS_FALSE_HANDLER} from '@taiga-ui/cdk';
import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus';
import {distinctUntilChanged, filter, map, merge, startWith, Subject} from 'rxjs';
import {distinctUntilChanged, map, merge, startWith, Subject} from 'rxjs';

@Component({
selector: 'header[tuiDocHeader]',
Expand All @@ -22,18 +22,13 @@ export class TuiDocHeaderComponent {
readonly open$ = merge(
this.router.events.pipe(map(ALWAYS_FALSE_HANDLER)),
this.stream$,
this.swipes$.pipe(
filter(swipe => swipe.direction === 'left' || swipe.direction === 'right'),
map(swipe => swipe.direction === 'right'),
),
).pipe(startWith(false), distinctUntilChanged());

constructor(
@Inject(TUI_DOC_ICONS) readonly icons: TuiDocIcons,
@Inject(TUI_DOC_LOGO) readonly logo: PolymorpheusContent,
@Inject(TUI_DOC_MENU_TEXT) readonly menu: string,
@Inject(Router) private readonly router: Router,
@Inject(TuiSwipeService) private readonly swipes$: TuiSwipeService,
) {}

onClick(): void {
Expand Down
1 change: 1 addition & 0 deletions projects/addon-mobile/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from '@taiga-ui/addon-mobile/components/mobile-dialog';
export * from '@taiga-ui/addon-mobile/components/pull-to-refresh';
export * from '@taiga-ui/addon-mobile/components/sheet';
export * from '@taiga-ui/addon-mobile/components/sheet-dialog';
export * from '@taiga-ui/addon-mobile/components/swipe-action';
export * from '@taiga-ui/addon-mobile/components/tab-bar';
export * from '@taiga-ui/addon-mobile/components/theme-android';
export * from '@taiga-ui/addon-mobile/components/theme-ios';
2 changes: 2 additions & 0 deletions projects/addon-mobile/components/swipe-action/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './swipe-actions.component';
export * from './swipe-actions-auto-close.directive';
5 changes: 5 additions & 0 deletions projects/addon-mobile/components/swipe-action/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"lib": {
"entryFile": "index.ts"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {Directive, ElementRef, Inject, Input} from '@angular/core';
import {tuiGetActualTarget} from '@taiga-ui/cdk';

@Directive({
standalone: true,
selector: 'tui-swipe-actions[autoClose]',
host: {
'(document:pointerdown.silent)': 'onPointer($event)',
},
})
export class TuiSwipeActionsAutoCloseDirective {
@Input()
autoClose = true;

constructor(@Inject(ElementRef) private readonly el: ElementRef<HTMLElement>) {}

onPointer(event: PointerEvent): void {
const target = tuiGetActualTarget(event);

if (this.autoClose && !this.el.nativeElement.contains(target)) {
this.close();
}
}

private close(): void {
this.el.nativeElement.scrollTo({
left: 0,
behavior: 'smooth',
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {ResizeObserverModule} from '@ng-web-apis/resize-observer';

@Component({
standalone: true,
selector: 'tui-swipe-actions',
imports: [ResizeObserverModule],
templateUrl: './swipe-actions.template.html',
styleUrls: ['./swipe-actions.style.less'],
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'[style.--t-actions-width]': 'actionsWidth',
},
})
export class TuiSwipeActionsComponent {
actionsWidth = 0;

onResize({target}: ResizeObserverEntry): void {
this.actionsWidth = target.clientWidth;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
@import '@taiga-ui/core/styles/taiga-ui-local';

:host {
.scrollbar-hidden();
--tui-action-gap: 24;
--tui-actions-padding: 0.5rem;
--tui-item-size: 44;

display: flex;
width: stretch;
align-items: center;
overflow-x: scroll;
overflow-y: hidden;
scroll-snap-type: x mandatory;
perspective: 1px;
perspective-origin: calc(100% + calc(1px * var(--tui-item-size) / 2) + var(--tui-actions-padding));
}

.t-content {
scroll-snap-align: start;
flex-shrink: 0;
width: 100%;
}

.t-actions {
display: flex;
gap: calc(1px * var(--tui-action-gap));
padding: 0 1rem 0 var(--tui-actions-padding);
scroll-snap-align: start;
align-items: center;
transform-style: preserve-3d;

::ng-deep & > * {
.loop(6);
}
}

.loop (@i) when (@i > 1) {
.loop(@i - 1);
&:nth-child(@{i}) {
--t-distance: ~'calc(var(--tui-item-size) + var(--tui-action-gap)) * calc(@{i} - 1)';
--t-factor: calc((var(--t-actions-width) - var(--t-distance)) / var(--t-actions-width));
--t-scale: calc(1 / var(--t-factor));
--t-translate: calc(1px * (1 - 1 / var(--t-factor)));
transform: ~'translate3d(calc(calc((-100% - calc(1px * var(--tui-action-gap))) * (@{i} - 1)) / var(--t-scale)), 0, var(--t-translate))';
scale: var(--t-scale);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<div class="t-content">
<ng-content></ng-content>
</div>

<div
class="t-actions"
(waResizeObserver)="onResize($event[0])"
>
<ng-content select="[tuiSwipeAction]"></ng-content>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export const IDENTIFIERS_TO_REPLACE: ReplacementIdentifier[] = [
from: {name: 'TuiCheckboxModule', moduleSpecifier: '@taiga-ui/experimental'},
to: {name: 'TuiCheckboxModule', moduleSpecifier: '@taiga-ui/kit'},
},
{
from: {name: 'TuiSwipeActionsModule', moduleSpecifier: '@taiga-ui/experimental'},
to: {name: 'TuiSwipeActionsComponent', moduleSpecifier: '@taiga-ui/addon-mobile'},
},
{
from: {name: 'TuiRadioModule', moduleSpecifier: '@taiga-ui/experimental'},
to: {name: 'TuiRadioModule', moduleSpecifier: '@taiga-ui/kit'},
Expand Down
4 changes: 1 addition & 3 deletions projects/core/styles/mixins/mixins.less
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,7 @@

&::-webkit-scrollbar,
&::-webkit-scrollbar-thumb {
background: transparent;
width: 0;
height: 0;
display: none;
}
}

Expand Down
5 changes: 0 additions & 5 deletions projects/demo/src/modules/app/app.providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import {
TUI_DIALOG_CLOSES_ON_BACK,
TUI_IS_E2E,
TUI_IS_PLAYWRIGHT,
TUI_SWIPE_OPTIONS,
TUI_TAKE_ONLY_TRUSTED_EVENTS,
tuiAssert,
} from '@taiga-ui/cdk';
Expand Down Expand Up @@ -146,10 +145,6 @@ export const APP_PROVIDERS: Provider[] = [
provide: TUI_DOC_EXAMPLE_CONTENT_PROCESSOR,
useValue: exampleContentProcessor,
},
{
provide: TUI_SWIPE_OPTIONS,
useValue: {timeout: 300, threshold: 60},
},
{
provide: TUI_HINT_OPTIONS,
useFactory: () =>
Expand Down
9 changes: 9 additions & 0 deletions projects/demo/src/modules/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,15 @@ export const ROUTES: Routes = [
title: 'Surface',
},
},
{
path: 'components/swipe-actions',
loadChildren: async () =>
(await import('../components/swipe-action/swipe-actions.module'))
.ExampleTuiSwipeActionsModule,
data: {
title: 'SwipeActions',
},
},
{
path: 'experimental/textfield',
loadChildren: async () =>
Expand Down
6 changes: 6 additions & 0 deletions projects/demo/src/modules/app/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,12 @@ export const pages: TuiDocPages = [
keywords: 'card, container, wrapper, image, blur, overlay',
route: '/experimental/surface',
},
{
section: 'Components',
title: 'SwipeActions',
keywords: 'swipe, action, свайп, card, действие',
route: '/components/swipe-actions',
},
{
section: 'Experimental',
title: 'Textfield',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<tui-swipe-actions>
<div tuiSurface="elevated">
<div tuiCell>
<tui-avatar
appearance="primary"
src="tuiIconDollarSignLarge"
></tui-avatar>
<div tuiTitle>
<strong>{{ 10000 | tuiAmount: 'USD' | async }}</strong>
<div tuiSubtitle>Dollar account</div>
</div>
</div>
</div>

<button
iconLeft="tuiIconEye"
size="m"
tuiIconButton
tuiSwipeAction
></button>
<button
iconLeft="tuiIconEdit3"
size="m"
tuiIconButton
tuiSwipeAction
></button>
<button
appearance="secondary"
iconLeft="tuiIconShare"
size="m"
tuiIconButton
tuiSwipeAction
></button>
</tui-swipe-actions>

<tui-swipe-actions>
<div tuiSurface="elevated">
<div tuiCell>
<tui-avatar
appearance="primary"
src="tuiIconGift"
></tui-avatar>
<div tuiTitle>
<strong>{{ 23000 | tuiAmount: 'EUR' | async }}</strong>
<div tuiSubtitle>Goal</div>
</div>
</div>
</div>

<button
iconLeft="tuiIconEye"
size="m"
tuiIconButton
tuiSwipeAction
></button>
</tui-swipe-actions>

<tui-swipe-actions
[style.--tui-action-gap]="16"
[style.--tui-item-size]="32"
>
<div tuiSurface="elevated">
<div tuiCell>
<tui-avatar
appearance="primary"
src="tuiIconBriefcase"
></tui-avatar>
<div tuiTitle>
<strong>{{ 5000 | tuiAmount: 'EUR' | async }}</strong>
<div tuiSubtitle>Vacations</div>
</div>
</div>
</div>

<button
iconLeft="tuiIconEye"
size="s"
tuiIconButton
tuiSwipeAction
></button>
<button
iconLeft="tuiIconEdit3"
size="s"
tuiIconButton
tuiSwipeAction
></button>
<button
appearance="secondary"
iconLeft="tuiIconShare"
size="s"
tuiIconButton
tuiSwipeAction
></button>
<button
appearance="destructive"
iconLeft="tuiIconTrash"
size="s"
tuiIconButton
tuiSwipeAction
></button>
</tui-swipe-actions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
:host {
display: flex;
flex-direction: column;
gap: 1rem;
width: 20rem;
margin: 2rem 0;
}

[tuiSurface] {
margin: 1.5rem 1rem;
}

tui-swipe-actions {
margin: -1.5rem -1rem;
}

button[tuiSwipeAction] {
border-radius: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {Component} from '@angular/core';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';

@Component({
selector: 'tui-swipe-action-example-1',
templateUrl: './index.html',
styleUrls: ['./index.less'],
encapsulation,
changeDetection,
})
export class TuiSwipeActionExample1 {}
Loading

0 comments on commit 363c532

Please sign in to comment.