Prepare 1.0.0-beta.6

This commit is contained in:
Ronan Berder
2026-06-23 18:14:19 +08:00
parent fbf3f47b75
commit a17eaa20d3
63 changed files with 2398 additions and 1502 deletions
+1
View File
@@ -80,6 +80,7 @@
- Keep `Usage` focused on the minimal working snippet and important Basecoat/upstream differences; put variants, states, RTL, and richer patterns under `Examples`.
- Keep snippets minimal and aligned with current behavior.
- In HTML snippets, keep text-only elements on one line, such as `<p>Text</p>`; use multiline formatting when the element contains child elements or when line length would hurt readability.
- In HTML examples, keep icons as single-line `<svg ...>...</svg>` elements, keep simple text-only or inline-formatting elements on one line, and avoid blank separator lines between adjacent markup parts.
- Document intentional differences from upstream near the relevant example.
## Validation
+13
View File
@@ -2,6 +2,19 @@
## Unreleased
## [1.0.0-beta.6] - 2026-06-23
### Changed
- Updated docs dependency to the published `reallysimpledocs@1.0.0-beta.5` package.
- Refined component documentation examples across the docs site, including Select, Table, Tabs, Switch, and Theme Switcher.
- Clarified CDN and npm installation guidance for default and named style bundles.
- Updated Table examples to avoid inline overlay menus inside scrollable table containers and documented the overflow limitation.
### Fixed
- Fixed dark-mode unchecked Switch thumb colors across all style packs to match upstream shadcn/ui behavior.
## [1.0.0-beta.5] - 2026-06-22
### Added
-2
View File
@@ -19,7 +19,6 @@ Nunjucks and Jinja macros are optional helpers for components with larger HTML s
<CodeGroup defaultTab="Nunjucks">
<Code title="Nunjucks" lang="jinja">{`{% from "select.njk" import select %}
{{ select(
name="fruit",
items=[
@@ -29,7 +28,6 @@ Nunjucks and Jinja macros are optional helpers for components with larger HTML s
]
) }}`}</Code>
<Code title="Jinja" lang="jinja">{`{% from "select.html.jinja" import select %}
{{ select(
name="fruit",
items=[
+56 -69
View File
@@ -9,27 +9,21 @@ A vertically stacked set of interactive headings that each reveal a section of c
What are your shipping options?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
We offer standard (5-7 days), express (2-3 days), and overnight shipping. Free shipping on international orders.
</section>
<section>We offer standard (5-7 days), express (2-3 days), and overnight shipping. Free shipping on international orders.</section>
</details>
<details>
<summary>
What is your return policy?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
You can return items within 30 days of delivery. Items must be unused and in their original packaging.
</section>
<section>You can return items within 30 days of delivery. Items must be unused and in their original packaging.</section>
</details>
<details>
<summary>
How can I contact customer support?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
Email support@example.com or use live chat during business hours.
</section>
<section>Email support@example.com or use live chat during business hours.</section>
</details>
</section>
</Preview>
@@ -37,13 +31,44 @@ A vertically stacked set of interactive headings that each reveal a section of c
## Usage
<Steps>
<Step title="Include the JavaScript files">
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Accordion component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/accordion.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Include JavaScript">
Copy or serve the full Basecoat JavaScript bundle.
```html
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/accordion.min.js" defer></script>
<script src="/assets/js/all.min.js" defer></script>
```
Or copy or serve the Basecoat runtime and Accordion script.
```html
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/accordion.min.js" defer></script>
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your accordion HTML">
@@ -54,9 +79,7 @@ A vertically stacked set of interactive headings that each reveal a section of c
Is it accessible?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
Yes. It uses native disclosure semantics.
</section>
<section>Yes. It uses native disclosure semantics.</section>
</details>
</section>
```
@@ -108,27 +131,21 @@ A basic accordion that shows one item at a time. The first item is open by defau
How do I reset my password?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
Click on 'Forgot Password' on the login page, enter your email address, and we'll send you a link to reset your password. The link will expire in 24 hours.
</section>
<section>Click on 'Forgot Password' on the login page, enter your email address, and we'll send you a link to reset your password. The link will expire in 24 hours.</section>
</details>
<details>
<summary>
Can I change my subscription plan?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
Yes. You can upgrade or downgrade your plan from the billing settings page.
</section>
<section>Yes. You can upgrade or downgrade your plan from the billing settings page.</section>
</details>
<details>
<summary>
What payment methods do you accept?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
We accept all major credit cards, PayPal, and bank transfers for annual plans.
</section>
<section>We accept all major credit cards, PayPal, and bank transfers for annual plans.</section>
</details>
</section>
</Preview>
@@ -144,27 +161,21 @@ Use `data-multiple` to allow multiple items to be open at the same time.
Notification Settings
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
Manage how you receive notifications. You can enable email alerts for updates or push notifications for mobile devices.
</section>
<section>Manage how you receive notifications. You can enable email alerts for updates or push notifications for mobile devices.</section>
</details>
<details>
<summary>
Privacy & Security
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
Control account security, session history, and privacy preferences.
</section>
<section>Control account security, session history, and privacy preferences.</section>
</details>
<details>
<summary>
Billing & Subscription
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
Review invoices, change plans, and update payment methods.
</section>
<section>Review invoices, change plans, and update payment methods.</section>
</details>
</section>
</Preview>
@@ -180,27 +191,21 @@ Use `aria-disabled="true"` on an item to disable it.
Can I access my account history?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
Yes. Your account history is available from the activity page.
</section>
<section>Yes. Your account history is available from the activity page.</section>
</details>
<details aria-disabled="true">
<summary>
Premium feature information
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
This item is disabled.
</section>
<section>This item is disabled.</section>
</details>
<details>
<summary>
How do I update my email address?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
Go to account settings, update your email, then confirm the change from your inbox.
</section>
<section>Go to account settings, update your email, then confirm the change from your inbox.</section>
</details>
</section>
</Preview>
@@ -216,27 +221,21 @@ Add horizontal padding to the rows when using a bordered root.
How does billing work?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
We offer monthly and annual subscription plans. Billing is charged at the beginning of each cycle, and you can cancel anytime. All plans include automatic backups, 24/7 support, and unlimited team members.
</section>
<section>We offer monthly and annual subscription plans. Billing is charged at the beginning of each cycle, and you can cancel anytime. All plans include automatic backups, 24/7 support, and unlimited team members.</section>
</details>
<details>
<summary>
Is my data secure?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
Data is encrypted in transit and at rest.
</section>
<section>Data is encrypted in transit and at rest.</section>
</details>
<details>
<summary>
What integrations do you support?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
We support Slack, GitHub, Google Workspace, and webhooks.
</section>
<section>We support Slack, GitHub, Google Workspace, and webhooks.</section>
</details>
</section>
</Preview>
@@ -258,27 +257,21 @@ Wrap the accordion in a card for grouped support or billing content.
What subscription plans do you offer?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
We offer three subscription tiers: Starter ($9/month), Professional ($29/month), and Enterprise ($99/month). Each plan includes increasing storage limits, API access, priority support, and team collaboration features.
</section>
<section>We offer three subscription tiers: Starter ($9/month), Professional ($29/month), and Enterprise ($99/month). Each plan includes increasing storage limits, API access, priority support, and team collaboration features.</section>
</details>
<details>
<summary>
How does billing work?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
Billing is charged at the beginning of each cycle.
</section>
<section>Billing is charged at the beginning of each cycle.</section>
</details>
<details>
<summary>
How do I cancel my subscription?
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
Cancel from billing settings. Your plan remains active until the end of the current cycle.
</section>
<section>Cancel from billing settings. Your plan remains active until the end of the current cycle.</section>
</details>
</section>
</section>
@@ -296,27 +289,21 @@ Accordion spacing uses logical properties. Set `dir="rtl"` on the accordion or a
كيف يمكنني إعادة تعيين كلمة المرور؟
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
انقر على 'نسيت كلمة المرور' في صفحة تسجيل الدخول، أدخل عنوان بريدك الإلكتروني، وسنرسل لك رابطا لإعادة تعيين كلمة المرور. سينتهي صلاحية الرابط خلال 24 ساعة.
</section>
<section>انقر على 'نسيت كلمة المرور' في صفحة تسجيل الدخول، أدخل عنوان بريدك الإلكتروني، وسنرسل لك رابطا لإعادة تعيين كلمة المرور. سينتهي صلاحية الرابط خلال 24 ساعة.</section>
</details>
<details>
<summary>
هل يمكنني تغيير خطة الاشتراك الخاصة بي؟
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
نعم، يمكنك تغيير الخطة من إعدادات الفوترة.
</section>
<section>نعم، يمكنك تغيير الخطة من إعدادات الفوترة.</section>
</details>
<details>
<summary>
ما هي طرق الدفع التي تقبلونها؟
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</summary>
<section>
نقبل بطاقات الائتمان الرئيسية والتحويلات البنكية.
</section>
<section>نقبل بطاقات الائتمان الرئيسية والتحويلات البنكية.</section>
</details>
</section>
</Preview>
+31 -6
View File
@@ -20,6 +20,32 @@ A modal dialog that interrupts the user with important content and expects a res
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Alert Dialog component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/dialog.css";
@import "basecoat-css/styles/vega.css";
```
Alert Dialog uses the Dialog component CSS.
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your alert dialog HTML">
Alert Dialog uses a native `<dialog class="alert-dialog">` element. Omit the close button and backdrop-click handler when the user must choose an explicit action.
```html
@@ -38,6 +64,9 @@ Alert Dialog uses a native `<dialog class="alert-dialog">` element. Omit the clo
</dialog>
```
</Step>
</Steps>
### HTML structure
<dl>
@@ -102,9 +131,7 @@ Use a `<figure>` in the header to add a media element such as an icon or image t
<dialog id="alert-dialog-media" class="alert-dialog" aria-labelledby="alert-dialog-media-title" aria-describedby="alert-dialog-media-description">
<div>
<header>
<figure>
<svg class="lucide lucide-circle-fading-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a10 10 0 0 1 7.38 16.75" /><path d="M12 8v8" /><path d="M16 12H8" /><path d="M2.5 8.88a10 10 0 0 0 0 6.24" /><path d="M4.64 4.64a10 10 0 0 0 0 14.72" /></svg>
</figure>
<figure><svg class="lucide lucide-circle-fading-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a10 10 0 0 1 7.38 16.75" /><path d="M12 8v8" /><path d="M16 12H8" /><path d="M2.5 8.88a10 10 0 0 0 0 6.24" /><path d="M4.64 4.64a10 10 0 0 0 0 14.72" /></svg></figure>
<h2 id="alert-dialog-media-title">Share this project?</h2>
<p id="alert-dialog-media-description">Anyone with the link will be able to view and edit this project.</p>
</header>
@@ -125,9 +152,7 @@ Use a destructive action button when the alert dialog confirms a destructive ope
<dialog id="alert-dialog-destructive" class="alert-dialog" aria-labelledby="alert-dialog-destructive-title" aria-describedby="alert-dialog-destructive-description">
<div>
<header>
<figure>
<svg class="lucide lucide-trash-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 11v6" /><path d="M14 11v6" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /><path d="M3 6h18" /><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /></svg>
</figure>
<figure><svg class="lucide lucide-trash-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 11v6" /><path d="M14 11v6" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /><path d="M3 6h18" /><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /></svg></figure>
<h2 id="alert-dialog-destructive-title">Delete this chat?</h2>
<p id="alert-dialog-destructive-description">This action cannot be undone. This will permanently delete the chat and remove it from your history.</p>
</header>
+35 -16
View File
@@ -2,13 +2,11 @@
<Preview class="w-full max-w-md">
<div class="grid items-start gap-4">
<div class="alert">
<svg class="lucide lucide-circle-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" /></svg>
<div class="alert"><svg class="lucide lucide-circle-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" /></svg>
<h2>Payment successful</h2>
<section>Your payment of $29.99 has been processed. A receipt has been sent to your email address.</section>
</div>
<div class="alert">
<svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg>
<div class="alert"><svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg>
<h2>New feature available</h2>
<section>We've added dark mode support. You can enable it in your account settings.</section>
</div>
@@ -17,11 +15,34 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Alert component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/alert.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your alert HTML">
Use `alert` for default styling. Add `data-variant="destructive"` for error states. Add a direct child `<footer>` for an inline-end action region.
```html
<div class="alert">
<svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg>
<div class="alert"><svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg>
<h2>Heads up!</h2>
<section>You can add components and dependencies to your app using the cli.</section>
<footer>
@@ -30,6 +51,9 @@ Use `alert` for default styling. Add `data-variant="destructive"` for error stat
</div>
```
</Step>
</Steps>
### HTML structure
<dl>
@@ -56,8 +80,7 @@ Use `alert` for default styling. Add `data-variant="destructive"` for error stat
A basic alert with an icon, title and description.
<Preview class="w-full max-w-md">
<div class="alert">
<svg class="lucide lucide-circle-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" /></svg>
<div class="alert"><svg class="lucide lucide-circle-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" /></svg>
<h2>Account updated successfully</h2>
<section>Your profile information has been saved. Changes will be reflected immediately.</section>
</div>
@@ -68,8 +91,7 @@ A basic alert with an icon, title and description.
Use `data-variant="destructive"` to create a destructive alert.
<Preview class="w-full max-w-md">
<div class="alert" data-variant="destructive">
<svg class="lucide lucide-circle-alert" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><line x1="12" x2="12" y1="8" y2="12" /><line x1="12" x2="12.01" y1="16" y2="16" /></svg>
<div class="alert" data-variant="destructive"><svg class="lucide lucide-circle-alert" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><line x1="12" x2="12" y1="8" y2="12" /><line x1="12" x2="12.01" y1="16" y2="16" /></svg>
<h2>Payment failed</h2>
<section>Your payment could not be processed. Please check your payment method and try again.</section>
</div>
@@ -94,8 +116,7 @@ Use `<footer>` to add a button or other action element to the alert.
You can customize the alert colors by adding custom classes such as `bg-amber-50 dark:bg-amber-950` to the alert.
<Preview class="w-full max-w-md">
<div class="alert border-amber-200 bg-amber-50 text-amber-900 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-50">
<svg class="lucide lucide-triangle-alert" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /><path d="M12 9v4" /><path d="M12 17h.01" /></svg>
<div class="alert border-amber-200 bg-amber-50 text-amber-900 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-50"><svg class="lucide lucide-triangle-alert" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /><path d="M12 9v4" /><path d="M12 17h.01" /></svg>
<h2>Your subscription will expire in 3 days.</h2>
<section>Renew now to avoid service interruption or upgrade to a paid plan to continue using the service.</section>
</div>
@@ -107,13 +128,11 @@ Add `dir="rtl"` to the alert or an ancestor.
<Preview class="w-full max-w-md">
<div class="grid items-start gap-4" dir="rtl">
<div class="alert">
<svg class="lucide lucide-circle-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" /></svg>
<div class="alert"><svg class="lucide lucide-circle-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" /></svg>
<h2>تم الدفع بنجاح</h2>
<section>تمت معالجة دفعتك البالغة 29.99 دولارًا. تم إرسال إيصال إلى عنوان بريدك الإلكتروني.</section>
</div>
<div class="alert">
<svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg>
<div class="alert"><svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg>
<h2>ميزة جديدة متاحة</h2>
<section>لقد أضفنا دعم الوضع الداكن. يمكنك تفعيله في إعدادات حسابك.</section>
</div>
+32 -15
View File
@@ -29,6 +29,30 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Avatar component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/avatar.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your avatar HTML">
Add `class="avatar"` to a small inline container. Add `data-size="sm"` or `data-size="lg"` when needed. Put the image first and a fallback `<span>` after it. Add `.avatar-badge` for a status badge or badge icon.
```html
@@ -38,6 +62,9 @@ Add `class="avatar"` to a small inline container. Add `data-size="sm"` or `data-
</span>
```
</Step>
</Steps>
### HTML structure
<dl>
@@ -90,9 +117,7 @@ Add `class="avatar"` to a small inline container. Add `data-size="sm"` or `data-
<span class="avatar">
<img src="https://github.com/pranathip.png" alt="@pranathip" />
<span>PP</span>
<span class="avatar-badge">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</span>
<span class="avatar-badge"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg></span>
</span>
</Preview>
@@ -124,9 +149,7 @@ Add `class="avatar"` to a small inline container. Add `data-size="sm"` or `data-
<span class="avatar"><img src="https://github.com/shadcn.png" alt="@shadcn" /><span>CN</span></span>
<span class="avatar"><img src="https://github.com/maxleiter.png" alt="@maxleiter" /><span>LR</span></span>
<span class="avatar"><img src="https://github.com/evilrabbit.png" alt="@evilrabbit" /><span>ER</span></span>
<span data-count aria-label="Additional avatars">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</span>
<span data-count aria-label="Additional avatars"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg></span>
</div>
</Preview>
@@ -149,15 +172,9 @@ Add `class="avatar"` to a small inline container. Add `data-size="sm"` or `data-
</span>
</div>
<div class="flex flex-wrap items-center gap-2">
<span class="avatar" data-size="sm">
<span>CN</span>
</span>
<span class="avatar">
<span>CN</span>
</span>
<span class="avatar" data-size="lg">
<span>CN</span>
</span>
<span class="avatar" data-size="sm"><span>CN</span></span>
<span class="avatar"><span>CN</span></span>
<span class="avatar" data-size="lg"><span>CN</span></span>
</div>
</div>
</Preview>
+30 -6
View File
@@ -11,6 +11,30 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Badge component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/badge.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your badge HTML">
Add `class="badge"` to an inline element. Add `data-variant` when the badge is not the default primary variant.
Inline SVG icons are spaced automatically by the badge gap.
@@ -23,6 +47,9 @@ Inline SVG icons are spaced automatically by the badge gap.
<span class="badge" data-variant="ghost">Ghost</span>
```
</Step>
</Steps>
Badges support right-to-left layouts through native text flow. Flip directional icons explicitly.
## Examples
@@ -47,8 +74,7 @@ Use `data-icon="inline-start"` or `data-icon="inline-end"` on the icon for icon-
<Preview>
<div class="flex flex-wrap gap-2">
<span class="badge">
<svg data-icon="inline-start" class="lucide lucide-badge-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" /><path d="m9 12 2 2 4-4" /></svg>
<span class="badge"><svg data-icon="inline-start" class="lucide lucide-badge-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" /><path d="m9 12 2 2 4-4" /></svg>
Verified
</span>
<span class="badge" data-variant="secondary">
@@ -64,8 +90,7 @@ Use an inline loading icon with `data-icon="inline-start"` or `data-icon="inline
<Preview>
<div class="flex flex-wrap gap-2">
<span class="badge" data-variant="destructive">
<svg aria-label="Loading" role="status" data-icon="inline-start" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<span class="badge" data-variant="destructive"><svg aria-label="Loading" role="status" data-icon="inline-start" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
Deleting
</span>
<span class="badge" data-variant="secondary">
@@ -104,8 +129,7 @@ Use an inline loading icon with `data-icon="inline-start"` or `data-icon="inline
<span class="badge" data-variant="secondary">ثانوي</span>
<span class="badge" data-variant="destructive">مدمر</span>
<span class="badge" data-variant="outline">مخطط</span>
<span class="badge">
<svg data-icon="inline-start" class="lucide lucide-badge-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" /><path d="m9 12 2 2 4-4" /></svg>
<span class="badge"><svg data-icon="inline-start" class="lucide lucide-badge-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" /><path d="m9 12 2 2 4-4" /></svg>
متحقق
</span>
<span class="badge" data-variant="secondary">
+44 -52
View File
@@ -4,13 +4,9 @@
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol>
<li><a href="#">Home</a></li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg></li>
<li><a href="#">Components</a></li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg></li>
<li><span aria-current="page">Breadcrumb</span></li>
</ol>
</nav>
@@ -18,20 +14,45 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Breadcrumb component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/breadcrumb.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your breadcrumb HTML">
Use a navigation landmark with an ordered list. Mark the current page with `aria-current="page"`.
```html
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol>
<li><a href="#">Home</a></li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" ...></svg>
</li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" ...></svg></li>
<li><span aria-current="page">Breadcrumb</span></li>
</ol>
</nav>
```
</Step>
</Steps>
## HTML structure
- `nav.breadcrumb` is the root landmark and should include `aria-label="Breadcrumb"`.
@@ -49,13 +70,9 @@ Use a navigation landmark with an ordered list. Mark the current page with `aria
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol>
<li><a href="#">Home</a></li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg></li>
<li><a href="#">Components</a></li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg></li>
<li><span aria-current="page">Breadcrumb</span></li>
</ol>
</nav>
@@ -67,13 +84,9 @@ Use a navigation landmark with an ordered list. Mark the current page with `aria
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol>
<li><a href="#">Home</a></li>
<li aria-hidden="true">
<svg class="lucide lucide-dot" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12.1" cy="12.1" r="1" /></svg>
</li>
<li aria-hidden="true"><svg class="lucide lucide-dot" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12.1" cy="12.1" r="1" /></svg></li>
<li><a href="#">Components</a></li>
<li aria-hidden="true">
<svg class="lucide lucide-dot" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12.1" cy="12.1" r="1" /></svg>
</li>
<li aria-hidden="true"><svg class="lucide lucide-dot" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12.1" cy="12.1" r="1" /></svg></li>
<li><span aria-current="page">Breadcrumb</span></li>
</ol>
</nav>
@@ -85,13 +98,10 @@ Use a navigation landmark with an ordered list. Mark the current page with `aria
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol>
<li><a href="#">Home</a></li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg></li>
<li>
<div id="breadcrumb-dropdown" class="dropdown-menu">
<button type="button" id="breadcrumb-dropdown-trigger" class="btn" data-variant="ghost" data-size="icon-sm" aria-haspopup="menu" aria-controls="breadcrumb-dropdown-menu" aria-expanded="false">
<svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg>
<button type="button" id="breadcrumb-dropdown-trigger" class="btn" data-variant="ghost" data-size="icon-sm" aria-haspopup="menu" aria-controls="breadcrumb-dropdown-menu" aria-expanded="false"><svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg>
<span class="sr-only">Toggle menu</span>
</button>
<div id="breadcrumb-dropdown-popover" data-popover aria-hidden="true">
@@ -105,13 +115,9 @@ Use a navigation landmark with an ordered list. Mark the current page with `aria
</div>
</div>
</li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg></li>
<li><a href="#">Components</a></li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg></li>
<li><span aria-current="page">Breadcrumb</span></li>
</ol>
</nav>
@@ -123,21 +129,11 @@ Use a navigation landmark with an ordered list. Mark the current page with `aria
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol>
<li><a href="#">Home</a></li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</li>
<li>
<span aria-hidden="true">
<svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg>
</span>
</li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg></li>
<li> <span aria-hidden="true"><svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg></span></li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg></li>
<li><a href="#">Components</a></li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg></li>
<li><span aria-current="page">Breadcrumb</span></li>
</ol>
</nav>
@@ -149,13 +145,9 @@ Use a navigation landmark with an ordered list. Mark the current page with `aria
<nav class="breadcrumb" aria-label="Breadcrumb" dir="rtl">
<ol>
<li><a href="#">الرئيسية</a></li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg></li>
<li><a href="#">المكونات</a></li>
<li aria-hidden="true">
<svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</li>
<li aria-hidden="true"><svg data-rtl-flip class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg></li>
<li><span aria-current="page">مسار التنقل</span></li>
</ol>
</nav>
+62 -83
View File
@@ -2,9 +2,7 @@
<Preview>
<div class="flex w-fit items-stretch gap-2">
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Go Back">
<svg class="lucide lucide-arrow-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Go Back"><svg class="lucide lucide-arrow-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg></button>
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline">Archive</button>
<button type="button" class="btn" data-variant="outline">Report</button>
@@ -12,35 +10,27 @@
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline">Snooze</button>
<div id="dropdown-menu-277805" class="dropdown-menu">
<button type="button" id="dropdown-menu-277805-trigger" aria-label="More archive options" aria-haspopup="menu" aria-controls="dropdown-menu-277805-menu" aria-expanded="false" class="btn" data-variant="outline" data-size="icon">
<svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg>
</button>
<button type="button" id="dropdown-menu-277805-trigger" aria-label="More archive options" aria-haspopup="menu" aria-controls="dropdown-menu-277805-menu" aria-expanded="false" class="btn" data-variant="outline" data-size="icon"><svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg></button>
<div id="dropdown-menu-277805-popover" data-popover aria-hidden="true" data-align="end">
<div role="menu" id="dropdown-menu-277805-menu" aria-labelledby="dropdown-menu-277805-trigger">
<div role="menuitem">
<svg class="lucide lucide-mail-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 13V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h8" /><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" /><path d="m16 19 2 2 4-4" /></svg>
<div role="menuitem"><svg class="lucide lucide-mail-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 13V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h8" /><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" /><path d="m16 19 2 2 4-4" /></svg>
Mark as Read
</div>
<div role="menuitem">
<svg class="lucide lucide-archive" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="5" x="2" y="3" rx="1" /><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8" /><path d="M10 12h4" /></svg>
<div role="menuitem"><svg class="lucide lucide-archive" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="5" x="2" y="3" rx="1" /><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8" /><path d="M10 12h4" /></svg>
Archive
</div>
<hr role="separator" />
<div role="menuitem">
<svg class="lucide lucide-clock" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 6v6l4 2" /></svg>
<div role="menuitem"><svg class="lucide lucide-clock" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 6v6l4 2" /></svg>
Snooze
</div>
<div role="menuitem">
<svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" /></svg>
<div role="menuitem"><svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" /></svg>
Add to Calendar
</div>
<div role="menuitem">
<svg class="lucide lucide-list-filter-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5H2" /><path d="M6 12h12" /><path d="M9 19h6" /><path d="M16 5h6" /><path d="M19 8V2" /></svg>
<div role="menuitem"><svg class="lucide lucide-list-filter-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5H2" /><path d="M6 12h12" /><path d="M9 19h6" /><path d="M16 5h6" /><path d="M19 8V2" /></svg>
Add to List
</div>
<hr role="separator" />
<div role="menuitem" class="text-destructive hover:bg-destructive/10 dark:hover:bg-destructive/20 focus:bg-destructive/10 dark:focus:bg-destructive/20 focus:text-destructive [&_svg]:!text-destructive">
<svg class="lucide lucide-trash-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 11v6" /><path d="M14 11v6" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /><path d="M3 6h18" /><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /></svg>
<div role="menuitem" class="text-destructive hover:bg-destructive/10 dark:hover:bg-destructive/20 focus:bg-destructive/10 dark:focus:bg-destructive/20 focus:text-destructive [&_svg]:!text-destructive"><svg class="lucide lucide-trash-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 11v6" /><path d="M14 11v6" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /><path d="M3 6h18" /><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /></svg>
Trash
</div>
</div>
@@ -52,6 +42,33 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, the component CSS files it composes, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/button-group.css";
@import "basecoat-css/components/button.css";
@import "basecoat-css/styles/vega.css";
```
Button Group composes Button styles for the child controls.
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your button group HTML">
Wrap related controls in a `button-group`.
```html
@@ -61,6 +78,9 @@ Wrap related controls in a `button-group`.
</div>
```
</Step>
</Steps>
Use `data-orientation="vertical"` to stack items. Use `<hr role="separator" />` between items when you need a visible divider, such as a split action. Use direct child `<span>`, `<label>`, or `<output>` elements for non-interactive text segments. Direct child `<div>` elements are left unstyled for custom layouts.
## Examples
@@ -71,12 +91,8 @@ Use `data-orientation="vertical"` to stack buttons vertically.
<Preview>
<div role="group" aria-label="Media controls" class="button-group h-fit" data-orientation="vertical">
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Zoom in">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Zoom out">
<svg class="lucide lucide-minus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Zoom in"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg></button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Zoom out"><svg class="lucide lucide-minus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /></svg></button>
</div>
</Preview>
@@ -88,25 +104,19 @@ Use `data-orientation="vertical"` to stack buttons vertically.
<button type="button" class="btn" data-variant="outline" data-size="sm">Small</button>
<button type="button" class="btn" data-variant="outline" data-size="sm">Button</button>
<button type="button" class="btn" data-variant="outline" data-size="sm">Group</button>
<button type="button" class="btn" data-variant="outline" data-size="icon-sm" aria-label="Add small item">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon-sm" aria-label="Add small item"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg></button>
</div>
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline">Default</button>
<button type="button" class="btn" data-variant="outline">Button</button>
<button type="button" class="btn" data-variant="outline">Group</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Add item">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Add item"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg></button>
</div>
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline" data-size="lg">Large</button>
<button type="button" class="btn" data-variant="outline" data-size="lg">Button</button>
<button type="button" class="btn" data-variant="outline" data-size="lg">Group</button>
<button type="button" class="btn" data-variant="outline" data-size="icon-lg" aria-label="Add large item">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon-lg" aria-label="Add large item"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg></button>
</div>
</div>
</Preview>
@@ -125,12 +135,8 @@ Nest `button-group` components to keep controls joined within each group while a
<button type="button" class="btn" data-variant="outline" data-size="sm">5</button>
</div>
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline" data-size="icon-sm" aria-label="Previous page">
<svg class="lucide lucide-arrow-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon-sm" aria-label="Next page">
<svg class="lucide lucide-arrow-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="m12 5 7 7-7 7" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon-sm" aria-label="Previous page"><svg class="lucide lucide-arrow-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg></button>
<button type="button" class="btn" data-variant="outline" data-size="icon-sm" aria-label="Next page"><svg class="lucide lucide-arrow-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="m12 5 7 7-7 7" /></svg></button>
</div>
</div>
</Preview>
@@ -155,9 +161,7 @@ Use a separator to create a split action.
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="secondary">Button</button>
<hr role="separator" />
<button type="button" class="btn" data-variant="secondary" data-size="icon" aria-label="Add">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</button>
<button type="button" class="btn" data-variant="secondary" data-size="icon" aria-label="Add"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg></button>
</div>
</Preview>
@@ -166,9 +170,7 @@ Use a separator to create a split action.
<Preview>
<div role="group" aria-label="Search" class="button-group">
<input type="text" class="input" placeholder="Search..." />
<button type="button" class="btn" data-variant="outline" aria-label="Search">
<svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" aria-label="Search"><svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg></button>
</div>
</Preview>
@@ -177,17 +179,13 @@ Use a separator to create a split action.
<Preview>
<div role="group" class="button-group">
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Add attachment">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Add attachment"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg></button>
</div>
<div role="group" class="button-group">
<div class="input-group">
<input type="text" placeholder="Send a message..." />
<div role="group" data-align="inline-end">
<button type="button" class="btn" data-variant="ghost" data-size="icon-xs" aria-label="Voice mode" aria-pressed="false">
<svg class="lucide lucide-audio-lines" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 10v3" /><path d="M6 6v11" /><path d="M10 3v18" /><path d="M14 8v7" /><path d="M18 5v13" /><path d="M22 10v3" /></svg>
</button>
<button type="button" class="btn" data-variant="ghost" data-size="icon-xs" aria-label="Voice mode" aria-pressed="false"><svg class="lucide lucide-audio-lines" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 10v3" /><path d="M6 6v11" /><path d="M10 3v18" /><path d="M14 8v7" /><path d="M18 5v13" /><path d="M22 10v3" /></svg></button>
</div>
</div>
</div>
@@ -199,40 +197,30 @@ Use a separator to create a split action.
<Preview>
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline">Follow</button>
<div id="dropdown-menu-609880" class="dropdown-menu">
<button type="button" id="dropdown-menu-609880-trigger" aria-label="More follow options" aria-haspopup="menu" aria-controls="dropdown-menu-609880-menu" aria-expanded="false" class="btn" data-variant="outline" data-size="icon">
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</button>
<button type="button" id="dropdown-menu-609880-trigger" aria-label="More follow options" aria-haspopup="menu" aria-controls="dropdown-menu-609880-menu" aria-expanded="false" class="btn" data-variant="outline" data-size="icon"><svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg></button>
<div id="dropdown-menu-609880-popover" data-popover aria-hidden="true" data-align="end">
<div role="menu" id="dropdown-menu-609880-menu" aria-labelledby="dropdown-menu-609880-trigger">
<div role="menuitem">
<svg class="lucide lucide-volume-off" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 9a5 5 0 0 1 .95 2.293" /><path d="M19.364 5.636a9 9 0 0 1 1.889 9.96" /><path d="m2 2 20 20" /><path d="m7 7-.587.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298V11" /><path d="M9.828 4.172A.686.686 0 0 1 11 4.657v.686" /></svg>
<div role="menuitem"><svg class="lucide lucide-volume-off" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 9a5 5 0 0 1 .95 2.293" /><path d="M19.364 5.636a9 9 0 0 1 1.889 9.96" /><path d="m2 2 20 20" /><path d="m7 7-.587.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298V11" /><path d="M9.828 4.172A.686.686 0 0 1 11 4.657v.686" /></svg>
Mute Conversation
</div>
<div role="menuitem">
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
<div role="menuitem"><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
Mark as Read
</div>
<div role="menuitem">
<svg class="lucide lucide-triangle-alert" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /><path d="M12 9v4" /><path d="M12 17h.01" /></svg>
<div role="menuitem"><svg class="lucide lucide-triangle-alert" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /><path d="M12 9v4" /><path d="M12 17h.01" /></svg>
Report Conversation
</div>
<div role="menuitem">
<svg class="lucide lucide-user-round-x" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 21a8 8 0 0 1 11.873-7" /><circle cx="10" cy="8" r="5" /><path d="m17 17 5 5" /><path d="m22 17-5 5" /></svg>
<div role="menuitem"><svg class="lucide lucide-user-round-x" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 21a8 8 0 0 1 11.873-7" /><circle cx="10" cy="8" r="5" /><path d="m17 17 5 5" /><path d="m22 17-5 5" /></svg>
Block User
</div>
<div role="menuitem">
<svg class="lucide lucide-share" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v13" /><path d="m16 6-4-4-4 4" /><path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" /></svg>
<div role="menuitem"><svg class="lucide lucide-share" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v13" /><path d="m16 6-4-4-4 4" /><path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" /></svg>
Share Conversation
</div>
<div role="menuitem">
<svg class="lucide lucide-copy" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2" /><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" /></svg>
<div role="menuitem"><svg class="lucide lucide-copy" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2" /><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" /></svg>
Copy Conversation
</div>
<hr role="separator" />
<div role="menuitem" class="text-destructive hover:bg-destructive/10 dark:hover:bg-destructive/20 focus:bg-destructive/10 dark:focus:bg-destructive/20 focus:text-destructive [&_svg]:!text-destructive">
<svg class="lucide lucide-trash-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 11v6" /><path d="M14 11v6" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /><path d="M3 6h18" /><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /></svg>
<div role="menuitem" class="text-destructive hover:bg-destructive/10 dark:hover:bg-destructive/20 focus:bg-destructive/10 dark:focus:bg-destructive/20 focus:text-destructive [&_svg]:!text-destructive"><svg class="lucide lucide-trash-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 11v6" /><path d="M14 11v6" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /><path d="M3 6h18" /><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /></svg>
Delete Conversation
</div>
</div>
@@ -271,9 +259,7 @@ Use a separator to create a split action.
</div>
<input type="text" class="input" placeholder="10.00" />
</div>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Submit amount">
<svg class="lucide lucide-arrow-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="m12 5 7 7-7 7" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Submit amount"><svg class="lucide lucide-arrow-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="m12 5 7 7-7 7" /></svg></button>
</div>
</Preview>
@@ -281,14 +267,11 @@ Use a separator to create a split action.
<Preview>
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline">
<svg class="lucide lucide-bot" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 8V4H8" /><rect width="16" height="12" x="4" y="8" rx="2" /><path d="M2 14h2" /><path d="M20 14h2" /><path d="M15 13v2" /><path d="M9 13v2" /></svg>
<button type="button" class="btn" data-variant="outline"><svg class="lucide lucide-bot" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 8V4H8" /><rect width="16" height="12" x="4" y="8" rx="2" /><path d="M2 14h2" /><path d="M20 14h2" /><path d="M15 13v2" /><path d="M9 13v2" /></svg>
Copilot
</button>
<div id="popover-788465" class="popover">
<button id="popover-788465-trigger" type="button" aria-label="Open Popover" aria-expanded="false" aria-controls="popover-788465-popover" class="btn" data-variant="outline" data-size="icon">
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</button>
<button id="popover-788465-trigger" type="button" aria-label="Open Popover" aria-expanded="false" aria-controls="popover-788465-popover" class="btn" data-variant="outline" data-size="icon"><svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg></button>
<div id="popover-788465-popover" data-popover aria-hidden="true" class="w-72 text-sm" data-align="end">
<div>
<p class="font-medium">Start a new task with Copilot</p>
@@ -309,9 +292,7 @@ Add `dir="rtl"` to the group or an ancestor. Flip directional icons explicitly.
<div dir="rtl">
<div role="group" aria-label="إجراءات الرسالة" class="button-group">
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="رجوع">
<svg class="rtl:rotate-180 lucide lucide-arrow-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="رجوع"><svg class="rtl:rotate-180 lucide lucide-arrow-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg></button>
</div>
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline">أرشفة</button>
@@ -319,9 +300,7 @@ Add `dir="rtl"` to the group or an ancestor. Flip directional icons explicitly.
</div>
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline">تأجيل</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="المزيد من الخيارات">
<svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="المزيد من الخيارات"><svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg></button>
</div>
</div>
</div>
+49 -53
View File
@@ -3,23 +3,46 @@
<Preview>
<div class="flex flex-wrap items-center gap-2">
<button type="button" class="btn" data-variant="outline">Button</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Submit">
<svg class="lucide lucide-arrow-up" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="m5 12 7-7 7 7" /><path d="M12 19V5" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Submit"><svg class="lucide lucide-arrow-up" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m5 12 7-7 7 7" /><path d="M12 19V5" /></svg></button>
</div>
</Preview>
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Button component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/button.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your button HTML">
```html
<button type="button" class="btn">Primary</button>
<button type="button" class="btn" data-variant="outline">Outline</button>
<button type="button" class="btn" data-variant="secondary" data-size="sm">Small secondary</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Settings">
<svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Settings"><svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg></button>
```
</Step>
</Steps>
Add `class="btn"` to a `<button>` or `<a>`. Add `data-variant` and `data-size` when needed. Add `data-icon="inline-start"` or `data-icon="inline-end"` to inline icons when a text button needs icon-aware spacing.
#### HTML structure
@@ -72,21 +95,13 @@ Use `data-size` to change the size of the button.
<Preview>
<div class="flex flex-wrap items-center gap-2">
<button type="button" class="btn" data-variant="outline" data-size="xs">Extra Small</button>
<button type="button" class="btn" data-variant="outline" data-size="icon-xs" aria-label="Submit">
<svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon-xs" aria-label="Submit"><svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg></button>
<button type="button" class="btn" data-variant="outline" data-size="sm">Small</button>
<button type="button" class="btn" data-variant="outline" data-size="icon-sm" aria-label="Submit">
<svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon-sm" aria-label="Submit"><svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg></button>
<button type="button" class="btn" data-variant="outline">Default</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Submit">
<svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Submit"><svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg></button>
<button type="button" class="btn" data-variant="outline" data-size="lg">Large</button>
<button type="button" class="btn" data-variant="outline" data-size="icon-lg" aria-label="Submit">
<svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon-lg" aria-label="Submit"><svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg></button>
</div>
</Preview>
@@ -129,9 +144,7 @@ Use `data-size` to change the size of the button.
### Icon
<Preview>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Open">
<svg class="lucide lucide-circle-fading-arrow-up" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M12 2a10 10 0 0 1 7.38 16.75" /><path d="m16 12-4-4-4 4" /><path d="M12 16V8" /><path d="M2.5 8.875a10 10 0 0 0-.5 3" /><path d="M2.83 16a10 10 0 0 0 2.43 3.4" /><path d="M4.636 5.235a10 10 0 0 1 .891-.857" /><path d="M8.644 21.42a10 10 0 0 0 7.631-.38" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Open"><svg class="lucide lucide-circle-fading-arrow-up" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a10 10 0 0 1 7.38 16.75" /><path d="m16 12-4-4-4 4" /><path d="M12 16V8" /><path d="M2.5 8.875a10 10 0 0 0-.5 3" /><path d="M2.83 16a10 10 0 0 0 2.43 3.4" /><path d="M4.636 5.235a10 10 0 0 1 .891-.857" /><path d="M8.644 21.42a10 10 0 0 0 7.631-.38" /></svg></button>
</Preview>
### With icon
@@ -139,8 +152,7 @@ Use `data-size` to change the size of the button.
Use `data-icon="inline-start"` or `data-icon="inline-end"` on inline icons to match upstream icon-aware spacing.
<Preview>
<button type="button" class="btn" data-variant="outline" data-size="sm">
<svg data-icon="inline-start" class="lucide lucide-git-branch" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M15 6a9 9 0 0 0-9 9V3" /><circle cx="18" cy="6" r="3" /><circle cx="6" cy="18" r="3" /></svg>
<button type="button" class="btn" data-variant="outline" data-size="sm"><svg data-icon="inline-start" class="lucide lucide-git-branch" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 6a9 9 0 0 0-9 9V3" /><circle cx="18" cy="6" r="3" /><circle cx="6" cy="18" r="3" /></svg>
New Branch
</button>
</Preview>
@@ -150,22 +162,19 @@ Use `data-icon="inline-start"` or `data-icon="inline-end"` on inline icons to ma
Use the `rounded-full` class to make the button rounded.
<Preview>
<button type="button" class="btn rounded-full" data-variant="outline" data-size="icon" aria-label="Scroll up">
<svg class="lucide lucide-arrow-up" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="m5 12 7-7 7 7" /><path d="M12 19V5" /></svg>
</button>
<button type="button" class="btn rounded-full" data-variant="outline" data-size="icon" aria-label="Scroll up"><svg class="lucide lucide-arrow-up" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m5 12 7-7 7 7" /><path d="M12 19V5" /></svg></button>
</Preview>
### Spinner
<Preview>
<div class="flex flex-wrap items-center gap-2">
<button type="button" class="btn" disabled>
<svg data-icon="inline-start" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<button type="button" class="btn" disabled><svg data-icon="inline-start" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
Generating
</button>
<button type="button" class="btn" data-variant="secondary" disabled>
Downloading
<svg data-icon="inline-end" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<svg data-icon="inline-end" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
</button>
</div>
</Preview>
@@ -176,9 +185,7 @@ To group related buttons, use the [Button Group](/components/button-group/) comp
<Preview>
<div class="flex w-fit items-stretch gap-2">
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Go back">
<svg class="lucide lucide-arrow-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Go back"><svg class="lucide lucide-arrow-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg></button>
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline">Archive</button>
<button type="button" class="btn" data-variant="outline">Report</button>
@@ -186,35 +193,27 @@ To group related buttons, use the [Button Group](/components/button-group/) comp
<div role="group" class="button-group">
<button type="button" class="btn" data-variant="outline">Snooze</button>
<div id="button-docs-actions" class="dropdown-menu">
<button type="button" id="button-docs-actions-trigger" aria-label="More options" aria-haspopup="menu" aria-controls="button-docs-actions-menu" aria-expanded="false" class="btn" data-variant="outline" data-size="icon">
<svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg>
</button>
<button type="button" id="button-docs-actions-trigger" aria-label="More options" aria-haspopup="menu" aria-controls="button-docs-actions-menu" aria-expanded="false" class="btn" data-variant="outline" data-size="icon"><svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg></button>
<div id="button-docs-actions-popover" data-popover aria-hidden="true" data-align="end">
<div role="menu" id="button-docs-actions-menu" aria-labelledby="button-docs-actions-trigger">
<div role="menuitem">
<svg class="lucide lucide-mail-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M22 13V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h8" /><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" /><path d="m16 19 2 2 4-4" /></svg>
<div role="menuitem"><svg class="lucide lucide-mail-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 13V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h8" /><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" /><path d="m16 19 2 2 4-4" /></svg>
Mark as Read
</div>
<div role="menuitem">
<svg class="lucide lucide-archive" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><rect width="20" height="5" x="2" y="3" rx="1" /><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8" /><path d="M10 12h4" /></svg>
<div role="menuitem"><svg class="lucide lucide-archive" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="5" x="2" y="3" rx="1" /><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8" /><path d="M10 12h4" /></svg>
Archive
</div>
<hr role="separator" />
<div role="menuitem">
<svg class="lucide lucide-clock" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><circle cx="12" cy="12" r="10" /><path d="M12 6v6l4 2" /></svg>
<div role="menuitem"><svg class="lucide lucide-clock" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 6v6l4 2" /></svg>
Snooze
</div>
<div role="menuitem">
<svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" /></svg>
<div role="menuitem"><svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" /></svg>
Add to Calendar
</div>
<div role="menuitem">
<svg class="lucide lucide-list-filter-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M12 5H2" /><path d="M6 12h12" /><path d="M9 19h6" /><path d="M16 5h6" /><path d="M19 8V2" /></svg>
<div role="menuitem"><svg class="lucide lucide-list-filter-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5H2" /><path d="M6 12h12" /><path d="M9 19h6" /><path d="M16 5h6" /><path d="M19 8V2" /></svg>
Add to List
</div>
<hr role="separator" />
<div role="menuitem" class="text-destructive hover:bg-destructive/10 dark:hover:bg-destructive/20 focus:bg-destructive/10 dark:focus:bg-destructive/20 focus:text-destructive [&_svg]:!text-destructive">
<svg class="lucide lucide-trash-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M10 11v6" /><path d="M14 11v6" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /><path d="M3 6h18" /><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /></svg>
<div role="menuitem" class="text-destructive hover:bg-destructive/10 dark:hover:bg-destructive/20 focus:bg-destructive/10 dark:focus:bg-destructive/20 focus:text-destructive [&_svg]:!text-destructive"><svg class="lucide lucide-trash-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 11v6" /><path d="M14 11v6" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /><path d="M3 6h18" /><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /></svg>
Trash
</div>
</div>
@@ -234,13 +233,10 @@ Add `dir="rtl"` to the button or an ancestor. Flip directional icons explicitly.
<button type="button" class="btn" data-variant="destructive">حذف</button>
<button type="button" class="btn" data-variant="outline">
إرسال
<svg data-icon="inline-end" class="rtl:rotate-180 lucide lucide-arrow-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M5 12h14" /><path d="m12 5 7 7-7 7" /></svg>
<svg data-icon="inline-end" class="rtl:rotate-180 lucide lucide-arrow-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="m12 5 7 7-7 7" /></svg>
</button>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Add">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</button>
<button type="button" class="btn" data-variant="secondary" disabled>
<svg data-icon="inline-start" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<button type="button" class="btn" data-variant="outline" data-size="icon" aria-label="Add"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg></button>
<button type="button" class="btn" data-variant="secondary" disabled><svg data-icon="inline-start" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
جاري التحميل
</button>
</div>
+29 -6
View File
@@ -33,6 +33,30 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Card component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/card.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your card HTML">
```html
<div class="card">
<header>
@@ -40,15 +64,16 @@
<p>Card Description</p>
<div class="card-action">Card Action</div>
</header>
<section>
<p>Card Content</p>
</section>
<section> <p>Card Content</p></section>
<footer>
<p>Card Footer</p>
</footer>
</div>
```
</Step>
</Steps>
## HTML structure
<dl>
@@ -91,9 +116,7 @@ Use `data-size="sm"` to set the size of the card to small. The small size varian
<button type="button" class="btn" data-size="sm" data-variant="outline">Action</button>
</div>
</header>
<section>
<p>The card component supports a size attribute that can be set to <code>sm</code> for a more compact appearance.</p>
</section>
<section> <p>The card component supports a size attribute that can be set to <code>sm</code> for a more compact appearance.</p></section>
</div>
</Preview>
+65 -9
View File
@@ -1,4 +1,6 @@
import chartExamplesUrl from "../site/chart-examples.js?url"
import basecoatRuntimeSource from "../../../src/js/basecoat.js?raw"
import chartRuntimeSource from "../../../src/js/chart.js?raw"
import chartExamplesSource from "../site/chart-examples.js?raw"
# Chart
@@ -12,19 +14,49 @@ Use Chart.js with Basecoat defaults for themed colors, external tooltips, and op
<canvas id="chart-example-overview" aria-label="Visitors by device"></canvas>
</Preview>
Chart is an optional JavaScript helper. Load Chart.js first, then `basecoat.js`, then `chart.js`.
## Usage
```html
<script src="https://cdn.jsdelivr.net/npm/chart.js/dist/chart.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/chart.min.js" defer></script>
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
## Usage
Or import only the base CSS, Chart component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/chart.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Include JavaScript">
Copy or serve Chart.js, the Basecoat runtime, and Chart script.
```html
<script src="/assets/js/chart.umd.min.js"></script>
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/chart.min.js" defer></script>
```
Chart is not included in the full Basecoat JavaScript bundle.
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your chart HTML">
```html
<canvas id="visitors-chart" aria-label="Monthly visitors"></canvas>
<script>
document.addEventListener("DOMContentLoaded", () => {
window.basecoat.chart("#visitors-chart", {
@@ -47,6 +79,9 @@ Chart is an optional JavaScript helper. Load Chart.js first, then `basecoat.js`,
</script>
```
</Step>
</Steps>
`basecoat.chart()` targets the `<canvas>` directly and creates Basecoat's internal `.chart` container for Chart.js sizing. You do not need to add a wrapper or class in your HTML.
Charts default to `aspect-video`. Use a height, `min-h-*`, or `aspect-*` utility on a parent element when you need a different measuring box.
@@ -186,7 +221,28 @@ window.basecoat.chart("#custom-chart", {
</Preview>
<script is:inline src="https://cdn.jsdelivr.net/npm/chart.js/dist/chart.umd.min.js"></script>
<script type="module" src={chartExamplesUrl}></script>
<script is:inline>{`
(() => {
const initChartPage = () => {
if (!window.Chart) {
requestAnimationFrame(initChartPage)
return
}
if (!window.basecoat) {
${basecoatRuntimeSource}
}
if (!window.basecoat.chart) {
${chartRuntimeSource}
}
${chartExamplesSource}
}
initChartPage()
})()
`}</script>
## API
+27
View File
@@ -31,12 +31,39 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Checkbox component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/checkbox.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your checkbox HTML">
Add `class="input"` to checkbox inputs. Pair it with [Field](/components/field) and a native `<label>` for layout and labeling.
```html
<input type="checkbox" class="input" />
```
</Step>
</Steps>
## Examples
### Basic
+41 -17
View File
@@ -2,8 +2,7 @@
<Preview>
<div id="framework-combobox" class="combobox">
<input type="text" role="combobox" placeholder="Select a framework" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="framework-combobox-listbox" />
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<input type="text" role="combobox" placeholder="Select a framework" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="framework-combobox-listbox" /><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<div id="framework-combobox-popover" data-popover aria-hidden="true">
<div role="listbox" id="framework-combobox-listbox" aria-orientation="vertical" data-empty="No items found.">
<div role="option" data-value="Next.js">Next.js</div>
@@ -24,13 +23,44 @@
</Callout>
<Steps>
<Step title="Include the JavaScript files">
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Combobox component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/combobox.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Include JavaScript">
Copy or serve the full Basecoat JavaScript bundle.
```html
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/combobox.min.js" defer></script>
<script src="/assets/js/all.min.js" defer></script>
```
Or copy or serve the Basecoat runtime and Combobox script.
```html
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/combobox.min.js" defer></script>
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your combobox HTML">
@@ -38,8 +68,7 @@ Combobox is input-first. The visible input filters the list; the hidden input st
```html
<div id="framework-combobox" class="combobox w-[240px]">
<input type="text" role="combobox" placeholder="Select a framework" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="framework-combobox-listbox" />
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<input type="text" role="combobox" placeholder="Select a framework" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="framework-combobox-listbox" /><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<div id="framework-combobox-popover" data-popover aria-hidden="true">
<div role="listbox" id="framework-combobox-listbox" aria-orientation="vertical" data-empty="No items found.">
<div role="option" data-value="Next.js">Next.js</div>
@@ -140,8 +169,7 @@ Combobox is input-first. The visible input filters the list; the hidden input st
<Preview>
<div id="timezone-combobox" class="combobox">
<input type="text" role="combobox" placeholder="Select a timezone" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="timezone-combobox-listbox" />
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<input type="text" role="combobox" placeholder="Select a timezone" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="timezone-combobox-listbox" /><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<div id="timezone-combobox-popover" data-popover aria-hidden="true">
<div role="listbox" id="timezone-combobox-listbox" class="scrollbar-sm" aria-orientation="vertical" data-empty="No timezones found.">
<div role="group" aria-labelledby="timezone-americas">
@@ -183,8 +211,7 @@ Combobox is input-first. The visible input filters the list; the hidden input st
<Preview>
<div id="country-combobox" class="combobox">
<input type="text" role="combobox" placeholder="Search countries" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="country-combobox-listbox" />
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<input type="text" role="combobox" placeholder="Search countries" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="country-combobox-listbox" /><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<div id="country-combobox-popover" data-popover aria-hidden="true">
<div role="listbox" id="country-combobox-listbox" aria-orientation="vertical" data-empty="No items found.">
<div role="option" data-value="argentina" data-label="Argentina" data-filter="Argentina South America"><span class="flex flex-col"><span>Argentina</span><span class="text-muted-foreground text-xs">South America</span></span></div>
@@ -202,8 +229,7 @@ Combobox is input-first. The visible input filters the list; the hidden input st
<div role="group" class="field" data-invalid="true">
<label for="invalid-combobox-input">Framework</label>
<div id="invalid-combobox" class="combobox">
<input type="text" role="combobox" placeholder="Select a framework" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="invalid-combobox-listbox" id="invalid-combobox-input" aria-invalid="true" />
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<input type="text" role="combobox" placeholder="Select a framework" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="invalid-combobox-listbox" id="invalid-combobox-input" aria-invalid="true" /><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<div id="invalid-combobox-popover" data-popover aria-hidden="true">
<div role="listbox" id="invalid-combobox-listbox" aria-orientation="vertical" data-empty="No items found.">
<div role="option" data-value="Next.js">Next.js</div>
@@ -223,8 +249,7 @@ Combobox is input-first. The visible input filters the list; the hidden input st
<Preview>
<div id="disabled-combobox" class="combobox">
<input type="text" role="combobox" placeholder="Select a framework" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="disabled-combobox-listbox" disabled />
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<input type="text" role="combobox" placeholder="Select a framework" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="disabled-combobox-listbox" disabled /><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<div id="disabled-combobox-popover" data-popover aria-hidden="true">
<div role="listbox" id="disabled-combobox-listbox" aria-orientation="vertical">
<div role="option" data-value="Next.js">Next.js</div>
@@ -240,8 +265,7 @@ Auto highlight makes the first visible option active when the list opens or filt
<Preview>
<div id="auto-highlight-combobox" class="combobox" data-auto-highlight="true">
<input type="text" role="combobox" placeholder="Select a framework" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="auto-highlight-combobox-listbox" />
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<input type="text" role="combobox" placeholder="Select a framework" autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="auto-highlight-combobox-listbox" /><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="combobox-trigger-icon"><path d="m6 9 6 6 6-6" /></svg>
<div id="auto-highlight-combobox-popover" data-popover aria-hidden="true">
<div role="listbox" id="auto-highlight-combobox-listbox" aria-orientation="vertical" data-empty="No items found.">
<div role="option" data-value="Next.js">Next.js</div>
+68 -71
View File
@@ -2,41 +2,34 @@
<Preview class="w-full max-w-sm">
<div id="demo-command-standalone" class="command rounded-lg border" aria-label="Command menu">
<header>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<header><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<input type="text" id="demo-command-standalone-input" placeholder="Type a command or search..." autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" role="combobox" aria-expanded="true" aria-controls="demo-command-standalone-menu" />
</header>
<div role="menu" id="demo-command-standalone-menu" aria-orientation="vertical" data-empty="No results found.">
<div role="group" aria-labelledby="suggestions">
<span role="heading" id="suggestions">Suggestions</span>
<div role="menuitem" data-filter="Calendar" data-keywords="date event schedule">
<svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" /></svg>
<div role="menuitem" data-filter="Calendar" data-keywords="date event schedule"><svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" /></svg>
<span>Calendar</span>
</div>
<div role="menuitem" data-filter="Search Emoji" data-keywords="emoji smile reaction">
<svg class="lucide lucide-smile" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M8 14s1.5 2 4 2 4-2 4-2" /><line x1="9" x2="9.01" y1="9" y2="9" /><line x1="15" x2="15.01" y1="9" y2="9" /></svg>
<div role="menuitem" data-filter="Search Emoji" data-keywords="emoji smile reaction"><svg class="lucide lucide-smile" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M8 14s1.5 2 4 2 4-2 4-2" /><line x1="9" x2="9.01" y1="9" y2="9" /><line x1="15" x2="15.01" y1="9" y2="9" /></svg>
<span>Search Emoji</span>
</div>
<div role="menuitem" aria-disabled="true">
<svg class="lucide lucide-calculator" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="16" height="20" x="4" y="2" rx="2" /><line x1="8" x2="16" y1="6" y2="6" /><line x1="16" x2="16" y1="14" y2="18" /><path d="M16 10h.01" /><path d="M12 10h.01" /><path d="M8 10h.01" /><path d="M12 14h.01" /><path d="M8 14h.01" /><path d="M12 18h.01" /><path d="M8 18h.01" /></svg>
<div role="menuitem" aria-disabled="true"><svg class="lucide lucide-calculator" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="16" height="20" x="4" y="2" rx="2" /><line x1="8" x2="16" y1="6" y2="6" /><line x1="16" x2="16" y1="14" y2="18" /><path d="M16 10h.01" /><path d="M12 10h.01" /><path d="M8 10h.01" /><path d="M12 14h.01" /><path d="M8 14h.01" /><path d="M12 18h.01" /><path d="M8 18h.01" /></svg>
<span>Calculator</span>
</div>
</div>
<hr role="separator" />
<div role="group" aria-labelledby="settings">
<span role="heading" id="settings">Settings</span>
<div role="menuitem" data-filter="Profile" data-keywords="user account">
<svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
<div role="menuitem" data-filter="Profile" data-keywords="user account"><svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
<span>Profile</span>
<span data-shortcut>⌘P</span>
</div>
<div role="menuitem" data-filter="Billing" data-keywords="invoice payment">
<svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
<div role="menuitem" data-filter="Billing" data-keywords="invoice payment"><svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
<span>Billing</span>
<span data-shortcut>⌘B</span>
</div>
<div role="menuitem" data-filter="Settings" data-keywords="config preferences">
<svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<div role="menuitem" data-filter="Settings" data-keywords="config preferences"><svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<span>Settings</span>
<span data-shortcut>⌘S</span>
</div>
@@ -52,53 +45,77 @@
</Callout>
<Steps>
<Step title="Include the JavaScript files">
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Command component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/command.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Include JavaScript">
Copy or serve the full Basecoat JavaScript bundle.
```html
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/command.min.js" defer></script>
<script src="/assets/js/all.min.js" defer></script>
```
Or copy or serve the Basecoat runtime and Command script.
```html
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/command.min.js" defer></script>
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your command HTML">
```html
<div id="demo-command-standalone" class="command border" aria-label="Command menu">
<header>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<header><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<input type="text" id="demo-command-standalone-input" placeholder="Type a command or search..." autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" role="combobox" aria-expanded="true" aria-controls="demo-command-standalone-menu" />
</header>
<div role="menu" id="demo-command-standalone-menu" aria-orientation="vertical" data-empty="No results found.">
<div role="group" aria-labelledby="suggestions">
<span role="heading" id="suggestions">Suggestions</span>
<div role="menuitem" data-filter="Calendar" data-keywords="date event schedule">
<svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" /></svg>
<div role="menuitem" data-filter="Calendar" data-keywords="date event schedule"><svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" /></svg>
<span>Calendar</span>
</div>
<div role="menuitem" data-filter="Search Emoji" data-keywords="emoji smile reaction">
<svg class="lucide lucide-smile" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M8 14s1.5 2 4 2 4-2 4-2" /><line x1="9" x2="9.01" y1="9" y2="9" /><line x1="15" x2="15.01" y1="9" y2="9" /></svg>
<div role="menuitem" data-filter="Search Emoji" data-keywords="emoji smile reaction"><svg class="lucide lucide-smile" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M8 14s1.5 2 4 2 4-2 4-2" /><line x1="9" x2="9.01" y1="9" y2="9" /><line x1="15" x2="15.01" y1="9" y2="9" /></svg>
<span>Search Emoji</span>
</div>
<div role="menuitem" aria-disabled="true">
<svg class="lucide lucide-calculator" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="16" height="20" x="4" y="2" rx="2" /><line x1="8" x2="16" y1="6" y2="6" /><line x1="16" x2="16" y1="14" y2="18" /><path d="M16 10h.01" /><path d="M12 10h.01" /><path d="M8 10h.01" /><path d="M12 14h.01" /><path d="M8 14h.01" /><path d="M12 18h.01" /><path d="M8 18h.01" /></svg>
<div role="menuitem" aria-disabled="true"><svg class="lucide lucide-calculator" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="16" height="20" x="4" y="2" rx="2" /><line x1="8" x2="16" y1="6" y2="6" /><line x1="16" x2="16" y1="14" y2="18" /><path d="M16 10h.01" /><path d="M12 10h.01" /><path d="M8 10h.01" /><path d="M12 14h.01" /><path d="M8 14h.01" /><path d="M12 18h.01" /><path d="M8 18h.01" /></svg>
<span>Calculator</span>
</div>
</div>
<hr role="separator" />
<div role="group" aria-labelledby="settings">
<span role="heading" id="settings">Settings</span>
<div role="menuitem" data-filter="Profile" data-keywords="user account">
<svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
<div role="menuitem" data-filter="Profile" data-keywords="user account"><svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
<span>Profile</span>
<span data-shortcut>⌘P</span>
</div>
<div role="menuitem" data-filter="Billing" data-keywords="invoice payment">
<svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
<div role="menuitem" data-filter="Billing" data-keywords="invoice payment"><svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
<span>Billing</span>
<span data-shortcut>⌘B</span>
</div>
<div role="menuitem" data-filter="Settings" data-keywords="config preferences">
<svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<div role="menuitem" data-filter="Settings" data-keywords="config preferences"><svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<span>Settings</span>
<span data-shortcut>⌘S</span>
</div>
@@ -182,8 +199,7 @@ A simple command menu in a dialog.
<button type="button" class="btn" data-variant="outline" onclick="document.getElementById('command-basic').showModal()">Open Menu</button>
<dialog id="command-basic" class="command-dialog" aria-label="Command menu" onclick="if (event.target === this) this.close()">
<div class="command">
<header>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<header><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<input type="text" id="command-basic-input" placeholder="Type a command or search..." autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" role="combobox" aria-expanded="true" aria-controls="command-basic-menu" />
</header>
<div role="menu" id="command-basic-menu" aria-orientation="vertical" data-empty="No results found.">
@@ -204,25 +220,21 @@ A simple command menu in a dialog.
<button type="button" class="btn" data-variant="outline" onclick="document.getElementById('command-shortcuts-dialog').showModal()">Open Menu</button>
<dialog id="command-shortcuts-dialog" class="command-dialog" aria-label="Command menu" onclick="if (event.target === this) this.close()">
<div class="command">
<header>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<header><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<input type="text" id="command-shortcuts-input" placeholder="Type a command or search..." autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" role="combobox" aria-expanded="true" aria-controls="command-shortcuts-menu" />
</header>
<div role="menu" id="command-shortcuts-menu" aria-orientation="vertical" data-empty="No results found.">
<div role="group" aria-labelledby="command-shortcuts-settings">
<span role="heading" id="command-shortcuts-settings">Settings</span>
<div role="menuitem" data-filter="Profile" data-keywords="user account">
<svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
<div role="menuitem" data-filter="Profile" data-keywords="user account"><svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
<span>Profile</span>
<span data-shortcut>⌘P</span>
</div>
<div role="menuitem" data-filter="Billing" data-keywords="invoice payment">
<svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
<div role="menuitem" data-filter="Billing" data-keywords="invoice payment"><svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
<span>Billing</span>
<span data-shortcut>⌘B</span>
</div>
<div role="menuitem" data-filter="Settings" data-keywords="config preferences">
<svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<div role="menuitem" data-filter="Settings" data-keywords="config preferences"><svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<span>Settings</span>
<span data-shortcut>⌘S</span>
</div>
@@ -238,41 +250,34 @@ A simple command menu in a dialog.
<button type="button" class="btn" data-variant="outline" onclick="document.getElementById('command-groups-dialog').showModal()">Open Menu</button>
<dialog id="command-groups-dialog" class="command-dialog" aria-label="Command menu" onclick="if (event.target === this) this.close()">
<div class="command">
<header>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<header><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<input type="text" id="command-groups-input" placeholder="Type a command or search..." autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" role="combobox" aria-expanded="true" aria-controls="command-groups-menu" />
</header>
<div role="menu" id="command-groups-menu" aria-orientation="vertical" data-empty="No results found.">
<div role="group" aria-labelledby="command-groups-suggestions">
<span role="heading" id="command-groups-suggestions">Suggestions</span>
<div role="menuitem" data-filter="Calendar" data-keywords="date event schedule">
<svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" /></svg>
<div role="menuitem" data-filter="Calendar" data-keywords="date event schedule"><svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" /></svg>
<span>Calendar</span>
</div>
<div role="menuitem" data-filter="Search Emoji" data-keywords="emoji smile reaction">
<svg class="lucide lucide-smile" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M8 14s1.5 2 4 2 4-2 4-2" /><line x1="9" x2="9.01" y1="9" y2="9" /><line x1="15" x2="15.01" y1="9" y2="9" /></svg>
<div role="menuitem" data-filter="Search Emoji" data-keywords="emoji smile reaction"><svg class="lucide lucide-smile" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M8 14s1.5 2 4 2 4-2 4-2" /><line x1="9" x2="9.01" y1="9" y2="9" /><line x1="15" x2="15.01" y1="9" y2="9" /></svg>
<span>Search Emoji</span>
</div>
<div role="menuitem" data-filter="Calculator">
<svg class="lucide lucide-calculator" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="16" height="20" x="4" y="2" rx="2" /><line x1="8" x2="16" y1="6" y2="6" /><line x1="16" x2="16" y1="14" y2="18" /><path d="M16 10h.01" /><path d="M12 10h.01" /><path d="M8 10h.01" /><path d="M12 14h.01" /><path d="M8 14h.01" /><path d="M12 18h.01" /><path d="M8 18h.01" /></svg>
<div role="menuitem" data-filter="Calculator"><svg class="lucide lucide-calculator" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="16" height="20" x="4" y="2" rx="2" /><line x1="8" x2="16" y1="6" y2="6" /><line x1="16" x2="16" y1="14" y2="18" /><path d="M16 10h.01" /><path d="M12 10h.01" /><path d="M8 10h.01" /><path d="M12 14h.01" /><path d="M8 14h.01" /><path d="M12 18h.01" /><path d="M8 18h.01" /></svg>
<span>Calculator</span>
</div>
</div>
<hr role="separator" />
<div role="group" aria-labelledby="command-groups-settings">
<span role="heading" id="command-groups-settings">Settings</span>
<div role="menuitem" data-filter="Profile" data-keywords="user account">
<svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
<div role="menuitem" data-filter="Profile" data-keywords="user account"><svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
<span>Profile</span>
<span data-shortcut>⌘P</span>
</div>
<div role="menuitem" data-filter="Billing" data-keywords="invoice payment">
<svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
<div role="menuitem" data-filter="Billing" data-keywords="invoice payment"><svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
<span>Billing</span>
<span data-shortcut>⌘B</span>
</div>
<div role="menuitem" data-filter="Settings" data-keywords="config preferences">
<svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<div role="menuitem" data-filter="Settings" data-keywords="config preferences"><svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<span>Settings</span>
<span data-shortcut>⌘S</span>
</div>
@@ -288,8 +293,7 @@ A simple command menu in a dialog.
<button type="button" class="btn" data-variant="outline" onclick="document.getElementById('command-scrollable-dialog').showModal()">Open Menu</button>
<dialog id="command-scrollable-dialog" class="command-dialog" aria-label="Command menu" onclick="if (event.target === this) this.close()">
<div class="command">
<header>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<header><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<input type="text" id="command-scrollable-input" placeholder="Type a command or search..." autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" role="combobox" aria-expanded="true" aria-controls="command-scrollable-menu" />
</header>
<div role="menu" id="command-scrollable-menu" aria-orientation="vertical" data-empty="No results found.">
@@ -347,42 +351,35 @@ Add `dir="rtl"` to the command root or an ancestor.
<Preview class="w-full max-w-sm">
<div dir="rtl">
<div id="command-rtl" class="command border" aria-label="Command menu">
<header>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<header><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
<input type="text" id="command-rtl-input" placeholder="اكتب أمرًا أو ابحث..." autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list" role="combobox" aria-expanded="true" aria-controls="command-rtl-menu" />
</header>
<div role="menu" id="command-rtl-menu" aria-orientation="vertical" data-empty="لم يتم العثور على نتائج.">
<div role="group" aria-labelledby="command-rtl-suggestions">
<span role="heading" id="command-rtl-suggestions">اقتراحات</span>
<div role="menuitem" data-filter="Calendar">
<svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" /></svg>
<div role="menuitem" data-filter="Calendar"><svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" /></svg>
<span>التقويم</span>
<span data-shortcut>⌘K</span>
</div>
<div role="menuitem" data-filter="Search Emoji">
<svg class="lucide lucide-smile" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M8 14s1.5 2 4 2 4-2 4-2" /><line x1="9" x2="9.01" y1="9" y2="9" /><line x1="15" x2="15.01" y1="9" y2="9" /></svg>
<div role="menuitem" data-filter="Search Emoji"><svg class="lucide lucide-smile" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M8 14s1.5 2 4 2 4-2 4-2" /><line x1="9" x2="9.01" y1="9" y2="9" /><line x1="15" x2="15.01" y1="9" y2="9" /></svg>
<span>البحث عن الرموز التعبيرية</span>
</div>
<div role="menuitem" aria-disabled="true" data-filter="Calculator">
<svg class="lucide lucide-calculator" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="16" height="20" x="4" y="2" rx="2" /><line x1="8" x2="16" y1="6" y2="6" /><line x1="16" x2="16" y1="14" y2="18" /><path d="M16 10h.01" /><path d="M12 10h.01" /><path d="M8 10h.01" /><path d="M12 14h.01" /><path d="M8 14h.01" /><path d="M12 18h.01" /><path d="M8 18h.01" /></svg>
<div role="menuitem" aria-disabled="true" data-filter="Calculator"><svg class="lucide lucide-calculator" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="16" height="20" x="4" y="2" rx="2" /><line x1="8" x2="16" y1="6" y2="6" /><line x1="16" x2="16" y1="14" y2="18" /><path d="M16 10h.01" /><path d="M12 10h.01" /><path d="M8 10h.01" /><path d="M12 14h.01" /><path d="M8 14h.01" /><path d="M12 18h.01" /><path d="M8 18h.01" /></svg>
<span>الآلة الحاسبة</span>
</div>
</div>
<hr role="separator" />
<div role="group" aria-labelledby="command-rtl-settings">
<span role="heading" id="command-rtl-settings">الإعدادات</span>
<div role="menuitem" data-filter="Profile">
<svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
<div role="menuitem" data-filter="Profile"><svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
<span>الملف الشخصي</span>
<span data-shortcut>⌘P</span>
</div>
<div role="menuitem" data-filter="Billing">
<svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
<div role="menuitem" data-filter="Billing"><svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
<span>الفوترة</span>
<span data-shortcut>⌘B</span>
</div>
<div role="menuitem" data-filter="Settings">
<svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<div role="menuitem" data-filter="Settings"><svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<span>الإعدادات</span>
<span data-shortcut>⌘S</span>
</div>
+32 -15
View File
@@ -24,9 +24,7 @@
<button class="btn" data-variant="outline" onclick="this.closest('dialog').close()">Cancel</button>
<button class="btn" onclick="this.closest('dialog').close()">Save changes</button>
</footer>
<button type="button" class="btn" data-variant="ghost" data-size="icon-sm" aria-label="Close dialog" onclick="this.closest('dialog').close()">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg>
</button>
<button type="button" class="btn" data-variant="ghost" data-size="icon-sm" aria-label="Close dialog" onclick="this.closest('dialog').close()"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg></button>
</div>
</dialog>
</Preview>
@@ -37,6 +35,30 @@
This component ships a `dialog()` macro for Jinja and Nunjucks.
</Callout>
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Dialog component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/dialog.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your dialog HTML">
Basecoat uses the native `<dialog>` element and `showModal()`. This differs from shadcn/ui's portalled Base UI implementation, but preserves native modality, focus handling, and inert page content without component JavaScript.
```html
@@ -63,13 +85,14 @@ Basecoat uses the native `<dialog>` element and `showModal()`. This differs from
<button class="btn" data-variant="outline" onclick="this.closest('dialog').close()">Cancel</button>
<button class="btn" onclick="this.closest('dialog').close()">Save changes</button>
</footer>
<button type="button" class="btn" data-variant="ghost" data-size="icon-sm" aria-label="Close dialog" onclick="this.closest('dialog').close()">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg>
</button>
<button type="button" class="btn" data-variant="ghost" data-size="icon-sm" aria-label="Close dialog" onclick="this.closest('dialog').close()"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg></button>
</div>
</dialog>
```
</Step>
</Steps>
### HTML structure
<dl>
@@ -167,9 +190,7 @@ Basecoat uses the native `<dialog>` element and `showModal()`. This differs from
<footer>
<button class="btn" data-variant="outline" onclick="this.closest('dialog').close()">Close</button>
</footer>
<button type="button" class="btn" data-variant="ghost" data-size="icon-sm" aria-label="Close dialog" onclick="this.closest('dialog').close()">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg>
</button>
<button type="button" class="btn" data-variant="ghost" data-size="icon-sm" aria-label="Close dialog" onclick="this.closest('dialog').close()"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg></button>
</div>
</dialog>
</Preview>
@@ -196,9 +217,7 @@ Basecoat uses the native `<dialog>` element and `showModal()`. This differs from
<p class="mb-4 leading-normal">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p class="mb-4 leading-normal">Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</section>
<button type="button" class="btn" data-variant="ghost" data-size="icon-sm" aria-label="Close dialog" onclick="this.closest('dialog').close()">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg>
</button>
<button type="button" class="btn" data-variant="ghost" data-size="icon-sm" aria-label="Close dialog" onclick="this.closest('dialog').close()"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg></button>
</div>
</dialog>
</Preview>
@@ -232,9 +251,7 @@ Dialog positioning and close button placement use logical properties. Set `dir="
<button class="btn" data-variant="outline" onclick="this.closest('dialog').close()">إلغاء</button>
<button class="btn" onclick="this.closest('dialog').close()">حفظ التغييرات</button>
</footer>
<button type="button" class="btn" data-variant="ghost" data-size="icon-sm" aria-label="Close dialog" onclick="this.closest('dialog').close()">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg>
</button>
<button type="button" class="btn" data-variant="ghost" data-size="icon-sm" aria-label="Close dialog" onclick="this.closest('dialog').close()"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg></button>
</div>
</dialog>
</div>
+69 -85
View File
@@ -55,13 +55,47 @@
Basecoat dropdown menus are inline-positioned relative to the `.dropdown-menu` wrapper. This differs from shadcn/ui's portalled Base UI implementation, but keeps the markup dependency-free and matches Basecoat's current popover/select positioning model.
<Steps>
<Step title="Include the JavaScript files">
```html
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/dropdown-menu.min.js" defer></script>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Dropdown Menu component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/dropdown-menu.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Include JavaScript">
Copy or serve the full Basecoat JavaScript bundle.
```html
<script src="/assets/js/all.min.js" defer></script>
```
Or copy or serve the Basecoat runtime and Dropdown Menu script.
```html
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/dropdown-menu.min.js" defer></script>
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your dropdown menu HTML">
```html
<div id="demo-dropdown-menu" class="dropdown-menu">
<button type="button" id="demo-dropdown-menu-trigger" aria-haspopup="menu" aria-controls="demo-dropdown-menu-menu" aria-expanded="false" class="btn" data-variant="outline">Open</button>
@@ -121,7 +155,7 @@ Basecoat dropdown menus are inline-positioned relative to the `.dropdown-menu` w
<dd>Trigger button. The script toggles <code>aria-expanded</code> and manages keyboard navigation.</dd>
<dt><code>&lt;div data-popover aria-hidden="true"&gt;</code></dt>
<dd>
Menu content popover. Set <code>data-side="top|right|bottom|left"</code> and <code>data-align="start|center|end"</code> to control placement.
Menu content popover. Set <code>data-side="top|right|bottom|left|inline-start|inline-end"</code> and <code>data-align="start|center|end"</code> to control placement.
<dl>
<dt><code>&lt;div role="menu"&gt;</code></dt>
<dd>
@@ -149,7 +183,6 @@ Basecoat dropdown menus are inline-positioned relative to the `.dropdown-menu` w
</dd>
</dl>
### JavaScript API
| API | Type | Description |
@@ -222,21 +255,17 @@ Basecoat dropdown menus are inline-positioned relative to the `.dropdown-menu` w
<button type="button" id="dropdown-icons-trigger" aria-haspopup="menu" aria-controls="dropdown-icons-menu" aria-expanded="false" class="btn" data-variant="outline">Open</button>
<div id="dropdown-icons-popover" data-popover aria-hidden="true" class="min-w-32">
<div role="menu" id="dropdown-icons-menu" aria-labelledby="dropdown-icons-trigger">
<div role="menuitem">
<svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
<div role="menuitem"><svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
Profile
</div>
<div role="menuitem">
<svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
<div role="menuitem"><svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
Billing
</div>
<div role="menuitem">
<svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<div role="menuitem"><svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
Settings
</div>
<hr role="separator" />
<div role="menuitem" data-variant="destructive">
<svg class="lucide lucide-log-out" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 17 5-5-5-5" /><path d="M21 12H9" /><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" /></svg>
<div role="menuitem" data-variant="destructive"><svg class="lucide lucide-log-out" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 17 5-5-5-5" /><path d="M21 12H9" /><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" /></svg>
Log out
</div>
</div>
@@ -254,21 +283,15 @@ Basecoat dropdown menus are inline-positioned relative to the `.dropdown-menu` w
<div role="group" aria-labelledby="dropdown-checkboxes-label">
<div role="heading" id="dropdown-checkboxes-label">Appearance</div>
<div role="menuitemcheckbox" aria-checked="true">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
Status Bar
</div>
<div role="menuitemcheckbox" aria-checked="false" aria-disabled="true">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
Activity Bar
</div>
<div role="menuitemcheckbox" aria-checked="false">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
Panel
</div>
</div>
@@ -287,23 +310,17 @@ Basecoat dropdown menus are inline-positioned relative to the `.dropdown-menu` w
<div role="group" aria-labelledby="dropdown-checkboxes-icons-label">
<div role="heading" id="dropdown-checkboxes-icons-label">Notification Preferences</div>
<div role="menuitemcheckbox" aria-checked="true">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
<svg class="lucide lucide-mail" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7" /><rect x="2" y="4" width="20" height="16" rx="2" /></svg>
Email notifications
</div>
<div role="menuitemcheckbox" aria-checked="false">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
<svg class="lucide lucide-message-square" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" /></svg>
SMS notifications
</div>
<div role="menuitemcheckbox" aria-checked="true">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
<svg class="lucide lucide-bell" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.268 21a2 2 0 0 0 3.464 0" /><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" /></svg>
Push notifications
</div>
@@ -323,21 +340,15 @@ Basecoat dropdown menus are inline-positioned relative to the `.dropdown-menu` w
<div role="group" aria-labelledby="dropdown-radio-label">
<div role="heading" id="dropdown-radio-label">Panel Position</div>
<div role="menuitemradio" aria-checked="false">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
Top
</div>
<div role="menuitemradio" aria-checked="true">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
Bottom
</div>
<div role="menuitemradio" aria-checked="false">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
Right
</div>
</div>
@@ -356,23 +367,17 @@ Basecoat dropdown menus are inline-positioned relative to the `.dropdown-menu` w
<div role="group" aria-labelledby="dropdown-radio-icons-label">
<div role="heading" id="dropdown-radio-icons-label">Select Payment Method</div>
<div role="menuitemradio" aria-checked="true">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
<svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
Credit Card
</div>
<div role="menuitemradio" aria-checked="false">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
<svg class="lucide lucide-wallet" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1" /><path d="M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4" /></svg>
PayPal
</div>
<div role="menuitemradio" aria-checked="false">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
<svg class="lucide lucide-building-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z" /><path d="M6 12H4a2 2 0 0 0-2 2v8h20v-8a2 2 0 0 0-2-2h-2" /><path d="M10 6h4" /><path d="M10 10h4" /><path d="M10 14h4" /><path d="M10 18h4" /></svg>
Bank Transfer
</div>
@@ -390,19 +395,16 @@ Basecoat dropdown menus are inline-positioned relative to the `.dropdown-menu` w
<div id="dropdown-destructive-popover" data-popover aria-hidden="true" class="min-w-32">
<div role="menu" id="dropdown-destructive-menu" aria-labelledby="dropdown-destructive-trigger">
<div role="group">
<div role="menuitem">
<svg class="lucide lucide-pencil" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9" /><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4Z" /></svg>
<div role="menuitem"><svg class="lucide lucide-pencil" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9" /><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4Z" /></svg>
Edit
</div>
<div role="menuitem">
<svg class="lucide lucide-share" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" /><polyline points="16 6 12 2 8 6" /><line x1="12" x2="12" y1="2" y2="15" /></svg>
<div role="menuitem"><svg class="lucide lucide-share" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" /><polyline points="16 6 12 2 8 6" /><line x1="12" x2="12" y1="2" y2="15" /></svg>
Share
</div>
</div>
<hr role="separator" />
<div role="group">
<div role="menuitem" data-variant="destructive">
<svg class="lucide lucide-trash" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18" /><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /></svg>
<div role="menuitem" data-variant="destructive"><svg class="lucide lucide-trash" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18" /><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /></svg>
Delete
</div>
</div>
@@ -424,22 +426,18 @@ Basecoat dropdown menus are inline-positioned relative to the `.dropdown-menu` w
<div id="dropdown-avatar-popover" data-popover aria-hidden="true" data-align="end">
<div role="menu" id="dropdown-avatar-menu" aria-labelledby="dropdown-avatar-trigger">
<div role="group">
<div role="menuitem">
<svg class="lucide lucide-badge-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" /><path d="m9 12 2 2 4-4" /></svg>
<div role="menuitem"><svg class="lucide lucide-badge-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" /><path d="m9 12 2 2 4-4" /></svg>
Account
</div>
<div role="menuitem">
<svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
<div role="menuitem"><svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
Billing
</div>
<div role="menuitem">
<svg class="lucide lucide-bell" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.268 21a2 2 0 0 0 3.464 0" /><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" /></svg>
<div role="menuitem"><svg class="lucide lucide-bell" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.268 21a2 2 0 0 0 3.464 0" /><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" /></svg>
Notifications
</div>
</div>
<hr role="separator" />
<div role="menuitem">
<svg class="lucide lucide-log-out" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 17 5-5-5-5" /><path d="M21 12H9" /><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" /></svg>
<div role="menuitem"><svg class="lucide lucide-log-out" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 17 5-5-5-5" /><path d="M21 12H9" /><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" /></svg>
Sign Out
</div>
</div>
@@ -469,21 +467,15 @@ Dropdown menus support document direction. Set `dir="rtl"` on the dropdown root
<div role="group" aria-labelledby="dropdown-rtl-view">
<div role="heading" id="dropdown-rtl-view">عرض</div>
<div role="menuitemcheckbox" aria-checked="true">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
شريط الحالة
</div>
<div role="menuitemcheckbox" aria-checked="false">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
شريط النشاط
</div>
<div role="menuitemcheckbox" aria-checked="false">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
اللوحة
</div>
</div>
@@ -491,27 +483,19 @@ Dropdown menus support document direction. Set `dir="rtl"` on the dropdown root
<div role="group" aria-labelledby="dropdown-rtl-position">
<div role="heading" id="dropdown-rtl-position">الموضع</div>
<div role="menuitemradio" aria-checked="false">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
أعلى
</div>
<div role="menuitemradio" aria-checked="true">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
أسفل
</div>
<div role="menuitemradio" aria-checked="false">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
يمين
</div>
<div role="menuitemradio" aria-checked="false">
<span data-indicator>
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-indicator><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
يسار
</div>
</div>
+38 -25
View File
@@ -3,9 +3,7 @@
<Preview>
<section class="empty">
<header>
<figure>
<svg class="lucide lucide-folder-code" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M10 10.5 8 13l2 2.5" /><path d="m14 10.5 2 2.5-2 2.5" /><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2z" /></svg>
</figure>
<figure><svg class="lucide lucide-folder-code" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 10.5 8 13l2 2.5" /><path d="m14 10.5 2 2.5-2 2.5" /><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2z" /></svg></figure>
<h3>No Projects Yet</h3>
<p>You haven't created any projects yet. Get started by creating your first project.</p>
</header>
@@ -16,7 +14,7 @@
</div>
<a href="#" class="btn text-muted-foreground" data-variant="link" data-size="sm">
Learn More
<svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg>
<svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg>
</a>
</footer>
</section>
@@ -24,14 +22,36 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Empty component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/empty.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your empty HTML">
Add `class="empty"` to a semantic container. The component styles common children like `header`, `figure`, headings, descriptions, and `footer`.
```html
<section class="empty">
<header>
<figure>
<svg class="lucide lucide-folder-code" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M10 10.5 8 13l2 2.5" /><path d="m14 10.5 2 2.5-2 2.5" /><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2z" /></svg>
</figure>
<figure><svg class="lucide lucide-folder-code" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 10.5 8 13l2 2.5" /><path d="m14 10.5 2 2.5-2 2.5" /><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2z" /></svg></figure>
<h3>No Projects Yet</h3>
<p>You haven't created any projects yet. Get started by creating your first project.</p>
</header>
@@ -42,12 +62,15 @@ Add `class="empty"` to a semantic container. The component styles common childre
</div>
<a href="#" class="btn text-muted-foreground" data-variant="link" data-size="sm">
Learn More
<svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg>
<svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg>
</a>
</footer>
</section>
```
</Step>
</Steps>
#### HTML structure
<dl>
@@ -80,9 +103,7 @@ Add `class="empty"` to a semantic container. The component styles common childre
<Preview class="w-full">
<section class="empty border border-dashed">
<header>
<figure>
<svg class="lucide lucide-cloud" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z" /></svg>
</figure>
<figure><svg class="lucide lucide-cloud" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z" /></svg></figure>
<h3>Cloud Storage Empty</h3>
<p>Upload files to your cloud storage to access them anywhere.</p>
</header>
@@ -97,15 +118,12 @@ Add `class="empty"` to a semantic container. The component styles common childre
<Preview class="w-full">
<section class="empty h-full bg-muted/30">
<header>
<figure>
<svg class="lucide lucide-bell" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.268 21a2 2 0 0 0 3.464 0" /><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" /></svg>
</figure>
<figure><svg class="lucide lucide-bell" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.268 21a2 2 0 0 0 3.464 0" /><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" /></svg></figure>
<h3>No Notifications</h3>
<p class="max-w-xs text-pretty">You're all caught up. New notifications will appear here.</p>
</header>
<footer>
<button class="btn" data-variant="outline">
<svg class="lucide lucide-refresh-ccw" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" /><path d="M3 3v5h5" /><path d="M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" /><path d="M16 16h5v5" /></svg>
<button class="btn" data-variant="outline"><svg class="lucide lucide-refresh-ccw" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" /><path d="M3 3v5h5" /><path d="M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" /><path d="M16 16h5v5" /></svg>
Refresh
</button>
</footer>
@@ -143,8 +161,7 @@ Add `class="empty"` to a semantic container. The component styles common childre
<p>Invite your team to collaborate on this project.</p>
</header>
<footer>
<button class="btn" data-size="sm">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M5 12h14" /><path d="M12 5v14" /></svg>
<button class="btn" data-size="sm"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
<span>Invite Members</span>
</button>
</footer>
@@ -162,9 +179,7 @@ Add `class="empty"` to a semantic container. The component styles common childre
<footer>
<div class="input-group sm:w-3/4">
<input type="search" placeholder="Try searching for pages..." />
<span data-align="start" aria-hidden="true">
<svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg>
</span>
<span data-align="start" aria-hidden="true"><svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg></span>
<span data-align="end"><kbd class="kbd">/</kbd></span>
</div>
<p>Need help? <a href="#">Contact support</a></p>
@@ -177,9 +192,7 @@ Add `class="empty"` to a semantic container. The component styles common childre
<Preview>
<section class="empty" dir="rtl">
<header>
<figure>
<svg class="lucide lucide-folder-code" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M10 10.5 8 13l2 2.5" /><path d="m14 10.5 2 2.5-2 2.5" /><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2z" /></svg>
</figure>
<figure><svg class="lucide lucide-folder-code" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 10.5 8 13l2 2.5" /><path d="m14 10.5 2 2.5-2 2.5" /><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2z" /></svg></figure>
<h3>لا توجد مشاريع بعد</h3>
<p>لم تقم بإنشاء أي مشاريع بعد. ابدأ بإنشاء مشروعك الأول.</p>
</header>
@@ -190,7 +203,7 @@ Add `class="empty"` to a semantic container. The component styles common childre
</div>
<a href="#" class="btn text-muted-foreground" data-variant="link" data-size="sm">
تعرف على المزيد
<svg class="lucide lucide-arrow-up-right rtl:rotate-270" data-icon="inline-end" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg>
<svg class="lucide lucide-arrow-up-right rtl:rotate-270" data-icon="inline-end" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 7h10v10" /><path d="M7 17 17 7" /></svg>
</a>
</footer>
</section>
+39 -20
View File
@@ -81,6 +81,30 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Field component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/field.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your field HTML">
Use `class="field"` for one control and `class="fieldset"` for related controls. Use a native `<fieldset>` when the group needs a `<legend>`; otherwise use a labelled `role="group"`.
```html
@@ -106,6 +130,9 @@ Use `class="field"` for one control and `class="fieldset"` for related controls.
</fieldset>
```
</Step>
</Steps>
### HTML structure
<dl>
@@ -396,6 +423,18 @@ Use `data-orientation="responsive"` to stack by default and switch to horizontal
</form>
</Preview>
### Validation and errors
Add `data-invalid` to `.field` and `aria-invalid="true"` to the invalid control.
<Preview class="w-full max-w-xs">
<div role="group" class="field" data-invalid>
<label for="invalid-email">Email</label>
<input id="invalid-email" type="email" value="wrong-email" aria-invalid="true" aria-describedby="invalid-email-error" />
<p id="invalid-email-error" role="alert">Enter a valid email address.</p>
</div>
</Preview>
### RTL
Add `dir="rtl"` to the field, fieldset, or an ancestor.
@@ -413,23 +452,3 @@ Add `dir="rtl"` to the field, fieldset, or an ancestor.
</div>
</fieldset>
</Preview>
## Validation and Errors
Add `data-invalid` to `.field` and `aria-invalid="true"` to the invalid control.
```html
<div role="group" class="field" data-invalid>
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email-error" />
<p id="email-error" role="alert">Enter a valid email address.</p>
</div>
```
<Preview class="w-full max-w-xs">
<div role="group" class="field" data-invalid>
<label for="invalid-email">Email</label>
<input id="invalid-email" type="email" value="wrong-email" aria-invalid="true" aria-describedby="invalid-email-error" />
<p id="invalid-email-error" role="alert">Enter a valid email address.</p>
</div>
</Preview>
+55 -76
View File
@@ -3,25 +3,48 @@
<Preview class="w-full max-w-xs">
<div class="input-group">
<input type="text" placeholder="Search..." />
<span data-align="start" aria-hidden="true">
<svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg>
</span>
<span data-align="start" aria-hidden="true"><svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg></span>
<span data-align="end">12 results</span>
</div>
</Preview>
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Input Group component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/input-group.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your input group HTML">
```html
<div class="input-group">
<input type="text" placeholder="Search..." />
<span data-align="start" aria-hidden="true">
<!-- icon -->
</span>
<span data-align="start" aria-hidden="true"> <!-- icon --></span>
<span data-align="end">12 results</span>
</div>
```
</Step>
</Steps>
Add `class="input-group"` to the root. Native controls stay semantic and become borderless children inside that shell.
<dl>
@@ -52,13 +75,11 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
### Inline start
<Preview class="w-full max-w-sm">
<div class="field max-w-sm">
<div class="field">
<label for="inline-start-input">Input</label>
<div class="input-group">
<input id="inline-start-input" type="text" placeholder="Search..." />
<span role="group" data-align="start" aria-hidden="true">
<svg class="text-muted-foreground lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg>
</span>
<span role="group" data-align="start" aria-hidden="true"><svg class="text-muted-foreground lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg></span>
</div>
<p>Icon positioned at the start.</p>
</div>
@@ -67,13 +88,11 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
### Inline end
<Preview class="w-full max-w-sm">
<div class="field max-w-sm">
<div class="field">
<label for="inline-end-input">Input</label>
<div class="input-group">
<input id="inline-end-input" type="password" placeholder="Enter password" />
<span role="group" data-align="end" aria-hidden="true">
<svg class="lucide lucide-eye-off" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49" /><path d="M14.084 14.158a3 3 0 0 1-4.242-4.242" /><path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143" /><path d="m2 2 20 20" /></svg>
</span>
<span role="group" data-align="end" aria-hidden="true"><svg class="lucide lucide-eye-off" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49" /><path d="M14.084 14.158a3 3 0 0 1-4.242-4.242" /><path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143" /><path d="m2 2 20 20" /></svg></span>
</div>
<p>Icon positioned at the end.</p>
</div>
@@ -82,7 +101,7 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
### Block start
<Preview class="w-full max-w-sm">
<div role="group" aria-label="Block start input group examples" class="fieldset max-w-sm">
<div role="group" aria-label="Block start input group examples" class="fieldset">
<div class="field">
<label for="block-start-input">Input</label>
<div class="input-group" data-orientation="vertical">
@@ -97,12 +116,9 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
<label for="block-start-textarea">Textarea</label>
<div class="input-group" data-orientation="vertical">
<textarea id="block-start-textarea" class="font-mono text-sm" placeholder="console.log('Hello, world!');"></textarea>
<header data-align="start">
<svg class="text-muted-foreground lucide lucide-file-code" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" /><path d="M14 2v5a1 1 0 0 0 1 1h5" /><path d="M10 12.5 8 15l2 2.5" /><path d="m14 12.5 2 2.5-2 2.5" /></svg>
<header data-align="start"><svg class="text-muted-foreground lucide lucide-file-code" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" /><path d="M14 2v5a1 1 0 0 0 1 1h5" /><path d="M10 12.5 8 15l2 2.5" /><path d="m14 12.5 2 2.5-2 2.5" /></svg>
<span class="font-mono">script.js</span>
<button type="button" class="btn ml-auto size-6" data-variant="ghost" data-size="icon-sm" aria-label="Copy">
<svg class="lucide lucide-copy" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2" /><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" /></svg>
</button>
<button type="button" class="btn ml-auto size-6" data-variant="ghost" data-size="icon-sm" aria-label="Copy"><svg class="lucide lucide-copy" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2" /><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" /></svg></button>
</header>
</div>
<p>Header positioned above the textarea.</p>
@@ -113,7 +129,7 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
### Block end
<Preview class="w-full max-w-sm">
<div role="group" aria-label="Block end input group examples" class="fieldset max-w-sm">
<div role="group" aria-label="Block end input group examples" class="fieldset">
<div class="field">
<label for="block-end-input">Input</label>
<div class="input-group" data-orientation="vertical">
@@ -124,7 +140,6 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
</div>
<p>Footer positioned below the input.</p>
</div>
<div class="field">
<label for="block-end-textarea">Textarea</label>
<div class="input-group" data-orientation="vertical">
@@ -145,31 +160,20 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
<div class="grid gap-6">
<div class="input-group">
<input type="text" placeholder="Search..." />
<span data-align="start" aria-hidden="true">
<svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg>
</span>
<span data-align="start" aria-hidden="true"><svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg></span>
</div>
<div class="input-group">
<input type="email" placeholder="Enter your email" />
<span data-align="start" aria-hidden="true">
<svg class="lucide lucide-mail" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7" /><rect x="2" y="4" width="20" height="16" rx="2" /></svg>
</span>
<span data-align="start" aria-hidden="true"><svg class="lucide lucide-mail" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7" /><rect x="2" y="4" width="20" height="16" rx="2" /></svg></span>
</div>
<div class="input-group">
<input type="text" placeholder="Card number" />
<span data-align="start" aria-hidden="true">
<svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg>
</span>
<span data-align="end" aria-hidden="true">
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</span>
<span data-align="start" aria-hidden="true"><svg class="lucide lucide-credit-card" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2" /><line x1="2" x2="22" y1="10" y2="10" /></svg></span>
<span data-align="end" aria-hidden="true"><svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg></span>
</div>
<div class="input-group">
<input type="text" placeholder="Card number" />
<span data-align="end" aria-hidden="true">
<svg class="lucide lucide-star" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z" /></svg>
<svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg>
</span>
<span data-align="end" aria-hidden="true"><svg class="lucide lucide-star" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z" /></svg><svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg></span>
</div>
</div>
</Preview>
@@ -207,19 +211,13 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
<div class="grid gap-6">
<div class="input-group">
<input type="text" readonly placeholder="https://x.com/shadcn" />
<button type="button" class="btn" data-variant="ghost" data-size="icon-xs" data-align="end" aria-label="Copy" title="Copy">
<svg class="lucide lucide-copy" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2" /><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" /></svg>
</button>
<button type="button" class="btn" data-variant="ghost" data-size="icon-xs" data-align="end" aria-label="Copy" title="Copy"><svg class="lucide lucide-copy" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2" /><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" /></svg></button>
</div>
<div class="input-group [--radius:9999px]">
<button type="button" class="btn" data-variant="secondary" data-size="icon-xs" data-align="start" aria-label="Connection information">
<svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg>
</button>
<button type="button" class="btn" data-variant="secondary" data-size="icon-xs" data-align="start" aria-label="Connection information"><svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg></button>
<span data-align="start" class="text-muted-foreground">https://</span>
<input type="text" id="input-secure-19" />
<button type="button" class="btn" data-variant="ghost" data-size="icon-xs" data-align="end" aria-label="Favorite">
<svg class="lucide lucide-star" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z" /></svg>
</button>
<button type="button" class="btn" data-variant="ghost" data-size="icon-xs" data-align="end" aria-label="Favorite"><svg class="lucide lucide-star" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z" /></svg></button>
</div>
<div class="input-group">
<input type="text" placeholder="Type to search..." />
@@ -233,9 +231,7 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
<Preview class="w-full max-w-sm">
<div class="input-group">
<input type="text" placeholder="Search..." />
<span data-align="start" aria-hidden="true">
<svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg>
</span>
<span data-align="start" aria-hidden="true"><svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg></span>
<span data-align="end"><kbd class="kbd">⌘K</kbd></span>
</div>
</Preview>
@@ -247,9 +243,7 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
<div class="input-group">
<input type="text" placeholder="Enter file name" />
<div id="dropdown-menu-601971" class="dropdown-menu" data-align="end">
<button type="button" id="dropdown-menu-601971-trigger" aria-haspopup="menu" aria-controls="dropdown-menu-601971-menu" aria-expanded="false" class="btn" data-variant="ghost" data-size="icon-xs" aria-label="Open file actions">
<svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg>
</button>
<button type="button" id="dropdown-menu-601971-trigger" aria-haspopup="menu" aria-controls="dropdown-menu-601971-menu" aria-expanded="false" class="btn" data-variant="ghost" data-size="icon-xs" aria-label="Open file actions"><svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg></button>
<div id="dropdown-menu-601971-popover" data-popover aria-hidden="true" data-align="end" class="min-w-32">
<div role="menu" id="dropdown-menu-601971-menu" aria-labelledby="dropdown-menu-601971-trigger">
<div id="dropdown-menu-601971-items-1" role="menuitem">Settings</div>
@@ -284,15 +278,11 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
<div class="grid gap-6">
<div class="input-group">
<input type="text" placeholder="Searching..." />
<span data-align="end">
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
</span>
<span data-align="end"><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg></span>
</div>
<div class="input-group">
<input type="text" placeholder="Processing..." />
<span data-align="start">
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
</span>
<span data-align="start"><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg></span>
</div>
<div class="input-group">
<input type="text" placeholder="Saving changes..." />
@@ -303,9 +293,7 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
</div>
<div class="input-group">
<input type="text" placeholder="Refreshing data..." />
<span data-align="start" aria-hidden="true">
<svg class="animate-spin lucide lucide-loader" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v4" /><path d="m16.2 7.8 2.9-2.9" /><path d="M18 12h4" /><path d="m16.2 16.2 2.9 2.9" /><path d="M12 18v4" /><path d="m4.9 19.1 2.9-2.9" /><path d="M2 12h4" /><path d="m4.9 4.9 2.9 2.9" /></svg>
</span>
<span data-align="start" aria-hidden="true"><svg class="animate-spin lucide lucide-loader" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v4" /><path d="m16.2 7.8 2.9-2.9" /><path d="M18 12h4" /><path d="m16.2 16.2 2.9 2.9" /><path d="M12 18v4" /><path d="m4.9 19.1 2.9-2.9" /><path d="M2 12h4" /><path d="m4.9 4.9 2.9 2.9" /></svg></span>
<span data-align="end" class="text-muted-foreground">Please wait...</span>
</div>
</div>
@@ -323,16 +311,11 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
<svg class="lucide lucide-corner-down-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 4v7a4 4 0 0 1-4 4H4" /><path d="m9 10-5 5 5 5" /></svg>
</button>
</footer>
<header data-align="start" class="border-b">
<svg class="text-muted-foreground lucide lucide-file-code" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" /><path d="M14 2v5a1 1 0 0 0 1 1h5" /><path d="M10 12.5 8 15l2 2.5" /><path d="m14 12.5 2 2.5-2 2.5" /></svg>
<header data-align="start" class="border-b"><svg class="text-muted-foreground lucide lucide-file-code" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" /><path d="M14 2v5a1 1 0 0 0 1 1h5" /><path d="M10 12.5 8 15l2 2.5" /><path d="m14 12.5 2 2.5-2 2.5" /></svg>
<span>script.js</span>
<div role="group" aria-label="File actions" class="ml-auto flex gap-1">
<button type="button" class="btn" data-variant="ghost" data-size="icon-xs" aria-label="Refresh file">
<svg class="lucide lucide-refresh-ccw" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" /><path d="M3 3v5h5" /><path d="M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" /><path d="M16 16h5v5" /></svg>
</button>
<button type="button" class="btn" data-variant="ghost" data-size="icon-xs" aria-label="Copy file">
<svg class="lucide lucide-copy" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2" /><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" /></svg>
</button>
<button type="button" class="btn" data-variant="ghost" data-size="icon-xs" aria-label="Refresh file"><svg class="lucide lucide-refresh-ccw" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" /><path d="M3 3v5h5" /><path d="M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" /><path d="M16 16h5v5" /></svg></button>
<button type="button" class="btn" data-variant="ghost" data-size="icon-xs" aria-label="Copy file"><svg class="lucide lucide-copy" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2" /><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" /></svg></button>
</div>
</header>
</div>
@@ -355,16 +338,12 @@ Use `data-align="start|end"` on addon wrappers to position them inline. Use `dat
<div dir="rtl" class="grid gap-6">
<div class="input-group">
<input type="text" placeholder="بحث..." />
<span role="group" data-align="start" aria-hidden="true">
<svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg>
</span>
<span role="group" data-align="start" aria-hidden="true"><svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg></span>
<span role="group" data-align="end">١٢ نتيجة</span>
</div>
<div class="input-group">
<input type="text" placeholder="جاري البحث..." />
<span role="group" data-align="end">
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
</span>
<span role="group" data-align="end"><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg></span>
</div>
<div class="input-group">
<input type="text" placeholder="جاري حفظ التغييرات..." />
+30 -10
View File
@@ -6,6 +6,30 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Input component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/input.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your input HTML">
Add `class="input"` to supported `<input>` elements. Inputs inside a `class="field"` container also receive the same styling automatically for common text-like input types.
Use native HTML attributes for behavior: `disabled` for disabled inputs, `required` for required fields, and `aria-invalid="true"` for invalid state styling.
@@ -14,6 +38,9 @@ Use native HTML attributes for behavior: `disabled` for disabled inputs, `requir
<input class="input" type="email" placeholder="Email" />
```
</Step>
</Steps>
## Examples
### Basic
@@ -58,11 +85,7 @@ Use `field` with a label and description to create an accessible field.
### Invalid
<Preview class="w-full max-w-xs">
<div role="group" class="field">
<label for="input-invalid">Email</label>
<input class="input" id="input-invalid" type="email" placeholder="Email" aria-invalid="true" />
<p>Please enter a valid email address.</p>
</div>
<input class="input" type="email" placeholder="Email" aria-invalid="true" />
</Preview>
### File
@@ -118,8 +141,7 @@ Use the [Input Group](/components/input-group/) patterns to add icons, text, or
<Preview class="w-full max-w-xs">
<div class="relative">
<input class="input ps-9" type="search" placeholder="Search..." />
<div class="pointer-events-none absolute start-3 top-1/2 -translate-y-1/2 text-muted-foreground [&>svg]:size-4">
<svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg>
<div class="pointer-events-none absolute start-3 top-1/2 -translate-y-1/2 text-muted-foreground [&>svg]:size-4"><svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg>
</div>
</div>
</Preview>
@@ -131,9 +153,7 @@ Use [Button Group](/components/button-group/) when an input should be grouped wi
<Preview class="w-full max-w-xs">
<div role="group" aria-label="Search" class="button-group">
<input class="input" type="search" placeholder="Search..." />
<button type="submit" class="btn" data-variant="outline" data-size="icon" aria-label="Search">
<svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg>
</button>
<button type="submit" class="btn" data-variant="outline" data-size="icon" aria-label="Search"><svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg></button>
</div>
</Preview>
+129 -70
View File
@@ -12,21 +12,42 @@
</aside>
</article>
<a href="#" class="item" data-variant="outline" data-size="sm">
<figure>
<svg class="lucide lucide-badge-check size-5" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"/><path d="m9 12 2 2 4-4"/></svg>
</figure>
<section>
<h3>Your profile has been verified.</h3>
</section>
<aside>
<svg class="lucide lucide-chevron-right size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</aside>
<figure><svg class="lucide lucide-badge-check size-5" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"/><path d="m9 12 2 2 4-4"/></svg></figure>
<section><h3>Your profile has been verified.</h3></section>
<aside><svg class="lucide lucide-chevron-right size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg></aside>
</a>
</div>
</Preview>
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, the component CSS files it composes, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/item.css";
@import "basecoat-css/components/button.css";
@import "basecoat-css/styles/vega.css";
```
Item composes Button styles when actions are rendered as buttons.
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your item HTML">
Add `class="item"` to a semantic element such as `<article>` or `<a>`. Use `class="item-group"` when listing multiple items.
```html
@@ -41,6 +62,9 @@ Add `class="item"` to a semantic element such as `<article>` or `<a>`. Use `clas
</article>
```
</Step>
</Steps>
#### HTML structure
<dl>
@@ -70,32 +94,34 @@ Add `class="item"` to a semantic element such as `<article>` or `<a>`. Use `clas
<dd>Groups related items. Use <code>role="listitem"</code> on child items when they are not native list items.</dd>
</dl>
## Examples
### Item vs Field
### Variants
Use `field` for form controls and validation. Use `item` for display content, actions, and navigation rows.
### Variant
<Preview class="w-full max-w-md">
<div class="flex w-full flex-col gap-6">
<article class="item">
<figure><svg class="lucide lucide-inbox" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" /><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" /></svg></figure>
<section>
<h3>Default Variant</h3>
<p>Transparent border for quiet item rows.</p>
<p>Transparent background with no border.</p>
</section>
<aside><button class="btn" data-variant="outline" data-size="sm">Open</button></aside>
</article>
<article class="item" data-variant="outline">
<figure><svg class="lucide lucide-inbox" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" /><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" /></svg></figure>
<section>
<h3>Outline Variant</h3>
<p>Outlined style with a visible border.</p>
</section>
<aside><button class="btn" data-variant="outline" data-size="sm">Open</button></aside>
</article>
<article class="item" data-variant="muted">
<figure><svg class="lucide lucide-inbox" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" /><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" /></svg></figure>
<section>
<h3>Muted Variant</h3>
<p>Subdued appearance for secondary content.</p>
<p>Muted background for secondary content.</p>
</section>
<aside><button class="btn" data-variant="outline" data-size="sm">Open</button></aside>
</article>
</div>
</Preview>
@@ -105,27 +131,37 @@ Add `class="item"` to a semantic element such as `<article>` or `<a>`. Use `clas
<Preview class="w-full max-w-md">
<div class="flex w-full flex-col gap-6">
<article class="item" data-variant="outline">
<section><h3>Basic Item</h3><p>A simple item with title and description.</p></section>
<aside><button class="btn" data-variant="outline" data-size="sm">Action</button></aside>
<figure><svg class="lucide lucide-inbox" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" /><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" /></svg></figure>
<section>
<h3>Default Size</h3>
<p>The standard size for most use cases.</p>
</section>
</article>
<article class="item" data-variant="outline" data-size="sm">
<figure><svg class="lucide lucide-inbox" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" /><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" /></svg></figure>
<section>
<h3>Small Size</h3>
<p>A compact size for dense layouts.</p>
</section>
</article>
<article class="item" data-variant="outline" data-size="xs">
<figure><svg class="lucide lucide-inbox" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" /><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" /></svg></figure>
<section>
<h3>Extra Small Size</h3>
<p>The most compact size available.</p>
</section>
</article>
<a href="#" class="item" data-variant="outline" data-size="sm">
<figure>
<svg class="lucide lucide-badge-check size-5" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"/><path d="m9 12 2 2 4-4"/></svg>
</figure>
<section><h3>Your profile has been verified.</h3></section>
<aside><svg class="lucide lucide-chevron-right size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg></aside>
</a>
</div>
</Preview>
## Examples
### Icon
<Preview class="w-full max-w-lg">
<div class="flex w-full flex-col gap-6">
<article class="item" data-variant="outline">
<figure>
<svg class="lucide lucide-shield-alert" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="M12 8v4"/><path d="M12 16h.01"/></svg>
</figure>
<figure><svg class="lucide lucide-shield-alert" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="M12 8v4"/><path d="M12 16h.01"/></svg></figure>
<section>
<h3>Security Alert</h3>
<p>New login detected from unknown device.</p>
@@ -148,9 +184,7 @@ Add `class="item"` to a semantic element such as `<article>` or `<a>`. Use `clas
<p>Last seen 5 months ago</p>
</section>
<aside>
<button class="btn rounded-full" data-variant="outline" data-size="icon-sm" aria-label="Invite Evil Rabbit">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg>
</button>
<button class="btn rounded-full" data-variant="outline" data-size="icon-sm" aria-label="Invite Evil Rabbit"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg></button>
</aside>
</article>
<article class="item" data-variant="outline">
@@ -201,29 +235,21 @@ Add `class="item"` to a semantic element such as `<article>` or `<a>`. Use `clas
<figure><span class="avatar"><img class="grayscale" src="https://github.com/shadcn.png" alt="@shadcn" /></span></figure>
<section><h3>shadcn</h3><p>shadcn@vercel.com</p></section>
<aside>
<button class="btn rounded-full" data-variant="ghost" data-size="icon" aria-label="Add shadcn">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg>
</button>
<button class="btn rounded-full" data-variant="ghost" data-size="icon" aria-label="Add shadcn"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg></button>
</aside>
</article>
<hr role="separator" />
<article class="item" role="listitem">
<figure><span class="avatar"><img class="grayscale" src="https://github.com/maxleiter.png" alt="@maxleiter" /></span></figure>
<section><h3>maxleiter</h3><p>maxleiter@vercel.com</p></section>
<aside>
<button class="btn rounded-full" data-variant="ghost" data-size="icon" aria-label="Add maxleiter">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg>
</button>
<button class="btn rounded-full" data-variant="ghost" data-size="icon" aria-label="Add maxleiter"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg></button>
</aside>
</article>
<hr role="separator" />
<article class="item" role="listitem">
<figure><span class="avatar"><img class="grayscale" src="https://github.com/evilrabbit.png" alt="@evilrabbit" /></span></figure>
<section><h3>evilrabbit</h3><p>evilrabbit@vercel.com</p></section>
<aside>
<button class="btn rounded-full" data-variant="ghost" data-size="icon" aria-label="Add evilrabbit">
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg>
</button>
<button class="btn rounded-full" data-variant="ghost" data-size="icon" aria-label="Add evilrabbit"><svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg></button>
</aside>
</article>
</div>
@@ -273,26 +299,53 @@ Add `class="item"` to a semantic element such as `<article>` or `<a>`. Use `clas
### Dropdown
<Preview class="w-full max-w-md">
<div class="flex min-h-64 w-full flex-col items-center gap-6">
<div class="dropdown-menu">
<button class="btn w-fit" data-variant="outline" data-size="sm" popovertarget="item-dropdown-menu">
<div class="flex min-h-64 w-full items-center justify-center">
<div id="item-dropdown" class="dropdown-menu">
<button type="button" id="item-dropdown-trigger" aria-haspopup="menu" aria-controls="item-dropdown-menu" aria-expanded="false" class="btn w-fit" data-variant="outline">
Select
<svg class="lucide lucide-chevron-down" data-icon="inline-end" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
</button>
<div id="item-dropdown-menu" popover data-popover class="w-72 [--radius:0.65rem]">
<div role="menu">
<button type="button" role="menuitem" class="item w-full p-2" data-size="sm">
<figure><span class="avatar"><img class="grayscale" src="https://github.com/shadcn.png" alt="@shadcn" /></span></figure>
<section class="gap-0.5"><h3>shadcn</h3><p>shadcn@vercel.com</p></section>
</button>
<button type="button" role="menuitem" class="item w-full p-2" data-size="sm">
<figure><span class="avatar"><img class="grayscale" src="https://github.com/maxleiter.png" alt="@maxleiter" /></span></figure>
<section class="gap-0.5"><h3>maxleiter</h3><p>maxleiter@vercel.com</p></section>
</button>
<button type="button" role="menuitem" class="item w-full p-2" data-size="sm">
<figure><span class="avatar"><img class="grayscale" src="https://github.com/evilrabbit.png" alt="@evilrabbit" /></span></figure>
<section class="gap-0.5"><h3>evilrabbit</h3><p>evilrabbit@vercel.com</p></section>
</button>
<div id="item-dropdown-popover" data-popover data-align="end" aria-hidden="true" class="w-48">
<div role="menu" id="item-dropdown-menu" aria-labelledby="item-dropdown-trigger">
<button type="button" role="menuitem">
<span class="item border-0 p-0 shadow-none" data-size="xs">
<figure>
<span class="avatar" data-size="sm">
<img class="grayscale" src="https://github.com/shadcn.png" alt="@shadcn" />
</span>
</figure>
<section class="gap-0">
<h3>shadcn</h3>
<p class="leading-none" aria-label="shadcn@vercel.com">shadcn<span aria-hidden="true">@</span>vercel.com</p>
</section>
</span>
</button>
<button type="button" role="menuitem">
<span class="item border-0 p-0 shadow-none" data-size="xs">
<figure>
<span class="avatar" data-size="sm">
<img class="grayscale" src="https://github.com/maxleiter.png" alt="@maxleiter" />
</span>
</figure>
<section class="gap-0">
<h3>maxleiter</h3>
<p class="leading-none" aria-label="maxleiter@vercel.com">maxleiter<span aria-hidden="true">@</span>vercel.com</p>
</section>
</span>
</button>
<button type="button" role="menuitem">
<span class="item border-0 p-0 shadow-none" data-size="xs">
<figure>
<span class="avatar" data-size="sm">
<img class="grayscale" src="https://github.com/evilrabbit.png" alt="@evilrabbit" />
</span>
</figure>
<section class="gap-0">
<h3>evilrabbit</h3>
<p class="leading-none" aria-label="evilrabbit@vercel.com">evilrabbit<span aria-hidden="true">@</span>vercel.com</p>
</section>
</span>
</button>
</div>
</div>
</div>
@@ -301,15 +354,21 @@ Add `class="item"` to a semantic element such as `<article>` or `<a>`. Use `clas
### RTL
<Preview class="w-full max-w-lg">
<article class="item" data-variant="outline" dir="rtl">
<figure>
<svg class="lucide lucide-shield-alert" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="M12 8v4"/><path d="M12 16h.01"/></svg>
</figure>
<section>
<h3>تنبيه أمني</h3>
<p>تم اكتشاف تسجيل دخول من جهاز غير معروف.</p>
</section>
<aside><button class="btn" data-variant="outline" data-size="sm">مراجعة</button></aside>
</article>
<Preview class="w-full max-w-md">
<div class="flex w-full flex-col gap-6" dir="rtl">
<article class="item" data-variant="outline">
<section>
<h3>عنصر أساسي</h3>
<p>عنصر بسيط يحتوي على عنوان ووصف.</p>
</section>
<aside>
<button class="btn" data-variant="outline" data-size="sm">إجراء</button>
</aside>
</article>
<a href="#" class="item" data-variant="outline" data-size="sm">
<figure><svg class="lucide lucide-badge-check size-5" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"/><path d="m9 12 2 2 4-4"/></svg></figure>
<section><h3>تم التحقق من ملفك الشخصي.</h3></section>
<aside><svg class="lucide lucide-chevron-right size-4 rtl:rotate-180" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg></aside>
</a>
</div>
</Preview>
+61 -33
View File
@@ -18,12 +18,45 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Kbd component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/button.css";
@import "basecoat-css/components/button-group.css";
@import "basecoat-css/components/input-group.css";
@import "basecoat-css/components/kbd.css";
@import "basecoat-css/components/tooltip.css";
@import "basecoat-css/styles/vega.css";
```
Kbd examples compose Button, Button Group, Input Group, and Tooltip styles.
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your kbd HTML">
Use `<kbd class="kbd">` for a key label. Use an inline wrapper with utilities when grouping multiple keys.
```html
<kbd class="kbd">⌘K</kbd>
```
</Step>
</Steps>
Keyboard labels are direction-neutral. Surrounding spacing should use logical utilities when position matters.
## Examples
@@ -31,52 +64,47 @@ Keyboard labels are direction-neutral. Surrounding spacing should use logical ut
### Group
<Preview>
<p class="text-muted-foreground text-sm">
Use
<span class="inline-flex items-center gap-1">
<kbd class="kbd">Ctrl + B</kbd>
<kbd class="kbd">Ctrl + K</kbd>
</span>
to open the command palette
</p>
<p class="text-muted-foreground text-sm">Use <span class="inline-flex items-center gap-1"><kbd class="kbd">Ctrl</kbd><span>+</span><kbd class="kbd">B</kbd></span> <span class="inline-flex items-center gap-1"><kbd class="kbd">Ctrl</kbd><span>+</span><kbd class="kbd">K</kbd></span> to open the command palette</p>
</Preview>
### Button
<Preview>
<div class="flex flex-wrap items-center gap-x-4">
<button class="btn pe-2" data-variant="outline" data-size="sm">
Accept
<kbd class="kbd">⏎</kbd>
</button>
<button class="btn pe-2" data-variant="outline" data-size="sm">
Cancel
<kbd class="kbd">Esc</kbd>
</button>
<button class="btn" data-variant="outline">
Accept
<kbd class="kbd translate-x-0.5" data-icon="inline-end">⏎</kbd>
</button>
</Preview>
### Input Group
<Preview class="w-full max-w-xs">
<div class="input-group">
<input type="search" placeholder="Search..." />
<span data-align="start" aria-hidden="true"><svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg></span>
<span class="inline-flex items-center gap-1" data-align="end">
<kbd class="kbd">⌘</kbd>
<kbd class="kbd">K</kbd>
</span>
</div>
</Preview>
### Input group
<Preview>
<div class="relative w-full max-w-sm">
<input type="search" class="input ps-9 pe-12" placeholder="Search..." />
<svg class="absolute start-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /><circle cx="11" cy="11" r="8" /></svg>
<kbd class="kbd absolute end-3 top-1/2 -translate-y-1/2">/</kbd>
</div>
</Preview>
### RTL
## RTL
Keyboard labels are direction-neutral. Surrounding spacing should use logical utilities when position matters.
<Preview>
<p dir="rtl" class="text-muted-foreground text-sm">
استخدم
<div class="flex flex-col items-center gap-4" dir="rtl">
<span class="inline-flex items-center gap-1">
<kbd class="kbd">⌘</kbd>
<kbd class="kbd">⇧</kbd>
<kbd class="kbd">⌥</kbd>
<kbd class="kbd">⌃</kbd>
</span>
<span class="inline-flex items-center gap-1">
<kbd class="kbd">Ctrl</kbd>
<kbd class="kbd">K</kbd>
<span>+</span>
<kbd class="kbd">B</kbd>
</span>
لفتح البحث
</p>
</div>
</Preview>
+27 -9
View File
@@ -9,23 +9,41 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Label component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/label.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your label HTML">
Add `class="label"` to a `<label>` element.
```html
<label class="label" for="email">Your email address</label>
```
</Step>
</Steps>
## Examples
### Disabled
<Preview>
<div class="grid gap-3">
<label class="label" for="email">Email</label>
<input class="input" id="email" type="email" placeholder="Email" disabled />
</div>
</Preview>
### RTL
Add `dir="rtl"` to the label or an ancestor.
+32 -5
View File
@@ -1,6 +1,6 @@
# Native Select
<Preview class="w-full max-w-48">
<Preview>
<select class="select w-full" aria-label="Fruit">
<option value="">Select a fruit</option>
<option value="apple">Apple</option>
@@ -12,6 +12,30 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Native Select component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/native-select.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your native select HTML">
Add `class="select"` to a native `<select>`. Use standard `<option>` and `<optgroup>` elements.
```html
@@ -24,13 +48,16 @@ Add `class="select"` to a native `<select>`. Use standard `<option>` and `<optgr
</select>
```
</Step>
</Steps>
Use Native Select for native browser behavior, form integration, and mobile-optimized pickers. Use [Select](/components/select/) for custom option content, multi-select behavior, or JavaScript APIs.
## Examples
### Groups
<Preview class="w-full max-w-48">
<Preview>
<select class="select w-full" aria-label="Food">
<option value="">Select food</option>
<optgroup label="Fruits">
@@ -48,7 +75,7 @@ Use Native Select for native browser behavior, form integration, and mobile-opti
### Disabled
<Preview class="w-full max-w-48">
<Preview>
<select class="select w-full" aria-label="Fruit" disabled>
<option value="">Select a fruit</option>
<option value="apple">Apple</option>
@@ -58,7 +85,7 @@ Use Native Select for native browser behavior, form integration, and mobile-opti
### Invalid
<Preview class="w-full max-w-48">
<Preview>
<div role="group" class="field" data-invalid="true">
<label for="native-select-invalid">Fruit</label>
<select id="native-select-invalid" class="select w-full" aria-invalid="true" aria-describedby="native-select-invalid-error">
@@ -91,7 +118,7 @@ Use Native Select for native browser behavior, form integration, and mobile-opti
Set `dir="rtl"` on the select or a parent element.
<Preview class="w-full max-w-48">
<Preview>
<select dir="rtl" class="select w-full" aria-label="الفاكهة">
<option value="">اختر فاكهة</option>
<option value="apple">تفاح</option>
+48 -49
View File
@@ -9,28 +9,18 @@
<ul class="flex flex-row items-center gap-1">
<li>
<a href="#" class="btn" data-variant="ghost">
<svg class="lucide lucide-chevron-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="m15 18-6-6 6-6" /></svg>
<svg class="lucide lucide-chevron-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6" /></svg>
<span>Previous</span>
</a>
</li>
<li>
<a href="#" class="btn" data-variant="ghost" data-size="icon">1</a>
</li>
<li>
<a href="#" class="btn" data-variant="outline" data-size="icon">2</a>
</li>
<li>
<a href="#" class="btn" data-variant="ghost" data-size="icon">3</a>
</li>
<li>
<div class="size-9 flex items-center justify-center">
<svg class="size-4 shrink-0 lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg>
</div>
</li>
<li><a href="#" class="btn" data-variant="ghost" data-size="icon">1</a></li>
<li><a href="#" class="btn" data-variant="outline" data-size="icon">2</a></li>
<li><a href="#" class="btn" data-variant="ghost" data-size="icon">3</a></li>
<li><div class="size-9 flex items-center justify-center"><svg class="size-4 shrink-0 lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg></div></li>
<li>
<a href="#" class="btn" data-variant="ghost">
<span>Next</span>
<svg class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="m9 18 6-6-6-6" /></svg>
<svg class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</a>
</li>
</ul>
@@ -39,6 +29,32 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Pagination component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/button.css";
@import "basecoat-css/styles/vega.css";
```
Pagination uses Button component CSS for its links and controls.
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your pagination HTML">
A pagination is fairly simple to implement with Tailwind using the Basecoat button classes:
```html
@@ -46,34 +62,27 @@ A pagination is fairly simple to implement with Tailwind using the Basecoat butt
<ul class="flex flex-row items-center gap-1">
<li>
<a href="#" class="btn" data-variant="ghost">
<svg class="lucide lucide-chevron-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="m15 18-6-6 6-6" /></svg>
<svg class="lucide lucide-chevron-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6" /></svg>
Previous
</a>
</li>
<li>
<a href="#" class="btn" data-variant="ghost" data-size="icon">1</a>
</li>
<li>
<a href="#" class="btn" data-variant="outline" data-size="icon">2</a>
</li>
<li>
<a href="#" class="btn" data-variant="ghost" data-size="icon">3</a>
</li>
<li>
<div class="size-9 flex items-center justify-center">
<svg class="size-4 shrink-0 lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg>
</div>
</li>
<li><a href="#" class="btn" data-variant="ghost" data-size="icon">1</a></li>
<li><a href="#" class="btn" data-variant="outline" data-size="icon">2</a></li>
<li><a href="#" class="btn" data-variant="ghost" data-size="icon">3</a></li>
<li><div class="size-9 flex items-center justify-center"><svg class="size-4 shrink-0 lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg></div></li>
<li>
<a href="#" class="btn" data-variant="ghost">
Next
<svg class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="m9 18 6-6-6-6" /></svg>
Next
<svg class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
</a>
</li>
</ul>
</nav>
```
</Step>
</Steps>
## Examples
### RTL
@@ -85,28 +94,18 @@ Pagination uses document direction and logical spacing. Set `dir="rtl"` on the p
<ul class="flex flex-row items-center gap-1">
<li>
<a href="#" class="btn" data-variant="ghost">
<svg class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="m9 18 6-6-6-6" /></svg>
<svg class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
<span>السابق</span>
</a>
</li>
<li>
<a href="#" class="btn" data-variant="ghost" data-size="icon">١</a>
</li>
<li>
<a href="#" class="btn" data-variant="outline" data-size="icon">٢</a>
</li>
<li>
<a href="#" class="btn" data-variant="ghost" data-size="icon">٣</a>
</li>
<li>
<div class="size-9 flex items-center justify-center">
<svg class="size-4 shrink-0 lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg>
</div>
</li>
<li><a href="#" class="btn" data-variant="ghost" data-size="icon">١</a></li>
<li><a href="#" class="btn" data-variant="outline" data-size="icon">٢</a></li>
<li><a href="#" class="btn" data-variant="ghost" data-size="icon">٣</a></li>
<li><div class="size-9 flex items-center justify-center"><svg class="size-4 shrink-0 lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" /></svg></div></li>
<li>
<a href="#" class="btn" data-variant="ghost">
<span>التالي</span>
<svg class="lucide lucide-chevron-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="m15 18-6-6 6-6" /></svg>
<svg class="lucide lucide-chevron-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6" /></svg>
</a>
</li>
</ul>
+50 -12
View File
@@ -8,7 +8,7 @@
<h4>Dimensions</h4>
<p>Set the dimensions for the layer.</p>
</header>
<form class="grid gap-2">
<form class="grid gap-2" onsubmit="event.preventDefault()">
<div class="grid grid-cols-3 items-center gap-4">
<label for="demo-popover-width">Width</label>
<input type="text" id="demo-popover-width" value="100%" class="input col-span-2 h-8" autofocus />
@@ -39,13 +39,44 @@
Basecoat popovers are inline-positioned relative to the `.popover` wrapper. This differs from shadcn/ui's portalled Base UI implementation, but keeps the markup dependency-free and works with Basecoat's existing dropdown/select positioning model.
<Steps>
<Step title="Include the JavaScript files">
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Popover component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/popover.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Include JavaScript">
Copy or serve the full Basecoat JavaScript bundle.
```html
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/popover.min.js" defer></script>
<script src="/assets/js/all.min.js" defer></script>
```
Or copy or serve the Basecoat runtime and Popover script.
```html
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/popover.min.js" defer></script>
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your popover HTML">
@@ -57,7 +88,7 @@ Basecoat popovers are inline-positioned relative to the `.popover` wrapper. This
<h4>Dimensions</h4>
<p>Set the dimensions for the layer.</p>
</header>
<form class="grid gap-2">
<form class="grid gap-2" onsubmit="event.preventDefault()">
<div class="grid grid-cols-3 items-center gap-4">
<label for="demo-popover-width">Width</label>
<input type="text" id="demo-popover-width" value="100%" class="input col-span-2 h-8" autofocus />
@@ -92,7 +123,7 @@ Basecoat popovers are inline-positioned relative to the `.popover` wrapper. This
<dt><code>&lt;button type="button" aria-expanded="false" aria-controls="&#123; POPOVER_ID &#125;"&gt;</code></dt>
<dd>Trigger button. The script toggles <code>aria-expanded</code> and opens or closes the content.</dd>
<dt><code>&lt;div data-popover id="&#123; POPOVER_ID &#125;" aria-hidden="true"&gt;</code></dt>
<dd>Popover content. Supports <code>data-side="top|right|bottom|left"</code> and <code>data-align="start|center|end"</code>.</dd>
<dd>Popover content. Supports <code>data-side="top|right|bottom|left|inline-start|inline-end"</code> and <code>data-align="start|center|end"</code>.</dd>
</dl>
</dd>
</dl>
@@ -123,14 +154,12 @@ Basecoat popovers are inline-positioned relative to the `.popover` wrapper. This
<p>Aligned to start.</p>
</div>
</div>
<div id="popover-align-center" class="popover">
<button id="popover-align-center-trigger" type="button" aria-expanded="false" aria-controls="popover-align-center-popover" class="btn" data-variant="outline">Center</button>
<div id="popover-align-center-popover" data-popover aria-hidden="true" class="w-56" data-align="center">
<p>Aligned to center.</p>
</div>
</div>
<div id="popover-align-end" class="popover">
<button id="popover-align-end-trigger" type="button" aria-expanded="false" aria-controls="popover-align-end-popover" class="btn" data-variant="outline">End</button>
<div id="popover-align-end-popover" data-popover aria-hidden="true" class="w-56" data-align="end">
@@ -144,33 +173,42 @@ Basecoat popovers are inline-positioned relative to the `.popover` wrapper. This
<Preview>
<div class="flex flex-wrap gap-3">
<div id="popover-side-inline-start" class="popover">
<button id="popover-side-inline-start-trigger" type="button" aria-expanded="false" aria-controls="popover-side-inline-start-popover" class="btn" data-variant="outline">Inline start</button>
<div id="popover-side-inline-start-popover" data-popover aria-hidden="true" data-side="inline-start" data-align="center" class="w-40">
<p>Inline start side.</p>
</div>
</div>
<div id="popover-side-top" class="popover">
<button id="popover-side-top-trigger" type="button" aria-expanded="false" aria-controls="popover-side-top-popover" class="btn" data-variant="outline">Top</button>
<div id="popover-side-top-popover" data-popover aria-hidden="true" data-side="top" data-align="center" class="w-40">
<p>Top side.</p>
</div>
</div>
<div id="popover-side-right" class="popover">
<button id="popover-side-right-trigger" type="button" aria-expanded="false" aria-controls="popover-side-right-popover" class="btn" data-variant="outline">Right</button>
<div id="popover-side-right-popover" data-popover aria-hidden="true" data-side="right" data-align="center" class="w-40">
<p>Right side.</p>
</div>
</div>
<div id="popover-side-bottom" class="popover">
<button id="popover-side-bottom-trigger" type="button" aria-expanded="false" aria-controls="popover-side-bottom-popover" class="btn" data-variant="outline">Bottom</button>
<div id="popover-side-bottom-popover" data-popover aria-hidden="true" data-side="bottom" data-align="center" class="w-40">
<p>Bottom side.</p>
</div>
</div>
<div id="popover-side-left" class="popover">
<button id="popover-side-left-trigger" type="button" aria-expanded="false" aria-controls="popover-side-left-popover" class="btn" data-variant="outline">Left</button>
<div id="popover-side-left-popover" data-popover aria-hidden="true" data-side="left" data-align="center" class="w-40">
<p>Left side.</p>
</div>
</div>
<div id="popover-side-inline-end" class="popover">
<button id="popover-side-inline-end-trigger" type="button" aria-expanded="false" aria-controls="popover-side-inline-end-popover" class="btn" data-variant="outline">Inline end</button>
<div id="popover-side-inline-end-popover" data-popover aria-hidden="true" data-side="inline-end" data-align="center" class="w-40">
<p>Inline end side.</p>
</div>
</div>
</div>
</Preview>
@@ -184,7 +222,7 @@ Basecoat popovers are inline-positioned relative to the `.popover` wrapper. This
<h4>Dimensions</h4>
<p>Set the dimensions for the layer.</p>
</header>
<form class="grid gap-2">
<form class="grid gap-2" onsubmit="event.preventDefault()">
<div class="grid grid-cols-3 items-center gap-4">
<label for="popover-form-width">Width</label>
<input type="text" id="popover-form-width" value="100%" class="input col-span-2 h-8" autofocus />
+48 -9
View File
@@ -1,13 +1,46 @@
# Progress
<Preview>
<div class="progress max-w-sm" role="progressbar" aria-label="Loading" aria-valuenow="66" aria-valuemin="0" aria-valuemax="100">
<span style="width: 66%"></span>
<Preview class="w-full max-w-sm">
<div id="progress-demo" class="progress" role="progressbar" aria-label="Loading" aria-valuenow="13" aria-valuemin="0" aria-valuemax="100">
<span style="width: 13%"></span>
</div>
<script>{`
setTimeout(() => {
const progress = document.getElementById("progress-demo");
const indicator = progress?.querySelector("span");
if (!progress || !indicator) return;
progress.setAttribute("aria-valuenow", "66");
indicator.style.width = "66%";
}, 500);
`}</script>
</Preview>
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Progress component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/progress.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your progress HTML">
Add `class="progress"` and `role="progressbar"` to the root. Use one child `<span>` as the visual indicator.
```html
@@ -16,6 +49,9 @@ Add `class="progress"` and `role="progressbar"` to the root. Use one child `<spa
</div>
```
</Step>
</Steps>
### HTML structure
<dl>
@@ -29,8 +65,8 @@ Add `class="progress"` and `role="progressbar"` to the root. Use one child `<spa
### Label
<Preview>
<div class="field max-w-sm">
<Preview class="w-full max-w-sm">
<div class="field">
<div class="flex items-center gap-3 text-sm">
<label id="progress-label">Upload progress</label>
<output class="ms-auto tabular-nums">66%</output>
@@ -43,10 +79,13 @@ Add `class="progress"` and `role="progressbar"` to the root. Use one child `<spa
### RTL
Progress uses logical direction. Set `dir="rtl"` on the progress root or a parent to fill from the right.
Progress supports `dir="rtl"` on the root or a parent.
<Preview>
<div dir="rtl" class="progress max-w-sm" role="progressbar" aria-label="تحميل" aria-valuenow="66" aria-valuemin="0" aria-valuemax="100">
<span style="width: 66%"></span>
<Preview class="w-full max-w-sm">
<div class="field w-full" dir="rtl">
<label id="progress-upload-rtl" for="progress-upload">تقدم الرفع <span class="ms-auto">٦٦%</span></label>
<div id="progress-upload" class="progress" role="progressbar" aria-labelledby="progress-upload-rtl" aria-valuenow="66" aria-valuemin="0" aria-valuemax="100">
<span style="width: 66%"></span>
</div>
</div>
</Preview>
+158 -93
View File
@@ -1,93 +1,123 @@
# Radio Group
<Preview class="w-full max-w-sm">
<fieldset class="fieldset">
<legend>Plan</legend>
<div role="radiogroup" aria-label="Plan" data-slot="radio-group">
<div role="group" class="field flex-row items-center gap-3">
<input type="radio" id="plan-free" name="plan" value="free" class="input" checked />
<label for="plan-free">Free</label>
</div>
<div role="group" class="field flex-row items-center gap-3">
<input type="radio" id="plan-pro" name="plan" value="pro" class="input" />
<label for="plan-pro">Pro</label>
</div>
<Preview>
<div role="radiogroup" aria-label="View density" data-slot="radio-group" class="w-fit">
<div class="flex items-center gap-3">
<input type="radio" id="r1" name="radio-demo" value="default" class="input" />
<label for="r1">Default</label>
</div>
</fieldset>
<div class="flex items-center gap-3">
<input type="radio" id="r2" name="radio-demo" value="comfortable" class="input" checked />
<label for="r2">Comfortable</label>
</div>
<div class="flex items-center gap-3">
<input type="radio" id="r3" name="radio-demo" value="compact" class="input" />
<label for="r3">Compact</label>
</div>
</div>
</Preview>
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Radio Group component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/field.css";
@import "basecoat-css/components/radio.css";
@import "basecoat-css/styles/vega.css";
```
Radio Group uses Radio styles and composes Field styles in the richer examples.
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your radio group HTML">
Add `class="input"` to radio inputs. Use a shared `name` attribute for mutually exclusive options, and wrap related options in a semantic `<fieldset>` or an element with `role="radiogroup"`.
```html
<input type="radio" name="plan" class="input" />
```
</Step>
</Steps>
## Examples
### Basic
<Preview class="w-full max-w-sm">
<div role="radiogroup" aria-label="View density" data-slot="radio-group">
<div role="group" class="field flex-row items-center gap-3">
<input type="radio" id="density-default" name="density" value="default" class="input" />
<label for="density-default">Default</label>
</div>
<div role="group" class="field flex-row items-center gap-3">
<input type="radio" id="density-comfortable" name="density" value="comfortable" class="input" checked />
<label for="density-comfortable">Comfortable</label>
</div>
<div role="group" class="field flex-row items-center gap-3">
<input type="radio" id="density-compact" name="density" value="compact" class="input" />
<label for="density-compact">Compact</label>
</div>
</div>
</Preview>
### Description
<Preview class="w-full max-w-sm">
<div role="radiogroup" aria-label="Notifications" data-slot="radio-group">
<div role="group" class="field flex-row items-start gap-3">
<input type="radio" id="notify-all" name="notifications" value="all" class="input" checked aria-describedby="notify-all-description" />
Radio group items with a description using the `Field` component.
<Preview>
<div role="radiogroup" aria-label="View density" data-slot="radio-group" class="w-fit">
<div role="group" class="field" data-orientation="horizontal">
<input type="radio" id="desc-r1" name="radio-description" value="default" class="input" />
<section>
<label for="notify-all">All new messages</label>
<p id="notify-all-description">Receive a notification for every new message.</p>
<label for="desc-r1">Default</label>
<p>Standard spacing for most use cases.</p>
</section>
</div>
<div role="group" class="field flex-row items-start gap-3">
<input type="radio" id="notify-mentions" name="notifications" value="mentions" class="input" aria-describedby="notify-mentions-description" />
<div role="group" class="field" data-orientation="horizontal">
<input type="radio" id="desc-r2" name="radio-description" value="comfortable" class="input" checked />
<section>
<label for="notify-mentions">Direct messages and mentions</label>
<p id="notify-mentions-description">Only notify me for direct messages and mentions.</p>
<label for="desc-r2">Comfortable</label>
<p>More space between elements.</p>
</section>
</div>
<div role="group" class="field" data-orientation="horizontal">
<input type="radio" id="desc-r3" name="radio-description" value="compact" class="input" />
<section>
<label for="desc-r3">Compact</label>
<p>Minimal spacing for dense layouts.</p>
</section>
</div>
</div>
</Preview>
### Choice card
### Choice Card
Wrap a `.field` in a native `<label>` when the whole card should select the option.
Use a native `<label>` to wrap the entire `.field` for a clickable card-style selection.
<Preview class="w-full">
<Preview class="w-full max-w-sm">
<div role="radiogroup" aria-label="Plans" data-slot="radio-group" class="w-full max-w-md">
<label>
<div role="group" class="field flex-row items-center justify-between">
<label for="plus-plan">
<div role="group" class="field" data-orientation="horizontal">
<section>
<span>Starter</span>
<span>For small teams getting started.</span>
<h3>Plus</h3>
<p>For individuals and small teams.</p>
</section>
<input type="radio" name="choice-plan" value="starter" class="input" checked />
<input type="radio" id="plus-plan" name="choice-plan" value="plus" class="input" checked />
</div>
</label>
<label>
<div role="group" class="field flex-row items-center justify-between">
<label for="pro-plan">
<div role="group" class="field" data-orientation="horizontal">
<section>
<span>Team</span>
<span>Collaboration tools for growing teams.</span>
<h3>Pro</h3>
<p>For growing businesses.</p>
</section>
<input type="radio" name="choice-plan" value="team" class="input" />
<input type="radio" id="pro-plan" name="choice-plan" value="pro" class="input" />
</div>
</label>
<label for="enterprise-plan">
<div role="group" class="field" data-orientation="horizontal">
<section>
<h3>Enterprise</h3>
<p>For large teams and enterprises.</p>
</section>
<input type="radio" id="enterprise-plan" name="choice-plan" value="enterprise" class="input" />
</div>
</label>
</div>
@@ -95,21 +125,24 @@ Wrap a `.field` in a native `<label>` when the whole card should select the opti
### Fieldset
<Preview class="w-full max-w-sm">
Use a native `<fieldset>` and `<legend>` to group radio items with a label and description.
<Preview>
<fieldset class="fieldset">
<legend>Notify me about...</legend>
<div role="radiogroup" aria-label="Notification preference" data-slot="radio-group">
<div role="group" class="field flex-row items-center gap-3">
<input class="input" type="radio" id="notify-all-fieldset" name="notify-fieldset" value="all" checked />
<label for="notify-all-fieldset">All new messages</label>
<legend data-variant="label">Subscription Plan</legend>
<p>Yearly and lifetime plans offer significant savings.</p>
<div role="radiogroup" aria-label="Subscription plan" data-slot="radio-group">
<div role="group" class="field" data-orientation="horizontal">
<input type="radio" id="plan-monthly" name="subscription-plan" value="monthly" class="input" checked />
<label for="plan-monthly" class="font-normal">Monthly ($9.99/month)</label>
</div>
<div role="group" class="field flex-row items-center gap-3">
<input class="input" type="radio" id="notify-mentions-fieldset" name="notify-fieldset" value="mentions" />
<label for="notify-mentions-fieldset">Direct messages and mentions</label>
<div role="group" class="field" data-orientation="horizontal">
<input type="radio" id="plan-yearly" name="subscription-plan" value="yearly" class="input" />
<label for="plan-yearly" class="font-normal">Yearly ($99.99/year)</label>
</div>
<div role="group" class="field flex-row items-center gap-3">
<input class="input" type="radio" id="notify-none-fieldset" name="notify-fieldset" value="none" />
<label for="notify-none-fieldset">Nothing</label>
<div role="group" class="field" data-orientation="horizontal">
<input type="radio" id="plan-lifetime" name="subscription-plan" value="lifetime" class="input" />
<label for="plan-lifetime" class="font-normal">Lifetime ($299.99)</label>
</div>
</div>
</fieldset>
@@ -117,44 +150,76 @@ Wrap a `.field` in a native `<label>` when the whole card should select the opti
### Disabled
<Preview class="w-full max-w-sm">
<div role="radiogroup" aria-label="Disabled notifications" data-slot="radio-group">
<div role="group" class="field flex-row items-center gap-3" data-disabled="true">
<input type="radio" id="radio-disabled" name="radio-disabled" class="input" disabled />
<label for="radio-disabled">Disabled option</label>
Use the `disabled` attribute to disable individual items.
<Preview>
<div role="radiogroup" aria-label="Disabled options" data-slot="radio-group" class="w-fit">
<div role="group" class="field" data-orientation="horizontal" data-disabled>
<input type="radio" id="disabled-1" name="radio-disabled" value="option1" class="input" disabled />
<label for="disabled-1" class="font-normal">Disabled</label>
</div>
<div role="group" class="field flex-row items-center gap-3" data-disabled="true">
<input type="radio" id="radio-disabled-checked" name="radio-disabled" class="input" checked disabled />
<label for="radio-disabled-checked">Disabled checked option</label>
<div role="group" class="field" data-orientation="horizontal">
<input type="radio" id="disabled-2" name="radio-disabled" value="option2" class="input" checked />
<label for="disabled-2" class="font-normal">Option 2</label>
</div>
<div role="group" class="field" data-orientation="horizontal">
<input type="radio" id="disabled-3" name="radio-disabled" value="option3" class="input" />
<label for="disabled-3" class="font-normal">Option 3</label>
</div>
</div>
</Preview>
### Invalid
<Preview class="w-full max-w-sm">
<div role="group" class="field flex-row items-start gap-3" data-invalid="true">
<input type="radio" id="radio-invalid" name="radio-invalid" class="input" aria-invalid="true" aria-describedby="radio-invalid-error" />
<section>
<label for="radio-invalid">I agree to the terms</label>
<p id="radio-invalid-error" role="alert">You must select an option to continue.</p>
</section>
</div>
Use `aria-invalid="true"` on radio inputs and `data-invalid` on fields to show validation errors.
<Preview>
<fieldset class="fieldset">
<legend data-variant="label">Notification Preferences</legend>
<p>Choose how you want to receive notifications.</p>
<div role="radiogroup" aria-label="Notification preferences" data-slot="radio-group">
<div role="group" class="field" data-orientation="horizontal" data-invalid>
<input type="radio" id="invalid-email" name="notification-preference" value="email" class="input" aria-invalid="true" checked />
<label for="invalid-email" class="font-normal">Email only</label>
</div>
<div role="group" class="field" data-orientation="horizontal" data-invalid>
<input type="radio" id="invalid-sms" name="notification-preference" value="sms" class="input" aria-invalid="true" />
<label for="invalid-sms" class="font-normal">SMS only</label>
</div>
<div role="group" class="field" data-orientation="horizontal" data-invalid>
<input type="radio" id="invalid-both" name="notification-preference" value="both" class="input" aria-invalid="true" />
<label for="invalid-both" class="font-normal">Both Email & SMS</label>
</div>
</div>
</fieldset>
</Preview>
### RTL
## RTL
Radio group layout uses document direction and logical spacing. Set `dir="rtl"` on a parent to render right-to-left.
Set `dir="rtl"` on the radio group or an ancestor.
<Preview class="w-full max-w-sm">
<div dir="rtl" role="radiogroup" aria-label="طريقة العرض" data-slot="radio-group">
<div role="group" class="field flex-row items-center gap-3">
<input type="radio" id="radio-rtl-default" name="radio-rtl" value="default" class="input" checked />
<label for="radio-rtl-default">افتراضي</label>
<Preview>
<div dir="rtl" role="radiogroup" aria-label="كثافة العرض" data-slot="radio-group" class="w-fit">
<div role="group" class="field" data-orientation="horizontal">
<input type="radio" id="r1-rtl" name="radio-rtl" value="default" class="input" />
<section>
<label for="r1-rtl">افتراضي</label>
<p>تباعد قياسي لمعظم حالات الاستخدام.</p>
</section>
</div>
<div role="group" class="field flex-row items-center gap-3">
<input type="radio" id="radio-rtl-comfortable" name="radio-rtl" value="comfortable" class="input" />
<label for="radio-rtl-comfortable">مريح</label>
<div role="group" class="field" data-orientation="horizontal">
<input type="radio" id="r2-rtl" name="radio-rtl" value="comfortable" class="input" checked />
<section>
<label for="r2-rtl">مريح</label>
<p>مساحة أكبر بين العناصر.</p>
</section>
</div>
<div role="group" class="field" data-orientation="horizontal">
<input type="radio" id="r3-rtl" name="radio-rtl" value="compact" class="input" />
<section>
<label for="r3-rtl">مضغوط</label>
<p>تباعد أدنى للتخطيطات الكثيفة.</p>
</section>
</div>
</div>
</Preview>
+28
View File
@@ -25,6 +25,31 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/styles/vega.css";
```
Scroll Area uses Basecoat base scrollbar utilities and has no dedicated component CSS file.
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your scroll area HTML">
Use `scrollbar` or `scrollbar-sm` on an element that already scrolls with `overflow-auto`, `overflow-y-auto`, or `overflow-x-auto`.
```html
@@ -33,6 +58,9 @@ Use `scrollbar` or `scrollbar-sm` on an element that already scrolls with `overf
</div>
```
</Step>
</Steps>
Use `scrollbar` or `scrollbar-sm` on an element that already scrolls with `overflow-auto`, `overflow-y-auto`, or `overflow-x-auto`.
The utility augments native scrolling for cross-browser styling. It does not wrap content, replace browser scroll behavior, or require JavaScript.
+161 -286
View File
@@ -1,19 +1,24 @@
# Select
<Preview>
<div id="select-855441" class="select">
<button type="button" class="w-[180px]" id="select-855441-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-855441-listbox">
<span class="truncate">Light</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
<div id="select-demo" class="select" data-placeholder="Select a fruit">
<button type="button" class="w-[180px]" id="select-demo-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-demo-listbox">
<span class="truncate">Select a fruit</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
</button>
<div id="select-855441-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-855441-listbox" aria-orientation="vertical" aria-labelledby="select-855441-trigger">
<div id="select-855441-items-1" role="option" data-value="light">Light</div>
<div id="select-855441-items-2" role="option" data-value="dark">Dark</div>
<div id="select-855441-items-3" role="option" data-value="system">System</div>
<div id="select-demo-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-demo-listbox" aria-orientation="vertical" aria-labelledby="select-demo-trigger">
<div role="group" aria-labelledby="select-demo-fruits">
<span role="heading" id="select-demo-fruits">Fruits</span>
<div role="option" data-value="apple">Apple</div>
<div role="option" data-value="banana">Banana</div>
<div role="option" data-value="blueberry">Blueberry</div>
<div role="option" data-value="grapes">Grapes</div>
<div role="option" data-value="pineapple">Pineapple</div>
</div>
</div>
</div>
<input type="hidden" name="select-855441-value" value="light" />
<input type="hidden" name="select-demo-value" value="" />
</div>
</Preview>
@@ -24,30 +29,61 @@
</Callout>
<Steps>
<Step title="Include the JavaScript files">
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Select component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/select.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Include JavaScript">
Copy or serve the full Basecoat JavaScript bundle.
```html
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/select.min.js" defer></script>
<script src="/assets/js/all.min.js" defer></script>
```
Or copy or serve the Basecoat runtime and Select script.
```html
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/select.min.js" defer></script>
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your select HTML">
```html
<div id="select-855441" class="select">
<button type="button" class="w-[180px]" id="select-855441-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-855441-listbox">
<span class="truncate">Light</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
<div id="select-theme" class="select" data-placeholder="Theme">
<button type="button" class="w-[180px]" id="select-theme-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-theme-listbox">
<span class="truncate">Theme</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
</button>
<div id="select-855441-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-855441-listbox" aria-orientation="vertical" aria-labelledby="select-855441-trigger">
<div id="select-855441-items-1" role="option" data-value="light">Light</div>
<div id="select-855441-items-2" role="option" data-value="dark">Dark</div>
<div id="select-855441-items-3" role="option" data-value="system">System</div>
<div id="select-theme-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-theme-listbox" aria-orientation="vertical" aria-labelledby="select-theme-trigger">
<div role="option" data-value="light">Light</div>
<div role="option" data-value="dark">Dark</div>
<div role="option" data-value="system">System</div>
</div>
</div>
<input type="hidden" name="select-855441-value" value="light" />
<input type="hidden" name="theme" value="" />
</div>
```
@@ -59,13 +95,13 @@
<dl>
<dt><code>&lt;div class="select"&gt;</code></dt>
<dd>
Select root. Supports <code>data-placeholder</code>, <code>data-close-on-select="true"</code>, and <code>data-format="object"</code>.
Select root. Add <code>data-placeholder</code> to show placeholder text when no value is selected. Supports <code>data-close-on-select="true"</code> for multiple select and <code>data-format="object"</code> for serialized object values.
<dl>
<dt><code>&lt;button type="button"&gt;</code></dt>
<dd>Trigger button. Use <code>aria-haspopup="listbox"</code>, <code>aria-expanded</code>, and <code>aria-controls</code>.</dd>
<dt><code>&lt;div data-popover aria-hidden="true"&gt;</code></dt>
<dd>
Popover content. Supports <code>data-side</code> and <code>data-align</code> through the shared popover rules.
Popover content. Supports <code>data-side</code> and <code>data-align</code> through the shared Popover rules.
<dl>
<dt><code>&lt;div role="listbox"&gt;</code></dt>
<dd>
@@ -84,7 +120,7 @@
</dl>
</dd>
<dt><code>&lt;input type="hidden"&gt;</code></dt>
<dd>Submitted value. Single select stores a string; multiselect stores a JSON array. With <code>data-format="object"</code>, values are serialized as <code>&#123; value, label &#125;</code> objects.</dd>
<dd>Submitted value. Empty value means no selection when the root has <code>data-placeholder</code>. Single select stores a string; multiple select stores a JSON array. With <code>data-format="object"</code>, values are serialized as <code>&#123; value, label &#125;</code> objects.</dd>
</dl>
</dd>
</dl>
@@ -98,324 +134,163 @@
## Examples
### Align
Use `data-align` on the popover to align the list to the trigger edge. Basecoat keeps the popup below the control; it does not implement shadcn/ui's selected-item-over-trigger positioning.
<Preview>
<div class="flex flex-wrap gap-3">
<div id="select-align-start" class="select">
<button type="button" class="w-[180px]" id="select-align-start-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-align-start-listbox">
<span class="truncate">Light</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
</button>
<div id="select-align-start-popover" data-popover aria-hidden="true" data-align="start" class="w-72">
<div role="listbox" id="select-align-start-listbox" aria-orientation="vertical" aria-labelledby="select-align-start-trigger">
<div id="select-align-start-items-1" role="option" data-value="light">Light</div>
<div id="select-align-start-items-2" role="option" data-value="dark">Dark</div>
<div id="select-align-start-items-3" role="option" data-value="system">System</div>
</div>
</div>
<input type="hidden" name="select-align-start-value" value="light" />
</div>
<div id="select-align-end" class="select">
<button type="button" class="w-[180px]" id="select-align-end-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-align-end-listbox">
<span class="truncate">Light</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
</button>
<div id="select-align-end-popover" data-popover aria-hidden="true" data-align="end" class="w-72">
<div role="listbox" id="select-align-end-listbox" aria-orientation="vertical" aria-labelledby="select-align-end-trigger">
<div id="select-align-end-items-1" role="option" data-value="light">Light</div>
<div id="select-align-end-items-2" role="option" data-value="dark">Dark</div>
<div id="select-align-end-items-3" role="option" data-value="system">System</div>
</div>
</div>
<input type="hidden" name="select-align-end-value" value="light" />
</div>
</div>
</Preview>
### Groups
<Preview>
<div id="select-groups" class="select" data-placeholder="Select food...">
<button type="button" class="w-[220px]" id="select-groups-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-groups-listbox">
<span class="truncate">Banana</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
<div id="select-groups" class="select" data-placeholder="Select a fruit">
<button type="button" class="w-[180px]" id="select-groups-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-groups-listbox">
<span class="truncate">Select a fruit</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
</button>
<div id="select-groups-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-groups-listbox" aria-orientation="vertical" aria-labelledby="select-groups-trigger">
<div role="group" aria-labelledby="select-groups-fruits">
<div role="heading" id="select-groups-fruits">Fruits</div>
<span role="heading" id="select-groups-fruits">Fruits</span>
<div role="option" data-value="apple">Apple</div>
<div role="option" data-value="banana" aria-selected="true">Banana</div>
<div role="option" data-value="banana">Banana</div>
<div role="option" data-value="blueberry">Blueberry</div>
</div>
<hr role="separator" />
<div role="group" aria-labelledby="select-groups-vegetables">
<div role="heading" id="select-groups-vegetables">Vegetables</div>
<span role="heading" id="select-groups-vegetables">Vegetables</span>
<div role="option" data-value="carrot">Carrot</div>
<div role="option" data-value="potato">Potato</div>
<div role="option" data-value="tomato">Tomato</div>
<div role="option" data-value="broccoli">Broccoli</div>
<div role="option" data-value="spinach">Spinach</div>
</div>
</div>
</div>
<input type="hidden" name="select-groups-value" value="banana" />
<input type="hidden" name="select-groups-value" value="" />
</div>
</Preview>
### Scrollable
A select with many items that scrolls.
<Preview>
<div id="select-679828" class="select" data-placeholder="Select an item...">
<button type="button" class="w-[180px]" id="select-679828-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-679828-listbox">
<span class="truncate">Item 0</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
<div id="select-scrollable" class="select" data-placeholder="Select a timezone">
<button type="button" class="w-[280px]" id="select-scrollable-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-scrollable-listbox">
<span class="truncate">Select a timezone</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
</button>
<div id="select-679828-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-679828-listbox" aria-orientation="vertical" aria-labelledby="select-679828-trigger" class="scrollbar-sm overflow-y-auto max-h-64">
<div role="option" data-value="item-0" aria-selected="true">Item 0</div>
<div role="option" data-value="item-1">Item 1</div>
<div role="option" data-value="item-2">Item 2</div>
<div role="option" data-value="item-3">Item 3</div>
<div role="option" data-value="item-4">Item 4</div>
<div role="option" data-value="item-5">Item 5</div>
<div role="option" data-value="item-6">Item 6</div>
<div role="option" data-value="item-7">Item 7</div>
<div role="option" data-value="item-8">Item 8</div>
<div role="option" data-value="item-9">Item 9</div>
<div role="option" data-value="item-10">Item 10</div>
<div role="option" data-value="item-11">Item 11</div>
<div role="option" data-value="item-12">Item 12</div>
<div role="option" data-value="item-13">Item 13</div>
<div role="option" data-value="item-14">Item 14</div>
<div role="option" data-value="item-15">Item 15</div>
<div role="option" data-value="item-16">Item 16</div>
<div role="option" data-value="item-17">Item 17</div>
<div role="option" data-value="item-18">Item 18</div>
<div role="option" data-value="item-19">Item 19</div>
<div role="option" data-value="item-20">Item 20</div>
<div role="option" data-value="item-21">Item 21</div>
<div role="option" data-value="item-22">Item 22</div>
<div role="option" data-value="item-23">Item 23</div>
<div role="option" data-value="item-24">Item 24</div>
<div role="option" data-value="item-25">Item 25</div>
<div role="option" data-value="item-26">Item 26</div>
<div role="option" data-value="item-27">Item 27</div>
<div role="option" data-value="item-28">Item 28</div>
<div role="option" data-value="item-29">Item 29</div>
<div role="option" data-value="item-30">Item 30</div>
<div role="option" data-value="item-31">Item 31</div>
<div role="option" data-value="item-32">Item 32</div>
<div role="option" data-value="item-33">Item 33</div>
<div role="option" data-value="item-34">Item 34</div>
<div role="option" data-value="item-35">Item 35</div>
<div role="option" data-value="item-36">Item 36</div>
<div role="option" data-value="item-37">Item 37</div>
<div role="option" data-value="item-38">Item 38</div>
<div role="option" data-value="item-39">Item 39</div>
<div role="option" data-value="item-40">Item 40</div>
<div role="option" data-value="item-41">Item 41</div>
<div role="option" data-value="item-42">Item 42</div>
<div role="option" data-value="item-43">Item 43</div>
<div role="option" data-value="item-44">Item 44</div>
<div role="option" data-value="item-45">Item 45</div>
<div role="option" data-value="item-46">Item 46</div>
<div role="option" data-value="item-47">Item 47</div>
<div role="option" data-value="item-48">Item 48</div>
<div role="option" data-value="item-49">Item 49</div>
<div role="option" data-value="item-50">Item 50</div>
<div role="option" data-value="item-51">Item 51</div>
<div role="option" data-value="item-52">Item 52</div>
<div role="option" data-value="item-53">Item 53</div>
<div role="option" data-value="item-54">Item 54</div>
<div role="option" data-value="item-55">Item 55</div>
<div role="option" data-value="item-56">Item 56</div>
<div role="option" data-value="item-57">Item 57</div>
<div role="option" data-value="item-58">Item 58</div>
<div role="option" data-value="item-59">Item 59</div>
<div role="option" data-value="item-60">Item 60</div>
<div role="option" data-value="item-61">Item 61</div>
<div role="option" data-value="item-62">Item 62</div>
<div role="option" data-value="item-63">Item 63</div>
<div role="option" data-value="item-64">Item 64</div>
<div role="option" data-value="item-65">Item 65</div>
<div role="option" data-value="item-66">Item 66</div>
<div role="option" data-value="item-67">Item 67</div>
<div role="option" data-value="item-68">Item 68</div>
<div role="option" data-value="item-69">Item 69</div>
<div role="option" data-value="item-70">Item 70</div>
<div role="option" data-value="item-71">Item 71</div>
<div role="option" data-value="item-72">Item 72</div>
<div role="option" data-value="item-73">Item 73</div>
<div role="option" data-value="item-74">Item 74</div>
<div role="option" data-value="item-75">Item 75</div>
<div role="option" data-value="item-76">Item 76</div>
<div role="option" data-value="item-77">Item 77</div>
<div role="option" data-value="item-78">Item 78</div>
<div role="option" data-value="item-79">Item 79</div>
<div role="option" data-value="item-80">Item 80</div>
<div role="option" data-value="item-81">Item 81</div>
<div role="option" data-value="item-82">Item 82</div>
<div role="option" data-value="item-83">Item 83</div>
<div role="option" data-value="item-84">Item 84</div>
<div role="option" data-value="item-85">Item 85</div>
<div role="option" data-value="item-86">Item 86</div>
<div role="option" data-value="item-87">Item 87</div>
<div role="option" data-value="item-88">Item 88</div>
<div role="option" data-value="item-89">Item 89</div>
<div role="option" data-value="item-90">Item 90</div>
<div role="option" data-value="item-91">Item 91</div>
<div role="option" data-value="item-92">Item 92</div>
<div role="option" data-value="item-93">Item 93</div>
<div role="option" data-value="item-94">Item 94</div>
<div role="option" data-value="item-95">Item 95</div>
<div role="option" data-value="item-96">Item 96</div>
<div role="option" data-value="item-97">Item 97</div>
<div role="option" data-value="item-98">Item 98</div>
<div id="select-scrollable-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-scrollable-listbox" class="scrollbar-sm max-h-70 overflow-y-auto" aria-orientation="vertical" aria-labelledby="select-scrollable-trigger">
<div role="group" aria-labelledby="select-scrollable-north-america">
<span role="heading" id="select-scrollable-north-america">North America</span>
<div role="option" data-value="est">Eastern Standard Time (EST)</div>
<div role="option" data-value="cst">Central Standard Time (CST)</div>
<div role="option" data-value="mst">Mountain Standard Time (MST)</div>
<div role="option" data-value="pst">Pacific Standard Time (PST)</div>
<div role="option" data-value="akst">Alaska Standard Time (AKST)</div>
<div role="option" data-value="hst">Hawaii Standard Time (HST)</div>
</div>
<div role="group" aria-labelledby="select-scrollable-europe-africa">
<span role="heading" id="select-scrollable-europe-africa">Europe &amp; Africa</span>
<div role="option" data-value="gmt">Greenwich Mean Time (GMT)</div>
<div role="option" data-value="cet">Central European Time (CET)</div>
<div role="option" data-value="eet">Eastern European Time (EET)</div>
<div role="option" data-value="west">Western European Summer Time (WEST)</div>
<div role="option" data-value="cat">Central Africa Time (CAT)</div>
<div role="option" data-value="eat">East Africa Time (EAT)</div>
</div>
<div role="group" aria-labelledby="select-scrollable-asia">
<span role="heading" id="select-scrollable-asia">Asia</span>
<div role="option" data-value="msk">Moscow Time (MSK)</div>
<div role="option" data-value="ist">India Standard Time (IST)</div>
<div role="option" data-value="cst_china">China Standard Time (CST)</div>
<div role="option" data-value="jst">Japan Standard Time (JST)</div>
<div role="option" data-value="kst">Korea Standard Time (KST)</div>
<div role="option" data-value="ist_indonesia">Indonesia Central Standard Time (WITA)</div>
</div>
<div role="group" aria-labelledby="select-scrollable-australia-pacific">
<span role="heading" id="select-scrollable-australia-pacific">Australia &amp; Pacific</span>
<div role="option" data-value="awst">Australian Western Standard Time (AWST)</div>
<div role="option" data-value="acst">Australian Central Standard Time (ACST)</div>
<div role="option" data-value="aest">Australian Eastern Standard Time (AEST)</div>
<div role="option" data-value="nzst">New Zealand Standard Time (NZST)</div>
<div role="option" data-value="fjt">Fiji Time (FJT)</div>
</div>
<div role="group" aria-labelledby="select-scrollable-south-america">
<span role="heading" id="select-scrollable-south-america">South America</span>
<div role="option" data-value="art">Argentina Time (ART)</div>
<div role="option" data-value="bot">Bolivia Time (BOT)</div>
<div role="option" data-value="brt">Brasilia Time (BRT)</div>
<div role="option" data-value="clt">Chile Standard Time (CLT)</div>
</div>
</div>
</div>
<input type="hidden" name="select-679828-value" value="item-0" />
<input type="hidden" name="select-scrollable-value" value="" />
</div>
</Preview>
### Disabled
<Preview>
<div id="select-877925" class="select">
<button type="button" class="w-[180px]" id="select-877925-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-877925-listbox" disabled="disabled">
<span class="truncate">Disabled</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
<div id="select-disabled" class="select" data-placeholder="Select a fruit">
<button type="button" class="w-[180px]" id="select-disabled-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-disabled-listbox" disabled>
<span class="truncate">Select a fruit</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
</button>
<div id="select-877925-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-877925-listbox" aria-orientation="vertical" aria-labelledby="select-877925-trigger">
<div role="option" data-value="disabled" aria-selected="true">Disabled</div>
<div id="select-disabled-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-disabled-listbox" aria-orientation="vertical" aria-labelledby="select-disabled-trigger">
<div role="option" data-value="apple">Apple</div>
<div role="option" data-value="banana">Banana</div>
<div role="option" data-value="blueberry">Blueberry</div>
<div role="option" data-value="grapes" aria-disabled="true">Grapes</div>
<div role="option" data-value="pineapple">Pineapple</div>
</div>
</div>
<input type="hidden" name="select-877925-value" value="disabled" />
<input type="hidden" name="select-disabled-value" value="" />
</div>
</Preview>
### Invalid
<Preview>
<div role="group" class="field w-full max-w-sm" data-invalid="true">
<label for="select-invalid-trigger">Role</label>
<div id="select-invalid" class="select">
<button type="button" class="w-[220px]" id="select-invalid-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-invalid-listbox" aria-invalid="true">
<span class="truncate">Select a role</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
<div class="field" data-invalid="true">
<label for="select-invalid-trigger">Fruit</label>
<div id="select-invalid" class="select" data-placeholder="Select a fruit">
<button type="button" class="w-[180px]" id="select-invalid-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-invalid-listbox" aria-invalid="true">
<span class="truncate">Select a fruit</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
</button>
<div id="select-invalid-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-invalid-listbox" aria-orientation="vertical" aria-labelledby="select-invalid-trigger">
<div id="select-invalid-items-1" role="option" data-value="">Select a role</div>
<div id="select-invalid-items-2" role="option" data-value="admin">Admin</div>
<div id="select-invalid-items-3" role="option" data-value="editor">Editor</div>
<div id="select-invalid-items-4" role="option" data-value="viewer">Viewer</div>
<div id="select-invalid-items-5" role="option" data-value="guest">Guest</div>
<div role="option" data-value="apple">Apple</div>
<div role="option" data-value="banana">Banana</div>
<div role="option" data-value="blueberry">Blueberry</div>
<div role="option" data-value="grapes">Grapes</div>
<div role="option" data-value="pineapple">Pineapple</div>
</div>
</div>
<input type="hidden" name="select-invalid-value" value="" />
<input type="hidden" name="fruit" value="" />
</div>
<p role="alert">Select a role to continue.</p>
</div>
</Preview>
### With icon
<Preview>
<div id="select-with-icons" class="select">
<button type="button" class="w-[180px]" id="select-with-icons-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-with-icons-listbox">
<span class="truncate">Bar</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
</button>
<div id="select-with-icons-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-with-icons-listbox" aria-orientation="vertical" aria-labelledby="select-with-icons-trigger">
<div role="option" data-value="bar" data-label="Bar" aria-selected="true">
<span class="flex items-center gap-2">
<svg class="text-muted-foreground lucide lucide-chart-bar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v16a2 2 0 0 0 2 2h16" /><path d="M7 16h8" /><path d="M7 11h12" /><path d="M7 6h3" /></svg>
Bar
</span>
</div>
<div role="option" data-value="line" data-label="Line">
<span class="flex items-center gap-2">
<svg class="text-muted-foreground lucide lucide-chart-line" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v16a2 2 0 0 0 2 2h16" /><path d="m19 9-5 5-4-4-3 3" /></svg>
Line
</span>
</div>
<div role="option" data-value="pie" data-label="Pie">
<span class="flex items-center gap-2">
<svg class="text-muted-foreground lucide lucide-chart-pie" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12c.552 0 1.005-.449.95-.998a10 10 0 0 0-8.953-8.951c-.55-.055-.998.398-.998.95v8a1 1 0 0 0 1 1z" /><path d="M21.21 15.89A10 10 0 1 1 8 2.83" /></svg>
Pie
</span>
</div>
</div>
</div>
<input type="hidden" name="select-with-icons-value" value="bar" />
</div>
</Preview>
### Multiple
Enable multiple selection by adding `aria-multiselectable="true"` to the `listbox`. The selected options are displayed as a comma-separated list in the trigger button. Use `data-label` to specify clean text labels for options that contain HTML (like icons), otherwise the text content will be extracted automatically.
<Preview>
<div id="select-multiple" class="select" data-placeholder="Select chart types...">
<button type="button" class="w-[220px]" id="select-multiple-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-multiple-listbox">
<span class="truncate"></span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
</button>
<div id="select-multiple-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-multiple-listbox" aria-orientation="vertical" aria-labelledby="select-multiple-trigger" aria-multiselectable="true">
<div role="option" data-value="bar" data-label="Bar">
<span class="flex items-center gap-2">
<svg class="text-muted-foreground lucide lucide-chart-bar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v16a2 2 0 0 0 2 2h16" /><path d="M7 16h8" /><path d="M7 11h12" /><path d="M7 6h3" /></svg>
Bar
</span>
</div>
<div role="option" data-value="line" data-label="Line">
<span class="flex items-center gap-2">
<svg class="text-muted-foreground lucide lucide-chart-line" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v16a2 2 0 0 0 2 2h16" /><path d="m19 9-5 5-4-4-3 3" /></svg>
Line
</span>
</div>
<div role="option" data-value="pie" data-label="Pie">
<span class="flex items-center gap-2">
<svg class="text-muted-foreground lucide lucide-chart-pie" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12c.552 0 1.005-.449.95-.998a10 10 0 0 0-8.953-8.951c-.55-.055-.998.398-.998.95v8a1 1 0 0 0 1 1z" /><path d="M21.21 15.89A10 10 0 1 1 8 2.83" /></svg>
Pie
</span>
</div>
<div role="option" data-value="area" data-label="Area">
<span class="flex items-center gap-2">
<svg class="text-muted-foreground lucide lucide-chart-area" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v16a2 2 0 0 0 2 2h16" /><path d="M7 11.207a.5.5 0 0 1 .146-.353l2-2a.5.5 0 0 1 .708 0l3.292 3.292a.5.5 0 0 0 .708 0l4.292-4.292a.5.5 0 0 1 .854.353V16a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1z" /></svg>
Area
</span>
</div>
</div>
</div>
<input type="hidden" name="chart-types" value='["bar","line"]' />
<p role="alert">Please select a valid fruit.</p>
</div>
</Preview>
### RTL
Set `dir="rtl"` on the select root or a parent element.
<Preview>
<div dir="rtl">
<div id="select-rtl" class="select">
<div id="select-rtl" class="select" data-placeholder="اختر فاكهة">
<button type="button" class="w-[180px]" id="select-rtl-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-rtl-listbox">
<span class="truncate">فاتح</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
<span class="truncate">اختر فاكهة</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
</button>
<div id="select-rtl-popover" data-popover aria-hidden="true" data-align="start">
<div id="select-rtl-popover" data-popover aria-hidden="true">
<div role="listbox" id="select-rtl-listbox" aria-orientation="vertical" aria-labelledby="select-rtl-trigger">
<div id="select-rtl-items-1" role="option" data-value="light">فاتح</div>
<div id="select-rtl-items-2" role="option" data-value="dark">داكن</div>
<div id="select-rtl-items-3" role="option" data-value="system">النظام</div>
<div role="group" aria-labelledby="select-rtl-fruits">
<span role="heading" id="select-rtl-fruits">الفواكه</span>
<div role="option" data-value="apple">تفاح</div>
<div role="option" data-value="banana">موز</div>
<div role="option" data-value="blueberry">توت أزرق</div>
<div role="option" data-value="grapes">عنب</div>
<div role="option" data-value="pineapple">أناناس</div>
</div>
</div>
</div>
<input type="hidden" name="select-rtl-value" value="light" />
<input type="hidden" name="select-rtl-value" value="" />
</div>
</div>
</Preview>
+47 -82
View File
@@ -9,11 +9,44 @@
Sidebar uses a native `<aside>` next to your page content. Basecoat owns the fixed positioning, overlay behavior, active states, nested lists, and `details` submenu styling. Your app still owns the navigation data and current route.
<Steps>
<Step title="Include the JavaScript files">
```html
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/sidebar.min.js" defer></script>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Sidebar component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/sidebar.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Include JavaScript">
Copy or serve the full Basecoat JavaScript bundle.
```html
<script src="/assets/js/all.min.js" defer></script>
```
Or copy or serve the Basecoat runtime and Sidebar script.
```html
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/sidebar.min.js" defer></script>
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your sidebar HTML">
```html
@@ -37,31 +70,14 @@ Sidebar uses a native `<aside>` next to your page content. Basecoat owns the fix
</li>
<li>
<details id="submenu-content-1-3">
<summary aria-controls="submenu-content-1-3-content">
<svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<summary aria-controls="submenu-content-1-3-content"><svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<span>Settings</span>
</summary>
<ul id="submenu-content-1-3-content">
<li>
<a href="#">
<span>General</span>
</a>
</li>
<li>
<a href="#">
<span>Team</span>
</a>
</li>
<li>
<a href="#">
<span>Billing</span>
</a>
</li>
<li>
<a href="#">
<span>Limits</span>
</a>
</li>
<li><a href="#"><span>General</span></a></li>
<li><a href="#"><span>Team</span></a></li>
<li><a href="#"><span>Billing</span></a></li>
<li><a href="#"><span>Limits</span></a></li>
</ul>
</details>
</li>
@@ -90,63 +106,10 @@ Set `dir="rtl"` on the sidebar or a parent element. Logical spacing, nested bord
Basecoat maps shadcn/ui's sidebar composition to regular navigation HTML: an `<aside>` root, one `<nav>`, optional header/footer regions, grouped lists, item controls, and native `<details>` for nested menus.
```html
<aside id="app-sidebar" class="sidebar" data-side="left">
<nav aria-label="Sidebar navigation">
<header>
<a href="/" aria-label="Home">
<svg aria-hidden="true"><!-- ... --></svg>
<span>Acme</span>
</a>
</header>
<section>
<div role="group" aria-labelledby="sidebar-main">
<h3 id="sidebar-main">Main</h3>
<ul>
<li>
<a href="/dashboard" aria-current="page">
<svg aria-hidden="true"><!-- ... --></svg>
<span>Dashboard</span>
</a>
</li>
<li>
<button type="button" data-active="true">
<svg aria-hidden="true"><!-- ... --></svg>
<span>Search</span>
</button>
</li>
<li>
<details id="sidebar-settings" open>
<summary aria-controls="sidebar-settings-menu">
<svg aria-hidden="true"><!-- ... --></svg>
<span>Settings</span>
</summary>
<ul id="sidebar-settings-menu">
<li><a href="/settings/profile">Profile</a></li>
<li><a href="/settings/team">Team</a></li>
<li><a href="/settings/billing">Billing</a></li>
</ul>
</details>
</li>
</ul>
</div>
</section>
<footer>
<button type="button">
<span>Ronan Berder</span>
</button>
</footer>
</nav>
</aside>
<main>...</main>
```
<dl>
<dt><code>&lt;aside class="sidebar"&gt;</code></dt>
<dd>
Sidebar root. Supports <code>id</code>, <code>data-side="left|right"</code>, <code>data-initial-open</code>, <code>data-initial-mobile-open</code>, and <code>data-breakpoint</code>. JavaScript manages <code>aria-hidden</code>.
Sidebar root. Supports <code>id</code>, <code>data-side="left|right"</code>, <code>data-initial-open="false"</code>, <code>data-initial-mobile-open="true"</code>, and <code>data-breakpoint</code>. JavaScript manages <code>aria-hidden</code>, <code>inert</code>, and the internal <code>data-sidebar-initialized</code> flag.
<dl>
<dt><code>&lt;nav aria-label="..."&gt;</code></dt>
<dd>
@@ -165,9 +128,9 @@ Basecoat maps shadcn/ui's sidebar composition to regular navigation HTML: an `<a
Menu and menu item structure. Top-level lists and nested submenu lists receive different spacing and borders.
<dl>
<dt><code>&lt;a&gt;</code> / <code>&lt;button&gt;</code></dt>
<dd>Menu item control. Use links for navigation and buttons for actions. Supports <code>data-variant="default|outline"</code> and <code>data-size="default|sm|lg"</code>. For links, use <code>&lt;a aria-current="page"&gt;</code> for the current page, otherwise use <code>data-active="true"</code> for active action state.</dd>
<dd>Menu item control. Use links for navigation and buttons for actions. Supports <code>data-variant="default|outline"</code>, <code>data-size="default|sm|lg"</code>, <code>data-active="true"</code>, <code>disabled</code> on buttons, and <code>aria-disabled="true"</code> on custom-disabled controls. For links, prefer <code>&lt;a aria-current="page"&gt;</code> for the current page. Add <code>data-keep-mobile-sidebar-open</code> on a clicked link, button, or ancestor when that control should not close the mobile sidebar.</dd>
<dt><code>&lt;details&gt;</code> / <code>&lt;summary&gt;</code></dt>
<dd>Native disclosure for collapsible submenus. Put the nested <code>&lt;ul&gt;</code> directly after <code>&lt;summary&gt;</code>. Add <code>id</code> and <code>aria-controls</code> when the relationship is not obvious from nearby markup.</dd>
<dd>Native disclosure for collapsible submenus. Put the nested <code>&lt;ul&gt;</code> directly after <code>&lt;summary&gt;</code>. The <code>&lt;summary&gt;</code> supports the same active, variant, and size attributes as menu item controls. Add <code>id</code> and <code>aria-controls</code> when the relationship is not obvious from nearby markup.</dd>
<dt><code>&lt;hr role="separator"&gt;</code></dt>
<dd>Optional separator between groups or menu sections.</dd>
</dl>
@@ -184,6 +147,8 @@ Basecoat maps shadcn/ui's sidebar composition to regular navigation HTML: an `<a
<dd>Sibling content wrapper. The desktop margin applies to the sibling immediately after the sidebar.</dd>
</dl>
Set `--sidebar-width` and `--sidebar-mobile-width` on `:root` or the sidebar root to override the default `16rem` desktop width and `18rem` mobile width.
### JavaScript API
| API | Type | Description |
+37 -12
View File
@@ -1,29 +1,56 @@
# Skeleton
<Preview>
<div class="flex w-fit items-center gap-4">
<div class="flex items-center gap-4">
<div class="skeleton size-10 shrink-0 rounded-full"></div>
<div class="grid gap-2">
<div class="skeleton h-4 w-[150px]"></div>
<div class="skeleton h-4 w-[100px]"></div>
<div class="skeleton h-4 w-[250px]"></div>
<div class="skeleton h-4 w-[200px]"></div>
</div>
</div>
</Preview>
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Skeleton component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/skeleton.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your skeleton HTML">
Add `class="skeleton"` with sizing utilities to create loading placeholders.
```html
<div class="skeleton h-4 w-[150px]"></div>
```
</Step>
</Steps>
## Examples
### Avatar
<Preview>
<div class="flex w-fit items-center gap-4">
<div class="flex items-center gap-4">
<div class="skeleton size-10 shrink-0 rounded-full"></div>
<div class="grid gap-2">
<div class="skeleton h-4 w-[150px]"></div>
@@ -40,16 +67,14 @@ Add `class="skeleton"` with sizing utilities to create loading placeholders.
<div class="skeleton h-4 w-2/3"></div>
<div class="skeleton h-4 w-1/2"></div>
</header>
<section>
<div class="skeleton aspect-square w-full"></div>
</section>
<section> <div class="skeleton aspect-video w-full"></div></section>
</div>
</Preview>
### Text
<Preview class="w-full max-w-xs">
<div class="flex w-full flex-col gap-2">
<Preview class="w-full max-w-sm">
<div class="flex flex-col gap-2">
<div class="skeleton h-4 w-full"></div>
<div class="skeleton h-4 w-full"></div>
<div class="skeleton h-4 w-3/4"></div>
@@ -59,7 +84,7 @@ Add `class="skeleton"` with sizing utilities to create loading placeholders.
### Form
<Preview class="w-full max-w-xs">
<div class="flex w-full flex-col gap-7">
<div class="flex flex-col gap-7">
<div class="flex flex-col gap-3">
<div class="skeleton h-4 w-20"></div>
<div class="skeleton h-10 w-full"></div>
@@ -75,7 +100,7 @@ Add `class="skeleton"` with sizing utilities to create loading placeholders.
### Table
<Preview class="w-full max-w-sm">
<div class="flex w-full flex-col gap-2">
<div class="flex flex-col gap-2">
<div class="flex gap-4">
<div class="skeleton h-4 flex-1"></div>
<div class="skeleton h-4 w-24"></div>
@@ -99,7 +124,7 @@ Add `class="skeleton"` with sizing utilities to create loading placeholders.
Skeleton blocks are direction-neutral. Use logical layout utilities around them when spacing depends on direction.
<Preview>
<div dir="rtl" class="flex w-fit items-center gap-4">
<div dir="rtl" class="flex items-center gap-4">
<div class="skeleton size-10 shrink-0 rounded-full"></div>
<div class="grid gap-2">
<div class="skeleton h-4 w-[150px]"></div>
+45 -3
View File
@@ -12,17 +12,59 @@
## Usage
Use a native `<input type="range" class="input">`. Include `range.js` so Basecoat can keep the filled track in sync with the input value.
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Slider component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/range.css";
@import "basecoat-css/styles/vega.css";
```
Slider uses the Range component CSS.
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Include JavaScript">
Copy or serve the full Basecoat JavaScript bundle.
```html
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/range.min.js" defer></script>
<script src="/assets/js/all.min.js" defer></script>
```
Or copy or serve the Basecoat runtime and Slider script.
```html
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/range.min.js" defer></script>
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your slider HTML">
Use a native `<input type="range" class="input">`. Include `range.js` so Basecoat can keep the filled track in sync with the input value.
```html
<input type="range" class="input w-full" min="0" max="100" value="50" />
```
</Step>
</Steps>
### HTML structure
<dl>
+40 -37
View File
@@ -7,21 +7,45 @@
<Preview class="w-full max-w-xs">
<article class="item bg-muted/50 border-transparent">
<figure><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg></figure>
<section>
<h3>Processing payment...</h3>
</section>
<section> <h3>Processing payment...</h3></section>
<aside class="tabular-nums text-sm">$100.00</aside>
</article>
</Preview>
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import Tailwind only when the component is not composed with other Basecoat components.
```css
@import "tailwindcss";
```
Spinner is pure HTML plus Tailwind utilities and has no dedicated component CSS file.
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your spinner HTML">
Spinners are pure HTML using the `loader-circle` Lucide icon with the `animate-spin` Tailwind utility. Add `role="status"` and `aria-label="Loading"` for accessibility.
```html
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
```
</Step>
</Steps>
## Examples
### Size
@@ -29,12 +53,7 @@ Spinners are pure HTML using the `loader-circle` Lucide icon with the `animate-s
Use the `size-*` utility class to change the size of the spinner.
<Preview>
<div class="flex items-center gap-6">
<svg aria-label="Loading" role="status" class="size-3 animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<svg aria-label="Loading" role="status" class="size-4 animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<svg aria-label="Loading" role="status" class="size-6 animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<svg aria-label="Loading" role="status" class="size-8 animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
</div>
<div class="flex items-center gap-6"><svg aria-label="Loading" role="status" class="size-3 animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg><svg aria-label="Loading" role="status" class="size-4 animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg><svg aria-label="Loading" role="status" class="size-6 animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg><svg aria-label="Loading" role="status" class="size-8 animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg></div>
</Preview>
### Button
@@ -43,16 +62,13 @@ Add a spinner to a button to indicate a loading state. Place the spinner before
<Preview>
<div class="flex flex-col items-center gap-4">
<button class="btn" data-size="sm" disabled>
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<button class="btn" data-size="sm" disabled><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
Loading...
</button>
<button class="btn" data-variant="outline" data-size="sm" disabled>
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<button class="btn" data-variant="outline" data-size="sm" disabled><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
Please wait
</button>
<button class="btn" data-variant="secondary" data-size="sm" disabled>
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<button class="btn" data-variant="secondary" data-size="sm" disabled><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
Processing
</button>
</div>
@@ -64,16 +80,13 @@ Add a spinner to a badge to indicate a loading state. Place the spinner before o
<Preview>
<div class="flex items-center gap-4">
<span class="badge">
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<span class="badge"><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
Syncing
</span>
<span class="badge">
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<span class="badge" data-variant="secondary"><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
Updating
</span>
<span class="badge">
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<span class="badge" data-variant="outline"><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
Processing
</span>
</div>
@@ -85,17 +98,13 @@ Add a spinner to a badge to indicate a loading state. Place the spinner before o
<div class="flex w-full max-w-md flex-col gap-4">
<div class="input-group">
<input placeholder="Send a message..." disabled />
<span data-align="inline-end">
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
</span>
<span data-align="inline-end"><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg></span>
</div>
<div class="input-group">
<textarea placeholder="Send a message..." disabled></textarea>
<footer data-align="block-end">
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
<footer data-align="block-end"><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
Validating...
<button type="button" class="btn ms-auto" data-size="icon-sm">
<svg class="lucide lucide-arrow-up" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m5 12 7-7 7 7" /><path d="M12 19V5" /></svg>
<button type="button" class="btn ms-auto" data-size="icon-sm"><svg class="lucide lucide-arrow-up" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m5 12 7-7 7 7" /><path d="M12 19V5" /></svg>
<span class="sr-only">Send</span>
</button>
</footer>
@@ -108,15 +117,11 @@ Add a spinner to a badge to indicate a loading state. Place the spinner before o
<Preview class="w-full">
<div class="empty w-full">
<header>
<figure>
<svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
</figure>
<figure><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg></figure>
<h3>Processing your request</h3>
<p>Please wait while we process your request. Do not refresh the page.</p>
</header>
<section>
<button class="btn" data-variant="outline" data-size="sm">Cancel</button>
</section>
<section> <button class="btn" data-variant="outline" data-size="sm">Cancel</button></section>
</div>
</Preview>
@@ -127,9 +132,7 @@ Spinner layout follows document direction. Use logical utilities when surroundin
<Preview class="w-full max-w-xs">
<article class="item bg-muted/50 border-transparent" dir="rtl">
<figure><svg aria-label="Loading" role="status" class="animate-spin lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg></figure>
<section>
<h3>جاري معالجة الدفع...</h3>
</section>
<section> <h3>جاري معالجة الدفع...</h3></section>
<aside class="tabular-nums text-sm">١٠٠.٠٠ دولار</aside>
</article>
</Preview>
+32 -11
View File
@@ -9,12 +9,39 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Switch component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/switch.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your switch HTML">
Add `class="input"` and `role="switch"` to a native checkbox. Use a native `<label>` or `aria-label` for accessible naming.
```html
<input type="checkbox" role="switch" class="input" />
```
</Step>
</Steps>
### HTML structure
<dl>
@@ -70,15 +97,9 @@ Use a wrapping `<label>` when the whole card should toggle the switch.
Add `disabled` to the switch and `data-disabled="true"` to the field wrapper when the surrounding field should use disabled styling.
<Preview>
<div class="grid gap-12">
<div role="group" class="field" data-orientation="horizontal" data-disabled="true">
<input type="checkbox" id="switch-disabled-unchecked" role="switch" class="input" disabled />
<label for="switch-disabled-unchecked">Disabled (Unchecked)</label>
</div>
<div role="group" class="field" data-orientation="horizontal" data-disabled="true">
<input type="checkbox" id="switch-disabled-checked" role="switch" class="input" checked disabled />
<label for="switch-disabled-checked">Disabled (Checked)</label>
</div>
<div role="group" class="field" data-orientation="horizontal" data-disabled="true">
<input type="checkbox" id="switch-disabled-unchecked" role="switch" class="input" disabled />
<label for="switch-disabled-unchecked">Disabled</label>
</div>
</Preview>
@@ -89,8 +110,8 @@ Add `aria-invalid="true"` to the switch and `data-invalid="true"` to the field w
<Preview class="w-full max-w-sm">
<div role="group" class="field" data-orientation="horizontal" data-invalid="true">
<section>
<label for="switch-invalid">Enable notifications</label>
<p role="alert">You must enable notifications to continue.</p>
<label for="switch-invalid">Accept terms and conditions.</label>
<p>You must accept the terms and conditions to continue.</p>
</section>
<input type="checkbox" id="switch-invalid" role="switch" class="input" aria-invalid="true" />
</div>
+88 -9
View File
@@ -68,6 +68,30 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Table component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/table.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your table HTML">
Add `class="table"` to your table element. Wrap it in `class="table-container"` when horizontal scrolling is needed.
```html
@@ -78,52 +102,107 @@ Add `class="table"` to your table element. Wrap it in `class="table-container"`
</div>
```
</Step>
</Steps>
<Callout type="warning" title="Scrollable tables clip overlays" icon="triangle-alert">
Do not place inline popovers, dropdown menus, selects, or tooltips inside `.table-container`. The table container uses horizontal overflow for wide tables, so absolutely positioned overlays can be clipped or create scrollbars. Keep overlay actions outside scrollable table regions, or omit `.table-container` when the table does not need horizontal scrolling.
</Callout>
## Examples
### Footer
Examples below follow upstream table patterns where they map cleanly to Basecoat's non-portalled HTML model.
### With Footer
<Preview class="w-full">
<div class="table-container">
<table class="table">
<caption>A list of your recent invoices.</caption>
<thead>
<tr>
<th>Invoice</th>
<th class="w-[100px]">Invoice</th>
<th>Status</th>
<th>Method</th>
<th class="text-end">Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>INV001</td>
<td class="font-medium">INV001</td>
<td>Paid</td>
<td>Credit Card</td>
<td class="text-end">$250.00</td>
</tr>
<tr>
<td class="font-medium">INV002</td>
<td>Pending</td>
<td>PayPal</td>
<td class="text-end">$150.00</td>
</tr>
<tr>
<td class="font-medium">INV003</td>
<td>Unpaid</td>
<td>Bank Transfer</td>
<td class="text-end">$350.00</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Total</td>
<td class="text-end">$250.00</td>
<td colspan="3">Total</td>
<td class="text-end">$2,500.00</td>
</tr>
</tfoot>
</table>
</div>
</Preview>
### Actions
### With Actions
<Preview class="w-full">
<div class="table-container">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Product</th>
<th>Price</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td class="font-medium">Project Alpha</td>
<td class="font-medium">Wireless Mouse</td>
<td>$29.99</td>
<td class="text-end">
<button type="button" class="btn" data-variant="outline" data-size="xs">Open</button>
<div class="inline-flex gap-2">
<button type="button" class="btn" data-variant="outline" data-size="sm">Edit</button>
<button type="button" class="btn" data-variant="destructive" data-size="sm">Delete</button>
</div>
</td>
</tr>
<tr>
<td class="font-medium">Mechanical Keyboard</td>
<td>$129.99</td>
<td class="text-end">
<div class="inline-flex gap-2">
<button type="button" class="btn" data-variant="outline" data-size="sm">Edit</button>
<button type="button" class="btn" data-variant="destructive" data-size="sm">Delete</button>
</div>
</td>
</tr>
<tr>
<td class="font-medium">USB-C Hub</td>
<td>$49.99</td>
<td class="text-end">
<div class="inline-flex gap-2">
<button type="button" class="btn" data-variant="outline" data-size="sm">Edit</button>
<button type="button" class="btn" data-variant="destructive" data-size="sm">Delete</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</Preview>
### RTL
+108 -50
View File
@@ -62,13 +62,44 @@
</Callout>
<Steps>
<Step title="Include the JavaScript files">
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Tabs component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/tabs.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Include JavaScript">
Copy or serve the full Basecoat JavaScript bundle.
```html
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/tabs.min.js" defer></script>
<script src="/assets/js/all.min.js" defer></script>
```
Or copy or serve the Basecoat runtime and Tabs script.
```html
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/tabs.min.js" defer></script>
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your tabs HTML">
@@ -165,28 +196,28 @@
<Preview>
<div class="tabs" id="tabs-line">
<nav role="tablist" aria-orientation="horizontal" data-variant="line">
<button type="button" role="tab" id="tabs-line-tab-1" aria-controls="tabs-line-panel-1" aria-selected="true" tabindex="0">Account</button>
<button type="button" role="tab" id="tabs-line-tab-2" aria-controls="tabs-line-panel-2" aria-selected="false" tabindex="-1">Password</button>
<button type="button" role="tab" id="tabs-line-tab-3" aria-controls="tabs-line-panel-3" aria-selected="false" tabindex="-1">Settings</button>
<button type="button" role="tab" id="tabs-line-tab-overview" aria-controls="tabs-line-panel-overview" aria-selected="true" tabindex="0">Overview</button>
<button type="button" role="tab" id="tabs-line-tab-analytics" aria-controls="tabs-line-panel-analytics" aria-selected="false" tabindex="-1">Analytics</button>
<button type="button" role="tab" id="tabs-line-tab-reports" aria-controls="tabs-line-panel-reports" aria-selected="false" tabindex="-1">Reports</button>
</nav>
<div role="tabpanel" id="tabs-line-panel-1" aria-labelledby="tabs-line-tab-1" tabindex="-1" aria-selected="true">Make changes to your account here.</div>
<div role="tabpanel" id="tabs-line-panel-2" aria-labelledby="tabs-line-tab-2" tabindex="-1" aria-selected="false" hidden>Change your password here.</div>
<div role="tabpanel" id="tabs-line-panel-3" aria-labelledby="tabs-line-tab-3" tabindex="-1" aria-selected="false" hidden>Update your settings here.</div>
<div role="tabpanel" id="tabs-line-panel-overview" aria-labelledby="tabs-line-tab-overview" tabindex="-1">Overview content.</div>
<div role="tabpanel" id="tabs-line-panel-analytics" aria-labelledby="tabs-line-tab-analytics" tabindex="-1" hidden>Analytics content.</div>
<div role="tabpanel" id="tabs-line-panel-reports" aria-labelledby="tabs-line-tab-reports" tabindex="-1" hidden>Reports content.</div>
</div>
</Preview>
### Vertical
<Preview>
<div class="tabs w-full" id="tabs-vertical">
<div class="tabs" id="tabs-vertical">
<nav role="tablist" aria-orientation="vertical">
<button type="button" role="tab" id="tabs-vertical-tab-1" aria-controls="tabs-vertical-panel-1" aria-selected="true" tabindex="0">Account</button>
<button type="button" role="tab" id="tabs-vertical-tab-2" aria-controls="tabs-vertical-panel-2" aria-selected="false" tabindex="-1">Password</button>
<button type="button" role="tab" id="tabs-vertical-tab-3" aria-controls="tabs-vertical-panel-3" aria-selected="false" tabindex="-1">Notifications</button>
<button type="button" role="tab" id="tabs-vertical-tab-account" aria-controls="tabs-vertical-panel-account" aria-selected="true" tabindex="0">Account</button>
<button type="button" role="tab" id="tabs-vertical-tab-password" aria-controls="tabs-vertical-panel-password" aria-selected="false" tabindex="-1">Password</button>
<button type="button" role="tab" id="tabs-vertical-tab-notifications" aria-controls="tabs-vertical-panel-notifications" aria-selected="false" tabindex="-1">Notifications</button>
</nav>
<div role="tabpanel" id="tabs-vertical-panel-1" aria-labelledby="tabs-vertical-tab-1" tabindex="-1" aria-selected="true">Manage account settings.</div>
<div role="tabpanel" id="tabs-vertical-panel-2" aria-labelledby="tabs-vertical-tab-2" tabindex="-1" aria-selected="false" hidden>Update your password.</div>
<div role="tabpanel" id="tabs-vertical-panel-3" aria-labelledby="tabs-vertical-tab-3" tabindex="-1" aria-selected="false" hidden>Configure notifications.</div>
<div role="tabpanel" id="tabs-vertical-panel-account" aria-labelledby="tabs-vertical-tab-account" tabindex="-1">Account content.</div>
<div role="tabpanel" id="tabs-vertical-panel-password" aria-labelledby="tabs-vertical-tab-password" tabindex="-1" hidden>Password content.</div>
<div role="tabpanel" id="tabs-vertical-panel-notifications" aria-labelledby="tabs-vertical-tab-notifications" tabindex="-1" hidden>Notifications content.</div>
</div>
</Preview>
@@ -195,55 +226,82 @@
<Preview>
<div class="tabs" id="tabs-disabled">
<nav role="tablist" aria-orientation="horizontal">
<button type="button" role="tab" id="tabs-disabled-tab-1" aria-controls="tabs-disabled-panel-1" aria-selected="true" tabindex="0">Account</button>
<button type="button" role="tab" id="tabs-disabled-tab-2" aria-controls="tabs-disabled-panel-2" aria-selected="false" tabindex="-1" disabled="disabled">Password</button>
<button type="button" role="tab" id="tabs-disabled-tab-3" aria-controls="tabs-disabled-panel-3" aria-selected="false" tabindex="-1">Settings</button>
<button type="button" role="tab" id="tabs-disabled-tab-home" aria-controls="tabs-disabled-panel-home" aria-selected="true" tabindex="0">Home</button>
<button type="button" role="tab" id="tabs-disabled-tab-settings" aria-controls="tabs-disabled-panel-settings" aria-selected="false" tabindex="-1" disabled>Disabled</button>
</nav>
<div role="tabpanel" id="tabs-disabled-panel-1" aria-labelledby="tabs-disabled-tab-1" tabindex="-1" aria-selected="true">Account content.</div>
<div role="tabpanel" id="tabs-disabled-panel-2" aria-labelledby="tabs-disabled-tab-2" tabindex="-1" aria-selected="false" hidden>Password content.</div>
<div role="tabpanel" id="tabs-disabled-panel-3" aria-labelledby="tabs-disabled-tab-3" tabindex="-1" aria-selected="false" hidden>Settings content.</div>
<div role="tabpanel" id="tabs-disabled-panel-home" aria-labelledby="tabs-disabled-tab-home" tabindex="-1">Home content.</div>
<div role="tabpanel" id="tabs-disabled-panel-settings" aria-labelledby="tabs-disabled-tab-settings" tabindex="-1" hidden>Settings content.</div>
</div>
</Preview>
### Icons
<Preview>
<div class="tabs" id="tabs-icons">
<div class="tabs" id="tabs-with-icons">
<nav role="tablist" aria-orientation="horizontal">
<button type="button" role="tab" id="tabs-icons-tab-1" aria-controls="tabs-icons-panel-1" aria-selected="true" tabindex="0">
<svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>
Account
</button>
<button type="button" role="tab" id="tabs-icons-tab-2" aria-controls="tabs-icons-panel-2" aria-selected="false" tabindex="-1">
<svg class="lucide lucide-lock" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="11" x="3" y="11" rx="2" ry="2" /><path d="M7 11V7a5 5 0 0 1 10 0v4" /></svg>
Password
</button>
<button type="button" role="tab" id="tabs-icons-tab-3" aria-controls="tabs-icons-panel-3" aria-selected="false" tabindex="-1">
<svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
Settings
</button>
<button type="button" role="tab" id="tabs-with-icons-tab-preview" aria-controls="tabs-with-icons-panel-preview" aria-selected="true" tabindex="0"><svg class="lucide lucide-app-window" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2" /><path d="M10 4v4" /><path d="M2 8h20" /><path d="M6 4v4" /></svg> Preview</button>
<button type="button" role="tab" id="tabs-with-icons-tab-code" aria-controls="tabs-with-icons-panel-code" aria-selected="false" tabindex="-1"><svg class="lucide lucide-code" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 18 6-6-6-6" /><path d="m8 6-6 6 6 6" /></svg> Code</button>
</nav>
<div role="tabpanel" id="tabs-icons-panel-1" aria-labelledby="tabs-icons-tab-1" tabindex="-1" aria-selected="true">Account content.</div>
<div role="tabpanel" id="tabs-icons-panel-2" aria-labelledby="tabs-icons-tab-2" tabindex="-1" aria-selected="false" hidden>Password content.</div>
<div role="tabpanel" id="tabs-icons-panel-3" aria-labelledby="tabs-icons-tab-3" tabindex="-1" aria-selected="false" hidden>Settings content.</div>
<div role="tabpanel" id="tabs-with-icons-panel-preview" aria-labelledby="tabs-with-icons-tab-preview" tabindex="-1">Preview content.</div>
<div role="tabpanel" id="tabs-with-icons-panel-code" aria-labelledby="tabs-with-icons-tab-code" tabindex="-1" hidden>Code content.</div>
</div>
</Preview>
### RTL
## RTL
Tabs support document direction. Set `dir="rtl"` on the tabs root or a parent element.
To enable RTL support, set `dir="rtl"` on the tabs root or a parent element.
<Preview>
<div dir="rtl">
<div class="tabs" id="tabs-rtl">
<nav role="tablist" aria-orientation="horizontal" data-variant="line">
<button type="button" role="tab" id="tabs-rtl-tab-1" aria-controls="tabs-rtl-panel-1" aria-selected="true" tabindex="0">الحساب</button>
<button type="button" role="tab" id="tabs-rtl-tab-2" aria-controls="tabs-rtl-panel-2" aria-selected="false" tabindex="-1">كلمة المرور</button>
<button type="button" role="tab" id="tabs-rtl-tab-3" aria-controls="tabs-rtl-panel-3" aria-selected="false" tabindex="-1">الإشعارات</button>
</nav>
<div role="tabpanel" id="tabs-rtl-panel-1" aria-labelledby="tabs-rtl-tab-1" tabindex="-1" aria-selected="true">إعدادات الحساب.</div>
<div role="tabpanel" id="tabs-rtl-panel-2" aria-labelledby="tabs-rtl-tab-2" tabindex="-1" aria-selected="false" hidden>تحديث كلمة المرور.</div>
<div role="tabpanel" id="tabs-rtl-panel-3" aria-labelledby="tabs-rtl-tab-3" tabindex="-1" aria-selected="false" hidden>إعدادات الإشعارات.</div>
<div class="tabs w-full max-w-sm" id="tabs-rtl" dir="rtl">
<nav role="tablist" aria-orientation="horizontal" dir="rtl">
<button type="button" role="tab" id="tabs-rtl-tab-overview" aria-controls="tabs-rtl-panel-overview" aria-selected="true" tabindex="0">نظرة عامة</button>
<button type="button" role="tab" id="tabs-rtl-tab-analytics" aria-controls="tabs-rtl-panel-analytics" aria-selected="false" tabindex="-1">التحليلات</button>
<button type="button" role="tab" id="tabs-rtl-tab-reports" aria-controls="tabs-rtl-panel-reports" aria-selected="false" tabindex="-1">التقارير</button>
<button type="button" role="tab" id="tabs-rtl-tab-settings" aria-controls="tabs-rtl-panel-settings" aria-selected="false" tabindex="-1">الإعدادات</button>
</nav>
<div role="tabpanel" id="tabs-rtl-panel-overview" aria-labelledby="tabs-rtl-tab-overview" tabindex="-1">
<div class="card">
<header>
<h2>نظرة عامة</h2>
<p>عرض مقاييسك الرئيسية وأنشطة المشروع الأخيرة. تتبع التقدم عبر جميع مشاريعك النشطة.</p>
</header>
<section>
<p class="text-muted-foreground text-sm">لديك ١٢ مشروعًا نشطًا و٣ مهام معلقة.</p>
</section>
</div>
</div>
<div role="tabpanel" id="tabs-rtl-panel-analytics" aria-labelledby="tabs-rtl-tab-analytics" tabindex="-1" hidden>
<div class="card">
<header>
<h2>التحليلات</h2>
<p>تتبع مقاييس الأداء ومشاركة المستخدمين. راقب الاتجاهات وحدد فرص النمو.</p>
</header>
<section>
<p class="text-muted-foreground text-sm">زادت مشاهدات الصفحة بنسبة ٢٥٪ مقارنة بالشهر الماضي.</p>
</section>
</div>
</div>
<div role="tabpanel" id="tabs-rtl-panel-reports" aria-labelledby="tabs-rtl-tab-reports" tabindex="-1" hidden>
<div class="card">
<header>
<h2>التقارير</h2>
<p>إنشاء وتنزيل تقاريرك التفصيلية. تصدير البيانات بتنسيقات متعددة للتحليل.</p>
</header>
<section>
<p class="text-muted-foreground text-sm">لديك ٥ تقارير جاهزة ومتاحة للتصدير.</p>
</section>
</div>
</div>
<div role="tabpanel" id="tabs-rtl-panel-settings" aria-labelledby="tabs-rtl-tab-settings" tabindex="-1" hidden>
<div class="card">
<header>
<h2>الإعدادات</h2>
<p>إدارة تفضيلات حسابك وخياراته. تخصيص تجربتك لتناسب احتياجاتك.</p>
</header>
<section>
<p class="text-muted-foreground text-sm">تكوين الإشعارات والأمان والسمات.</p>
</section>
</div>
</div>
</div>
</Preview>
+27
View File
@@ -6,6 +6,30 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Textarea component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/textarea.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your textarea HTML">
Add `class="textarea"` to a `<textarea>` element. Textareas inside a `class="field"` container also receive the same styling automatically.
Use native HTML attributes for behavior: `disabled` for disabled textareas and `aria-invalid="true"` for invalid state styling.
@@ -14,6 +38,9 @@ Use native HTML attributes for behavior: `disabled` for disabled textareas and `
<textarea class="textarea" placeholder="Type your message here"></textarea>
```
</Step>
</Steps>
Textareas support right-to-left layouts through native browser direction handling.
## Examples
+46 -15
View File
@@ -9,18 +9,55 @@
onclick="window.basecoat.theme.toggle()"
class="btn size-8" data-variant="outline" data-size="icon"
>
<span class="hidden dark:block">
<svg class="lucide lucide-sun" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4" /><path d="M12 2v2" /><path d="M12 20v2" /><path d="m4.93 4.93 1.41 1.41" /><path d="m17.66 17.66 1.41 1.41" /><path d="M2 12h2" /><path d="M20 12h2" /><path d="m6.34 17.66-1.41 1.41" /><path d="m19.07 4.93-1.41 1.41" /></svg>
</span>
<span class="block dark:hidden">
<svg class="lucide lucide-moon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401" /></svg>
</span>
<span class="hidden dark:block"><svg class="lucide lucide-sun" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4" /><path d="M12 2v2" /><path d="M12 20v2" /><path d="m4.93 4.93 1.41 1.41" /><path d="m17.66 17.66 1.41 1.41" /><path d="M2 12h2" /><path d="M20 12h2" /><path d="m6.34 17.66-1.41 1.41" /><path d="m19.07 4.93-1.41 1.41" /></svg></span>
<span class="block dark:hidden"><svg class="lucide lucide-moon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401" /></svg></span>
</button>
</Preview>
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, the component CSS files it composes, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/button.css";
@import "basecoat-css/components/tooltip.css";
@import "basecoat-css/styles/vega.css";
```
Theme Switcher composes Button and Tooltip component CSS.
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Include JavaScript">
Copy or serve the full Basecoat JavaScript bundle.
```html
<script src="/assets/js/all.min.js" defer></script>
```
Or copy or serve the Basecoat runtime only.
```html
<script src="/assets/js/basecoat.min.js" defer></script>
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Avoid the initial flash">
Add this inline script before loading your styles so the stored mode is applied before the page renders.
@@ -39,18 +76,12 @@ Add this inline script before loading your styles so the stored mode is applied
```
</Step>
<Step title="Add your switcher">
Load `basecoat.js` or the bundled JavaScript before calling `window.basecoat.theme`.
<Step title="Add your switcher HTML">
```html
<button type="button" aria-label="Toggle dark mode" data-tooltip="Toggle dark mode" data-side="bottom" onclick="window.basecoat.theme.toggle()" class="btn size-8" data-variant="outline" data-size="icon">
<span class="hidden dark:block">
<svg class="lucide lucide-sun" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4" /><path d="M12 2v2" /><path d="M12 20v2" /><path d="m4.93 4.93 1.41 1.41" /><path d="m17.66 17.66 1.41 1.41" /><path d="M2 12h2" /><path d="M20 12h2" /><path d="m6.34 17.66-1.41 1.41" /><path d="m19.07 4.93-1.41 1.41" /></svg>
</span>
<span class="block dark:hidden">
<svg class="lucide lucide-moon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401" /></svg>
</span>
<span class="hidden dark:block"><svg class="lucide lucide-sun" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4" /><path d="M12 2v2" /><path d="M12 20v2" /><path d="m4.93 4.93 1.41 1.41" /><path d="m17.66 17.66 1.41 1.41" /><path d="M2 12h2" /><path d="M20 12h2" /><path d="m6.34 17.66-1.41 1.41" /><path d="m19.07 4.93-1.41 1.41" /></svg></span>
<span class="block dark:hidden"><svg class="lucide lucide-moon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401" /></svg></span>
</button>
```
+38 -15
View File
@@ -1,7 +1,6 @@
# Toast
<div id="toaster" class="toaster"></div>
<script src="/assets/js/htmx.min.js" defer></script>
<Preview class="max-w-md">
<button
@@ -11,9 +10,7 @@
hx-get="/fragments/toast/success"
hx-target="#toaster"
hx-swap="beforeend"
>
Toast from backend (with HTMX)
</button>
>Toast from backend (with HTMX)</button>
</Preview>
<Preview class="max-w-md">
@@ -27,9 +24,7 @@
label: 'Dismiss'
}
})"
>
Toast from front-end
</button>
>Toast from front-end</button>
</Preview>
## Usage
@@ -39,13 +34,44 @@
</Callout>
<Steps>
<Step title="Include the JavaScript files">
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Toast component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/toast.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Include JavaScript">
Copy or serve the full Basecoat JavaScript bundle.
```html
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/toast.min.js" defer></script>
<script src="/assets/js/all.min.js" defer></script>
```
Or copy or serve the Basecoat runtime and Toast script.
```html
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/toast.min.js" defer></script>
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add the toaster HTML">
@@ -65,8 +91,7 @@ Append server-rendered toast markup to the toaster, or create one from JavaScrip
```html
<div id="toaster" class="toaster">
<div class="toast" role="status" aria-atomic="true" aria-hidden="false" data-category="success">
<div class="toast-content">
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" /></svg>
<div class="toast-content"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" /></svg>
<section>
<h2>Success</h2>
<p>A success toast called from the front-end.</p>
@@ -89,9 +114,7 @@ Append server-rendered toast markup to the toaster, or create one from JavaScrip
cancel: {
label: 'Dismiss'
}
})">
Toast from front-end
</button>
})">Toast from front-end</button>
```
</Step>
+29 -6
View File
@@ -6,6 +6,30 @@
## Usage
<Steps>
<Step title="Include CSS">
Import Tailwind and one full Basecoat style bundle.
```css
@import "tailwindcss";
@import "basecoat-css/vega.css";
```
Or import only the base CSS, Tooltip component CSS, and one style pack.
```css
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/tooltip.css";
@import "basecoat-css/styles/vega.css";
```
Using CDN or bundler imports? See the [Installation page](/installation).
</Step>
<Step title="Add your tooltip HTML">
Add `data-tooltip` to the trigger element. Use `data-side` and `data-align` to change the position:
- `data-tooltip`: Tooltip text.
@@ -18,6 +42,9 @@ Basecoat tooltips are CSS-only and text-only. This intentionally differs from sh
<button class="btn" data-variant="outline" data-tooltip="Tooltip text" data-side="bottom" data-align="center">Bottom</button>
```
</Step>
</Steps>
## Examples
### Default
@@ -40,17 +67,13 @@ Basecoat tooltips are CSS-only and text-only. This intentionally differs from sh
### Icon button
<Preview>
<button class="btn" data-variant="ghost" data-size="icon" data-tooltip="Additional information" aria-label="Info">
<svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg>
</button>
<button class="btn" data-variant="ghost" data-size="icon" data-tooltip="Additional information" aria-label="Info"><svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg></button>
</Preview>
### Disabled button
<Preview>
<span class="inline-block" data-tooltip="This feature is currently unavailable">
<button class="btn" data-variant="outline" disabled>Disabled</button>
</span>
<span class="inline-block" data-tooltip="This feature is currently unavailable"> <button class="btn" data-variant="outline" disabled>Disabled</button></span>
</Preview>
### Link
-2
View File
@@ -66,7 +66,6 @@ Then import the font files and override the font tokens after Basecoat:
@import "@fontsource/geist-mono/500.css";
@import "@fontsource/geist-mono/600.css";
@import "@fontsource/geist-mono/700.css";
:root {
--font-sans: "Geist Sans", ui-sans-serif, system-ui, sans-serif;
--font-heading: "Geist Sans", ui-sans-serif, system-ui, sans-serif;
@@ -121,7 +120,6 @@ The practical way to start is to copy one existing style pack from `basecoat-css
```css
@import "basecoat-css/base";
@import "./styles/acme.css";
/* ./styles/acme.css can start as a copy of basecoat-css/styles/nova. */
```
+46 -16
View File
@@ -7,14 +7,16 @@ Basecoat can be used from a CDN or installed with npm. Use the CDN for simple st
<Steps>
<Step title="Add the stylesheet">
Use the default bundled stylesheet, or choose one standalone style bundle.
Use the default bundled stylesheet. It is an alias for the Vega style bundle.
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/basecoat.cdn.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.6/dist/basecoat.cdn.min.css" />
```
You can also use one of the named style bundles: `vega`, `nova`, `maia`, `lyra`, `mira`, `luma`, `sera`, or `rhea`.
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/basecoat-maia.cdn.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.6/dist/basecoat-maia.cdn.min.css" />
```
</Step>
@@ -23,15 +25,15 @@ Use the default bundled stylesheet, or choose one standalone style bundle.
Most components are CSS-only. Interactive components need JavaScript. Use the all-in-one bundle when file size is not a concern.
```html
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/all.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.6/dist/js/all.min.js" defer></script>
```
Or load the Basecoat runtime once, then only the component scripts you use.
```html
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/dropdown-menu.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.4/dist/js/select.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.6/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.6/dist/js/dropdown-menu.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0-beta.6/dist/js/select.min.js" defer></script>
```
</Step>
@@ -39,7 +41,6 @@ Or load the Basecoat runtime once, then only the component scripts you use.
```html
<button class="btn">Button</button>
<div class="card">
<header>
<h3>Card title</h3>
@@ -60,7 +61,7 @@ Or load the Basecoat runtime once, then only the component scripts you use.
| File | Description |
| --- | --- |
| `dist/basecoat.cdn.min.css` | Default standalone CDN stylesheet. |
| `dist/basecoat.cdn.min.css` | Default standalone CDN stylesheet. Alias for the Vega style. |
| `dist/basecoat-{style}.cdn.min.css` | Standalone CDN stylesheet for `vega`, `nova`, `maia`, `lyra`, `mira`, `luma`, `sera`, or `rhea`. |
| `dist/basecoat-base.cdn.min.css` | Base tokens, utilities, and component structure without a style pack. |
| `dist/basecoat-compat.cdn.min.css` | Optional pre-1.0 compatibility aliases. Load after Basecoat. |
@@ -87,17 +88,31 @@ Basecoat is authored for Tailwind CSS. Install Tailwind first if your project do
<Code title="yarn" lang="bash">{`yarn add basecoat-css`}</Code>
</CodeGroup>
</Step>
<Step title="Import CSS">
If you are not using a bundler, copy or serve the files you need from `node_modules/basecoat-css/dist`.
Import Tailwind, then import one Basecoat bundle.
</Step>
<Step title="Add CSS">
Include one Basecoat stylesheet after your Tailwind CSS. The default stylesheet is an alias for the Vega style bundle.
```html
<link rel="stylesheet" href="/assets/basecoat.css" />
```
You can also use one of the named style bundles: `vega`, `nova`, `maia`, `lyra`, `mira`, `luma`, `sera`, or `rhea`.
```html
<link rel="stylesheet" href="/assets/basecoat-maia.css" />
```
If your build tool supports CSS package imports, import Tailwind and then one Basecoat bundle.
```css
@import "tailwindcss";
@import "basecoat-css";
```
To choose a specific style, import that style bundle instead.
Or import a named style bundle.
```css
@import "tailwindcss";
@@ -109,9 +124,23 @@ To choose a specific style, import that style bundle instead.
</Callout>
</Step>
<Step title="Import JavaScript when needed">
<Step title="Add JavaScript when needed">
Use the all-in-one import:
Most components are CSS-only. Interactive components need JavaScript. Include the all-in-one script when file size is not a concern.
```html
<script src="/assets/js/all.min.js" defer></script>
```
Or include the Basecoat runtime once, then only the component scripts you use.
```html
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/dropdown-menu.min.js" defer></script>
<script src="/assets/js/select.min.js" defer></script>
```
If your build tool supports JavaScript package imports, use the all-in-one import:
```js
import "basecoat-css/all";
@@ -132,12 +161,13 @@ import "basecoat-css/select";
| Import | Description |
| --- | --- |
| `basecoat-css` | Default full stylesheet. |
| `basecoat-css` | Default full stylesheet. Alias for `basecoat-css/vega`. |
| `basecoat-css/{style}` | Full stylesheet for `vega`, `nova`, `maia`, `lyra`, `mira`, `luma`, `sera`, or `rhea`. |
| `basecoat-css/base` | Base tokens, utilities, and component structure without a style pack. Use this before a custom style. |
| `basecoat-css/components` | All component structure without a style pack. |
| `basecoat-css/components/button` | Individual component CSS. Replace `button` with any component file. |
| `basecoat-css/styles/maia` | Individual style-pack CSS. Use with `basecoat-css/base` or `basecoat-css/components`. |
| `basecoat-css/all.css` | Full default stylesheet plus all style-pack CSS. Use only when you need every style pack available at runtime. |
| `basecoat-css/compat` | Optional pre-1.0 compatibility aliases. Load after Basecoat. |
### JavaScript imports
+47
View File
@@ -8,6 +8,7 @@ import lumaUrl from "../assets/styles/style-luma.css?url";
import seraUrl from "../assets/styles/style-sera.css?url";
import rheaUrl from "../assets/styles/style-rhea.css?url";
import demoInteractionsUrl from "./demo-interactions.js?url";
import htmxUrl from "htmx.org/dist/htmx.min.js?url";
const styleUrls = {
vega: vegaUrl,
@@ -80,4 +81,50 @@ const styleUrls = {
})();
</script>
<script is:inline>
(() => {
const pageKey = (href) => {
const url = new URL(href, window.location.origin);
return `${url.pathname.replace(/\/$/, "")}${url.search}`;
};
const updateSidebarState = () => {
const sidebar = document.getElementById("sidebar");
if (!sidebar) return;
const currentKey = pageKey(window.location.href);
sidebar.querySelectorAll("a[href]").forEach((link) => {
const isCurrent = pageKey(link.href) === currentKey;
if (isCurrent) {
link.setAttribute("aria-current", "page");
link.closest("details")?.setAttribute("open", "");
} else {
link.removeAttribute("aria-current");
}
});
};
document.addEventListener("DOMContentLoaded", () => {
const content = document.getElementById("content");
if (!content) return;
document.body.setAttribute("hx-boost", "true");
document.body.setAttribute("hx-target", "#content");
document.body.setAttribute("hx-select", "#content");
document.body.setAttribute("hx-swap", "outerHTML");
document.body.setAttribute("hx-push-url", "true");
window.htmx?.process(document.body);
updateSidebarState();
});
document.addEventListener("htmx:afterSettle", () => {
window.basecoat?.initAll?.();
updateSidebarState();
});
window.addEventListener("popstate", updateSidebarState);
})();
</script>
<script src={htmxUrl} defer></script>
<script type="module" src={demoInteractionsUrl}></script>
+18 -3
View File
@@ -1,6 +1,3 @@
import "../../../src/js/basecoat.js";
import "../../../src/js/chart.js";
const visitorsByDay = [
{ date: "Apr 1", desktop: 222, mobile: 150 },
{ date: "Apr 5", desktop: 373, mobile: 290 },
@@ -228,3 +225,21 @@ if (document.readyState === "loading") {
} else {
initChartExamples();
}
if (!window.__basecoatChartExamplesObserver) {
let pending = false;
const queueInitChartExamples = () => {
if (pending) return;
pending = true;
requestAnimationFrame(() => {
pending = false;
initChartExamples();
});
};
window.__basecoatChartExamplesObserver = new MutationObserver(queueInitChartExamples);
window.__basecoatChartExamplesObserver.observe(document.body, {
childList: true,
subtree: true,
});
}
+5 -5
View File
@@ -1,12 +1,12 @@
{
"name": "basecoat",
"version": "1.0.0-beta.5",
"version": "1.0.0-beta.6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "basecoat",
"version": "1.0.0-beta.5",
"version": "1.0.0-beta.6",
"license": "MIT",
"workspaces": [
"packages/*"
@@ -20,7 +20,7 @@
"lucide-static": "^1.17.0",
"nunjucks": "^3.2.4",
"prettier": "^3.5.3",
"reallysimpledocs": "^1.0.0-beta.5",
"reallysimpledocs": "1.0.0-beta.5",
"tailwindcss": "^4.1.17",
"terser": "^5.42.0",
"wrangler": "^4.50.0"
@@ -9880,7 +9880,7 @@
},
"packages/cli": {
"name": "basecoat-cli",
"version": "1.0.0-beta.5",
"version": "1.0.0-beta.6",
"license": "MIT",
"dependencies": {
"commander": "^13.1.0",
@@ -9893,7 +9893,7 @@
},
"packages/css": {
"name": "basecoat-css",
"version": "1.0.0-beta.5",
"version": "1.0.0-beta.6",
"license": "MIT"
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "basecoat",
"version": "1.0.0-beta.5",
"version": "1.0.0-beta.6",
"description": "shadcn/ui for the rest of us",
"author": "hunvreus",
"type": "module",
@@ -49,7 +49,7 @@
"lucide-static": "^1.17.0",
"nunjucks": "^3.2.4",
"prettier": "^3.5.3",
"reallysimpledocs": "^1.0.0-beta.5",
"reallysimpledocs": "1.0.0-beta.5",
"tailwindcss": "^4.1.17",
"terser": "^5.42.0",
"wrangler": "^4.50.0"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "basecoat-cli",
"version": "1.0.0-beta.5",
"version": "1.0.0-beta.6",
"description": "Add Basecoat components to your project",
"author": "hunvreus",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "basecoat-css",
"version": "1.0.0-beta.5",
"version": "1.0.0-beta.6",
"description": "Tailwind CSS for Basecoat components",
"author": {
"name": "hunvreus",
+27 -1
View File
@@ -22,6 +22,22 @@
&[data-side='right'] {
@apply -translate-x-2;
}
&[data-side='inline-start'] {
@apply translate-x-2;
}
&[data-side='inline-start']:dir(rtl) {
@apply -translate-x-2;
}
&[data-side='inline-end'] {
@apply -translate-x-2;
}
&[data-side='inline-end']:dir(rtl) {
@apply translate-x-2;
}
}
&:not([data-side]),
@@ -41,6 +57,14 @@
@apply ms-1 start-full;
}
&[data-side='inline-start'] {
@apply me-1 end-full;
}
&[data-side='inline-end'] {
@apply ms-1 start-full;
}
&:not([data-side]),
&[data-side='bottom'],
&[data-side='top'] {
@@ -59,7 +83,9 @@
}
&[data-side='left'],
&[data-side='right'] {
&[data-side='right'],
&[data-side='inline-start'],
&[data-side='inline-end'] {
&:not([data-align]),
&[data-align='start'] {
@apply top-0;
+9 -1
View File
@@ -767,7 +767,15 @@
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):before {
@apply bg-background dark:not-checked:bg-foreground dark:checked:bg-primary-foreground rounded-full shadow-sm not-dark:bg-clip-padding;
@apply bg-background rounded-full shadow-sm not-dark:bg-clip-padding;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not(:checked):before {
@apply bg-foreground;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):checked:before {
@apply bg-primary-foreground;
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not([data-size='sm']):before {
+9 -1
View File
@@ -747,7 +747,15 @@
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):before {
@apply bg-background dark:not-checked:bg-foreground dark:checked:bg-primary-foreground rounded-full;
@apply bg-background rounded-full;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not(:checked):before {
@apply bg-foreground;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):checked:before {
@apply bg-primary-foreground;
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not([data-size='sm']):before {
+9 -1
View File
@@ -755,7 +755,15 @@
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):before {
@apply bg-background dark:not-checked:bg-foreground dark:checked:bg-primary-foreground rounded-full;
@apply bg-background rounded-full;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not(:checked):before {
@apply bg-foreground;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):checked:before {
@apply bg-primary-foreground;
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not([data-size='sm']):before {
+9 -1
View File
@@ -759,7 +759,15 @@
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):before {
@apply bg-background dark:not-checked:bg-foreground dark:checked:bg-primary-foreground rounded-full;
@apply bg-background rounded-full;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not(:checked):before {
@apply bg-foreground;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):checked:before {
@apply bg-primary-foreground;
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not([data-size='sm']):before {
+9 -1
View File
@@ -755,7 +755,15 @@
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):before {
@apply bg-background dark:not-checked:bg-foreground dark:checked:bg-primary-foreground rounded-full;
@apply bg-background rounded-full;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not(:checked):before {
@apply bg-foreground;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):checked:before {
@apply bg-primary-foreground;
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not([data-size='sm']):before {
+9 -1
View File
@@ -767,7 +767,15 @@
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):before {
@apply bg-background dark:not-checked:bg-foreground dark:checked:bg-primary-foreground rounded-2xl shadow-sm not-dark:bg-clip-padding;
@apply bg-background rounded-2xl shadow-sm not-dark:bg-clip-padding;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not(:checked):before {
@apply bg-foreground;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):checked:before {
@apply bg-primary-foreground;
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not([data-size='sm']):before {
+9 -1
View File
@@ -771,7 +771,15 @@
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):before {
@apply bg-background dark:not-checked:bg-foreground dark:checked:bg-primary-foreground;
@apply bg-background;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not(:checked):before {
@apply bg-foreground;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):checked:before {
@apply bg-primary-foreground;
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not([data-size='sm']):before {
+9 -1
View File
@@ -755,7 +755,15 @@
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):before {
@apply bg-background dark:not-checked:bg-foreground dark:checked:bg-primary-foreground rounded-full;
@apply bg-background rounded-full;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not(:checked):before {
@apply bg-foreground;
}
.dark :is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):checked:before {
@apply bg-primary-foreground;
}
:is(.field > input[type='checkbox'][role='switch'], .input[type='checkbox'][role='switch']):not([data-size='sm']):before {
+4 -4
View File
@@ -5,7 +5,7 @@
@param selected {string|array} [optional] - The initially selected value(s).
@param name {string} [optional] - The name attribute for the hidden input storing the selected value.
@param multiple {boolean} [optional] [default=false] - Enables multiple selection mode.
@param placeholder {string} [optional] - Placeholder text shown when no options are selected (multiple mode only).
@param placeholder {string} [optional] - Placeholder text shown when no option is selected.
@param close_on_select {boolean} [optional] [default=false] - Closes the popover when selecting an option in multiple mode.
@param main_attrs {object} [optional] - Additional HTML attributes for the main container div.
@param trigger_attrs {object} [optional] - Additional HTML attributes for the trigger button.
@@ -62,14 +62,14 @@
{% endfor %}
{% endif %}
{% set default_option = (selected_options.items[0] if selected_options.items else first_option.item) %}
{% set default_option = (selected_options.items[0] if selected_options.items else (none if placeholder else first_option.item)) %}
{% set labels = [] %}
{% if multiple and selected_options.items %}
{% for opt in selected_options.items %}
{% set labels = labels + [opt.label] %}
{% endfor %}
{% endif %}
{% set default_label = (', '.join(labels) if (multiple and selected_options.items) else ((placeholder or '') if (multiple and not selected_options.items) else (default_option.label if default_option else ''))) %}
{% set default_label = (', '.join(labels) if (multiple and selected_options.items) else ((placeholder or '') if (placeholder and not selected_options.items) else (default_option.label if default_option else ''))) %}
{% set selected_payload = namespace(items=[]) %}
{% if multiple and selected_options.items %}
{% for opt in selected_options.items %}
@@ -83,7 +83,7 @@
id="{{ id }}"
class="select {{ main_attrs.class }}"
{% if format == "object" %}data-format="object"{% endif %}
{% if multiple and placeholder %}data-placeholder="{{ placeholder }}"{% endif %}
{% if placeholder %}data-placeholder="{{ placeholder }}"{% endif %}
{% if multiple and close_on_select %}data-close-on-select="true"{% endif %}
{% for key, value in main_attrs.items() %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
+46 -13
View File
@@ -59,6 +59,12 @@
return state.isMultiple ? JSON.stringify(value) : (value[0] || '');
};
const showPlaceholder = (state) => {
state.selectedLabel.textContent = state.placeholder || '';
state.selectedLabel.classList.toggle('text-muted-foreground', Boolean(state.placeholder));
state.input.value = state.isMultiple ? serializeSelection(state, []) : '';
};
const scrollOptionIntoListbox = (state, option) => {
const optionRect = option.getBoundingClientRect();
const listboxRect = state.listbox.getBoundingClientRect();
@@ -114,19 +120,26 @@
state.input.value = serializeSelection(state, selectedDetail);
} else {
const option = optionOrOptions;
if (!option) return;
if (option.dataset.label) {
state.selectedLabel.textContent = option.dataset.label;
if (!option) {
state.options.forEach(option => option.removeAttribute('aria-selected'));
showPlaceholder(state);
selectedDetail = null;
value = '';
} else {
state.selectedLabel.innerHTML = option.innerHTML;
if (option.dataset.label) {
state.selectedLabel.textContent = option.dataset.label;
} else {
state.selectedLabel.innerHTML = option.innerHTML;
}
state.selectedLabel.classList.remove('text-muted-foreground');
selectedDetail = toSelected(option);
value = selectedDetail.value;
state.input.value = serializeSelection(state, [selectedDetail]);
}
selectedDetail = toSelected(option);
value = selectedDetail.value;
state.input.value = serializeSelection(state, [selectedDetail]);
}
state.options.forEach(option => {
const isSelected = state.isMultiple ? state.selectedOptions.has(option) : option === optionOrOptions;
const isSelected = state.isMultiple ? state.selectedOptions.has(option) : optionOrOptions && option === optionOrOptions;
if (isSelected) {
option.setAttribute('aria-selected', 'true');
} else {
@@ -171,7 +184,7 @@
state.visibleOptions = [...state.options];
state.isMultiple = state.listbox.getAttribute('aria-multiselectable') === 'true';
state.format = getFormat(root);
state.placeholder = state.isMultiple ? (root.dataset.placeholder || '') : null;
state.placeholder = root.dataset.placeholder || '';
state.closeOnSelect = root.dataset.closeOnSelect === 'true';
if (state.isMultiple) {
@@ -183,10 +196,12 @@
updateValue(root, selected, false);
} else {
const value = parseStoredValues(previousValue, state);
const selected = state.options.find(option => getValue(option) === value)
const selected = value === '' && state.placeholder
? null
: state.options.find(option => getValue(option) === value)
|| state.options.find(option => option.getAttribute('aria-selected') === 'true');
state.options.forEach(option => option.removeAttribute('aria-selected'));
if (selected) updateValue(root, selected, false);
updateValue(root, selected || null, false);
}
const selectedOption = state.listbox.querySelector('[role="option"][aria-selected="true"]');
@@ -213,6 +228,11 @@
} else {
const option = state.options.find(opt => getValue(opt) === value);
if (!option) return;
if (state.placeholder && getValue(option) === '') {
updateValue(root, null);
closePopover(state);
return;
}
if (root.value !== value) updateValue(root, option);
closePopover(state);
}
@@ -255,7 +275,11 @@
toggleMultipleValue(root, option);
if (state.closeOnSelect) root.close();
} else {
if (root.value !== getValue(option)) updateValue(root, option);
if (state.placeholder && getValue(option) === '') {
updateValue(root, null);
} else if (root.value !== getValue(option)) {
updateValue(root, option);
}
root.close();
}
}
@@ -337,7 +361,11 @@
state.trigger.focus();
}
} else {
if (root.value !== getValue(option)) updateValue(root, option);
if (state.placeholder && getValue(option) === '') {
updateValue(root, null);
} else if (root.value !== getValue(option)) {
updateValue(root, option);
}
root.close();
}
};
@@ -385,6 +413,11 @@
const values = Array.isArray(value) ? value : (value != null ? [value] : []);
updateValue(root, values.map(v => state.options.find(option => getValue(option) === v)).filter(Boolean));
} else {
if (value == null || value === '') {
updateValue(root, null);
root.close();
return;
}
const option = state.options.find(opt => getValue(opt) === value);
if (option) {
updateValue(root, option);
+4 -4
View File
@@ -5,7 +5,7 @@
@param selected {string|array} [optional] - The initially selected value(s).
@param name {string} [optional] - The name attribute for the hidden input storing the selected value.
@param multiple {boolean} [optional] [default=false] - Enables multiple selection mode.
@param placeholder {string} [optional] - Placeholder text shown when no options are selected (multiple mode only).
@param placeholder {string} [optional] - Placeholder text shown when no option is selected.
@param close_on_select {boolean} [optional] [default=false] - Closes the popover when selecting an option in multiple mode.
@param format {string} [optional] [default="value"] - Hidden input serialization format: "value" or "object".
@param main_attrs {object} [optional] - Additional HTML attributes for the main container div.
@@ -63,14 +63,14 @@
{% endfor %}
{% endif %}
{% set default_option = (selected_options[0] if selected_options[0] else (first_option[0] if first_option[0] else None)) %}
{% set default_option = (selected_options[0] if selected_options[0] else (None if placeholder else (first_option[0] if first_option[0] else None))) %}
{% set labels = [] %}
{% if multiple and selected_options %}
{% for opt in selected_options %}
{% set labels = (labels.push(opt.label), labels) %}
{% endfor %}
{% endif %}
{% set default_label = (labels | join(', ') if (multiple and selected_options) else ((placeholder or '') if (multiple and not selected_options) else (default_option.label if default_option else ''))) %}
{% set default_label = (labels | join(', ') if (multiple and selected_options) else ((placeholder or '') if (placeholder and not selected_options) else (default_option.label if default_option else ''))) %}
{% set selected_payload = [] %}
{% if multiple and selected_options %}
{% for opt in selected_options %}
@@ -84,7 +84,7 @@
id="{{ id }}"
class="select {{ main_attrs.class }}"
{% if format == "object" %}data-format="object"{% endif %}
{% if multiple and placeholder %}data-placeholder="{{ placeholder }}"{% endif %}
{% if placeholder %}data-placeholder="{{ placeholder }}"{% endif %}
{% if multiple and close_on_select %}data-close-on-select="true"{% endif %}
{% for key, value in main_attrs %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}