mirror of
https://github.com/tabler/tabler.git
synced 2026-10-12 05:06:55 +04:00
Add Stepper component for quantity inputs (#3281)
This commit is contained in:
1 parent
d75c5d6a7d
commit
0e4a07b82a
17 files changed
+1746
-3
No files matched your search
@@ -16,6 +16,7 @@ import ListGroupItem from '@ui/ListGroupItem.astro'
|
||||
import Icon from '@ui/Icon.astro'
|
||||
import Payment from '@ui/Payment.astro'
|
||||
import Progress from '@ui/Progress.astro'
|
||||
import Stepper from '@ui/Stepper.astro'
|
||||
import type { PaymentProvider } from '@shared/lib/tokens'
|
||||
|
||||
const usage = { used: 7420, limit: 10000 }
|
||||
@@ -79,7 +80,12 @@ const invoiceStatus = {
|
||||
<Datagrid>
|
||||
<DatagridItem title="Billing period">Monthly</DatagridItem>
|
||||
<DatagridItem title="Next invoice">September 18, 2026</DatagridItem>
|
||||
<DatagridItem title="Seats">8 of 10 used</DatagridItem>
|
||||
<DatagridItem title="Seats">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<Stepper size="sm" value={10} min={8} max={100} ariaLabel="Seats in the plan" />
|
||||
<span class="text-secondary">8 used</span>
|
||||
</div>
|
||||
</DatagridItem>
|
||||
</Datagrid>
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
||||
@@ -11,6 +11,7 @@ import Layout from '@shared/components/cards/form/Layout.astro'
|
||||
import InputIcon from '@ui/form/InputIcon.astro'
|
||||
import InputMask from '@ui/form/InputMask.astro'
|
||||
import OtpInput from '@ui/OtpInput.astro'
|
||||
import Stepper from '@ui/Stepper.astro'
|
||||
import Button from '@ui/Button.astro'
|
||||
import Avatar from '@ui/Avatar.astro'
|
||||
import Card from '@ui/Card.astro'
|
||||
@@ -158,6 +159,18 @@ const rows = [
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6">
|
||||
<Card>
|
||||
<CardHeader title="Stepper" />
|
||||
<CardBody>
|
||||
<FormGroup label="Quantity" for="stepper-basic"><Stepper id="stepper-basic" value={1} min={1} max={99} /></FormGroup>
|
||||
<FormGroup label="Step of 0.25" for="stepper-decimal"><Stepper id="stepper-decimal" value={1.5} min={0} max={10} step={0.25} /></FormGroup>
|
||||
<FormGroup label="Without bounds" for="stepper-unbounded"><Stepper id="stepper-unbounded" value={0} /></FormGroup>
|
||||
<FormGroup label="Native number input" for="stepper-number"><Stepper id="stepper-number" type="number" value={5} min={0} max={10} /></FormGroup>
|
||||
<FormGroup label="Disabled" for="stepper-disabled"><Stepper id="stepper-disabled" value={3} disabled /></FormGroup>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6">
|
||||
<Card as="form" class="h-100">
|
||||
<CardHeader title="My Profile" />
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import SettingsLayout from '@shared/layouts/SettingsLayout.astro'
|
||||
import PricingCard from '@shared/components/cards/PricingCard.astro'
|
||||
import PricingCardEnterprise from '@shared/components/cards/PricingCardEnterprise.astro'
|
||||
import Stepper from '@ui/Stepper.astro'
|
||||
import FormGroup from '@ui/FormGroup.astro'
|
||||
---
|
||||
|
||||
<SettingsLayout active="settings-plan" title="Plans">
|
||||
@@ -10,6 +12,8 @@ import PricingCardEnterprise from '@shared/components/cards/PricingCardEnterpris
|
||||
|
||||
<p class="text-secondary mb-4">This workspace’s Basic Plan is set to $34 per month and will renew on June 19, 2022.</p>
|
||||
|
||||
<FormGroup label="Users" for="plan-users" hint="Each plan is billed per user. Pick how many people need access." class="mb-4"><Stepper id="plan-users" value={10} min={1} max={100} /></FormGroup>
|
||||
|
||||
<div class="row row-cards">
|
||||
<div class="col-lg-4">
|
||||
<PricingCard price="0" users={3} category="Free" />
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
---
|
||||
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 FormGroup from '@ui/FormGroup.astro'
|
||||
import Stepper from '@ui/Stepper.astro'
|
||||
import Icon from '@ui/Icon.astro'
|
||||
|
||||
const cart = [
|
||||
{ name: 'Hex nut M8 DIN 934, zinc plated', code: '8-934-8-ZN', price: '12.40', quantity: 2, max: 50 },
|
||||
{ name: 'Lock nut M8 DIN 985, stainless A2', code: '8-985-A2', price: '28.90', quantity: 1, max: 20 },
|
||||
{ name: 'Cap nut M8 DIN 1587, brass', code: '8-1587-MS', price: '41.00', quantity: 3, max: 3 },
|
||||
]
|
||||
---
|
||||
|
||||
<DefaultLayout title="Stepper" pageMenu="base.stepper" description="A stepper is a number field with a decrease and an increase button, for a quantity or any value changed in fixed steps.">
|
||||
<DocsLink slot="page-header-actions" path="/ui/forms/stepper" />
|
||||
|
||||
<div class="row row-cards">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Basic</CardTitle>
|
||||
<CardSubtitle>Add <code>data-bs-toggle="stepper"</code> to the input; the plugin renders the box and the buttons, <code>min</code> and <code>max</code> set the bounds.</CardSubtitle>
|
||||
<Stepper value={1} min={1} max={99} ariaLabel="Quantity" />
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>At a bound</CardTitle>
|
||||
<CardSubtitle>The button at <code>min</code> or <code>max</code> goes disabled, so the user sees the value cannot go further.</CardSubtitle>
|
||||
<div class="d-flex flex-wrap gap-3">
|
||||
<Stepper value={0} min={0} max={10} ariaLabel="At the minimum" />
|
||||
<Stepper value={10} min={0} max={10} ariaLabel="At the maximum" />
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Step and precision</CardTitle>
|
||||
<CardSubtitle>A fractional <code>step</code> sets how many decimals the value keeps.</CardSubtitle>
|
||||
<div class="d-flex flex-wrap gap-3">
|
||||
<Stepper value={1.5} min={0} max={10} step={0.25} ariaLabel="Hours" />
|
||||
<Stepper value={500} min={0} step={100} ariaLabel="Amount" style="--tblr-stepper-input-width: 5rem" />
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Sizes</CardTitle>
|
||||
<CardSubtitle>Add <code>.form-control-sm</code> or <code>.form-control-lg</code> to the input; the box gets <code>.stepper-sm</code> or <code>-lg</code>.</CardSubtitle>
|
||||
<div class="d-flex flex-wrap align-items-center gap-3">
|
||||
<Stepper size="sm" value={1} min={0} ariaLabel="Small" />
|
||||
<Stepper value={1} min={0} ariaLabel="Default" />
|
||||
<Stepper size="lg" value={1} min={0} ariaLabel="Large" />
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Without bounds</CardTitle>
|
||||
<CardSubtitle>Without <code>min</code> and <code>max</code> the value goes both ways, so a minus sign can be typed too.</CardSubtitle>
|
||||
<Stepper value={0} ariaLabel="Offset" />
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Native number input</CardTitle>
|
||||
<CardSubtitle>Use <code>type="number"</code> to keep the browser's own validation; the stepper only hides its spin buttons.</CardSubtitle>
|
||||
<Stepper type="number" value={5} min={0} max={10} ariaLabel="Seats" />
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>No repeat</CardTitle>
|
||||
<CardSubtitle>Add <code>data-bs-repeat="false"</code> to step once per click instead of repeating while the button is held.</CardSubtitle>
|
||||
<Stepper value={1} min={1} max={99} repeat={false} ariaLabel="Quantity, one step per click" />
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Wider input</CardTitle>
|
||||
<CardSubtitle>Set <code>--tblr-stepper-input-width</code> on the input for longer values.</CardSubtitle>
|
||||
<Stepper value={125000} min={0} step={1000} ariaLabel="Budget" style="--tblr-stepper-input-width: 7rem" />
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Disabled and readonly</CardTitle>
|
||||
<CardSubtitle>Add <code>disabled</code> or <code>readonly</code> to the input; both buttons follow.</CardSubtitle>
|
||||
<div class="d-flex flex-wrap gap-3">
|
||||
<Stepper value={3} disabled ariaLabel="Disabled" />
|
||||
<Stepper value={3} readonly ariaLabel="Readonly" />
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Validation</CardTitle>
|
||||
<CardSubtitle>Add <code>.is-valid</code> or <code>.is-invalid</code> to the input, like on any <code>.form-control</code>; the feedback text after it still shows.</CardSubtitle>
|
||||
<div class="space-y-3">
|
||||
<div>
|
||||
<Stepper class="is-valid" value={2} min={1} max={5} ariaLabel="Valid quantity" />
|
||||
<div class="valid-feedback">In stock, ships today.</div>
|
||||
</div>
|
||||
<div>
|
||||
<Stepper class="is-invalid" value={5} min={1} max={5} ariaLabel="Invalid quantity" />
|
||||
<div class="invalid-feedback">Only 5 pieces left.</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>Custom buttons</CardTitle>
|
||||
<CardSubtitle>Write the <code>.stepper</code> markup yourself to change the icons or labels; <code>data-bs-stepper-action</code> marks the buttons.</CardSubtitle>
|
||||
<div class="stepper" data-bs-toggle="stepper">
|
||||
<button type="button" class="btn btn-icon" data-bs-stepper-action="decrement" aria-label="Fewer"><Icon name="chevron-down" /></button>
|
||||
<input type="text" class="form-control" value="1" min="1" max="99" aria-label="Quantity with custom buttons" />
|
||||
<button type="button" class="btn btn-icon" data-bs-stepper-action="increment" aria-label="More"><Icon name="chevron-up" /></button>
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>With a label and hint</CardTitle>
|
||||
<CardSubtitle>A stepper sits in a <code>FormGroup</code> like any other control.</CardSubtitle>
|
||||
<FormGroup label="Number of seats" for="stepper-seats" hint="Up to 8 seats per booking."><Stepper id="stepper-seats" name="seats" value={2} min={1} max={8} /></FormGroup>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="col-md-12 col-lg-8">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<CardTitle>In a cart</CardTitle>
|
||||
<CardSubtitle>The usual place for a stepper: a quantity per line, with <code>max</code> set to the stock.</CardSubtitle>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Product</th>
|
||||
<th>Price</th>
|
||||
<th>Quantity</th>
|
||||
<th class="w-1"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
cart.map((item) => (
|
||||
<tr>
|
||||
<td>
|
||||
<div>{item.name}</div>
|
||||
<div class="text-secondary">{item.code}</div>
|
||||
</td>
|
||||
<td class="text-nowrap">${item.price}</td>
|
||||
<td>
|
||||
<Stepper value={item.quantity} min={1} max={item.max} ariaLabel={`Quantity of ${item.name}`} />
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-icon btn-ghost-secondary" aria-label={`Remove ${item.name}`}>
|
||||
<Icon name="trash" />
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</DefaultLayout>
|
||||
Reference in new issue
Block a user