Taiga UI 5.0 is out!

Tiles KIT

Examples API GitHub

On this page

Tiles is a light-weight touch-friendly tiles grid drag and drop component with no predefined styles.

Basic

Item 1

Order - 0

Item 2

Order - 1

Item 3

Order - 2

Item 4

Order - 3

Item 5

Order - 4

Item 6

Order - 5

Item 8

Order - 7

Item 9

Order - 8
    
      
    
    
      <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;
    }
}

    

Vertical

With media query width control
John Cleese
Eric Idle
Michael Palin
Graham Chapman
Terry Gilliam
Terry Jones
    
      
    
    
      <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);
    }
}

    

Nested tiles

Item 1

Order - 0

Item 1
Item 2
Item 3
Item 4
Item 2

Order - 1

Item 1
Item 2
Item 3
Item 4
Item 3

Order - 2

Item 1
Item 2
Item 3
Item 4
Item 4

Order - 3

Item 1
Item 2
Item 3
Item 4
    
      
    
    
      <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;
    }
}