diff --git a/CHANGELOG.md b/CHANGELOG.md index c8e40c9..1c58bdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ ## Unreleased +## [1.0.0-beta.7] - 2026-06-25 + +### Added + +- Added a beta Drawer component with native `` markup, side placement, animated close behavior, backdrop and Escape handling, style-pack visuals, JavaScript entrypoints, and docs. + +### Changed + +- Updated the docs dependency to `reallysimpledocs@^1.0.2`. +- Marked Chart and Drawer as beta components in the docs navigation. +- Promoted the Chart docs warning from alpha to beta. +- Updated installation CDN examples for `basecoat-css@1.0.0-beta.7`. + +### Fixed + +- Aligned Drawer examples more closely with upstream shadcn/ui while avoiding Chart API coupling in Drawer docs. + ## [1.0.0-beta.6] - 2026-06-23 ### Changed diff --git a/docs/src/components/chart.mdx b/docs/src/components/chart.mdx index 8ea999a..777a15f 100644 --- a/docs/src/components/chart.mdx +++ b/docs/src/components/chart.mdx @@ -4,8 +4,8 @@ import chartExamplesSource from "../site/chart-examples.js?raw" # Chart - - Chart support is alpha. The JavaScript API, generated markup, and option names may change before the stable 1.0 release. + + Chart support is beta. The JavaScript API, generated markup, and option names may change before the stable 1.0 release. Use Chart.js with Basecoat defaults for themed colors, external tooltips, and optional generated legends. diff --git a/docs/src/components/drawer.mdx b/docs/src/components/drawer.mdx new file mode 100644 index 0000000..073da4d --- /dev/null +++ b/docs/src/components/drawer.mdx @@ -0,0 +1,312 @@ +# Drawer + + + + +
+
+

Move Goal

+

Set your daily activity goal.

+
+
+
+
+ +
+
350
+
Calories/day
+
+ +
+
+
+
+ + +
+
+
+
+ +## Usage + + + + +Import Tailwind and one full Basecoat style bundle. + +```css +@import "tailwindcss"; +@import "basecoat-css/vega.css"; +``` + +Or import only the base CSS, Drawer component CSS, and one style pack. + +```css +@import "tailwindcss"; +@import "basecoat-css/base.css"; +@import "basecoat-css/components/drawer.css"; +@import "basecoat-css/styles/vega.css"; +``` + +Using CDN or bundler imports? See the [Installation page](/installation). + + + + +Copy or serve the full Basecoat JavaScript bundle. + +```html + +``` + +Or copy or serve the Basecoat runtime and Drawer script. + +```html + + +``` + +Using CDN or bundler imports? See the [Installation page](/installation). + + + + +Basecoat maps shadcn/ui's Vaul Drawer to a native `` element. This keeps modality, focus handling, and inert page content in the browser platform. The Drawer script adds safe backdrop-click close and lets the exit animation finish before calling the native close. Drag gestures, snap points, and the drag handle are intentionally not included. + +```html + + +
+
+

Move Goal

+

Set your daily activity goal.

+
+
+
+
+ +
+
350
+
Calories/day
+
+ +
+
+
+
+ + +
+
+
+``` + +
+
+ +### HTML structure + + + Basecoat does not implement Vaul's drag-to-close gesture, snap points, or drag handle. Drawers close with outside click, Escape, or explicit close controls. + + +
+
<button type="button" onclick="drawer.showModal()"> Optional
+
Trigger button. Basecoat intentionally uses the native HTMLDialogElement.showModal() method.
+
<dialog class="drawer" data-side="bottom|top|left|right">
+
+ Native modal drawer. Omit data-side for the default bottom drawer. Add aria-labelledby and aria-describedby when title and description are present. JavaScript adds the data-drawer-initialized flag and manages animated close behavior. +
+
<article>
+
+ Drawer content surface. +
+
<header> Optional
+
Drawer header with a title and optional description.
+
<section> Optional
+
Scrollable body/content area.
+
<footer> Optional
+
Action area pinned after the drawer body.
+
+
+
+
+
+ +## Examples + +### Sides + +Use `data-side` to set the viewport side. Available values are `top`, `right`, `bottom`, and `left`. + + +
+ + + + +
+ +
+
+

Move Goal

+

Set your daily activity goal.

+
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+
+
+ + +
+
+
+ +
+
+

Move Goal

+

Set your daily activity goal.

+
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+
+
+ + +
+
+
+ +
+
+

Move Goal

+

Set your daily activity goal.

+
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+
+
+ + +
+
+
+ +
+
+

Move Goal

+

Set your daily activity goal.

+
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+
+
+ + +
+
+
+
+ +### Scrollable content + +Keep actions visible while the drawer body scrolls. + + + + +
+
+

Move Goal

+

Set your daily activity goal.

+
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+
+
+ + +
+
+
+
+ +### RTL + +Drawer sides are physical viewport sides. Content spacing and text alignment follow document direction. + + +
+ + +
+
+

نقل الهدف

+

حدد هدف نشاطك اليومي.

+
+
+
+
+ +
+
٣٥٠
+
سعرات حرارية/يوم
+
+ +
+
+
+
+ + +
+
+
+
+
diff --git a/docs/src/docs.json b/docs/src/docs.json index a6fef81..bbec6f5 100644 --- a/docs/src/docs.json +++ b/docs/src/docs.json @@ -68,12 +68,17 @@ { "type": "item", "slug": "components/chart", - "badge": "Alpha" + "badge": "Beta" }, "components/checkbox", "components/combobox", "components/command", "components/dialog", + { + "type": "item", + "slug": "components/drawer", + "badge": "Beta" + }, "components/dropdown-menu", "components/empty", "components/field", diff --git a/docs/src/installation.mdx b/docs/src/installation.mdx index c0b75aa..7b1f208 100644 --- a/docs/src/installation.mdx +++ b/docs/src/installation.mdx @@ -10,13 +10,13 @@ Basecoat can be used from a CDN or installed with npm. Use the CDN for simple st Use the default bundled stylesheet. It is an alias for the Vega style bundle. ```html - + ``` You can also use one of the named style bundles: `vega`, `nova`, `maia`, `lyra`, `mira`, `luma`, `sera`, or `rhea`. ```html - + ``` @@ -25,15 +25,15 @@ You can also use one of the named style bundles: `vega`, `nova`, `maia`, `lyra`, Most components are CSS-only. Interactive components need JavaScript. Use the all-in-one bundle when file size is not a concern. ```html - + ``` Or load the Basecoat runtime once, then only the component scripts you use. ```html - - - + + + ``` @@ -203,6 +203,7 @@ These components need JavaScript for behavior: - [Combobox](/components/combobox) - [Command](/components/command) +- [Drawer](/components/drawer) - [Dropdown Menu](/components/dropdown-menu) - [Popover](/components/popover) - [Select](/components/select) diff --git a/package-lock.json b/package-lock.json index ff5485f..0ef27e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "basecoat", - "version": "1.0.0-beta.6", + "version": "1.0.0-beta.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "basecoat", - "version": "1.0.0-beta.6", + "version": "1.0.0-beta.7", "license": "MIT", "workspaces": [ "packages/*" @@ -20,7 +20,7 @@ "lucide-static": "^1.17.0", "nunjucks": "^3.2.4", "prettier": "^3.5.3", - "reallysimpledocs": "^1.0.1", + "reallysimpledocs": "^1.0.2", "tailwindcss": "^4.1.17", "terser": "^5.42.0", "wrangler": "^4.50.0" @@ -7823,9 +7823,9 @@ "license": "MIT" }, "node_modules/reallysimpledocs": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reallysimpledocs/-/reallysimpledocs-1.0.1.tgz", - "integrity": "sha512-a0ekB68JP/khU8MXnwEql/jyO+NUi25EyfDgtlIQCpRFfuUgsY9b0U1eewBpsmUfxznqvNG4oBkUcRBfydcM2g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/reallysimpledocs/-/reallysimpledocs-1.0.2.tgz", + "integrity": "sha512-nAPX+sc02/zfGQb3+6eILRLtK0OwLDTdfv1DXDeCCgUSEN4hMNBjsZLYMMvXAshYxvCHv41Tmj5xY6gquKcVhA==", "dev": true, "dependencies": { "@astrojs/markdown-remark": "^7.2.0", @@ -9883,7 +9883,7 @@ }, "packages/cli": { "name": "basecoat-cli", - "version": "1.0.0-beta.6", + "version": "1.0.0-beta.7", "license": "MIT", "dependencies": { "commander": "^13.1.0", @@ -9896,7 +9896,7 @@ }, "packages/css": { "name": "basecoat-css", - "version": "1.0.0-beta.6", + "version": "1.0.0-beta.7", "license": "MIT" } } diff --git a/package.json b/package.json index 05caffb..c825a0a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "basecoat", - "version": "1.0.0-beta.6", + "version": "1.0.0-beta.7", "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.1", + "reallysimpledocs": "^1.0.2", "tailwindcss": "^4.1.17", "terser": "^5.42.0", "wrangler": "^4.50.0" diff --git a/packages/cli/package.json b/packages/cli/package.json index 4594f5d..81c6070 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,12 +1,12 @@ { "name": "basecoat-cli", - "version": "1.0.0-beta.6", + "version": "1.0.0-beta.7", "description": "Add Basecoat components to your project", "author": "hunvreus", "license": "MIT", "type": "module", "bin": { - "basecoat-cli": "./dist/index.js" + "basecoat-cli": "dist/index.js" }, "files": [ "dist/" diff --git a/packages/css/package.json b/packages/css/package.json index 4900b2f..171374c 100644 --- a/packages/css/package.json +++ b/packages/css/package.json @@ -1,6 +1,6 @@ { "name": "basecoat-css", - "version": "1.0.0-beta.6", + "version": "1.0.0-beta.7", "description": "Tailwind CSS for Basecoat components", "author": { "name": "hunvreus", @@ -52,6 +52,8 @@ "./command.min": "./dist/js/command.min.js", "./dropdown-menu": "./dist/js/dropdown-menu.js", "./dropdown-menu.min": "./dist/js/dropdown-menu.min.js", + "./drawer": "./dist/js/drawer.js", + "./drawer.min": "./dist/js/drawer.min.js", "./popover": "./dist/js/popover.js", "./popover.min": "./dist/js/popover.min.js", "./range": "./dist/js/range.js", diff --git a/scripts/build.js b/scripts/build.js index 45cb5f8..b646726 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -125,7 +125,7 @@ async function build() { // Create combined component files console.log('Creating combined component files...'); - const componentsToCombine = ['basecoat.js', 'accordion.js', 'command.js', 'combobox.js', 'dropdown-menu.js', 'popover.js', 'range.js', 'select.js', 'sidebar.js', 'tabs.js', 'toast.js']; + const componentsToCombine = ['basecoat.js', 'accordion.js', 'command.js', 'combobox.js', 'drawer.js', 'dropdown-menu.js', 'popover.js', 'range.js', 'select.js', 'sidebar.js', 'tabs.js', 'toast.js']; const componentPaths = componentsToCombine.map(f => path.join(srcJsDir, f)); // Create non-minified bundle diff --git a/scripts/generate-css-entrypoints.js b/scripts/generate-css-entrypoints.js index 39160b9..1b90c98 100644 --- a/scripts/generate-css-entrypoints.js +++ b/scripts/generate-css-entrypoints.js @@ -19,6 +19,7 @@ const componentOrder = [ 'command', 'combobox', 'dialog', + 'drawer', 'dropdown-menu', 'empty', 'field', diff --git a/src/css/basecoat-components.css b/src/css/basecoat-components.css index 6422f7e..208bdce 100644 --- a/src/css/basecoat-components.css +++ b/src/css/basecoat-components.css @@ -12,6 +12,7 @@ @import "./components/command.css"; @import "./components/combobox.css"; @import "./components/dialog.css"; +@import "./components/drawer.css"; @import "./components/dropdown-menu.css"; @import "./components/empty.css"; @import "./components/field.css"; diff --git a/src/css/components/drawer.css b/src/css/components/drawer.css new file mode 100644 index 0000000..c5f8f8b --- /dev/null +++ b/src/css/components/drawer.css @@ -0,0 +1,89 @@ +/* Drawer */ +@layer components { + .drawer { + @apply fixed inset-0 m-0 size-auto max-h-none max-w-none overflow-visible bg-transparent p-0 text-inherit opacity-0 transition-all transition-discrete duration-500 ease-[cubic-bezier(0.32,0.72,0,1)] backdrop:opacity-0 backdrop:transition-all backdrop:transition-discrete backdrop:duration-500 backdrop:ease-[cubic-bezier(0.32,0.72,0,1)]; + + > * { + @apply fixed z-50 flex h-auto flex-col transition-transform duration-500 ease-[cubic-bezier(0.32,0.72,0,1)] will-change-transform outline-hidden; + } + + &:not([data-side]) > *, + &[data-side='bottom'] > * { + @apply inset-x-0 bottom-0 mt-24 max-h-[80vh] translate-y-full; + } + + &[data-side='top'] > * { + @apply inset-x-0 top-0 mb-24 max-h-[80vh] -translate-y-full; + } + + &[data-side='left'] > * { + @apply inset-y-0 left-0 w-3/4 max-w-sm -translate-x-full; + } + + &[data-side='right'] > * { + @apply inset-y-0 right-0 w-3/4 max-w-sm translate-x-full; + } + + &[data-closing] { + @apply opacity-0 backdrop:opacity-0; + } + + &[data-closing]:not([data-side]) > *, + &[data-closing][data-side='bottom'] > * { + @apply translate-y-full; + } + + &[data-closing][data-side='top'] > * { + @apply -translate-y-full; + } + + &[data-closing][data-side='left'] > * { + @apply -translate-x-full; + } + + &[data-closing][data-side='right'] > * { + @apply translate-x-full; + } + + &:is([open], :popover-open):not([data-closing]) { + @apply opacity-100 backdrop:opacity-100; + + > * { + @apply translate-x-0 translate-y-0; + } + + @starting-style { + @apply opacity-0 backdrop:opacity-0; + + &:not([data-side]) > *, + &[data-side='bottom'] > * { + @apply translate-y-full; + } + + &[data-side='top'] > * { + @apply -translate-y-full; + } + + &[data-side='left'] > * { + @apply -translate-x-full; + } + + &[data-side='right'] > * { + @apply translate-x-full; + } + } + } + + > * > header { + @apply flex flex-col; + } + + > * > section { + @apply min-h-0 flex-1 overflow-y-auto; + } + + > * > footer { + @apply mt-auto flex flex-col; + } + } +} diff --git a/src/css/styles/luma.css b/src/css/styles/luma.css index e9d65f4..b5f95e0 100644 --- a/src/css/styles/luma.css +++ b/src/css/styles/luma.css @@ -589,6 +589,39 @@ @apply text-muted-foreground text-sm text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a:hover]:text-foreground; } + /* Drawer */ + .drawer::backdrop { + @apply bg-black/30 backdrop-blur-sm; + } + + .drawer > * { + @apply before:bg-popover before:border-border relative bg-transparent p-4 text-sm before:absolute before:inset-2 before:-z-10 before:rounded-4xl before:border before:shadow-xl; + } + + .drawer > * > header { + @apply gap-0.5 p-4 text-start md:gap-1.5; + } + + .drawer:not([data-side]) > * > header, + .drawer[data-side='bottom'] > * > header, + .drawer[data-side='top'] > * > header { + @apply text-center; + } + + .drawer > * > footer { + @apply gap-2 p-4; + } + + .drawer > * > header > h2, + .drawer > * > [data-title] { + @apply text-lg font-semibold leading-none tracking-tight; + } + + .drawer > * > header > p, + .drawer > * > [data-description] { + @apply text-muted-foreground text-sm; + } + /* Dropdown Menu */ .dropdown-menu > [data-popover] { @apply bg-popover text-popover-foreground ring-foreground/5 dark:ring-foreground/10 min-w-48 gap-0 overflow-x-hidden overflow-y-auto rounded-3xl p-1.5 shadow-lg ring-1 duration-100; diff --git a/src/css/styles/lyra.css b/src/css/styles/lyra.css index f0562fd..4a4936c 100644 --- a/src/css/styles/lyra.css +++ b/src/css/styles/lyra.css @@ -565,6 +565,56 @@ @apply text-muted-foreground text-xs/relaxed text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a:hover]:text-foreground; } + /* Drawer */ + .drawer::backdrop { + @apply bg-black/10 backdrop-blur-xs; + } + + .drawer > * { + @apply bg-popover text-popover-foreground text-xs/relaxed; + } + + .drawer:not([data-side]) > *, + .drawer[data-side='bottom'] > * { + @apply rounded-none border-t; + } + + .drawer[data-side='top'] > * { + @apply rounded-none border-b; + } + + .drawer[data-side='left'] > * { + @apply rounded-none border-r; + } + + .drawer[data-side='right'] > * { + @apply rounded-none border-l; + } + + .drawer > * > header { + @apply gap-0.5 p-4 text-start; + } + + .drawer:not([data-side]) > * > header, + .drawer[data-side='bottom'] > * > header, + .drawer[data-side='top'] > * > header { + @apply text-center; + } + + .drawer > * > footer { + @apply gap-2 p-4; + } + + .drawer > * > header > h2, + .drawer > * > [data-title] { + @apply text-sm font-medium; + } + + .drawer > * > header > p, + .drawer > * > [data-description] { + @apply text-muted-foreground text-xs/relaxed; + } + /* Dropdown Menu */ .dropdown-menu > [data-popover] { @apply bg-popover text-popover-foreground ring-foreground/10 gap-0 overflow-x-hidden overflow-y-auto rounded-none p-0 shadow-md ring-1 duration-100; diff --git a/src/css/styles/maia.css b/src/css/styles/maia.css index 35fde30..a0c0905 100644 --- a/src/css/styles/maia.css +++ b/src/css/styles/maia.css @@ -577,6 +577,39 @@ @apply text-muted-foreground text-sm text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a:hover]:text-foreground; } + /* Drawer */ + .drawer::backdrop { + @apply bg-black/80 backdrop-blur-xs; + } + + .drawer > * { + @apply before:bg-popover text-popover-foreground before:border-border relative bg-transparent p-4 text-sm before:absolute before:inset-2 before:-z-10 before:rounded-4xl before:border; + } + + .drawer > * > header { + @apply gap-0.5 p-4 text-start md:gap-1.5; + } + + .drawer:not([data-side]) > * > header, + .drawer[data-side='bottom'] > * > header, + .drawer[data-side='top'] > * > header { + @apply text-center; + } + + .drawer > * > footer { + @apply gap-2 p-4; + } + + .drawer > * > header > h2, + .drawer > * > [data-title] { + @apply text-lg font-semibold leading-none tracking-tight; + } + + .drawer > * > header > p, + .drawer > * > [data-description] { + @apply text-muted-foreground text-sm; + } + /* Dropdown Menu */ .dropdown-menu > [data-popover] { @apply bg-popover text-popover-foreground ring-foreground/5 dark:ring-foreground/10 min-w-48 gap-0 overflow-x-hidden overflow-y-auto rounded-2xl p-1 shadow-2xl ring-1 duration-100; diff --git a/src/css/styles/mira.css b/src/css/styles/mira.css index ab82404..0841f4c 100644 --- a/src/css/styles/mira.css +++ b/src/css/styles/mira.css @@ -581,6 +581,39 @@ @apply text-muted-foreground text-xs/relaxed text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a:hover]:text-foreground; } + /* Drawer */ + .drawer::backdrop { + @apply bg-black/80 backdrop-blur-xs; + } + + .drawer > * { + @apply before:bg-popover text-popover-foreground before:border-border relative bg-transparent p-2 text-xs/relaxed before:absolute before:inset-2 before:-z-10 before:rounded-xl before:border; + } + + .drawer > * > header { + @apply gap-1 p-4 text-start; + } + + .drawer:not([data-side]) > * > header, + .drawer[data-side='bottom'] > * > header, + .drawer[data-side='top'] > * > header { + @apply text-center; + } + + .drawer > * > footer { + @apply gap-2 p-4; + } + + .drawer > * > header > h2, + .drawer > * > [data-title] { + @apply text-sm font-medium; + } + + .drawer > * > header > p, + .drawer > * > [data-description] { + @apply text-muted-foreground text-xs/relaxed; + } + /* Dropdown Menu */ .dropdown-menu > [data-popover] { @apply bg-popover text-popover-foreground ring-foreground/10 gap-0 overflow-x-hidden overflow-y-auto rounded-lg p-1 shadow-md ring-1 duration-100; diff --git a/src/css/styles/nova.css b/src/css/styles/nova.css index 4657568..8d772fc 100644 --- a/src/css/styles/nova.css +++ b/src/css/styles/nova.css @@ -573,6 +573,56 @@ @apply text-muted-foreground text-sm text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a:hover]:text-foreground; } + /* Drawer */ + .drawer::backdrop { + @apply bg-black/10 backdrop-blur-xs; + } + + .drawer > * { + @apply bg-popover text-popover-foreground text-sm; + } + + .drawer:not([data-side]) > *, + .drawer[data-side='bottom'] > * { + @apply rounded-t-xl border-t; + } + + .drawer[data-side='top'] > * { + @apply rounded-b-xl border-b; + } + + .drawer[data-side='left'] > * { + @apply rounded-r-xl border-r; + } + + .drawer[data-side='right'] > * { + @apply rounded-l-xl border-l; + } + + .drawer > * > header { + @apply gap-0.5 p-4 text-start; + } + + .drawer:not([data-side]) > * > header, + .drawer[data-side='bottom'] > * > header, + .drawer[data-side='top'] > * > header { + @apply text-center; + } + + .drawer > * > footer { + @apply gap-2 p-4; + } + + .drawer > * > header > h2, + .drawer > * > [data-title] { + @apply text-lg font-semibold leading-none tracking-tight; + } + + .drawer > * > header > p, + .drawer > * > [data-description] { + @apply text-muted-foreground text-sm; + } + /* Dropdown Menu */ .dropdown-menu > [data-popover] { @apply bg-popover text-popover-foreground ring-foreground/10 gap-0 overflow-x-hidden overflow-y-auto rounded-lg p-1 shadow-md ring-1 duration-100; diff --git a/src/css/styles/rhea.css b/src/css/styles/rhea.css index 4e62c11..5b0b6f1 100644 --- a/src/css/styles/rhea.css +++ b/src/css/styles/rhea.css @@ -589,6 +589,39 @@ @apply text-muted-foreground text-sm text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a:hover]:text-foreground; } + /* Drawer */ + .drawer::backdrop { + @apply bg-black/30 backdrop-blur-sm; + } + + .drawer > * { + @apply before:bg-popover before:border-border relative bg-transparent p-4 text-sm before:absolute before:inset-2 before:-z-10 before:rounded-[min(var(--radius-4xl),24px)] before:border before:shadow-xl; + } + + .drawer > * > header { + @apply gap-0.5 p-4 text-start md:gap-1.5; + } + + .drawer:not([data-side]) > * > header, + .drawer[data-side='bottom'] > * > header, + .drawer[data-side='top'] > * > header { + @apply text-center; + } + + .drawer > * > footer { + @apply gap-2 p-4; + } + + .drawer > * > header > h2, + .drawer > * > [data-title] { + @apply text-lg font-semibold leading-none tracking-tight; + } + + .drawer > * > header > p, + .drawer > * > [data-description] { + @apply text-muted-foreground text-sm; + } + /* Dropdown Menu */ .dropdown-menu > [data-popover] { @apply bg-popover text-popover-foreground ring-foreground/5 dark:ring-foreground/10 gap-0 overflow-x-hidden overflow-y-auto rounded-2xl p-1 shadow-lg ring-1 duration-100; diff --git a/src/css/styles/sera.css b/src/css/styles/sera.css index c269c50..dc978ca 100644 --- a/src/css/styles/sera.css +++ b/src/css/styles/sera.css @@ -593,6 +593,56 @@ @apply text-muted-foreground mt-0.5 text-sm leading-relaxed text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a:hover]:text-foreground; } + /* Drawer */ + .drawer::backdrop { + @apply bg-black/20 backdrop-blur-sm; + } + + .drawer > * { + @apply bg-popover text-popover-foreground text-sm; + } + + .drawer:not([data-side]) > *, + .drawer[data-side='bottom'] > * { + @apply rounded-none border-t; + } + + .drawer[data-side='top'] > * { + @apply rounded-none border-b; + } + + .drawer[data-side='left'] > * { + @apply rounded-none border-r; + } + + .drawer[data-side='right'] > * { + @apply rounded-none border-l; + } + + .drawer > * > header { + @apply gap-1 p-4 text-start md:gap-2; + } + + .drawer:not([data-side]) > * > header, + .drawer[data-side='bottom'] > * > header, + .drawer[data-side='top'] > * > header { + @apply text-center; + } + + .drawer > * > footer { + @apply gap-2 p-4; + } + + .drawer > * > header > h2, + .drawer > * > [data-title] { + @apply text-lg font-semibold tracking-wider uppercase; + } + + .drawer > * > header > p, + .drawer > * > [data-description] { + @apply text-muted-foreground mt-0.5 text-sm leading-relaxed; + } + /* Dropdown Menu */ .dropdown-menu > [data-popover] { @apply bg-popover text-popover-foreground ring-foreground/10 min-w-48 gap-0 overflow-x-hidden overflow-y-auto rounded-none p-1.5 shadow-md ring-1 duration-100; diff --git a/src/css/styles/vega.css b/src/css/styles/vega.css index e2b68ad..096516c 100644 --- a/src/css/styles/vega.css +++ b/src/css/styles/vega.css @@ -573,6 +573,56 @@ @apply text-muted-foreground text-sm text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a:hover]:text-foreground; } + /* Drawer */ + .drawer::backdrop { + @apply bg-black/10 backdrop-blur-xs; + } + + .drawer > * { + @apply bg-popover text-popover-foreground text-sm; + } + + .drawer:not([data-side]) > *, + .drawer[data-side='bottom'] > * { + @apply rounded-t-xl border-t; + } + + .drawer[data-side='top'] > * { + @apply rounded-b-xl border-b; + } + + .drawer[data-side='left'] > * { + @apply rounded-r-xl border-r; + } + + .drawer[data-side='right'] > * { + @apply rounded-l-xl border-l; + } + + .drawer > * > header { + @apply gap-0.5 p-4 text-start md:gap-1.5; + } + + .drawer:not([data-side]) > * > header, + .drawer[data-side='bottom'] > * > header, + .drawer[data-side='top'] > * > header { + @apply text-center; + } + + .drawer > * > footer { + @apply gap-2 p-4; + } + + .drawer > * > header > h2, + .drawer > * > [data-title] { + @apply text-lg font-semibold leading-none tracking-tight; + } + + .drawer > * > header > p, + .drawer > * > [data-description] { + @apply text-muted-foreground text-sm; + } + /* Dropdown Menu */ .dropdown-menu > [data-popover] { @apply bg-popover text-popover-foreground ring-foreground/10 gap-0 overflow-x-hidden overflow-y-auto rounded-md p-1 shadow-md ring-1 duration-100; diff --git a/src/js/drawer.js b/src/js/drawer.js new file mode 100644 index 0000000..0cf32c3 --- /dev/null +++ b/src/js/drawer.js @@ -0,0 +1,84 @@ +(() => { + const toMs = (value) => { + if (!value) return 0; + const trimmed = value.trim(); + if (trimmed.endsWith('ms')) return parseFloat(trimmed) || 0; + if (trimmed.endsWith('s')) return (parseFloat(trimmed) || 0) * 1000; + return parseFloat(trimmed) || 0; + }; + + const maxTransitionMs = (element) => { + if (!element) return 0; + const styles = getComputedStyle(element); + const durations = styles.transitionDuration.split(',').map(toMs); + const delays = styles.transitionDelay.split(',').map(toMs); + return Math.max(0, ...durations.map((duration, index) => duration + (delays[index] || delays[0] || 0))); + }; + + const initDrawer = (drawer) => { + if (drawer.dataset.drawerInitialized) return; + + const nativeClose = drawer.close.bind(drawer); + let pointerStartedOnBackdrop = false; + let closeTimer = null; + + const finishClose = (returnValue) => { + window.clearTimeout(closeTimer); + closeTimer = null; + drawer.removeAttribute('data-closing'); + nativeClose(returnValue); + }; + + drawer.close = (returnValue = '') => { + if (!drawer.open) return; + if (drawer.dataset.closing) return; + + const content = drawer.firstElementChild; + const duration = maxTransitionMs(content); + + if (duration === 0 || window.matchMedia('(prefers-reduced-motion: reduce)').matches) { + finishClose(returnValue); + return; + } + + drawer.dataset.closing = 'true'; + closeTimer = window.setTimeout(() => finishClose(returnValue), duration + 50); + }; + + const handleCancel = (event) => { + event.preventDefault(); + drawer.close(); + }; + + const handlePointerDown = (event) => { + pointerStartedOnBackdrop = event.target === drawer; + }; + + const handlePointerUp = (event) => { + if (pointerStartedOnBackdrop && event.target === drawer) { + drawer.close(); + } + pointerStartedOnBackdrop = false; + }; + + drawer.addEventListener('cancel', handleCancel); + drawer.addEventListener('pointerdown', handlePointerDown); + drawer.addEventListener('pointerup', handlePointerUp); + + drawer._destroy = () => { + window.clearTimeout(closeTimer); + drawer.removeEventListener('cancel', handleCancel); + drawer.removeEventListener('pointerdown', handlePointerDown); + drawer.removeEventListener('pointerup', handlePointerUp); + drawer.close = nativeClose; + delete drawer._destroy; + }; + + drawer.dataset.drawerInitialized = 'true'; + drawer.dispatchEvent(new CustomEvent('basecoat:initialized')); + }; + + if (window.basecoat) { + window.basecoat.register('drawer', '.drawer:not([data-drawer-initialized])', initDrawer); + } +})();