Data Cards
<gstock-data-cards>
|
GstockDataCards
Examples
El componente Data Cards muestra datos como tarjetas personalizables en un layout de grid responsivo. Cada tarjeta se renderiza mediante una función cardRenderer proporcionada por el consumidor, lo que permite total personalización del contenido.
<gstock-data-cards></gstock-data-cards>
<script type="module">
customElements.whenDefined('gstock-data-cards').then(() => {
const cards = document.querySelector('gstock-data-cards');
cards.data = [
{
id: 1,
name: 'Juan Pérez',
email: 'juan.perez@example.com',
role: 'Administrador',
status: 'Activo',
},
{
id: 2,
name: 'María García',
email: 'maria.garcia@example.com',
role: 'Usuario',
status: 'Activo',
},
{
id: 3,
name: 'Carlos López',
email: 'carlos.lopez@example.com',
role: 'Editor',
status: 'Inactivo',
},
{
id: 4,
name: 'Ana Rodríguez',
email: 'ana.rodriguez@example.com',
role: 'Usuario',
status: 'Activo',
},
{
id: 5,
name: 'Luis Martín',
email: 'luis.martin@example.com',
role: 'Editor',
status: 'Activo',
},
];
cards.cardRenderer = (row, index, options) => {
return `
<div class="user-card">
<div class="user-card__header">
<gstock-avatar initials="${row.name.charAt(0)}" size="medium"></gstock-avatar>
<div class="user-card__info">
<strong>${row.name}</strong>
<span class="user-card__role">${row.role}</span>
</div>
</div>
<div class="user-card__body">
<div class="user-card__field">
<gstock-icon name="mail" library="default"></gstock-icon>
<span>${row.email}</span>
</div>
<gstock-tag size="small" variant="${row.status === 'Activo' ? 'success' : 'neutral'}">
${row.status}
</gstock-tag>
</div>
</div>
`;
};
});
</script>
<style>
.user-card {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.user-card__header {
display: flex;
align-items: center;
gap: 0.75rem;
}
.user-card__info {
display: flex;
flex-direction: column;
}
.user-card__info strong {
font-size: 0.9375rem;
}
.user-card__role {
font-size: 0.8125rem;
color: var(--gstock-color-text-subtle);
}
.user-card__body {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.user-card__field {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.8125rem;
color: var(--gstock-color-text-subtle);
}
.user-card__field gstock-icon {
font-size: 1rem;
}
</style>
Tamaño
Utilice el atributo size para cambiar el tamaño de las tarjetas. Los valores disponibles son small, medium y large.
Small
Medium (por defecto)
Large
<div class="sizes-demo">
<div>
<h4>Small</h4>
<gstock-data-cards id="cards-small" size="small"></gstock-data-cards>
</div>
<div>
<h4>Medium (por defecto)</h4>
<gstock-data-cards id="cards-medium" size="medium"></gstock-data-cards>
</div>
<div>
<h4>Large</h4>
<gstock-data-cards id="cards-large" size="large"></gstock-data-cards>
</div>
</div>
<script type="module">
customElements.whenDefined('gstock-data-cards').then(() => {
const data = [
{ id: 1, name: 'Producto A', price: '€12.99', category: 'Bebidas' },
{ id: 2, name: 'Producto B', price: '€8.50', category: 'Alimentación' },
{ id: 3, name: 'Producto C', price: '€24.00', category: 'Bebidas' },
];
const renderer = row => {
return `
<div class="product-card">
<strong>${row.name}</strong>
<span class="product-card__price">${row.price}</span>
<span class="product-card__category">${row.category}</span>
</div>
`;
};
['cards-small', 'cards-medium', 'cards-large'].forEach(id => {
const el = document.querySelector(`#${id}`);
el.data = data;
el.cardRenderer = renderer;
});
});
</script>
<style>
.sizes-demo {
display: flex;
flex-direction: column;
gap: 2rem;
}
.sizes-demo h4 {
margin: 0 0 0.5rem;
color: var(--gstock-color-text-subtle);
font-size: 0.875rem;
}
.product-card {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.product-card__price {
font-weight: 600;
color: var(--gstock-color-text-brand);
}
.product-card__category {
font-size: 0.8125rem;
color: var(--gstock-color-text-subtle);
}
</style>
Seleccionable
Combine los atributos selectable y multi-select para permitir la selección de tarjetas. Cada tarjeta muestra un checkbox para seleccionarla.
<div class="selection-info">
<div id="selection-info">
Seleccionados:
<strong>0</strong>
elementos
</div>
</div>
<gstock-data-cards selectable multi-select></gstock-data-cards>
<script type="module">
customElements.whenDefined('gstock-data-cards').then(() => {
const cards = document.querySelector('gstock-data-cards');
const selectionInfo = document.querySelector('#selection-info');
cards.data = [
{ id: 1, name: 'Cerveza IPA', price: '€3.50', stock: 120 },
{ id: 2, name: 'Vino Tinto Reserva', price: '€12.00', stock: 45 },
{ id: 3, name: 'Agua Mineral', price: '€1.20', stock: 300 },
{ id: 4, name: 'Refresco Cola', price: '€1.80', stock: 200 },
{ id: 5, name: 'Zumo de Naranja', price: '€2.50', stock: 85 },
{ id: 6, name: 'Café Espresso', price: '€1.50', stock: 150 },
];
cards.cardRenderer = (row, index, options) => {
return `
<div class="item-card">
<strong>${row.name}</strong>
<div class="item-card__details">
<span class="item-card__price">${row.price}</span>
<span class="item-card__stock">Stock: ${row.stock}</span>
</div>
</div>
`;
};
cards.addEventListener('gstock-data-grid-selection-change-event', e => {
const count = e.detail.selectedIds.length;
selectionInfo.innerHTML = `Seleccionados: <strong>${count}</strong> ${count === 1 ? 'elemento' : 'elementos'}`;
});
});
</script>
<style>
.selection-info {
background: var(--gstock-color-neutral-100);
padding: 1rem;
border-radius: var(--gstock-border-radius-md);
margin-bottom: 1rem;
border-left: 4px solid var(--gstock-color-primary-500);
font-size: 0.875rem;
}
.item-card {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.item-card__details {
display: flex;
justify-content: space-between;
align-items: center;
}
.item-card__price {
font-weight: 600;
color: var(--gstock-color-text-brand);
}
.item-card__stock {
font-size: 0.8125rem;
color: var(--gstock-color-text-subtle);
}
</style>
Paginación
Utilice el atributo paginated junto con page-size para paginar las tarjetas. Opcionalmente, active show-page-size-selector para permitir al usuario cambiar el tamaño de página.
<gstock-data-cards paginated page-size="4" show-page-size-selector></gstock-data-cards>
<script type="module">
customElements.whenDefined('gstock-data-cards').then(() => {
const cards = document.querySelector('gstock-data-cards');
cards.data = Array.from({ length: 12 }, (_, i) => ({
id: i + 1,
name: `Producto ${i + 1}`,
price: `€${(Math.random() * 50 + 1).toFixed(2)}`,
category: ['Bebidas', 'Alimentación', 'Limpieza', 'Otros'][i % 4],
}));
cards.cardRenderer = row => {
return `
<div class="product-card">
<div class="product-card__name">${row.name}</div>
<div class="product-card__price">${row.price}</div>
<gstock-tag size="small" variant="neutral">${row.category}</gstock-tag>
</div>
`;
};
});
</script>
<style>
.product-card {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.product-card__name {
font-weight: 600;
}
.product-card__price {
font-size: 1.125rem;
font-weight: 700;
color: var(--gstock-color-text-brand);
}
</style>
Estado de carga
Utilice el atributo loading para mostrar un indicador de carga. El mensaje se puede personalizar con loading-message.
<gstock-data-cards loading loading-message="Cargando productos..."></gstock-data-cards>
Estado vacío
Cuando no hay datos, se muestra un estado vacío. El mensaje se puede personalizar con empty-message.
<gstock-data-cards empty-message="No se encontraron productos"></gstock-data-cards>
Personalización del grid
Utilice las propiedades CSS --card-min-width, --card-gap y --card-border-radius para personalizar el layout del grid y la apariencia de las tarjetas.
<gstock-data-cards id="cards-custom"></gstock-data-cards>
<script type="module">
customElements.whenDefined('gstock-data-cards').then(() => {
const cards = document.querySelector('#cards-custom');
cards.data = [
{ id: 1, name: 'Mesa redonda', sku: 'MES-001', price: '€149.99', image: '🪑' },
{ id: 2, name: 'Silla ergonómica', sku: 'SIL-002', price: '€89.50', image: '🪑' },
{ id: 3, name: 'Lámpara LED', sku: 'LAM-003', price: '€34.99', image: '💡' },
{ id: 4, name: 'Estantería', sku: 'EST-004', price: '€199.00', image: '📚' },
{ id: 5, name: 'Alfombra', sku: 'ALF-005', price: '€59.99', image: '🧶' },
{ id: 6, name: 'Cortinas', sku: 'COR-006', price: '€45.00', image: '🪟' },
];
cards.cardRenderer = row => {
return `
<div class="product-card-custom">
<div class="product-card-custom__image">${row.image}</div>
<div class="product-card-custom__info">
<strong>${row.name}</strong>
<code>${row.sku}</code>
<div class="product-card-custom__price">${row.price}</div>
</div>
</div>
`;
};
});
</script>
<style>
#cards-custom {
--card-min-width: 200px;
--card-gap: 1rem;
--card-border-radius: var(--gstock-border-radius-lg);
}
.product-card-custom {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
gap: 0.75rem;
}
.product-card-custom__image {
font-size: 2.5rem;
}
.product-card-custom__info {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.product-card-custom__info code {
font-size: 0.75rem;
color: var(--gstock-color-text-subtlest);
}
.product-card-custom__price {
font-weight: 700;
font-size: 1.125rem;
color: var(--gstock-color-text-brand);
margin-top: 0.25rem;
}
</style>