mirror of
https://github.com/tabler/tabler.git
synced 2026-10-21 15:24:19 +04:00
Add Icon list component (#3274)
This commit is contained in:
1 parent
3275bff800
commit
c4934364a0
17 files changed
+792
-139
No files matched your search
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
"@tabler/preview": minor
|
||||
"@tabler/docs": minor
|
||||
---
|
||||
|
||||
Added the icon list component: `.list-icon` turns a plain list into a list with icon markers, such as a checklist of features, with `.list-icon-inline` for entries in a row.
|
||||
@@ -2043,6 +2043,15 @@ $list-group-item-gap-lg: 1.25rem !default;
|
||||
$list-group-variant-border-alpha: 0.24 !default;
|
||||
$list-group-variant-hover-alpha: 0.16 !default;
|
||||
|
||||
// Icon list
|
||||
// scss-docs-start list-icon-variables
|
||||
$list-icon-gap: 0.5rem !default;
|
||||
$list-icon-row-gap: 0.5rem !default;
|
||||
$list-icon-inline-gap: 1.5rem !default;
|
||||
$list-icon-size: 1rem !default;
|
||||
$list-icon-color: var(--secondary) !default;
|
||||
// scss-docs-end list-icon-variables
|
||||
|
||||
// Forms
|
||||
$input-disabled-bg: var(--bg-forms-disabled) !default;
|
||||
$input-border-color: var(--border-color) !default;
|
||||
|
||||
@@ -204,3 +204,42 @@
|
||||
content: ' · ';
|
||||
}
|
||||
}
|
||||
|
||||
// Icon list: a list whose markers are icons instead of bullets, such as a
|
||||
// checklist of features. The first `.icon` in an entry is the marker.
|
||||
.list-icon {
|
||||
// scss-docs-start list-icon-css-vars
|
||||
--list-icon-gap: #{$list-icon-gap};
|
||||
--list-icon-row-gap: #{$list-icon-row-gap};
|
||||
--list-icon-inline-gap: #{$list-icon-inline-gap};
|
||||
--list-icon-size: #{$list-icon-size};
|
||||
--list-icon-color: #{$list-icon-color};
|
||||
// scss-docs-end list-icon-css-vars
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--list-icon-row-gap);
|
||||
padding-inline-start: 0;
|
||||
list-style: none;
|
||||
|
||||
> * {
|
||||
display: flex;
|
||||
gap: var(--list-icon-gap);
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
> * > .icon:first-child {
|
||||
--icon-size: var(--list-icon-size);
|
||||
flex-shrink: 0;
|
||||
// center the marker on the first line of text: `.icon` sets its own font
|
||||
// size, which would make `1lh` the icon's line height, so inherit the text's
|
||||
margin-top: calc((1lh - var(--list-icon-size)) / 2);
|
||||
font-size: inherit;
|
||||
color: var(--list-icon-color);
|
||||
}
|
||||
}
|
||||
|
||||
// Entries in a row that wraps, for a short list of highlights
|
||||
.list-icon-inline {
|
||||
flex-flow: row wrap;
|
||||
gap: var(--list-icon-row-gap) var(--list-icon-inline-gap);
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
---
|
||||
title: Icon list
|
||||
summary: An icon list replaces the bullets of a list with icons, such as a check mark in a list of features, a plan's benefits or the steps of a setup.
|
||||
description: Show a list with icon markers instead of bullets. Change the icon and the color per list or per entry, or lay the entries out in a row.
|
||||
related: [/ui/components/list-group, /ui/components/icon]
|
||||
source: core/scss/ui/_lists.scss
|
||||
css-vars: list-icon
|
||||
classnames:
|
||||
component:
|
||||
- class: list-icon
|
||||
desc: The list, on a ul, ol or div
|
||||
part:
|
||||
- class: icon
|
||||
desc: The first icon in an entry becomes its marker
|
||||
direction:
|
||||
- class: list-icon-inline
|
||||
desc: Lays the entries out in a row that wraps
|
||||
color:
|
||||
- class: text-{color}
|
||||
desc: Colors the marker of one entry, for example text-green on the icon
|
||||
---
|
||||
import Example from '@components/Example.astro';
|
||||
import Icon from '@ui/Icon.astro';
|
||||
|
||||
## Default markup
|
||||
|
||||
Add `.list-icon` to a list and start each entry with an icon. The first icon in an entry is the marker: it sits in front of the text, centered on the first line, in the secondary color.
|
||||
|
||||
<Example>
|
||||
<ul class="list-icon">
|
||||
<li><Icon name="check" /> Unlimited projects</li>
|
||||
<li><Icon name="check" /> Priority support</li>
|
||||
<li><Icon name="check" /> Custom domains</li>
|
||||
<li><Icon name="check" /> Advanced analytics</li>
|
||||
</ul>
|
||||
</Example>
|
||||
|
||||
## Color
|
||||
|
||||
Color all markers at once with the `--tblr-list-icon-color` variable on the list. A `text-{color}` utility on one icon colors that marker only.
|
||||
|
||||
<Example>
|
||||
<ul class="list-icon" style="--tblr-list-icon-color: var(--tblr-green)">
|
||||
<li><Icon name="check" /> Unlimited projects</li>
|
||||
<li><Icon name="check" /> Priority support</li>
|
||||
<li><Icon name="check" /> Custom domains</li>
|
||||
<li><Icon name="check" class="text-red" /> No phone support</li>
|
||||
</ul>
|
||||
</Example>
|
||||
|
||||
## Different icons
|
||||
|
||||
Each entry can use its own icon. Combine icons and colors to show a status, for example the steps of a setup.
|
||||
|
||||
<Example>
|
||||
<ul class="list-icon">
|
||||
<li><Icon name="circle-check" class="text-green" /> Account created</li>
|
||||
<li><Icon name="circle-check" class="text-green" /> Email confirmed</li>
|
||||
<li><Icon name="progress" class="text-blue" /> Profile in progress</li>
|
||||
<li><Icon name="circle-dashed" /> Add a payment method</li>
|
||||
</ul>
|
||||
</Example>
|
||||
|
||||
## Included and excluded
|
||||
|
||||
In a pricing table, use a check for what the plan has and a muted cross for what it lacks. Mute the whole entry with `.text-secondary` so the text reads as unavailable too.
|
||||
|
||||
<Example>
|
||||
<ul class="list-icon" style="--tblr-list-icon-color: var(--tblr-green)">
|
||||
<li><Icon name="check" /> Unlimited projects</li>
|
||||
<li><Icon name="check" /> Priority support</li>
|
||||
<li class="text-secondary"><Icon name="x" class="text-secondary" /> Custom domains</li>
|
||||
<li class="text-secondary"><Icon name="x" class="text-secondary" /> Advanced analytics</li>
|
||||
</ul>
|
||||
</Example>
|
||||
|
||||
## Inline
|
||||
|
||||
Add `.list-icon-inline` to show short entries in a row that wraps, for example the highlights under a product name.
|
||||
|
||||
<Example>
|
||||
<ul class="list-icon list-icon-inline" style="--tblr-list-icon-color: var(--tblr-green)">
|
||||
<li><Icon name="check" /> Free shipping</li>
|
||||
<li><Icon name="check" /> 30-day returns</li>
|
||||
<li><Icon name="check" /> 2-year warranty</li>
|
||||
<li><Icon name="check" /> In stock</li>
|
||||
</ul>
|
||||
</Example>
|
||||
|
||||
## Long entries
|
||||
|
||||
When an entry wraps to more lines, the marker stays on the first line. The marker follows the line height of the list, so it also fits small or large text.
|
||||
|
||||
<Example>
|
||||
<ul class="list-icon">
|
||||
<li><Icon name="shield-check" class="text-green" /> Two-factor authentication keeps the account safe even when the password leaks.</li>
|
||||
<li><Icon name="cloud-upload" class="text-blue" /> Backups run every night and are kept for thirty days in a separate region.</li>
|
||||
<li><Icon name="headset" class="text-purple" /> Support answers within one business day.</li>
|
||||
</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.
|
||||
|
||||
<Example>
|
||||
<ul class="list-icon fs-3" style="--tblr-list-icon-size: 1.5rem; --tblr-list-icon-row-gap: 1rem; --tblr-list-icon-color: var(--tblr-primary)">
|
||||
<li><Icon name="check" /> Unlimited projects</li>
|
||||
<li><Icon name="check" /> Priority support</li>
|
||||
<li><Icon name="check" /> Custom domains</li>
|
||||
</ul>
|
||||
</Example>
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Use a real list element, `ul` or `ol`, so screen readers announce the number of entries and let the user jump between them.
|
||||
- The icons are decorative, so screen readers skip them. When the icon carries meaning, for example a check against a cross, add the meaning as a `.visually-hidden` text, such as "Included" or "Not included".
|
||||
@@ -0,0 +1,337 @@
|
||||
---
|
||||
import DefaultLayout from '@shared/layouts/DefaultLayout.astro'
|
||||
import Card from '@ui/Card.astro'
|
||||
import CardBody from '@ui/CardBody.astro'
|
||||
import CardTitle from '@ui/CardTitle.astro'
|
||||
import CardSubtitle from '@ui/CardSubtitle.astro'
|
||||
import DocsLink from '@ui/DocsLink.astro'
|
||||
import IconList from '@ui/IconList.astro'
|
||||
import IconListItem from '@ui/IconListItem.astro'
|
||||
|
||||
const features = ['Unlimited projects', 'Priority support', 'Custom domains', 'Advanced analytics']
|
||||
|
||||
const layouts = ['Boxed', 'Combined', 'Condensed', 'Fluid', 'Horizontal', 'Vertical', 'RTL mode', 'Dark mode']
|
||||
|
||||
const plans = [
|
||||
{ name: 'Free', price: '$0', included: 2 },
|
||||
{ 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' },
|
||||
{ icon: 'progress', color: 'blue', text: 'Profile in progress' },
|
||||
{ icon: 'circle-dashed', color: 'secondary', text: 'Add a payment method' },
|
||||
]
|
||||
---
|
||||
|
||||
<DefaultLayout title="Icon lists" pageMenu="base.icon-lists" description="Icon lists replace the bullets of a list with icons, such as a checklist of features.">
|
||||
<DocsLink slot="page-header-actions" path="/ui/components/icon-list" />
|
||||
|
||||
<div class="row row-cards">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Basic</CardTitle>
|
||||
<CardSubtitle>Add <code>.list-icon</code> to a list. The first icon in each entry is the marker.</CardSubtitle>
|
||||
<IconList>
|
||||
{features.map((text) => <IconListItem>{text}</IconListItem>)}
|
||||
</IconList>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Color</CardTitle>
|
||||
<CardSubtitle>
|
||||
Color all markers with the <code>--tblr-list-icon-color</code> variable, or one marker with a <code>text-*</code> utility.
|
||||
</CardSubtitle>
|
||||
<IconList color="green">
|
||||
{features.map((text) => <IconListItem>{text}</IconListItem>)}
|
||||
</IconList>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Different icons</CardTitle>
|
||||
<CardSubtitle>Each entry can use its own icon and color, for example a status.</CardSubtitle>
|
||||
<IconList>
|
||||
{
|
||||
steps.map((step) => (
|
||||
<IconListItem icon={step.icon} color={step.color}>
|
||||
{step.text}
|
||||
</IconListItem>
|
||||
))
|
||||
}
|
||||
</IconList>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Included and excluded</CardTitle>
|
||||
<CardSubtitle>A check for what the plan has and a muted cross for what it lacks.</CardSubtitle>
|
||||
<IconList>
|
||||
{
|
||||
features.map((text, i) =>
|
||||
i < 2 ? (
|
||||
<IconListItem color="green">{text}</IconListItem>
|
||||
) : (
|
||||
<IconListItem icon="x" class="text-secondary">
|
||||
{text}
|
||||
</IconListItem>
|
||||
),
|
||||
)
|
||||
}
|
||||
</IconList>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Inline</CardTitle>
|
||||
<CardSubtitle>
|
||||
Add <code>.list-icon-inline</code> to show short entries in a row that wraps.
|
||||
</CardSubtitle>
|
||||
<IconList inline color="green">
|
||||
{layouts.map((text) => <IconListItem>{text}</IconListItem>)}
|
||||
</IconList>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Long entries</CardTitle>
|
||||
<CardSubtitle>The marker stays on the first line when an entry wraps.</CardSubtitle>
|
||||
<IconList>
|
||||
<IconListItem icon="shield-check" color="green">Two-factor authentication keeps the account safe even when the password leaks.</IconListItem>
|
||||
<IconListItem icon="cloud-upload" color="blue">Backups run every night and are kept for thirty days in a separate region.</IconListItem>
|
||||
<IconListItem icon="headset" color="purple">Support answers within one business day, in English and Polish.</IconListItem>
|
||||
</IconList>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Small text</CardTitle>
|
||||
<CardSubtitle>The marker follows the line height of the list, so it also fits small or large text.</CardSubtitle>
|
||||
<IconList class="small" color="green">
|
||||
{features.map((text) => <IconListItem>{text}</IconListItem>)}
|
||||
</IconList>
|
||||
</CardBody>
|
||||
</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">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>{plan.name}</CardTitle>
|
||||
<div class="display-6 fw-bold mb-3">
|
||||
{plan.price}
|
||||
<span class="fs-4 fw-normal text-secondary">/mo</span>
|
||||
</div>
|
||||
<IconList class="mb-3">
|
||||
{features.map((text, i) =>
|
||||
i < plan.included ? (
|
||||
<IconListItem color="green">{text}</IconListItem>
|
||||
) : (
|
||||
<IconListItem icon="x" class="text-secondary">
|
||||
{text}
|
||||
</IconListItem>
|
||||
),
|
||||
)}
|
||||
</IconList>
|
||||
<a href="#" class:list={['btn w-100', plan.included === features.length && 'btn-primary']}>
|
||||
Choose {plan.name}
|
||||
</a>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</DefaultLayout>
|
||||
+15
-13
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
// Icon list in context: two cards side by side. On the left a pricing plan
|
||||
// with green checks for what is included and muted crosses for what is not;
|
||||
// on the right a setup checklist where every entry has its own icon, color
|
||||
// and a short description. Both show the marker centered on the first line.
|
||||
import ScreenshotLayout from '../layouts/ScreenshotLayout.astro'
|
||||
import Card from '@ui/Card.astro'
|
||||
import CardBody from '@ui/CardBody.astro'
|
||||
import CardTitle from '@ui/CardTitle.astro'
|
||||
import IconList from '@ui/IconList.astro'
|
||||
import IconListItem from '@ui/IconListItem.astro'
|
||||
|
||||
const plan = [
|
||||
{ text: 'Unlimited projects', included: true },
|
||||
{ text: 'Up to 10 team members', included: true },
|
||||
{ text: 'Custom domains', included: true },
|
||||
{ text: 'Priority support', included: true },
|
||||
{ text: 'Advanced analytics', included: false },
|
||||
{ text: 'Single sign-on', included: false },
|
||||
]
|
||||
|
||||
const checklist = [
|
||||
{ icon: 'circle-check', color: 'green', title: 'Account created', text: 'Your workspace is ready to use.' },
|
||||
{ icon: 'circle-check', color: 'green', title: 'Email confirmed', text: 'We sent a link to your inbox.' },
|
||||
{ icon: 'progress', color: 'blue', title: 'Team invited', text: '2 of 5 invitations accepted.' },
|
||||
{ icon: 'circle-dashed', color: 'secondary', title: 'Add a payment method', text: 'Needed before the trial ends.' },
|
||||
]
|
||||
---
|
||||
|
||||
<ScreenshotLayout title="Icon list" columns={2.4}>
|
||||
<div class="row g-4 align-items-start">
|
||||
<div class="col-6">
|
||||
<Card class="card-md">
|
||||
<CardBody>
|
||||
<div class="text-uppercase text-secondary fw-medium">Pro plan</div>
|
||||
<div class="d-flex align-items-baseline gap-1 my-3">
|
||||
<div class="display-5 fw-bold">$29</div>
|
||||
<div class="text-secondary">/ month</div>
|
||||
</div>
|
||||
<IconList class="mb-4" style="--tblr-list-icon-row-gap: 0.75rem">
|
||||
{
|
||||
plan.map((row) =>
|
||||
row.included ? (
|
||||
<IconListItem color="green">{row.text}</IconListItem>
|
||||
) : (
|
||||
<IconListItem icon="x" class="text-secondary">
|
||||
{row.text}
|
||||
</IconListItem>
|
||||
),
|
||||
)
|
||||
}
|
||||
</IconList>
|
||||
<a href="#" class="btn btn-primary w-100">Choose Pro</a>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<Card class="card-md">
|
||||
<CardBody>
|
||||
<CardTitle>Getting started</CardTitle>
|
||||
<IconList style="--tblr-list-icon-row-gap: 1.25rem; --tblr-list-icon-size: 1.25rem">
|
||||
{
|
||||
checklist.map((step) => (
|
||||
<IconListItem icon={step.icon} color={step.color}>
|
||||
<span>
|
||||
<strong class="d-block">{step.title}</strong>
|
||||
<span class="d-block text-secondary">{step.text}</span>
|
||||
</span>
|
||||
</IconListItem>
|
||||
))
|
||||
}
|
||||
</IconList>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</ScreenshotLayout>
|
||||
@@ -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>
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -234,6 +234,10 @@
|
||||
"title": "Icon",
|
||||
"url": "/ui/components/icon"
|
||||
},
|
||||
{
|
||||
"title": "Icon list",
|
||||
"url": "/ui/components/icon-list"
|
||||
},
|
||||
{
|
||||
"title": "Image label",
|
||||
"url": "/ui/components/image-label"
|
||||
|
||||
@@ -173,6 +173,11 @@
|
||||
"title": "Hover gallery",
|
||||
"badge": "New"
|
||||
},
|
||||
"icon-lists": {
|
||||
"url": "icon-lists.html",
|
||||
"title": "Icon lists",
|
||||
"badge": "New"
|
||||
},
|
||||
"image-labels": {
|
||||
"url": "image-labels.html",
|
||||
"title": "Image labels",
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
// Icon list (.list-icon): a list whose markers are icons instead of bullets.
|
||||
// Fill it with `IconListItem` entries.
|
||||
|
||||
interface Props {
|
||||
/** entries in a row that wraps (`.list-icon-inline`) */
|
||||
inline?: boolean
|
||||
/** marker color for the whole list, any base color name, for example `green` */
|
||||
color?: string | undefined
|
||||
class?: string
|
||||
/** remaining attributes (id, data-*, aria-*, …) are forwarded to the root element */
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
const { inline, color, class: className, style, ...rest } = Astro.props
|
||||
|
||||
const colorStyle = color ? `--tblr-list-icon-color: var(--tblr-${color})` : undefined
|
||||
const styles = [colorStyle, style].filter(Boolean).join('; ') || undefined
|
||||
---
|
||||
|
||||
<ul class:list={['list-icon', inline && 'list-icon-inline', className]} style={styles} {...rest}><slot /></ul>
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
// Icon list entry: an icon marker followed by the text. Place inside `IconList`.
|
||||
import Icon from '@ui/Icon.astro'
|
||||
|
||||
interface Props {
|
||||
/** Tabler icon name of the marker */
|
||||
icon?: string
|
||||
/** filled icon variant */
|
||||
filled?: boolean | undefined
|
||||
/** marker color of this entry only, `text-{color}` on the icon */
|
||||
color?: string | undefined
|
||||
class?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
const { icon = 'check', filled, color, class: className, ...rest } = Astro.props
|
||||
---
|
||||
|
||||
<li class={className} {...rest}><Icon name={icon} filled={filled ?? false} color={color} /><slot /></li>
|
||||
Reference in new issue
Block a user