Add .datagrid-horizontal and .datagrid-cols-{n} classes, more datagrid examples (#3247)

This commit is contained in:
Paweł Kuna authored and GitHub committed 2026-10-02 13:03:56 +02:00
1 parent a1b46ae15e
commit ace9a4f123
9 files changed
+651 -26

No files matched your search

-2
View File
@@ -3,8 +3,6 @@
callout-note
clipboard-feedback
clipboard-label
datagrid-content
datagrid-item
datatable
docs-classnames
docs-page-lead
+7
View File
@@ -0,0 +1,7 @@
---
"@tabler/core": minor
"@tabler/preview": minor
"@tabler/docs": minor
---
Added `.datagrid-horizontal` and `.datagrid-cols-{n}` classes and more datagrid examples and docs.
+2
View File
@@ -1357,6 +1357,8 @@ $btn-close-white-filter: invert(1) grayscale(100%) brightness(200%) !default; //
$datagrid-padding: 1.5rem !default;
$datagrid-item-width: 15rem !default;
$datagrid-title-margin-bottom: 0.25rem !default;
$datagrid-title-width: 10rem !default;
$datagrid-columns: 4 !default;
// scss-docs-end datagrid-variables
// Empty
+24
View File
@@ -9,6 +9,7 @@
--datagrid-padding: #{$datagrid-padding};
--datagrid-item-width: #{$datagrid-item-width};
--datagrid-title-margin-bottom: #{$datagrid-title-margin-bottom};
--datagrid-title-width: #{$datagrid-title-width};
// scss-docs-end datagrid-css-vars
display: grid;
@@ -20,3 +21,26 @@
@include subheader();
margin-bottom: var(--datagrid-title-margin-bottom);
}
.datagrid-content {
margin: 0;
}
.datagrid-horizontal {
--datagrid-title-margin-bottom: 0;
grid-template-columns: minmax(0, 1fr);
.datagrid-item {
display: grid;
grid-template-columns: var(--datagrid-title-width) 1fr;
gap: 1rem;
align-items: baseline;
}
}
@for $i from 1 through $datagrid-columns {
.datagrid-cols-#{$i} {
grid-template-columns: repeat(#{$i}, minmax(0, 1fr));
}
}
+269 -9
View File
@@ -2,7 +2,7 @@
title: Data grid
summary: Use the data grid component to display detailed information about your product. The data is displayed as a column of items consisting of a title and content.
description: Display labeled data in a compact datagrid - a responsive list of title and content pairs, ideal for detail panels and summaries.
related: [/ui/components/table]
related: [/ui/components/table, /ui/plugins/clipboard]
source: core/scss/ui/_datagrid.scss
css-vars: datagrid
classnames:
@@ -10,8 +10,18 @@ classnames:
- class: datagrid
desc: Container element, a responsive grid of label and value pairs
part:
- class: datagrid-item
desc: One label and value pair
- class: datagrid-title
desc: Label above a value
desc: Label of a value, styled as a subheader
- class: datagrid-content
desc: Value of the pair, with the margin reset so a dd fits
modifier:
- class: datagrid-cols-{n}
desc: Fixed number of columns, from 1 to 4
direction:
- class: datagrid-horizontal
desc: Puts the label beside the value and shows one pair per row
---
import Example from '@components/Example.astro';
import Icon from '@ui/Icon.astro'
@@ -116,14 +126,264 @@ A value is a plain container, so it takes anything: text, [avatars](/ui/componen
</div>
</Example>
## Horizontal
Add the `.datagrid-horizontal` class to put the label beside the value. Each pair takes a full row, which is easy to scan when the values are long.
<Example>
<div class="datagrid datagrid-horizontal">
<div class="datagrid-item">
<div class="datagrid-title">Plan</div>
<div class="datagrid-content">Business</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Status</div>
<div class="datagrid-content"><span class="status status-green">Active</span></div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Address</div>
<div class="datagrid-content">44 Harbor Street, Portland, OR 97209, United States</div>
</div>
</div>
</Example>
Set `--tblr-datagrid-title-width` to change the width of the label column. Add a `.datagrid-cols-{n}` class to show several pairs in a row.
<Example>
<div class="datagrid datagrid-horizontal datagrid-cols-2" style="--tblr-datagrid-title-width: 5rem">
<div class="datagrid-item">
<div class="datagrid-title">CPU</div>
<div class="datagrid-content">8 cores</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Memory</div>
<div class="datagrid-content">32 GB</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Storage</div>
<div class="datagrid-content">512 GB</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Region</div>
<div class="datagrid-content">eu-central</div>
</div>
</div>
</Example>
## Column width
Columns are generated with `auto-fit`, so the item width decides how many fit in a row. Set the two custom properties on the `.datagrid` element to change the layout:
Columns are generated with `auto-fit`, so the item width decides how many fit in a row. Set the custom properties on the `.datagrid` element to change the layout:
| Variable | Description | Default |
|------------------------------|--------------------------------|----------|
| `--tblr-datagrid-item-width` | Width of the datagrid item | `15rem` |
| `--tblr-datagrid-padding` | Gap between the datagrid items | `1.5rem` |
| Variable | Description | Default |
|------------------------------|--------------------------------------|----------|
| `--tblr-datagrid-item-width` | Minimum width of a column | `15rem` |
| `--tblr-datagrid-padding` | Gap between the items | `1.5rem` |
| `--tblr-datagrid-title-width`| Label column in a horizontal datagrid| `10rem` |
Use a lower item width for short values, such as numbers or single words. More columns then fit in a row.
<Example>
<div class="datagrid" style="--tblr-datagrid-item-width: 7rem">
<div class="datagrid-item">
<div class="datagrid-title">CPU</div>
<div class="datagrid-content">8 cores</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Memory</div>
<div class="datagrid-content">32 GB</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Storage</div>
<div class="datagrid-content">512 GB</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Region</div>
<div class="datagrid-content">eu-central</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Uptime</div>
<div class="datagrid-content">99.98%</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Backups</div>
<div class="datagrid-content">Daily</div>
</div>
</div>
</Example>
### Fixed number of columns
Add a `.datagrid-cols-{n}` class to keep the same number of columns at any container width. The classes go from `.datagrid-cols-1` to `.datagrid-cols-4`. The item width is ignored then.
<Example>
<div class="datagrid datagrid-cols-2">
<div class="datagrid-item">
<div class="datagrid-title">Order</div>
<div class="datagrid-content">#48213</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Status</div>
<div class="datagrid-content"><span class="badge bg-green-lt">Paid</span></div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Placed</div>
<div class="datagrid-content">September 12, 2026</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Total</div>
<div class="datagrid-content"><strong>$248.00</strong></div>
</div>
</div>
</Example>
A single column works well in a narrow sidebar or an offcanvas.
<Example>
<div class="datagrid datagrid-cols-1">
<div class="datagrid-item">
<div class="datagrid-title">Email</div>
<div class="datagrid-content"><a href="#">billing@tabler.io</a></div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Shipping address</div>
<div class="datagrid-content">44 Harbor Street, Portland, OR 97209, United States</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Notes</div>
<div class="datagrid-content text-secondary">Not set</div>
</div>
</div>
</Example>
### Gap
Lower `--tblr-datagrid-padding` to make a dense datagrid. The same value is used between columns and between rows.
<Example>
<div class="datagrid" style="--tblr-datagrid-item-width: 7rem; --tblr-datagrid-padding: 0.75rem">
<div class="datagrid-item">
<div class="datagrid-title">CPU</div>
<div class="datagrid-content">8 cores</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Memory</div>
<div class="datagrid-content">32 GB</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Storage</div>
<div class="datagrid-content">512 GB</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Region</div>
<div class="datagrid-content">eu-central</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Uptime</div>
<div class="datagrid-content">99.98%</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Backups</div>
<div class="datagrid-content">Daily</div>
</div>
</div>
</Example>
## Examples
### Inside a card
A datagrid has no border or background of its own. Put it in a [card](/ui/components/card) to build a detail panel. The card header holds the title and the footer holds the actions.
<Example bg="surface-secondary">
<div class="card">
<div class="card-header">
<h3 class="card-title">Domain details</h3>
<div class="card-actions">
<a href="#" class="btn btn-sm"><Icon name="pencil" /> Edit</a>
</div>
</div>
<div class="card-body">
<div class="datagrid" style="--tblr-datagrid-item-width: 12rem">
<div class="datagrid-item">
<div class="datagrid-title">Domain</div>
<div class="datagrid-content"><a href="#">tabler.io</a></div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Registrar</div>
<div class="datagrid-content">Third Party</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">SSL certificate</div>
<div class="datagrid-content"><Icon name="lock" class="text-green" inline /> Valid until May 2, 2027</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Expiration date</div>
<div class="datagrid-content">–</div>
</div>
</div>
</div>
<div class="card-footer text-end">
<button type="button" class="btn btn-primary">Renew domain</button>
</div>
</div>
</Example>
### Statuses and progress
Show the state of a resource with a [status](/ui/components/status), a [badge](/ui/components/badge) or a [progress bar](/ui/components/progress).
<Example>
<div class="datagrid">
<div class="datagrid-item">
<div class="datagrid-title">State</div>
<div class="datagrid-content"><span class="status status-green">Running</span></div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Environment</div>
<div class="datagrid-content"><span class="badge bg-blue-lt">Production</span></div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Disk usage</div>
<div class="datagrid-content">
<div class="mb-1">68%</div>
<div class="progress progress-sm">
<div class="progress-bar" style="width: 68%" role="progressbar" aria-valuenow="68" aria-valuemin="0" aria-valuemax="100" aria-label="68% used"></div>
</div>
</div>
</div>
</div>
</Example>
### Values to copy
Add a [clipboard](/ui/plugins/clipboard) button next to a value that users copy, such as an API key. Point `data-bs-target` at the element with the value and give the button an `aria-label` that names it.
<Example>
<div class="datagrid datagrid-cols-1">
<div class="datagrid-item">
<div class="datagrid-title">Client ID</div>
<div class="datagrid-content d-flex align-items-center gap-2">
<code id="datagrid-client-id">tblr_live_8f3a2c91d7e4</code>
<button type="button" class="btn btn-sm btn-icon btn-action" data-bs-toggle="clipboard" data-bs-target="#datagrid-client-id" aria-label="Copy the client ID">
<Icon name="clipboard" class="clipboard-label" />
<Icon name="check" class="clipboard-feedback text-green" />
<span class="clipboard-feedback visually-hidden">Copied</span>
</button>
</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">Webhook URL</div>
<div class="datagrid-content d-flex align-items-center gap-2">
<code id="datagrid-webhook-url">https://example.com/hooks/tabler</code>
<button type="button" class="btn btn-sm btn-icon btn-action" data-bs-toggle="clipboard" data-bs-target="#datagrid-webhook-url" aria-label="Copy the webhook URL">
<Icon name="clipboard" class="clipboard-label" />
<Icon name="check" class="clipboard-feedback text-green" />
<span class="clipboard-feedback visually-hidden">Copied</span>
</button>
</div>
</div>
</div>
</Example>
## Accessibility
@@ -138,11 +398,11 @@ The pairs are only visually connected, so tell assistive tech how they belong to
<dl class="datagrid">
<div class="datagrid-item">
<dt class="datagrid-title">Registrar</dt>
<dd class="datagrid-content mb-0">Third Party</dd>
<dd class="datagrid-content">Third Party</dd>
</div>
<div class="datagrid-item">
<dt class="datagrid-title">Expiration date</dt>
<dd class="datagrid-content mb-0">–</dd>
<dd class="datagrid-content">–</dd>
</div>
</dl>
</Example>
+261 -7
View File
@@ -3,17 +3,271 @@ import DefaultLayout from '@shared/layouts/DefaultLayout.astro'
import Card from '@ui/Card.astro'
import CardHeader from '@ui/CardHeader.astro'
import CardBody from '@ui/CardBody.astro'
import Datagrid from '@shared/components/parts/Datagrid.astro'
import CardFooter from '@ui/CardFooter.astro'
import CardTitle from '@ui/CardTitle.astro'
import CardSubtitle from '@ui/CardSubtitle.astro'
import CardActions from '@ui/CardActions.astro'
import Avatar from '@ui/Avatar.astro'
import Badge from '@ui/Badge.astro'
import Button from '@ui/Button.astro'
import ButtonList from '@ui/ButtonList.astro'
import Icon from '@ui/Icon.astro'
import Progress from '@ui/Progress.astro'
import Datagrid from '@ui/Datagrid.astro'
import DatagridItem from '@ui/DatagridItem.astro'
import DatagridDemo from '@shared/components/parts/Datagrid.astro'
import DocsLink from '@ui/DocsLink.astro'
import { people } from '@shared/lib/people'
import { requireIndex } from '@shared/lib/array'
const customer = requireIndex(people, 2)
const owner = requireIndex(people, 4)
---
<DefaultLayout title="Data grid" pageMenu="base.datagrid" description="A data grid lays out label/value pairs in a compact, aligned grid.">
<DocsLink slot="page-header-actions" path="/ui/components/datagrid" />
<Card>
<CardHeader title="Base info" />
<CardBody>
<Datagrid />
</CardBody>
</Card>
<div class="row row-cards">
<div class="col-12">
<Card>
<CardHeader title="Base info" />
<CardBody>
<DatagridDemo />
</CardBody>
</Card>
</div>
<div class="col-lg-6">
<Card>
<CardBody>
<CardTitle>Basic</CardTitle>
<CardSubtitle>A <code>.datagrid</code> with plain text values.</CardSubtitle>
<Datagrid>
<DatagridItem title="Plan">Business</DatagridItem>
<DatagridItem title="Billing period">Monthly</DatagridItem>
<DatagridItem title="Next invoice">October 18, 2026</DatagridItem>
<DatagridItem title="Seats">8 of 10 used</DatagridItem>
</Datagrid>
</CardBody>
</Card>
</div>
<div class="col-lg-6">
<Card>
<CardBody>
<CardTitle>Description list</CardTitle>
<CardSubtitle>Use <code>dl</code>, <code>dt</code> and <code>dd</code> so screen readers announce the pairs.</CardSubtitle>
<Datagrid as="dl">
<DatagridItem list title="Company">Tabler Ltd.</DatagridItem>
<DatagridItem list title="Tax ID">EU123456789</DatagridItem>
<DatagridItem list title="Billing email">billing@tabler.io</DatagridItem>
<DatagridItem list title="Country">Poland</DatagridItem>
</Datagrid>
</CardBody>
</Card>
</div>
<div class="col-lg-6">
<Card>
<CardBody>
<CardTitle>Narrow columns</CardTitle>
<CardSubtitle>Lower <code>--tblr-datagrid-item-width</code> to fit more columns in a row.</CardSubtitle>
<Datagrid itemWidth="7rem">
<DatagridItem title="CPU">8 cores</DatagridItem>
<DatagridItem title="Memory">32 GB</DatagridItem>
<DatagridItem title="Storage">512 GB</DatagridItem>
<DatagridItem title="Region">eu-central</DatagridItem>
<DatagridItem title="Uptime">99.98%</DatagridItem>
<DatagridItem title="Backups">Daily</DatagridItem>
<DatagridItem title="IPv6">Enabled</DatagridItem>
<DatagridItem title="Port">3306</DatagridItem>
</Datagrid>
</CardBody>
</Card>
</div>
<div class="col-lg-6">
<Card>
<CardBody>
<CardTitle>Compact gap</CardTitle>
<CardSubtitle>Lower <code>--tblr-datagrid-padding</code> to bring the items closer together.</CardSubtitle>
<Datagrid itemWidth="7rem" gap="0.75rem">
<DatagridItem title="CPU">8 cores</DatagridItem>
<DatagridItem title="Memory">32 GB</DatagridItem>
<DatagridItem title="Storage">512 GB</DatagridItem>
<DatagridItem title="Region">eu-central</DatagridItem>
<DatagridItem title="Uptime">99.98%</DatagridItem>
<DatagridItem title="Backups">Daily</DatagridItem>
<DatagridItem title="IPv6">Enabled</DatagridItem>
<DatagridItem title="Port">3306</DatagridItem>
</Datagrid>
</CardBody>
</Card>
</div>
<div class="col-lg-6">
<Card>
<CardBody>
<CardTitle>Horizontal</CardTitle>
<CardSubtitle>Add <code>.datagrid-horizontal</code> to put the label beside the value.</CardSubtitle>
<Datagrid variant="horizontal" gap="1rem">
<DatagridItem title="Plan">Business</DatagridItem>
<DatagridItem title="Status"><span class="status status-green">Active</span></DatagridItem>
<DatagridItem title="Next invoice">October 18, 2026</DatagridItem>
<DatagridItem title="Address">44 Harbor Street, Portland, OR 97209, United States</DatagridItem>
</Datagrid>
</CardBody>
</Card>
</div>
<div class="col-lg-6">
<Card>
<CardBody>
<CardTitle>Horizontal in columns</CardTitle>
<CardSubtitle>Add <code>.datagrid-cols-2</code> and lower <code>--tblr-datagrid-title-width</code> to fit two pairs in a row.</CardSubtitle>
<Datagrid variant="horizontal" columns={2} titleWidth="5rem" gap="1rem">
<DatagridItem title="CPU">8 cores</DatagridItem>
<DatagridItem title="Memory">32 GB</DatagridItem>
<DatagridItem title="Storage">512 GB</DatagridItem>
<DatagridItem title="Region">eu-central</DatagridItem>
<DatagridItem title="Uptime">99.98%</DatagridItem>
<DatagridItem title="Backups">Daily</DatagridItem>
</Datagrid>
</CardBody>
</Card>
</div>
<div class="col-md-6 col-lg-4">
<Card>
<CardBody>
<CardTitle>Single column</CardTitle>
<CardSubtitle>Add <code>.datagrid-cols-1</code> to stack the items.</CardSubtitle>
<Datagrid columns={1} gap="1rem">
<DatagridItem title="Customer">
<div class="d-flex align-items-center">
<Avatar person={customer} size="xs" class="me-2" />
{customer.full_name}
</div>
</DatagridItem>
<DatagridItem title="Email"><a href="#">{customer.email}</a></DatagridItem>
<DatagridItem title="Shipping address">44 Harbor Street, Portland, OR 97209, United States</DatagridItem>
<DatagridItem title="Notes"><span class="text-secondary">Not set</span></DatagridItem>
</Datagrid>
</CardBody>
</Card>
</div>
<div class="col-md-6 col-lg-4">
<Card>
<CardBody>
<CardTitle>Two columns</CardTitle>
<CardSubtitle>Add <code>.datagrid-cols-2</code> to keep two columns at any width.</CardSubtitle>
<Datagrid columns={2} gap="1rem">
<DatagridItem title="Order">#48213</DatagridItem>
<DatagridItem title="Status"><Badge color="green" light text="Paid" /></DatagridItem>
<DatagridItem title="Placed">September 12, 2026</DatagridItem>
<DatagridItem title="Delivery">September 16, 2026</DatagridItem>
<DatagridItem title="Items">3</DatagridItem>
<DatagridItem title="Total"><strong>$248.00</strong></DatagridItem>
<DatagridItem title="Payment">Visa ending 4242</DatagridItem>
<DatagridItem title="Carrier">DHL Express</DatagridItem>
</Datagrid>
</CardBody>
</Card>
</div>
<div class="col-md-6 col-lg-4">
<Card>
<CardBody>
<CardTitle>Statuses and progress</CardTitle>
<CardSubtitle>A value can hold a status, a badge or a progress bar.</CardSubtitle>
<Datagrid columns={2} gap="1rem">
<DatagridItem title="State"><span class="status status-green">Running</span></DatagridItem>
<DatagridItem title="Health"><span class="status status-yellow">Degraded</span></DatagridItem>
<DatagridItem title="Environment"><Badge color="blue" light text="Production" /></DatagridItem>
<DatagridItem title="Version"><code>v1.6.1</code></DatagridItem>
<DatagridItem title="Disk usage">
<div class="mb-1">68%</div>
<Progress value={68} size="sm" />
</DatagridItem>
<DatagridItem title="Memory usage">
<div class="mb-1">41%</div>
<Progress value={41} size="sm" color="green" />
</DatagridItem>
</Datagrid>
</CardBody>
</Card>
</div>
<div class="col-lg-6">
<Card>
<CardHeader title="Domain details">
<CardActions>
<Button text="Edit" icon="pencil" size="sm" />
</CardActions>
</CardHeader>
<CardBody>
<Datagrid itemWidth="12rem">
<DatagridItem title="Domain"><a href="#">tabler.io <Icon name="external-link" inline /></a></DatagridItem>
<DatagridItem title="Registrar">Third Party</DatagridItem>
<DatagridItem title="SSL certificate">
<Icon name="lock" color="green" inline />
Valid until May 2, 2027
</DatagridItem>
<DatagridItem title="Auto renew">
<label class="form-check form-switch mb-0">
<input class="form-check-input" type="checkbox" checked />
<span class="form-check-label">Enabled</span>
</label>
</DatagridItem>
<DatagridItem title="Owner">
<div class="d-flex align-items-center">
<Avatar person={owner} size="xs" class="me-2" />
{owner.full_name}
</div>
</DatagridItem>
<DatagridItem title="Expiration date">–</DatagridItem>
</Datagrid>
</CardBody>
<CardFooter>
<ButtonList class="justify-content-end">
<Button text="Transfer" variant="ghost" color="secondary" />
<Button text="Renew domain" color="primary" />
</ButtonList>
</CardFooter>
</Card>
</div>
<div class="col-lg-6">
<Card>
<CardHeader title="API credentials" />
<CardBody>
<CardSubtitle>Add a <code>data-bs-toggle="clipboard"</code> button to let users copy a value.</CardSubtitle>
<Datagrid columns={1} gap="1rem">
<DatagridItem title="Client ID">
<div class="d-flex align-items-center gap-2">
<code id="datagrid-client-id" class="text-truncate">tblr_live_8f3a2c91d7e4</code>
<button type="button" class="btn btn-sm btn-icon btn-action" data-bs-toggle="clipboard" data-bs-target="#datagrid-client-id" aria-label="Copy the client ID">
<Icon name="clipboard" class="clipboard-label" />
<Icon name="check" class="clipboard-feedback text-green" />
<span class="clipboard-feedback visually-hidden">Copied</span>
</button>
</div>
</DatagridItem>
<DatagridItem title="Webhook URL">
<div class="d-flex align-items-center gap-2">
<code id="datagrid-webhook-url" class="text-truncate">https://example.com/hooks/tabler</code>
<button type="button" class="btn btn-sm btn-icon btn-action" data-bs-toggle="clipboard" data-bs-target="#datagrid-webhook-url" aria-label="Copy the webhook URL">
<Icon name="clipboard" class="clipboard-label" />
<Icon name="check" class="clipboard-feedback text-green" />
<span class="clipboard-feedback visually-hidden">Copied</span>
</button>
</div>
</DatagridItem>
<DatagridItem title="Last used">2 hours ago</DatagridItem>
</Datagrid>
</CardBody>
</Card>
</div>
</div>
</DefaultLayout>
+59
View File
@@ -0,0 +1,59 @@
---
// Datagrid in its natural place: the details panel of a domain in a hosting
// dashboard. The values mix plain text, a status, an avatar, an icon and a
// progress bar, so the picture shows that a value can hold any content.
import ScreenshotLayout from '../layouts/ScreenshotLayout.astro'
import Card from '@ui/Card.astro'
import CardHeader from '@ui/CardHeader.astro'
import CardBody from '@ui/CardBody.astro'
import CardActions from '@ui/CardActions.astro'
import Avatar from '@ui/Avatar.astro'
import Badge from '@ui/Badge.astro'
import Button from '@ui/Button.astro'
import Icon from '@ui/Icon.astro'
import Progress from '@ui/Progress.astro'
import Datagrid from '@ui/Datagrid.astro'
import DatagridItem from '@ui/DatagridItem.astro'
import { people } from '@shared/lib/people'
import { requireIndex } from '@shared/lib/array'
const owner = requireIndex(people, 4)
---
<ScreenshotLayout title="Data grid" columns={2}>
<Card>
<CardHeader title="Domain details">
<CardActions>
<Button text="Edit" icon="pencil" size="sm" />
</CardActions>
</CardHeader>
<CardBody class="p-4">
<Datagrid columns={3}>
<DatagridItem title="Domain">tabler.io</DatagridItem>
<DatagridItem title="Registrar">Third Party</DatagridItem>
<DatagridItem title="Edge network">
<span class="status status-green">Active</span>
</DatagridItem>
<DatagridItem title="Owner">
<div class="d-flex align-items-center">
<Avatar person={owner} size="xs" class="me-2" />
{owner.full_name}
</div>
</DatagridItem>
<DatagridItem title="Environment">
<Badge color="blue" light text="Production" />
</DatagridItem>
<DatagridItem title="Port number">3306</DatagridItem>
<DatagridItem title="SSL certificate">
<Icon name="lock" color="green" inline />
Valid
</DatagridItem>
<DatagridItem title="Expiration date">May 2, 2027</DatagridItem>
<DatagridItem title="Disk usage">
<div class="mb-1">68%</div>
<Progress value={68} size="sm" />
</DatagridItem>
</Datagrid>
</CardBody>
</Card>
</ScreenshotLayout>
+20 -4
View File
@@ -1,13 +1,29 @@
---
// Data grid container (.datagrid); holds DatagridItem children.
interface Props {
type PolymorphicProps = { as?: 'div' | 'dl' }
interface Props extends PolymorphicProps {
/** core/scss/ui/_datagrid.scss `.datagrid-horizontal`: label beside the value, one pair per row */
variant?: 'horizontal' | undefined
/** `.datagrid-cols-{n}`: a fixed number of columns instead of as many as fit */
columns?: 1 | 2 | 3 | 4 | undefined
/** sets --tblr-datagrid-item-width, the minimum width of a column (e.g. `10rem`) */
itemWidth?: string | undefined
/** sets --tblr-datagrid-padding, the gap between items (e.g. `1rem`) */
gap?: string | undefined
/** sets --tblr-datagrid-title-width, the label column of the horizontal variant (e.g. `8rem`) */
titleWidth?: string | undefined
class?: string
/** remaining attributes (id, data-*, aria-*, …) are forwarded to the root element */
[key: string]: unknown
}
const { class: className } = Astro.props
const { as: Tag = 'div', variant, columns, itemWidth, gap, titleWidth, class: className, ...rest }: Props = Astro.props
const style = [itemWidth && `--tblr-datagrid-item-width: ${itemWidth}`, gap && `--tblr-datagrid-padding: ${gap}`, titleWidth && `--tblr-datagrid-title-width: ${titleWidth}`].filter(Boolean).join('; ')
---
<div class:list={['datagrid', className]}>
<Tag class:list={['datagrid', variant && `datagrid-${variant}`, columns && `datagrid-cols-${columns}`, className]} style={style || undefined} {...rest}>
<slot />
</div>
</Tag>
+9 -4
View File
@@ -3,15 +3,20 @@
interface Props {
title: string
/** renders dt/dd instead of divs, for an item inside `<Datagrid as="dl">` */
list?: boolean
class?: string
}
const { title, class: className } = Astro.props
const { title, list = false, class: className } = Astro.props
const TitleTag = list ? 'dt' : 'div'
const ContentTag = list ? 'dd' : 'div'
---
<div class:list={['datagrid-item', className]}>
<div class="datagrid-title">{title}</div>
<div class="datagrid-content">
<TitleTag class="datagrid-title">{title}</TitleTag>
<ContentTag class="datagrid-content">
<slot />
</div>
</ContentTag>
</div>