Quarterly report
ReadyRevenue, churn and support volume for July to September, with a note from each team lead.
A content card with a title, a status badge, a short description and two actions.
Revenue, churn and support volume for July to September, with a note from each team lead.
The markup of the preview. Classes come from the prebuilt dist/nuvoui.min.css, or from your own build with $generate-utility-classes: true.
<article class="bg-surface text-regular border rounded-lg shadow-sm hover:shadow-md transition-shadow p-6 max-w-sm">
<div class="flex between x-center gap-3">
<h3 class="text-lg font-semibold m-0">Quarterly report</h3>
<span class="bg-success-subtle text-success text-xs font-medium rounded-full px-2 py-1">Ready</span>
</div>
<p class="text-muted mt-2 mb-0">Revenue, churn and support volume for July to September, with a note from each team lead.</p>
<div class="flex wrap gap-2 mt-4">
<button class="rounded-md" type="button">Open report</button>
<button class="bg-alternate text-regular hover:bg-hover rounded-md" type="button">Download PDF</button>
</div>
</article>The same result with BEM class names and no utility classes. @use "@nuvoui/core" as *; emits the tokens and base styles, and each apply() writes one rule.
@use "@nuvoui/core" as *;
.card {
@include apply(
max-width(sm), // max width: the sm breakpoint, 640px
p(6), // padding: spacing key 6 (1.5rem)
bg(surface), // surface background, follows the theme
text-color(regular), // regular text color, follows the theme
border(1), // 1px border (width key 1), regular color
rounded(lg), // corner radius: size key lg (0.75rem)
shadow(sm), // small shadow (size key sm)
transition-shadow, // animate box-shadow changes
shadow(md) hover // medium shadow on hover, at every width
);
}
.card__header {
@include apply(
flex, // display: flex
between, // main axis: space between (justify-content)
x-center, // cross axis: center (align-items)
gap(3) // gap: spacing key 3 (0.75rem)
);
}
.card__title {
@include apply(
m(0), // margin: 0
font-size(lg), // font size key lg (1.25rem)
font(semibold) // font weight: semibold (600)
);
}
.card__badge {
@include apply(
px(2), // horizontal padding: spacing key 2 (0.5rem)
py(1), // vertical padding: spacing key 1 (0.25rem)
rounded(full), // fully rounded ends (pill shape)
bg(success-subtle), // light success tint background
text-color(success), // success text color
font-size(xs), // font size key xs (0.75rem)
font(medium) // font weight: medium (500)
);
}
.card__text {
@include apply(
mt(2), // top margin: spacing key 2 (0.5rem)
mb(0), // bottom margin: 0
text-color(muted) // muted text color, follows the theme
);
}
.card__actions {
@include apply(
flex, // display: flex
wrap, // let items wrap onto new lines
gap(2), // gap: spacing key 2 (0.5rem)
mt(4) // top margin: spacing key 4 (1rem)
);
}
.card__button {
@include apply(rounded(md)); // corner radius: size key md (0.5rem)
}
.card__button--secondary {
@include apply(
bg(alternate), // alternate background, follows the theme
text-color(regular), // regular text color, follows the theme
bg(hover) hover // hover background on hover
);
}<article class="card">
<div class="card__header">
<h3 class="card__title">Quarterly report</h3>
<span class="card__badge">Ready</span>
</div>
<p class="card__text">Revenue, churn and support volume for July to September, with a note from each team lead.</p>
<div class="card__actions">
<button class="card__button" type="button">Open report</button>
<button class="card__button card__button--secondary" type="button">Download PDF</button>
</div>
</article>Every color comes from a theme token, so the recipe follows the light, dark and inverse themes with no extra CSS.
bg-surface, text-regularborder-regulartext-mutedsuccess-subtle, text-successbrand, brand-hover, text-on-brandbg-alternate, bg-hovershadow-sm, shadow-md