Tiles is a light-weight touch-friendly tiles grid drag and drop component with no predefined styles.
<tui-tiles
class="tiles"
[debounce]="500"
[(order)]="order"
>
@for (item of items; track item) {
<tui-tile
class="tile"
[height]="item.h"
[style.order]="order.get($index)"
[width]="item.w"
>
<div
class="content"
[class.rick]="item.content === 'rick'"
>
@if (item.content === 'rick') {
<iframe
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
src="https://www.youtube.com/embed/dQw4w9WgXcQ?modestbranding=1&autohide=1&showinfo=0&controls=0"
title="YouTube video player"
class="rick"
></iframe>
} @else {
<h2 class="title">{{ item.content }}</h2>
Order - {{ order.get($index) ?? $index }}
}
<tui-icon
icon="@tui.grip-vertical"
tuiTileHandle
class="handle"
/>
<tui-icon
icon="@tui.grip-vertical"
tuiTileHandle
class="handle"
/>
</div>
</tui-tile>
}
</tui-tiles>
@import '@taiga-ui/styles/utils.less';
.tiles {
gap: 1rem;
grid-auto-rows: minmax(6.25rem, auto);
}
.tile::before {
content: 'Drop here';
display: flex;
block-size: 100%;
justify-content: center;
align-items: center;
box-sizing: border-box;
color: var(--tui-border-normal);
border-radius: var(--tui-radius-l);
border: 2px dashed var(--tui-border-normal);
}
.content {
.transition(box-shadow);
block-size: 100%;
padding: 1rem;
background: var(--tui-background-base);
box-sizing: border-box;
border-radius: var(--tui-radius-l);
border: 1px solid var(--tui-border-normal);
overflow: hidden;
tui-tile._dragged & {
box-shadow: var(--tui-shadow-small-hover);
}
}
.rick {
inline-size: 100%;
block-size: 100%;
padding: 0;
}
.title {
margin: 0 0 1rem;
}
.handle {
.transition(opacity);
position: absolute;
inset-inline-end: 0.75rem;
inset-block-start: 1rem;
background: var(--tui-background-base);
opacity: 0;
cursor: move;
tui-tiles:not(._dragged) tui-tile:hover &,
tui-tile._dragged & {
opacity: 0.7;
}
}
<tui-tiles
class="tiles"
[(order)]="order"
>
@for (item of items; track item) {
<tui-tile
tuiTileHandle
class="tile"
[class.tile_tall]="item === 'John Cleese'"
[style.order]="order.get($index)"
>
<div class="content">{{ item }}</div>
</tui-tile>
}
</tui-tiles>
@import '@taiga-ui/styles/utils.less';
.tiles {
inline-size: 10rem;
gap: 1rem;
grid-auto-rows: minmax(var(--tui-height-m), auto);
}
@media @tui-mobile {
.tile_tall {
--tui-height: 2;
}
}
.content {
.transition(box-shadow);
display: flex;
block-size: 100%;
align-items: center;
padding: 0 1rem;
background: var(--tui-background-base);
border-radius: var(--tui-radius-l);
border: 1px solid var(--tui-border-normal);
cursor: ns-resize;
tui-tile._dragged & {
box-shadow: var(--tui-shadow-small-hover);
}
}
Order - 0
Order - 1
Order - 2
Order - 3
<tui-tiles
class="tiles"
[debounce]="500"
[(order)]="order"
>
@for (item of items; track item; let i = $index) {
<tui-tile
class="tile"
[style.order]="order.get(i)"
>
<div class="content">
<tui-icon
icon="@tui.grip-vertical"
tuiTileHandle
class="handle"
/>
<strong>{{ item.content }}</strong>
<p>Order - {{ order.get(i) ?? i }}</p>
<tui-tiles
class="nested"
[(order)]="item.order"
>
@for (child of items; track child; let j = $index) {
<tui-tile
tuiTileHandle
class="tile"
[style.order]="item.order.get(j)"
>
<div class="content">
{{ child.content }}
</div>
</tui-tile>
}
</tui-tiles>
</div>
</tui-tile>
}
</tui-tiles>
@import '@taiga-ui/styles/utils.less';
.tiles {
gap: 1rem;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 15rem;
}
.nested {
gap: 1rem;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 3.5rem;
}
.tile::before {
content: 'Drop here';
display: flex;
block-size: 100%;
justify-content: center;
align-items: center;
box-sizing: border-box;
color: var(--tui-border-normal);
border-radius: var(--tui-radius-l);
border: 2px dashed var(--tui-border-normal);
}
.content {
.transition(box-shadow);
block-size: 100%;
padding: 1rem;
background: var(--tui-background-base);
box-sizing: border-box;
border-radius: var(--tui-radius-l);
border: 1px solid var(--tui-border-normal);
overflow: hidden;
tui-tile._dragged & {
box-shadow: var(--tui-shadow-small-hover);
}
tui-tile._dragged tui-tile:not(._dragged) & {
box-shadow: none;
}
}