Add more Icon list examples and use it in demo pages

- more cards on the demo page and sections in docs
- license, pricing cards, trial-ended and user info use IconList
This commit is contained in:
codecalm committed 2026-10-06 10:32:35 +02:00
1 parent 7829d7b1c3
commit 6c348b44a7
9 files changed
+326 -139

No files matched your search

+57
View File
@@ -99,6 +99,63 @@ When an entry wraps to more lines, the marker stays on the first line. The marke
</ul>
</Example>
## Pros and cons
Put two lists side by side to compare: green checks on one side, red crosses on the other.
<Example>
<div class="row g-3">
<div class="col-6">
<ul class="list-icon" style="--tblr-list-icon-color: var(--tblr-green)">
<li><Icon name="check" /> Fast to set up</li>
<li><Icon name="check" /> No vendor lock-in</li>
<li><Icon name="check" /> Great documentation</li>
</ul>
</div>
<div class="col-6">
<ul class="list-icon" style="--tblr-list-icon-color: var(--tblr-red)">
<li><Icon name="x" /> No built-in auth</li>
<li><Icon name="x" /> Smaller community</li>
</ul>
</div>
</div>
</Example>
## Entries with a description
An entry can hold more than one line: wrap the content in an element with a title and a muted description. The marker stays next to the title. Raise `--tblr-list-icon-row-gap` to give the entries more room.
<Example>
<ul class="list-icon" style="--tblr-list-icon-color: var(--tblr-green); --tblr-list-icon-row-gap: 1rem">
<li>
<Icon name="check" />
<div>
<div class="fw-medium">Unlimited projects</div>
<div class="text-secondary small">Create as many projects as you need, with no extra charge.</div>
</div>
</li>
<li>
<Icon name="check" />
<div>
<div class="fw-medium">Priority support</div>
<div class="text-secondary small">Your questions go to the top of the queue.</div>
</div>
</li>
</ul>
</Example>
## Links
The marker can describe the entry instead of ticking it off, for example in a list of contact details with links.
<Example>
<ul class="list-icon">
<li><Icon name="mail" /> <a href="#">hello@tabler.io</a></li>
<li><Icon name="phone" /> <a href="#">+1 (555) 123-4567</a></li>
<li><Icon name="map-pin" /> 1 Market Street, San Francisco</li>
</ul>
</Example>
## Custom look
Set the `--tblr-list-icon-*` variables on the list to change the size of the markers and the gaps between the entries.
+169
View File
@@ -17,6 +17,41 @@ const plans = [
{ name: 'Pro', price: '$29', included: 4 },
]
const overview = [
['Boxed', 'Combined', 'Condensed', 'Fluid', 'Horizontal', 'Vertical'],
['Dark mode', 'RTL mode', 'Navbar sticky', 'Navbar overlap', 'Folded sidebar', 'Auto color mode'],
]
const pros = ['Fast to set up', 'No vendor lock-in', 'Great documentation']
const cons = ['No built-in auth', 'Smaller community']
const requirements = [
{ text: 'At least 8 characters', met: true },
{ text: 'One upper case letter', met: true },
{ text: 'One number', met: false },
{ text: 'One special character', met: false },
]
const changes = [
{ icon: 'plus', color: 'green', text: 'Added the icon list component' },
{ icon: 'arrow-up', color: 'blue', text: 'Faster rendering of large tables' },
{ icon: 'bug', color: 'red', text: 'Fixed the dropdown position in RTL mode' },
{ icon: 'trash', color: 'secondary', text: 'Removed the old inline list dots' },
]
const contact = [
{ icon: 'mail', text: 'hello@tabler.io', href: 'mailto:hello@tabler.io' },
{ icon: 'phone', text: '+1 (555) 123-4567', href: 'tel:+15551234567' },
{ icon: 'map-pin', text: '1 Market Street, San Francisco' },
{ icon: 'world', text: 'tabler.io', href: 'https://tabler.io' },
]
const details = [
{ title: 'Unlimited projects', text: 'Create as many projects as you need, with no extra charge.' },
{ title: 'Priority support', text: 'Your questions go to the top of the queue.' },
{ title: 'Custom domains', text: 'Serve every project from your own domain with a free certificate.' },
]
const steps = [
{ icon: 'circle-check', color: 'green', text: 'Account created' },
{ icon: 'circle-check', color: 'green', text: 'Email confirmed' },
@@ -135,6 +170,140 @@ const steps = [
</Card>
</div>
<div class="col-md-6 col-lg-4">
<Card>
<CardBody>
<CardTitle>Pros and cons</CardTitle>
<CardSubtitle>Two lists side by side, green checks against red crosses.</CardSubtitle>
<div class="row g-3">
<div class="col-6">
<IconList color="green">
{pros.map((text) => <IconListItem>{text}</IconListItem>)}
</IconList>
</div>
<div class="col-6">
<IconList color="red">
{cons.map((text) => <IconListItem icon="x">{text}</IconListItem>)}
</IconList>
</div>
</div>
</CardBody>
</Card>
</div>
<div class="col-md-6 col-lg-4">
<Card>
<CardBody>
<CardTitle>Password requirements</CardTitle>
<CardSubtitle>A checklist under a form field, each rule marked as met or not.</CardSubtitle>
<div class="mb-3">
<label class="form-label" for="icon-list-password">Password</label>
<input type="password" class="form-control" id="icon-list-password" value="Tabler2026" autocomplete="new-password" />
</div>
<IconList class="small">
{
requirements.map((rule) =>
rule.met ? (
<IconListItem icon="circle-check" color="green">
{rule.text}
</IconListItem>
) : (
<IconListItem icon="circle" class="text-secondary">
{rule.text}
</IconListItem>
),
)
}
</IconList>
</CardBody>
</Card>
</div>
<div class="col-md-6 col-lg-4">
<Card>
<CardBody>
<CardTitle>Release notes</CardTitle>
<CardSubtitle>An icon per kind of change: added, improved, fixed, removed.</CardSubtitle>
<IconList>
{
changes.map((change) => (
<IconListItem icon={change.icon} color={change.color}>
{change.text}
</IconListItem>
))
}
</IconList>
</CardBody>
</Card>
</div>
<div class="col-md-6 col-lg-4">
<Card>
<CardBody>
<CardTitle>Contact details</CardTitle>
<CardSubtitle>Icons as markers for a list of links.</CardSubtitle>
<IconList>
{contact.map((row) => <IconListItem icon={row.icon}>{row.href ? <a href={row.href}>{row.text}</a> : row.text}</IconListItem>)}
</IconList>
</CardBody>
</Card>
</div>
<div class="col-md-6 col-lg-4">
<Card>
<CardBody>
<CardTitle>Entries with a description</CardTitle>
<CardSubtitle>A title and a muted second line in each entry; the marker stays on the title.</CardSubtitle>
<IconList color="green" style="--tblr-list-icon-row-gap: 1rem">
{
details.map((row) => (
<IconListItem>
<div>
<div class="fw-medium">{row.title}</div>
<div class="text-secondary small">{row.text}</div>
</div>
</IconListItem>
))
}
</IconList>
</CardBody>
</Card>
</div>
<div class="col-md-6 col-lg-4">
<Card>
<CardBody>
<CardTitle>Large text</CardTitle>
<CardSubtitle>Raise the font size and the marker size together for a landing page.</CardSubtitle>
<IconList class="fs-3" color="primary" style="--tblr-list-icon-size: 1.5rem; --tblr-list-icon-row-gap: 0.75rem">
{features.slice(0, 3).map((text) => <IconListItem>{text}</IconListItem>)}
</IconList>
</CardBody>
</Card>
</div>
<div class="col-lg-8">
<Card>
<CardBody>
<CardTitle>Feature overview</CardTitle>
<CardSubtitle>A long list split into columns, as on a comparison or a landing page.</CardSubtitle>
<div class="row g-3">
{
overview.map((column) => (
<div class="col-sm-6">
<IconList color="green">
{column.map((text) => (
<IconListItem>{text}</IconListItem>
))}
</IconList>
</div>
))
}
</div>
</CardBody>
</Card>
</div>
{
plans.map((plan) => (
<div class="col-md-6 col-lg-4">
+15 -13
View File
@@ -1,6 +1,8 @@
---
import DefaultLayout from '@shared/layouts/DefaultLayout.astro'
import Icon from '@ui/Icon.astro'
import IconList from '@ui/IconList.astro'
import IconListItem from '@ui/IconListItem.astro'
import Card from '@ui/Card.astro'
import CardBody from '@ui/CardBody.astro'
import CardFooter from '@ui/CardFooter.astro'
@@ -62,23 +64,23 @@ const licenseHtml = `
<h4>Permissions</h4>
<ul class="list-unstyled space-y-1">
<li><Icon name="check" inline class="text-green" /> Commercial use</li>
<li><Icon name="check" inline class="text-green" /> Modification</li>
<li><Icon name="check" inline class="text-green" /> Distribution</li>
<li><Icon name="check" inline class="text-green" /> Private use</li>
</ul>
<IconList color="green">
<IconListItem>Commercial use</IconListItem>
<IconListItem>Modification</IconListItem>
<IconListItem>Distribution</IconListItem>
<IconListItem>Private use</IconListItem>
</IconList>
<h4>Limitations</h4>
<ul class="list-unstyled space-y-1">
<li><Icon name="x" inline class="text-red" /> Liability</li>
<li><Icon name="x" inline class="text-red" /> Warranty</li>
</ul>
<IconList color="red">
<IconListItem icon="x">Liability</IconListItem>
<IconListItem icon="x">Warranty</IconListItem>
</IconList>
<h4>Conditions</h4>
<ul class="list-unstyled space-y-1">
<li><Icon name="info-circle" inline class="text-blue" /> License and copyright notice</li>
</ul>
<IconList color="blue">
<IconListItem icon="info-circle">License and copyright notice</IconListItem>
</IconList>
</CardBody>
<CardFooter>
This is not legal advice.
+13 -15
View File
@@ -1,6 +1,7 @@
---
import SingleLayout from '@shared/layouts/SingleLayout.astro'
import Icon from '@ui/Icon.astro'
import IconList from '@ui/IconList.astro'
import IconListItem from '@ui/IconListItem.astro'
---
<SingleLayout title="Trial ended">
@@ -10,29 +11,26 @@ import Icon from '@ui/Icon.astro'
<p class="text-secondary mb-4">If you want to continue to benefit from Tabler, it's time to upgrade your plan.</p>
<ul class="list-unstyled space-y">
<li class="row g-2">
<span class="col-auto"><Icon name="check" class="me-1 text-success" /></span>
<span class="col">
<IconList color="success" style="--tblr-list-icon-row-gap: 1rem">
<IconListItem>
<span>
<strong class="d-block">Over 800+ productions</strong>
<span class="d-block text-secondary">Unlimited movies, TV shows and more.</span>
</span>
</li>
<li class="row g-2">
<span class="col-auto"><Icon name="check" class="me-1 text-success" /></span>
<span class="col">
</IconListItem>
<IconListItem>
<span>
<strong class="d-block">Watch everywhere</strong>
<span class="d-block text-secondary">Watch on smart TVs, PlayStation, Xbox, Apple TV, Blu-ray players and more.</span>
</span>
</li>
<li class="row g-2">
<span class="col-auto"><Icon name="check" class="me-1 text-success" /></span>
<span class="col">
</IconListItem>
<IconListItem>
<span>
<strong class="d-block">Personalize</strong>
<span class="d-block text-secondary">Choose your own style, watch what you like.</span>
</span>
</li>
</ul>
</IconListItem>
</IconList>
<div class="my-4">
<a href="#" class="btn btn-primary w-100"> Upgrade to a paid plan </a>
+16 -9
View File
@@ -1,6 +1,8 @@
---
// Feature names are a fixed list; the `features` string is split per-character into a 1/0 availability mask.
import Icon from '@ui/Icon.astro'
import IconList from '@ui/IconList.astro'
import IconListItem from '@ui/IconListItem.astro'
interface Props {
price?: string
@@ -31,17 +33,22 @@ const availableFeatures = features.split('')
<div class="display-5 fw-bold my-3">${price}</div>
<ul class="list-unstyled lh-lg">
<li><strong>{users}</strong> Users</li>
<IconList class="align-items-center">
<IconListItem icon="users">
<span><strong>{users}</strong> Users</span>
</IconListItem>
{
featureNames.map((feature, i) => (
<li>
{availableFeatures[i] === '1' ? <Icon name="check" inline class="me-1 text-success" /> : <Icon name="x" inline class="me-1 text-danger" />}
{feature}
</li>
))
featureNames.map((feature, i) =>
availableFeatures[i] === '1' ? (
<IconListItem color="success">{feature}</IconListItem>
) : (
<IconListItem icon="x" color="danger">
{feature}
</IconListItem>
),
)
}
</ul>
</IconList>
<div class="text-center mt-4">
<a href="#" class={`btn${featuredColor ? ` btn-${featuredColor}` : ''} w-100`}>Choose plan</a>
+14 -19
View File
@@ -1,6 +1,7 @@
---
import Icon from '@ui/Icon.astro'
import Button from '@ui/Button.astro'
import IconList from '@ui/IconList.astro'
import IconListItem from '@ui/IconListItem.astro'
---
<div class="card card-gradient card-gradient-love">
@@ -11,24 +12,18 @@ import Button from '@ui/Button.astro'
<div class="display-5">$199</div>
<div class="fs-1 text-secondary">/ month</div>
</div>
<ul class="list-unstyled mt-6 space-y space-y-2">
<li class="d-flex gap-2">
<div><Icon name="check" color="success" /></div>
<div><strong>Unlimited</strong> Target Audience</div>
</li>
<li class="d-flex gap-2">
<div><Icon name="check" color="success" /></div>
<div><strong>1</strong> User Account</div>
</li>
<li class="d-flex gap-2">
<div><Icon name="check" color="success" /></div>
<div><strong>100+</strong> Video Tuts</div>
</li>
<li class="d-flex gap-2">
<div><Icon name="x" color="secondary" /></div>
<div class="text-secondary">Public Displays</div>
</li>
</ul>
<IconList color="success" class="mt-6">
<IconListItem>
<span><strong>Unlimited</strong> Target Audience</span>
</IconListItem>
<IconListItem>
<span><strong>1</strong> User Account</span>
</IconListItem>
<IconListItem>
<span><strong>100+</strong> Video Tuts</span>
</IconListItem>
<IconListItem icon="x" color="secondary" class="text-secondary">Public Displays</IconListItem>
</IconList>
<p class="mt-4 text-muted">This plan is perfect for small businesses and startups. It includes all the features you need to get started.</p>
<div class="mt-6">
<Button text="Purchase Now" color="pink" block />
+22 -25
View File
@@ -1,5 +1,6 @@
---
import Icon from '@ui/Icon.astro'
import IconList from '@ui/IconList.astro'
import IconListItem from '@ui/IconListItem.astro'
import type { FlagCountry } from '@shared/lib/tokens'
import { people } from '@shared/lib/people'
import Flag from '@ui/Flag.astro'
@@ -12,29 +13,25 @@ const person = requireIndex(people, 24)
<div class="card">
<div class="card-body">
<CardTitle>Basic info</CardTitle>
<div class="mb-2">
<Icon name="book" inline class="me-2 text-secondary" />
Went to: <strong>{person.university}</strong>
</div>
<div class="mb-2">
<Icon name="briefcase" inline class="me-2 text-secondary" />
Worked at: <strong>{person.company}</strong>
</div>
<div class="mb-2">
<Icon name="home" inline class="me-2 text-secondary" />
Lives in: <strong>{person.city}, {person.country}</strong>
</div>
<div class="mb-2">
<Icon name="map-pin" inline class="me-2 text-secondary" />
From: <strong><Flag size="xs" flag={(person.country_code ?? '') as FlagCountry} /> {person.country}</strong>
</div>
<div class="mb-2">
<Icon name="calendar" inline class="me-2 text-secondary" />
Birth date: <strong>{person.birth_date}</strong>
</div>
<div>
<Icon name="clock" inline class="me-2 text-secondary" />
Time zone: <strong>{person.time_zone}</strong>
</div>
<IconList>
<IconListItem icon="book">
<span>Went to: <strong>{person.university}</strong></span>
</IconListItem>
<IconListItem icon="briefcase">
<span>Worked at: <strong>{person.company}</strong></span>
</IconListItem>
<IconListItem icon="home">
<span>Lives in: <strong>{person.city}, {person.country}</strong></span>
</IconListItem>
<IconListItem icon="map-pin">
<span>From: <strong><Flag size="xs" flag={(person.country_code ?? '') as FlagCountry} /> {person.country}</strong></span>
</IconListItem>
<IconListItem icon="calendar">
<span>Birth date: <strong>{person.birth_date}</strong></span>
</IconListItem>
<IconListItem icon="clock">
<span>Time zone: <strong>{person.time_zone}</strong></span>
</IconListItem>
</IconList>
</div>
</div>
@@ -1,5 +1,6 @@
---
import Icon from '@ui/Icon.astro'
import IconList from '@ui/IconList.astro'
import IconListItem from '@ui/IconListItem.astro'
interface Props {
class?: string
@@ -8,6 +9,8 @@ interface Props {
const { class: className } = Astro.props
const sectionClass = ['section', className]
const features = ['Up to 5 developers', 'All marketing + app components', 'Figma UI Kit', 'Lifetime free updates']
---
<section class:list={sectionClass}>
@@ -22,20 +25,9 @@ const sectionClass = ['section', className]
<div>per year</div>
</div>
</div>
<ul class="pricing-features my-5">
<li>
<Icon name="check" color="green" class="icon-inline me-1" />Up to 5 developers
</li>
<li>
<Icon name="check" color="green" class="icon-inline me-1" />All marketing + app components
</li>
<li>
<Icon name="check" color="green" class="icon-inline me-1" />Figma UI Kit
</li>
<li>
<Icon name="check" color="green" class="icon-inline me-1" />Lifetime free updates
</li>
</ul>
<IconList color="green" class="my-5">
{features.map((text) => <IconListItem>{text}</IconListItem>)}
</IconList>
<div class="pricing-btn"><a href="#" class="btn w-100">Get started</a></div>
</div>
<div class="pricing-card featured">
@@ -48,20 +40,9 @@ const sectionClass = ['section', className]
<div>per year</div>
</div>
</div>
<ul class="pricing-features my-5">
<li>
<Icon name="check" color="green" class="icon-inline me-1" />Up to 5 developers
</li>
<li>
<Icon name="check" color="green" class="icon-inline me-1" />All marketing + app components
</li>
<li>
<Icon name="check" color="green" class="icon-inline me-1" />Figma UI Kit
</li>
<li>
<Icon name="check" color="green" class="icon-inline me-1" />Lifetime free updates
</li>
</ul>
<IconList color="green" class="my-5">
{features.map((text) => <IconListItem>{text}</IconListItem>)}
</IconList>
<div class="pricing-btn"><a href="#" class="btn w-100 btn-primary">Get started</a></div>
</div>
<div class="pricing-card">
@@ -73,20 +54,9 @@ const sectionClass = ['section', className]
<div>per year</div>
</div>
</div>
<ul class="pricing-features my-5">
<li>
<Icon name="check" color="green" class="icon-inline me-1" />Up to 5 developers
</li>
<li>
<Icon name="check" color="green" class="icon-inline me-1" />All marketing + app components
</li>
<li>
<Icon name="check" color="green" class="icon-inline me-1" />Figma UI Kit
</li>
<li>
<Icon name="check" color="green" class="icon-inline me-1" />Lifetime free updates
</li>
</ul>
<IconList color="green" class="my-5">
{features.map((text) => <IconListItem>{text}</IconListItem>)}
</IconList>
<div class="pricing-btn"><a href="#" class="btn w-100">Get started</a></div>
</div>
</div>
@@ -1,7 +1,10 @@
---
import Icon from '@ui/Icon.astro'
import IconList from '@ui/IconList.astro'
import IconListItem from '@ui/IconListItem.astro'
const sectionClass = ['section']
const features = ['Up to 5 developers', 'All marketing + app components', 'Figma UI Kit', 'Lifetime free updates']
---
<section class:list={sectionClass}>
@@ -13,20 +16,9 @@ const sectionClass = ['section']
<p class="m-0 text-secondary">Get Marketing + Application UI for you and your team</p>
</div>
<div class="col-lg">
<ul class="list-unstyled m-0">
<li>
<Icon name="check" color="green" class="icon-inline me-1" />Up to 5 developers
</li>
<li>
<Icon name="check" color="green" class="icon-inline me-1" />All marketing + app components
</li>
<li>
<Icon name="check" color="green" class="icon-inline me-1" />Figma UI Kit
</li>
<li>
<Icon name="check" color="green" class="icon-inline me-1" />Lifetime free updates
</li>
</ul>
<IconList color="green" class="m-0">
{features.map((text) => <IconListItem>{text}</IconListItem>)}
</IconList>
</div>
<div class="col-sm-6 col-lg">
<div class="pricing-price m-0">