Skip to content

Tile Manager Specification

Maria Tsvyatkova edited this page Feb 11, 2025 · 34 revisions

Tile Manager (Tile Layout?) Specification [Draft]

Contents

  1. Overview
  2. User Stories
  3. Functionality
  4. Test Scenarios
  5. Accessibility
  6. Assumptions and Limitations
  7. References

Owned by

Team Name: CodeX

Developer Name: Maria Tsvyatkova, Ivaylo Barakov

Designer Name: Silvia Ivanova

Requires approval from

  • Peer Developer Name | Date:
  • Design Manager Name | Date:

Signed off by

  • Radoslav Mirchev | Date:
  • Radoslav Karaivanov | Date:

Revision History

Version Users Date Notes
1 Maria Tsvyatkova 19-Sep-2024 Initial draft
1.1 Maria Tsvyatkova 09-Oct-2024 Update User Stories
1.2 Ivaylo Barakov 03-Feb-2025 Update Functionality with resizing draft
1.3 Galina Edinakova 07-Feb-2025 IgcTileManagerComponent API update

The igc-tile-manager component enables the display of content in tiles, offering users the flexibility to rearrange and resize them in the way that best suits their needs.

Objectives

The Tile Manager provides a base tile layout behavior, managing the placement of tiles in maximized or normal state. The tiles can be sized independently of each other and used to form complex layouts. End users can reorder tiles by dragging and dropping.

Acceptance criteria

  1. The Tile Manager should allow maximizing a single tile. Dragging and resizing interactions are not allowed when a tile is maximized.
  2. The Tile Manager should allow tile resizing by dragging the resize adorners.
  3. The Tile Manager should allow rearranging of tiles by dragging and dropping a tile.
  4. The Tile Manager should support tile's header customization.
  5. The Tile Manager should allow serialization of the tile layout so that it can be saved and loaded.
  6. The Tile Manager should emit events on resizing, dragging, dropping a tile.

Developer stories:

  • Story 1: As a developer, I want to define N number of tiles, so that I can display many different types of information in a single layout.
  • Story 2: As a developer, I want to define number columns, so that I can control the maximum number of tiles which can be displayed in a given row.
  • Story 3: As a developer, I want to specify how many rows and columns a tile should span, so that I can display tiles with different sizes.
  • Story 4: As a developer, I want to have an option to allow tiles' dragging only by their header, so that I can let users interact with the tile's content.
  • Story 5: As a developer, I want to restrict triggering any interactions with the content itself, so that I can provide an option to drag and drop by clicking on the tile's content.
  • Story 6: As a developer, I want to control the tile's state with a property, so that I can place a tile in a maximized state.
  • Story 7: As a developer, I want to have an event which is emitted when a tile changes its size, so that I can easily track the size of each tile.
  • Story 8: As a developer, I want to have an event which is emitted when a tile changes its state, so that I can add custom logic to react to that change.
  • Story 9: As a developer, I want to have an event which is emitted when a tile is dragged, so that I can provide a custom code to highlight the currently targeted tile.
  • Story 10: As a developer, I want to have an event which is emitted when a tile is dropped, so that I can validate its drop location.
  • Story 11: As a developer, I want to configure the layout to use either a Slide or Swap transition when tiles are reordered via drag and drop, so that I can control the user experience of my application.
  • Story 12: As a developer, I want to be able to 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.
  • Story 13: As a developer, I want to be able to save the current layout, so that I can reload it when needed.
  • Story 14: As a developer, I want to restrict the end user from resizing or dragging a specific tile, so that I can ensure it is always displayed as I intended.
  • Story 15: As a developer, I want to have a completely customizable tile header, so that I can modify its content based on my application logic.

End-user stories:

  • Story 1: As an end-user, I want to be able to resize a tile by dragging its corner, bottom or right edge, so that I can have a better view of the content.
  • Story 2: As an end-user, I want to reorder tiles via drag and drop, so that I can place the information in the order I desire.
  • Story 3: As an end-user, I want to see a preview of a new tile position before dropping, so that I can understand the impact of placing the tile.
  • Story 4: As an end-user, I want to be able to maximize a tile with ease, so that I can better focus on its content.
  • Story 5: As an end-user, I want to have the tiles rearrange themselves in new rows when I reduce the size of the layout, so that I can keep a clear view of their content.

Stories to consider for future implementation:

  • Story 1: As a developer, I want to 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.
  • Story 2: As a developer, I want to 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.
  • Story 3: As a developer, I want to use a custom style for the tile drag preview, so that I can provide a customized view of a tile while being dragged.
  • Story 4: As an end-user, I want to 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)

Describe behavior, design, look and feel of the implemented feature. Always include visual mock-up

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

Limitations

There are several constraints and limitations in the resizing process:

  • A tile cannot be resized smaller than its defined minimum width or height (minColWidth, minRowHeight)

  • A tile cannot be resized beyond the maximum available space in the 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.

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.

3.1. End-User Experience

Design Handoff

3.2. Developer Experience

<igc-tile-manager>
    <igc-tile>
        <h3 slot="title">Title 1</h3>
        <igc-icon name="home" slot="actions"></igc-icon>
        
        <p>Tile 1 content</p>
    </igc-tile>
    <igc-tile maximized>
        <p>Tile 2 content</p>
    </igc-tile>
</igc-tile-manager>

3.3. Globalization/Localization

Describe any special localization requirements such as the number of localizable strings, regional formats

3.4. Keyboard Navigation

Keys Description
Esc Cancel the drag/resize operation and restore the tile to its original position/size.

3.5. API

IgcTileManagerComponent

Properties

Name Attribute Description Type Default value
columnCount column-count Determines the number of CSS Grid columns used to arrange the tiles. If it is less than one, as many columns as can fit will be created, with each column being at least 20px wide and able to grow to take up an equal share of the remaining space. number 0
dragMode drag-mode Determines whether drag and drop operations are enabled. TileManagerDragMode = none | tile-header | tile none
dragAction drag-action Determines whether the tiles will slide or swap on drop during a drag and drop operation. TileManagerDragAction = slide | swap slide
minColumnWidth min-column-width Defines the minimum width for a column unit in the tile manager. string | undefined undefined
minRowHeight min-row-height Defines the minimum height for a row unit in the tile manager. string | undefined undefined
gap gap Defines the gap size of the tile manager. string | undefined undefined
resizeMode resize-mode Determines whether resize operations are enabled. TileManagerResizeMode = none | hover | always none
tiles - Gets the tiles sorted by their position in the layout. IgcTileComponent[] []

Methods

Name Description Return type Parameters
saveLayout Saves the current state of the tile manager. string -
loadLayout Loads the previously saved state of the tile manager. - data: string

Events

Name Description Cancelable Parameters
igcResizeStart Emitted when tile size started changing. true { tile: IgcTileComponent }
igcResizeEnd Emitted when tile size is changed. false { tile: IgcTileComponent }
igcTileDragStarted Emitted when an owning tile begins a drag operation. true { tile: IgcTileComponent }
igcTileDragEnded Emitted when a tile drag ends. false { tile: IgcTileComponent }

Slots

Name Description
(default) Default slot for the tile manager. Any igc-tile controls should be projected here.

CSS Parts

Name Description
base The base wrapper of the tile manager.
maximized-tile Added when there is a maximized tile.

IgcTileComponent

Properties

Name Attribute Description Type Default value
tileId tile-id Identifier of the tile. If not explicitly set, a unique one will be assigned in the format tile-<number> string | null null
fullscreen - Indicates whether the tile occupies the whole screen. boolean false
maximized maximized Indicates whether the tile occupies all available space within the layout. Dragging and resizing are not allowed when it is true. boolean false
colSpan col-span Specifies the number of columns the tile spans across in the layout. Values <= 1 will be coerced to 1. number 1
rowSpan row-span Specifies the number of rows the tile spans across in the layout. Values <= 1 will be coerced to 1. number 1
colStart col-start Specifies the starting column where the tile is placed. If it is null, the tile will be auto placed starting from the next free column. number | null null
rowStart row-start Specifies the starting row where the tile is placed. If it is null, the tile will be auto placed starting from the next free row. number | null null
disableResize disable-resize Disable tile resizing. boolean false
disableDrag disable-drag Disable tile dragging. boolean false
position - Gets/sets the tile's visual position in the layout. Corresponds to the CSS order property. number -1

Slots

Name Description
title A slot for the title in the header.
default-actions Unites the slots for the default actions - maximize and fullscreen.
maximize-action A slot for the maximize action. An icon button is projected by default.
fullscreen-action A slot for the fullscreen action. An icon button is projected by default.
actions Any custom actions are projected here, after the default ones.
(default) A slot for the tile's content.

CSS Parts

Name Description
base The wrapper of a tile.
drag-over Added when a tile is dragged over the current tile.
dragging Added when the tile is dragged.
resizing Added when the tile is resized.
draggable Added when disableDrag is false.
resizable Added when disableResize is false.
fullscreen Added to the wrapper when a tile is in fullscreen state.
header The header wrapper of a tile.
title The title of a tile.
actions A section where action buttons are added.
content-container The content wrapper of a tile.

Automation

Rendering and initialization

  • passes the default WAI-ARIA automation
  • is initialized with proper default state
  • renders properly
  • slots user provided content in the tile
  • slots user provided title in tile's header
  • project custom default actions
  • slots user provided actions in tile's header

Column spans

  • render tile manager with correct number of children
  • each tile has correct grid area (column and row span)
  • row and column template style properties are properly set
  • respect tile row and column start properties

Manual slot assignment

  • only accepts igc-tile element
  • initialize with the correct tiles in the tiles collection
  • update the tiles collection when a tile is added to the light DOM
  • update the tiles collection when a tile is removed from the light DOM
  • update the slot when tile is added
  • update the slot when a tile is removed

Resize

  • create a ghost element on resize start
  • update ghost element's size during pointer move
  • set proper size on the tile and remove the ghost element on resize end
  • update ghost element styles during pointer move
  • correctly resize column with auto grid
  • correctly create/remove implicit rows and resize row with auto grid
  • initialize tile span as columnCount if it is greater than columnCount
  • maintain column position on resize when colStart is set
  • maintain row position on resize when rowStart is set
  • cancel resize by pressing ESC key
  • prevent resizing when disableResize is true
  • update tile parts on resizing

Drag and drop

  • fire the igcTileDragStarted when drag operation is started
  • fire the igcTileDragEnded when drag operation is ended
  • adjust reflected tiles positions with slide action
  • keep the same order if dropped on the same tile with slide action
  • swap the dragged tile with the drop target with swap action
  • keep the same order if dropped on the same tile with swap action
  • prevent dragging when disableDrag is true
  • cancel dragging with Escape
  • disable drag and drop when tile is maximized
  • disable drag and drop when tile is in fullscreen mode

State change behavior

  • correctly fire igcTileFullscreen event
  • igcTileFullscreen event is cancelable
  • correctly fire igcTileMaximize event
  • igcTileMaximize event is cancelable

Serialization

  • serialize tiles to JSON string
  • deserialize tiles from JSON string, applying all their settings

ARIA Support

RTL Support

Assumptions Limitation Notes
Fullscreen mode could not be set on initial render The requestFullscreen method requires transient user activation, meaning it must follow recent user interaction.

Specify all referenced external sources

Clone this wiki locally