Skip to content

Tile Manager Specification

Radoslav Karaivanov edited this page Feb 27, 2025 · 36 revisions

Tile Manager Specification

Owned By

Team name: CodeX

Developer names: Maria Tsvyatkova, Ivaylo Barakov

Designer name: Silvia Ivanova

Requires approval from:

  • Damyan Petev
  • Svilen Dimchevski

Signed off by:

  • Radoslav Karaivanov
  • Radoslav Mirchev

Revision history

Version Author Date Notes
1 Maria Tsvyatkova 2024-09-19 Initial draft
1.1 Maria Tsvyatkova 2024-10-09 Updated user stories
1.2 Ivaylo Barakov 2025-02-03 Update Functionality with resizing draft
1.3 Galina Edinakova 2025-02-07 IgcTileManagerComponent API update
1.4 Radoslav Karaivanov 2025-02-27 Updated with latest implementation changes

Overview

The igc-tile-manager component enables developers to layout different content inside of tile containers. The tile manager will try to position and arrange those tile containers based on either user provided configuration or its default one. Additional features such a tile drag rearrangement, resizing of tiles, maximized and fullscreen states can be enabled for users to interact with.

Typical use-cases for the tile manager are product and image galleries, dashboards for reports or metrics and bespoke UI scenarios.

Objectives

The tile manager provides a base tile layout behavior based on the native CSS Grid specification. Tiles accept slotted content and the manager will arrange them based on its and their configuration. Each tile can be configured and sized independently of each other. Features such as rearranging and resizing tiles are also available after configuration. Additional states such as maximized and fullscreen mode can be enabled/disabled per tile, with a default UI that can be customized.

Acceptance criteria

The igc-tile-manager component must:

  • support rendering user-provided tiles and content inside those tiles.
  • expose an API to configure the underlying CSS Grid in order to accommodate specific user scenarios.
  • expose an API to enable dragging and rearrangement of tiles.
  • expose and API to enable resizing of tiles.
  • expose an API to serialize the configuration of its tiles into a standard JSON format, so it can be saved either locally or remotely.
  • expose an API to deserialize a previously exported configuration and apply it to its current tile descendants.
  • follow WAI-ARIA best practices.

The igc-tile component must:

  • expose an API to configure its initial position and layout inside the tile manager.
  • support customization of the its content and DOM parts. Users must be able to customize different parts of the tile (header, action buttons, etc) with slots.
  • provide a default UI for maximized and fullscreen states as well as expose API to control those states and modify the default UI associated with them.
  • participate in tile drag rearrangement when configured by the tile manager.
  • participate in tile resizing when configured by the tile manager.
  • expose an API to disable resize behavior per tile.

User stories

End-user stories

As an end-user I expect to be able to:

  • resize a tile by dragging its corner, in order to better view its content or highlight the importance of its content.
  • reorder tiles via drag and drop, in order to control the layout and information flow in the tile manager.
  • see a preview of a drag and drop operation, in order to understand the impact of placing the tile at the position.
  • maximize a tile, in order to focus attention on its content.
  • have the tiles inside the tile manager rearrange themselves when the tile manager or the viewport dimensions are changed so I can have a responsive view of the content.

Developer stories

As a developer I expect to be able to:

  • declaratively define tiles and their content inside the tile manager.
  • define the number of columns, so that I can control the maximum number of tiles which can be displayed in a given row.
  • specify how many rows and columns a tile should span, so that I can display tiles with different sizes.
  • have an option to allow tile dragging only by their header, so that I can let users interact with the tile's content.
  • have an option to allow tile dragging by initiating a drag operation on the tile itself (header + content).
  • add/remove tile with different sizes dynamically and the tiles should rearrange minimizing the empty space between them, so that I can have a compact layout.
  • save the current layout, so that I can reload it when needed.
  • restrict the end user from resizing a specific tile, so that I can ensure it is always displayed as I intended.
  • have a completely customizable tile header, so that I can modify its content based on my application logic.

Stories to consider for future implementation:

  • expose a mode where the layout has a maximized tile and a list of minimized tiles beside it.
  • set the size and position of the maximized tile and minimized tiles list, so that I can control the arrangement of tiles in the layout. Default maximized left.
  • define the content displayed in each tile based on its current state, so that I can customize the appearance of tiles in minimized, minimized-expanded, maximized, and normal states.
  • use a custom style for the tile drag preview, so that I can provide a customized view of a tile while being dragged.
  • be able to drill into a minimized tile without making it the maximized tile, so that I can see tile's content without changing the currently maximized tile. (This is applicable if we have both minimized and minimized-expanded states)

Functionality

End-user experience

Design Hand-off

Developer experience

Basic layout and initialization

The tile manager wraps its projected tile components into an internal

Drag rearrangement

Types of drag

Dragging behavior in the tile manager is enabled by setting the dragMode property ot one of the following values:

  • none - Dragging of tiles is disabled.
  • tile-header - Dragging is initiated by a click inside the title slot of the tile header.
  • tile - Dragging is initiated by a click inside the tile.

Important

Since both drag & resize operations are based on the native PointerEvent API, in order to keep user interaction consistent between resize and drag, when a click is initiated on a resize adorner it will take precedence over the dragging behavior.

Dragging is also ignored on pointer interaction with any elements inside the tile actions slot which includes the default UI for maximize and fullscreen as well as any user provided content.

Dragging and rearrangements

When initiating a drag operation a ghost copy of the dragged tile is created while the original element is transitioned into a drag state. While dragging the ghost copy around the tile manager for each pointer enter event into a tile, the original copy will switch position and relevant properties (colStart, rowStart) with the touched tile.

This will be valid for all tiles along the path of the drag operation and since the CSS Grid container is set to dense there could be general shift between the a group of tiles if the dragged tile cannot fit into the new position.

Additionllay

Important

asdsa

Integration with other behaviors
  • While the tile is in maximized or fullscreen states, the tile cannot be dragged.

Resizing

Types of resizing

Resizing in the tile manager is a functionality that allows tiles to be resized using three different resize adorners.

  • Side Adorner - Adjusts width by modifying the column span.
  • Bottom Adorner - Adjusts height by modifying the row span.
  • Corner Adorner - Adjusts both width and height simultaneously.
Deferred resizing using a ghost element

To achieve smooth resizing, a ghost element is used instead of directly modifying the tile's dimensions. It appears on top of the original tile with it's current dimensions when resizing starts and updates in real time as the user drags any of the resize handles. This approach is known as deferred resizing, meaning that no changes are applied to the actual tile until resizing is complete.

Snapping behavior

Tiles always resize in alignment with the CSS grid, meaning they can only expand or shrink in full grid units. When resizing horizontally or vertically, the ghost will snap to the next column or row once it reaches the halfway point of that unit. If the resize remains below the halfway threshold when resizing is completed, the tile maintains its current span. This prevents partial resizing and ensures that tiles conform to the grid's structure.

Additionally, grid gaps (grid-gap values) are taken into account during resizing, ensuring that the spacing between tiles remains consistent.

Applying new size

Once the user releases the resize handle, the final grid-row and grid-column spans are calculated based on the ghost's position and size. At this point, the ghost element is removed, and the actual tile is updated to reflect its new size.

Note

If the ghost exceeds the available grid space, it will be resized to the largest possible span within the grid's limits.

The CSS grid automatically rearranges itself when a tile changes size, ensuring that there is minimal empty space. Thats why expanding a tile may push adjacent tiles into new positions, while shrinking creates gaps that other tiles may fill dynamically. This ensures that the tile manager remains as compact as possible without any overlapping tiles and all movements remain within the defined grid structure.

Events

The resize process emits three key events corresponding to pointer interactions:

  • igcResizeStart - fired on pointerdown when the user initiates resizing by clicking any of the resize handles
  • igcResize - fired on pointermove, continuously updating the ghost element’s size as the user resizes
  • igcResizeEnd - fired on lostpointercapture when resizing ends, applying the new dimensions to the tile and removing the ghost element
  • igcResizeCancel - fired on pressing Escape during a resize operation. Doing so will cancel the current resize operation, remove the ghost element and leave the state of the tile as it was before the start of the operation.
Integration with other behaviors
  • Developers can override a tile resize behavior by setting disableResizing to true.
  • While the tile is in maximized or fullscreen states, the tile cannot be resized.
  • The resize adorners of the tile can be customized through their slots. See the API table below for information.
Limitations

There are several constraints and limitations in the resizing process:

  • A tile cannot be resized smaller than the tile manager's defined minimum column and row values (minColWidth, minRowHeight)
  • A tile cannot be resized beyond the maximum available space in the CSS grid. If a tile starts at a certain column/row and the user attempts to resize it beyond the visible grid area, it will only expand up to the maximum available columns/rows from its starting position.

Note

E.g. if there are 7 columns and a tile starts at column 4, resizing it to 2000px width will not extend beyond column 7, as that is the maximum available space.

Localization

No specific implementation details are required. Tiles and their content are user controlled, so localization handling is left to the user as an application scenario.

Note

This may not be entirely true, since the tile headers have default icon-buttons which should have an aria-label.

Keyboard interaction

Key Description
Escape Applicable only during drag and resize interactions. Cancels the current interaction.

Behavior

  • Pressing Escape during resize will cancel the current resize operation, remove the ghost element and leave the state of the tile as it was before the start of the operation.
  • Pressing Escape during drag will unwind all the rearranged tiles during the operation back to their initial state and remove the ghost element.

API

IgcTileManagerComponent

Properties

Property Attribute Reflected Property Type Default Description
columnCount column-count No number 0 Sets the number of columns in the tile manager. Settings this to 0 or a negative value
minColumnWidth min-column-width No string - Sets the minimum width for a column in the tile manager
minRowHeight min-row-height No string - Sets the minimum height for a row in the tile manager
gap gap No string - Sets the CSS Grid gap size
tiles - No readonly Array<IgcTileComponent> - Get the underlying tiles sorted by their position
dragMode drag-mode No none | tile-header | tile none
resizeMode resize-mode No none | hover | always none

Methods

Name Type signature Description
saveLayout (): string Returns the current tiles layout configuration an properties serialized as a JSON string
loadLayout (data: string): void Loads a previously serialized configuration and attempts to restore the state to the current tiles
? setFullscreen ? (tile: string | IgcTileComponent): void

Events

Name Cancellable Parameters Description
igcTileDragStart true IgcTileComponent Emitted when a drag operation is initiated
igcTileDragEnd false IgcTileComponent Emitted when a drag operation is completed
igcTileDragCancel false IgcTileComponent Emitted when a drag operation is discarded
igcTileResizeStart true IgcTileComponent Emitted when a resize operation is initiated
igcTileResizeEnd false IgcTileComponent Emitted when a resize operation is completed
igcTileResizeCancel false IgcTileComponent Emitted when a resize operation is discarded
igcTileFullscreen true { IgcTileComponent, state: boolean} Emitted when a tile is entering into fullscreen state through the default tile header UI
igcTileMaximized true { IgcTileComponent state: boolean } Emitted a a tile maximized state i toggled through the default tile header UI

Note

Possibly stop the internal event from propagating up the DOM tree.

Slots

Name Description
(default) Default slot for slotting tile components into the manager

CSS parts

Name Description
base The tile manager internal CSS Grid container

CSS variables

Name Description

IgcTileComponent

Properties

Property Attribute Reflected Property Type Default Description
tileId tile-id Yes string - A unique identifier for the tile. Used for serialization and deserialization. Autogenerated if not set
colStart col-start No number - The column in the CSS Grid container where the tile will start. If not set, it implicitly fallbacks to 'auto'
colSpan col-span No number 1 The number of CSS columns the tile will span. Setting values which are less than 1 are rejected and coerced to 1
rowStart row-start No number - The row in the CSS Grid container where the tile will start. If not set, it implicitly fallbacks to 'auto'
rowSpan row-span No number 1 The number of CSS rows the tile will span. Setting values which are less than 1 are rejected and coerced to 1
position position No number -1
disableFullscreen disable-fullscreen Yes boolean false When set hides the default fullscreen action button
disableMaximize disable-maximize Yes boolean false When set hides the default maximize toggle action button
disableResize disable-resize Yes boolean false When set, resize behavior is disabled for the tile regardless of the parent tile manager configuration
fullscreen - - readonly boolean false Whether the tile current state is fullscreen

Events

Name Cancellable Parameters Description
igcTileDragStarted true IgcTileComponent Emitted when a drag operation is initiated
igcTileDragEnded false IgcTileComponent Emitted when a drag operation is completed
igcTileDragCancel false IgcTileComponent Emitted when a drag operation is discarded
igcTileResizeStart true IgcTileComponent Emitted when a resize operation is initiated
igcTileResizeEnd false IgcTileComponent Emitted when a resize operation is completed
igcTileResizeCancel false IgcTileComponent Emitted when a resize operation is discarded
igcTileFullscreen true { IgcTileComponent, state: boolean} Emitted when a tile is entering into fullscreen state through the default tile header UI
igcTileMaximized true { IgcTileComponent state: boolean } Emitted a a tile maximized state i toggled through the default tile header UI

Slots

Name Description
(default) Default slot for slotting content into the tile
title Content for the tile header
fullscreen-action Overwrite the default fullscreen action content
maximize-action Overwrite the default maximize action content
actions Custom content rendered after the default actions
side-adorner Overwrite the default horizontal resize adorner
corner-adorner Overwrite the default diagonal resize adorner
bottom-adorner Overwrite the default vertical resize adorner

CSS parts

Name Description
base The wrapping container of the tile component
header The header container of the tile, including title and actions parts.
title The title container
actions The actions container
content-container The container wrapping the tile default slot
trigger-side Horizontal adorner.
trigger Diagonal adorner
trigger-bottom Vertical adorner

CSS variables

Name Description

Test scenarios

Automation

Rendering and initialization

  • is defined and rendered
  • is initialized with proper default state
  • passes the default WAI-ARIA automated tests
  • accepts and renders only slotted igc-tile component(s)
  • correct rendering state of slotted tiles
  • correct rendering state of slotted content inside a tile
  • correct rendering state of slotted content inside the tile header
  • DOM and internal state are correct when a tile is added dynamically
  • DOM and internal state are correct when a tile is removed dynamically

Grid sizing and positions

Serialization

  • correctly serializes tiles collection properties to a JSON string
  • correctly deserializes a serialized tiles collection and assign back the properties to the tiles

Accessibility

In general the tile manager and the tile components do not describe explicit ARIA roles.

WAI-ARIA

There is a limitation around the use of the CSS order property which means that the viewport layout may differ from the DOM hierarchy. In that case default keyboard focus behavior may seem weird since the position in the viewport could be different from the actual DOM hierarchy position.

RTL

Assumptions and limitations

Limitations

Clone this wiki locally