upp-thumb
A thumbnail card component used to represent items visually in grids and lists. It supports multiple shapes (default, round), content projection slots (top-left, top-right, bottom), card mode with detail and foot text, long-press detection, and automatic view mode switching when used inside upp-grid.
When to Use
- You need to display items as visual thumbnails in a product grid or catalog.
- You want to show badges, labels, or action icons overlaid on thumbnails via projection slots.
- You need card-mode thumbnails with additional detail and price/footer text.
- You need round avatar-style thumbnails for user or contact lists.
- You want to support both tap (select) and long-press interactions on items.
Demo
Source Code
- HTML
- TypeScript
- SCSS
<div class="demo-scroll-container">
<upp-scrollable [scrollbar]="'y'">
<div class="demo-content">
<h2>upp-thumb</h2>
<p class="demo-description">Team member cards showcasing different <code>upp-thumb</code> configurations. Use the color buttons to override all thumbnails.</p>
<div class="demo-section">
<h3>Team Members</h3>
<div class="demo-controls">
<ion-button size="small" fill="outline" (click)="setColorOverride(null)"
[fill]="colorOverride === null ? 'solid' : 'outline'">Default</ion-button>
<ion-button *ngFor="let c of colors" size="small" [color]="c"
[fill]="colorOverride === c ? 'solid' : 'outline'"
(click)="setColorOverride(c)">{{ c }}</ion-button>
</div>
<div class="thumb-row">
<!-- 1. Basic -->
<div class="thumb-item">
<upp-thumb
[title]="members[0].name"
[detail]="members[0].role"
[color]="getColor(members[0])"
[icon]="members[0].icon"
(Select)="onThumbSelect(members[0].name)">
</upp-thumb>
</div>
<!-- 2. Simple -->
<div class="thumb-item">
<upp-thumb
[title]="members[1].name"
[detail]="members[1].role"
[color]="getColor(members[1])"
[icon]="members[1].icon"
(Select)="onThumbSelect(members[1].name)">
</upp-thumb>
</div>
<!-- 3. Round avatar -->
<div class="thumb-item">
<upp-thumb
[title]="members[2].name"
[detail]="members[2].role"
[color]="getColor(members[2])"
[icon]="members[2].icon"
[shape]="members[2].shape"
(Select)="onThumbSelect(members[2].name)">
</upp-thumb>
</div>
<!-- 4. Card with footer -->
<div class="thumb-item">
<upp-thumb
[title]="members[3].name"
[detail]="members[3].role"
[foot]="members[3].team"
[color]="getColor(members[3])"
[icon]="members[3].icon"
[card]="members[3].card"
(Select)="onThumbSelect(members[3].name)">
</upp-thumb>
</div>
</div>
</div>
</div>
</upp-scrollable>
</div>
import { Component } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
interface TeamMember {
name: string;
role: string;
team: string;
icon: string;
defaultColor: string;
shape: 'default' | 'round';
card: string | null;
badge: number | null;
}
@Component({
selector: 'demo-upp-thumb',
templateUrl: './demo-upp-thumb.html',
styleUrls: ['../demo-common.scss', './demo-upp-thumb.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DemoUppThumbComponent {
colorOverride: string | null = null;
colors = ['primary', 'success', 'warning', 'danger'];
members: TeamMember[] = [
{ name: 'Alice', role: 'Developer', team: '', icon: 'person-outline', defaultColor: 'primary', shape: 'default', card: null, badge: null },
{ name: 'Bob', role: 'Designer', team: '', icon: 'color-palette-outline', defaultColor: 'success', shape: 'default', card: null, badge: null },
{ name: 'Carol', role: 'QA Lead', team: '', icon: 'person-outline', defaultColor: 'tertiary', shape: 'round', card: null, badge: null },
{ name: 'Dave', role: 'Team Lead', team: 'Engineering', icon: 'briefcase-outline', defaultColor: 'warning', shape: 'default', card: 'card', badge: null },
];
constructor(private change: ChangeDetectorRef) {}
getColor(member: TeamMember): string {
return this.colorOverride || member.defaultColor;
}
setColorOverride(color: string | null) {
this.colorOverride = color;
this.change.markForCheck();
}
onThumbSelect(name: string) {
console.log('Selected:', name);
}
}
:host {
display: block;
height: 100vh;
}
.demo-scroll-container {
height: 100%;
}
.demo-content {
padding: 12px;
}
.thumb-row {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.thumb-item {
width: 130px;
}
.notification-badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 20px;
height: 20px;
padding: 0 5px;
border-radius: 10px;
background: var(--ion-color-danger, #eb445a);
color: #fff;
font-size: 11px;
font-weight: 700;
line-height: 1;
}
API Reference
upp-thumb
Selector: upp-thumb
Extends: ViewModeDirective (inherits GRID/LIST view mode from parent upp-grid)
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
title | string | null | null | Title text displayed on the thumbnail. Also used to generate the avatar URL. |
color | string | 'medium' | Ionic color name applied to the thumbnail background. |
shape | 'default' | 'round' | 'default' | Thumbnail shape. Use 'round' for circular avatar-style thumbnails. |
icon | string | null | null | Ionic icon name displayed in the thumbnail. |
card | string | null | null | Card-mode value. When set, the thumbnail renders in card layout. |
detail | string | null | null | Detail text displayed below the title in card mode. |
foot | string | null | null | Footer text (e.g., price) displayed at the bottom in card mode. |
wait | boolean | false | When true, shows a loading/wait state. |
press | boolean | false | Enables long-press detection (1 second). When false, Pressed output never fires. |
Outputs
| Name | Type | Description |
|---|---|---|
Select | EventEmitter<void> | Emits when the thumbnail is tapped/clicked (suppressed if a long-press just fired). |
Pressed | EventEmitter<void> | Emits when the thumbnail is long-pressed (held for 1 second). Requires press="true". |
Projection Slots
| Component | Selector | Description |
|---|---|---|
UppThumbTopLeftComponent | upp-thumb-top-left | Content projected to the top-left corner of the thumbnail (badges, icons). |
UppThumbTopRightComponent | upp-thumb-top-right | Content projected to the top-right corner of the thumbnail (actions, menus). |
UppThumbBottomComponent | upp-thumb-bottom | Content projected below the thumbnail (labels, descriptions). |