app/components/Card/preview-card.latte
{*
Preview Card — generic card s obrázkem, titulkem, metadaty a footerem.
Vhodné pro výpisy produktů, článků, referencí, kategorií...
Parametry:
- $href (string|null) link na detail (pokud zadán, celá karta klik.)
- $image (string|null) URL obrázku
- $alt (string) alt text obrázku (default '')
- $title (string) titulek (povinné)
- $meta (string|null) podtitulek/meta řádek (popis, kategorie, datum...)
- $badges (array) pole [['text' => 'Novinka', 'modifier' => 'new'], ...]
- $footer (string|null) HTML obsah footeru (cena + button apod.)
- $class (string|null) extra třída
*}
{var $href = $href ?? null}
{var $image = $image ?? null}
{var $alt = $alt ?? ''}
{var $title = $title ?? ''}
{var $meta = $meta ?? null}
{var $badges = $badges ?? []}
{var $footer = $footer ?? null}
{var $class = $class ?? null}
{if $href}<a href="{$href}" class="preview-card{if $class} {$class}{/if}">{else}<div class="preview-card{if $class} {$class}{/if}">{/if}
{if $image}
<span class="preview-card__image">
{if $badges}
<span class="preview-card__badges">
{foreach $badges as $badge}
<span class="preview-card__badge{if isset($badge['modifier'])} preview-card__badge--{$badge['modifier']}{/if}">
{$badge['text']}
</span>
{/foreach}
</span>
{/if}
<img src="{$image}" alt="{$alt}" loading="lazy">
</span>
{/if}
<div class="preview-card__body">
<h3 class="preview-card__title">{$title}</h3>
{if $meta}
<div class="preview-card__meta">{$meta|noescape}</div>
{/if}
{if $footer}
<div class="preview-card__footer">{$footer|noescape}</div>
{/if}
</div>
{if $href}</a>{else}</div>{/if}
resources/sass/components/_preview-card.scss
// ─── Configurable variables (override before @import) ──────────────────
$cgui-preview-card-bg: #fff !default;
$cgui-preview-card-border: 1px solid $cgui-color-border !default;
$cgui-preview-card-radius: $cgui-radius !default;
$cgui-preview-card-padding: 24px !default;
$cgui-preview-card-shadow: none !default;
$cgui-preview-card-shadow-hover: 0 4px 16px rgba(0, 0, 0, 0.08) !default;
$cgui-preview-card-transition: box-shadow 0.2s, transform 0.2s !default;
$cgui-preview-card-image-bg: $cgui-color-bg-gray-light !default;
$cgui-preview-card-image-aspect: 1 / 1 !default;
$cgui-preview-card-image-radius: calc(#{$cgui-preview-card-radius} - 6px) !default;
$cgui-preview-card-title-size: 26px !default;
$cgui-preview-card-title-weight: 500 !default;
$cgui-preview-card-title-color: $cgui-color-text !default;
$cgui-preview-card-meta-size: 21px !default;
$cgui-preview-card-meta-color: $cgui-color-text-gray !default;
$cgui-preview-card-gap: 13px !default;
// ───────────────────────────────────────────────────────────────────────
.preview-card {
display: flex;
flex-direction: column;
background: $cgui-preview-card-bg;
border: $cgui-preview-card-border;
border-radius: $cgui-preview-card-radius;
padding: $cgui-preview-card-padding;
box-shadow: $cgui-preview-card-shadow;
transition: $cgui-preview-card-transition;
color: $cgui-preview-card-title-color;
text-decoration: none;
height: 100%;
&:hover,
&:focus-within {
box-shadow: $cgui-preview-card-shadow-hover;
transform: translateY(-2px);
}
&__image {
display: block;
width: 100%;
aspect-ratio: $cgui-preview-card-image-aspect;
background: $cgui-preview-card-image-bg;
border-radius: $cgui-preview-card-image-radius;
overflow: hidden;
margin-bottom: $cgui-preview-card-gap;
position: relative;
img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
}
&:hover &__image img {
transform: scale(1.04);
}
&__badges {
position: absolute;
top: 13px;
left: 13px;
display: flex;
flex-direction: column;
gap: 6px;
z-index: 1;
}
&__badge {
display: inline-flex;
align-items: center;
padding: 5px 13px;
font-size: 19px;
font-weight: 600;
line-height: 1.2;
color: #fff;
background: $cgui-color-primary;
border-radius: 6px;
&--discount { background: #E91E63; }
&--new { background: $cgui-color-brand; }
&--sale { background: $cgui-color-yellow; color: $cgui-color-text; }
}
&__body {
display: flex;
flex-direction: column;
gap: $cgui-preview-card-gap;
flex: 1;
min-width: 0;
}
&__title {
font-size: $cgui-preview-card-title-size;
font-weight: $cgui-preview-card-title-weight;
color: $cgui-preview-card-title-color;
margin: 0;
line-height: 1.3;
text-decoration: none;
a {
color: inherit;
text-decoration: none;
@include cgui-hover() {
&:hover, &:focus { color: $cgui-color-primary; }
}
}
}
&__meta {
font-size: $cgui-preview-card-meta-size;
color: $cgui-preview-card-meta-color;
line-height: 1.4;
}
&__footer {
margin-top: auto;
display: flex;
align-items: center;
justify-content: space-between;
gap: $cgui-preview-card-gap;
padding-top: $cgui-preview-card-gap;
}
}