From bae366816836f465e203a4cf3fe8bbb62c8cd1e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubom=C3=ADr=20Bla=C5=BEek?= Date: Thu, 25 Jun 2026 15:48:54 +0200 Subject: [PATCH 01/35] feat: remove TailwindCSS v3 references and update docs for v4-only configuration --- docs/.vitepress/config.ts | 4 - docs/docs/base/config.md | 214 +----------------------------- docs/docs/base/theme.md | 23 +--- docs/docs/base/transitions.md | 2 +- docs/docs/index.md | 98 ++++---------- docs/docs/layers.md | 37 ------ docs/docs/utilities/accent.md | 5 +- docs/docs/utilities/animation.md | 27 +--- docs/docs/utilities/divide-gap.md | 5 +- 9 files changed, 39 insertions(+), 376 deletions(-) delete mode 100644 docs/docs/layers.md diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index a317796..1f9ae69 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -104,10 +104,6 @@ export default defineConfig({ text: 'Grid', link: '/docs/grid' }, - { - text: 'Layers', - link: '/docs/layers' - }, { text: 'Tokens', link: '/docs/tokens' diff --git a/docs/docs/base/config.md b/docs/docs/base/config.md index d5f0ee2..4a3be04 100644 --- a/docs/docs/base/config.md +++ b/docs/docs/base/config.md @@ -7,7 +7,7 @@ so you can use these properties in both current and future versions of TailwindC <<< @/../node_modules/winduum/src/theme/config/index.css -## Tailwind CSS v4 +## Tailwind CSS In the new version of TailwindCSS the configuration is done via CSS, so no plugin is necessary. Most of the config CSS properties are also part of the new version. @@ -15,214 +15,4 @@ Most of the config CSS properties are also part of the new version. @import "tailwindcss/theme.css" layer(theme); @import "winduum/tailwindcss/theme/config/index.css" layer(theme); @import "winduum/tailwindcss/theme/default.css" layer(theme); -``` - -## Tailwind CSS v3 - -To add `winduum` to TailwindCSS v3, add folowing plugin to `tailwind.config.js` configuration file. - -```js -import winduum from 'winduum' - -export default { - darkMode: 'class', - content: [ - './node_modules/winduum/src/**/*.js', - './src/**/*.{js,html}' - ], - plugins: [ - winduum({ - // config options - }) - ], -} -``` - -You can customize config with options listed bellow. - -This plugin disables by default following TailwindCSS corePlugins - -* **preflight** - custom modern css reset is used, see [Reset](/docs/base/reset) - -Winduum also exports useful helper functions you can use in your `tailwind.config.js`, see [`utils/tailwind.js`](https://github.com/winduum/winduum/blob/main/utils/tailwind.js) for more info. - -### settings.rgb -Include `-rgb` color variants. Learn more about this in [Compatibility](/docs/base/theme.html#compatibility) section. - -* **Type:** `boolean` -* **Default:** `false` - -### settings.colorMix -Use `color-mix` in color variants instead of rgb. Learn more about this in [Compatibility](/docs/base/theme.html#compatibility) section. - -* **Type:** `boolean` -* **Default:** `true` - -### colors -* **Type:** `string[] | string` -* **Default:** `undefined` - -These are additional color tokens that can be used with TailwindCSS as CSS custom properties, which can be then defined in `.css`. See [Colors](/docs/colors) for more info. -Or you can add a path to `.css` file containing the CSS custom properties, and it will be parsed automatically. - -Example `bg-primary`: -```css -.bg-primary { - background-color: color-mix(in sRGB, var(--color-primary) calc(var(--tw-bg-opacity, 1) * 100%), transparent); -} -``` - -### fontFamily -* **Type:** `string[] | string` -* **Default:** `undefined` - -These are additional font-family tokens that can be used with TailwindCSS as CSS properties, which can be then defined in `.css`. -Or you can add a path to `.css` file containing the CSS custom properties, and it will be parsed automatically. - -Example `font-primary`: -```css -.font-primary { - font-family: var(--font-primary); -} -``` - -### fontWeight -* **Type:** `string[] | string` -* **Default:** `undefined` - -These are additional font-weight tokens that can be used with TailwindCSS as CSS properties, which can be then defined in `.css`. -Or you can add a path to `.css` file containing the CSS custom properties, and it will be parsed automatically. - -Example `font-bold`: -```css -.font-bold { - font-weight: var(--font-bold); -} -``` - -### ease -* **Type:** `string[] | string` -* **Default:** `undefined` - -These are additional transition easing tokens that can be used with TailwindCSS as CSS properties, which can be then defined in `.css`. -Or you can add a path to `.css` file containing the CSS custom properties, and it will be parsed automatically. - -Example `ease-linear`: -```css -.ease-linear { - transition-timing-function: var(--ease-linear); -} -``` - -### zIndex -* **Type:** `string[] | string` -* **Default:** `undefined` - -These are additional z-index tokens that can be used with TailwindCSS as CSS properties, which can be then defined in `.css`. -Or you can add a path to `.css` file containing the CSS custom properties, and it will be parsed automatically. - -Example `z-10`: -```css -.z-10 { - z-index: var(--z-10); -} -``` - -### fontSize -* **Type:** `string[] | string` -* **Default:** `undefined` - -These are additional `font-size` tokens that can be used with TailwindCSS as CSS properties, which can be then defined in `.css`. -Or you can add a path to `.css` file containing the CSS custom properties, and it will be parsed automatically. - -Example `text-md`: -```css -.text-md { - font-size: var(--font-size-md); - line-height: calc(var(--font-size-md) + 0.5rem); -} -``` - -### spacing -* **Type:** `string[] | string` -* **Default:** `undefined` - -These are additional spacing tokens that can be used with TailwindCSS as CSS properties, which can be then defined in `.css`. -Or you can add a path to `.css` file containing the CSS custom properties, and it will be parsed automatically. - -Example `gap-4`: -```css -.gap-4 { - gap: var(--spacing-4); -} -``` - -Example `px-4`: -```css -.px-4 { - padding-left: var(--spacing-4); - padding-right: var(--spacing-4); -} -``` - -### borderRadius -* **Type:** `string[] | string` -* **Default:** `undefined` - -These are additional border-radius tokens that can be used with TailwindCSS as CSS properties, which can be then defined in `.css`. -Or you can add a path to `.css` file containing the CSS custom properties, and it will be parsed automatically. - -Example `rounded-md`: -```css -.rounded-md { - border-radius: var(--radius-md); -} -``` - -### animations -* **Type:** `string[]` -* **Default:** `['fade-in', 'fade-out', 'ripple', 'spin', 'move-indeterminate']` - -These are additional animation tokens that can be used with TailwindCSS as CSS properties, which can be then defined in `.css`. -Or you can add a path to `.css` file containing the CSS custom properties, and it will be parsed automatically. - -Example `animation-fade-in`: -```css -.animation-fade-in { - animation-name: fade-in; -} -``` - -### mask -* **Type:** `string[] | string` -* **Default:** `undefined` - -These are additional mask tokens that can be used with TailwindCSS as CSS properties, which can be then defined in `.css`. -Or you can add a path to `.css` file containing the CSS custom properties, and it will be parsed automatically. - -Example `animation-fade-in`: -```css -.mask-check { - mask: var(--mask-check) -} -``` - -### screens -* **Type:** `object` -* **Default:** -```js -{ - 'xs': '22.5em', - 'sm': '26em', - 'md': '48em', - 'lg': '60em', - 'xl': '76em', - '2xl': '82em', - '3xl': '88em', - '4xl': '100em', - 'xxl': '126em', - '2xxl': '158em' -} -``` - -These are new media queries tokens that can be used with TailwindCSS, see more in [Breakpoints](/docs/base/breakpoints) +``` \ No newline at end of file diff --git a/docs/docs/base/theme.md b/docs/docs/base/theme.md index bd17261..ff478d2 100644 --- a/docs/docs/base/theme.md +++ b/docs/docs/base/theme.md @@ -6,17 +6,18 @@ Theming in Winduum is really easy. All it takes is a few CSS properties. There a Each `color-mix` function also contains `--default-color-space` property, which you can change from `sRGB` to mix colors in different color spaces. You can use colors in any format you want. -### TailwindCSS v4 +### Without TailwindCSS + +[`src/theme/default.css`](https://github.com/winduum/winduum/blob/main/src/theme/default.css) + +### TailwindCSS Instead of `:root, :host` the `v4` `@theme` at-rule is used. [`tailwindcss/theme/default.css`](https://github.com/winduum/winduum/blob/main/tailwindcss/theme/default.css) -### TailwindCSS v3 - -[`src/theme/default.css`](https://github.com/winduum/winduum/blob/main/src/theme/default.css) +<<< @/../node_modules/winduum/tailwindcss/theme/default.css -<<< @/../node_modules/winduum/src/theme/default.css ## Default P3 @@ -31,15 +32,3 @@ Better high range colors for P3 capable displays. [`src/theme/dark.css`](https://github.com/winduum/winduum/blob/main/src/theme/dark.css) <<< @/../node_modules/winduum/src/theme/dark.css - - - -## Compatibility - -Support for `color-mix` is almost `90%` global usage. -But if you want better compatibility you can still use `rgb` -which can be enabled it in the [Config](/docs/base/config.html#settings-rgb) (only for TailwindCSS v3). -In that case, you have to use rgb variants for theming in your own components. - -* [`src/theme/default-rgb.css`](https://github.com/winduum/winduum/blob/main/src/theme/default-rgb.css) -* [`src/theme/dark-rgb.css`](https://github.com/winduum/winduum/blob/main/src/theme/dark-rgb.css) diff --git a/docs/docs/base/transitions.md b/docs/docs/base/transitions.md index f2b86b1..8941ece 100644 --- a/docs/docs/base/transitions.md +++ b/docs/docs/base/transitions.md @@ -1,7 +1,7 @@ # Transitions This activates the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) with cross-document animations.
-CSS properties can be changed via [Config](https://github.com/winduum/winduum/blob/main/src/theme/config.css). +CSS properties can be changed via [Config](/docs/base/config/). [`src/base/transitions.css`](https://github.com/winduum/winduum/blob/main/src/base/transitions.css) diff --git a/docs/docs/index.md b/docs/docs/index.md index a961488..fdd2408 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -3,9 +3,6 @@ You can use Winduum with or without [TailwindCSS](https://tailwindcss.com/). Check out the [About](/docs/about) page to learn more about Winduum and its philosophy. -Winduum `2.x` is using compatible naming for CSS custom properties that work with both current and old versions of TailwindCSS, -specifically `v4` and `v3`. - ## Get started You can install Winduum via **npm** and use it in your **Node.js** project.
@@ -21,45 +18,10 @@ See [Trying Winduum Online](#trying-winduum-online) section below to see all pos npm i winduum ``` -The components are written in plain CSS, so sources can be also loaded in browsers without a build step or used in any other build tool such as **PostCSS** or **LightningCSS**. - -```css -@import "winduum/src/theme/index.css" layer(theme); -@import "winduum/src/base/index.css" layer(base); -@import "winduum/src/components/index.css" layer(utilities); -@import "winduum/src/utilities/index.css" layer(utilities); -``` - -Or you can include components separately, follow usage steps with each component. - -```css -@import "winduum/src/theme/index.css" layer(theme); -@import "winduum/src/base/index.css" layer(base); -@import "winduum/src/components/button/index.css" layer(utilities); -@import "winduum/src/utilities/index.css" layer(utilities); -``` - -Or paste the source code to your project and make it your own! - -```css -@import "@/styles/theme/index.css" layer(theme); -@import "@/styles/base/index.css" layer(base); -@import "@/styles/components/button/index.css" layer(utilities); -@import "@/styles/utilities/index.css" layer(utilities); -``` - - - -With `layer(utilities)` you can use TailwindCSS variant classes, for example `class="x-button lg:square"` to make button square only from `lg` breakpoint. (Not wokring with TailwindCSS v4 currently) - ### TailwindCSS It's optional but recommended to leverage the full functionality of the library! -#### v4 - -To use TailwindCSS `v4`, you will have to import TailwindCSS and Winduum imports individually. - ```css @import "tailwindcss/theme.css" layer(theme); @import "winduum/tailwindcss/theme/config/index.css" layer(theme); @@ -83,50 +45,40 @@ To use TailwindCSS `v4`, you will have to import TailwindCSS and Winduum imports @import "winduum/src/base/transitions.css"; ``` -TailwindCSS `v4` can be used in any project with Vite and works out of the box. -No `tailwind.config.js` needed! -All configuration is done in CSS! +Follow the installation steps in [TailwindCSS](https://tailwindcss.com/docs/installation/using-vite) docs. -```javascript -import tailwindcss from '@tailwindcss/vite' -import { defineConfig } from 'vite' +### Without TailwindCSS -export default defineConfig({ - plugins: [tailwindcss()], -}) -``` +The components are written in plain CSS, so sources can be also loaded in browsers without a build step or used in any other build tool such as **PostCSS** or **LightningCSS**. -#### v3 +```css +@import "winduum/src/theme/index.css" layer(theme); +@import "winduum/src/base/index.css" layer(base); + +/* all components in one import */ +@import "winduum/src/components/index.css" layer(utilities); +@import "winduum/src/utilities/index.css" layer(utilities); +``` -To use TailwindCSS `v3`, you will have to import TailwindCSS and Winduum imports individually. +Or you can include components separately, follow usage steps with each component. ```css -@import "winduum/src/theme/index.css"; -@import "winduum/src/base/index.css"; -@import "winduum/src/components/index.css" layer(utilities); +@import "winduum/src/theme/index.css" layer(theme); +@import "winduum/src/base/index.css" layer(base); + +/* one component at a time */ +@import "winduum/src/components/button/index.css" layer(utilities); @import "winduum/src/utilities/index.css" layer(utilities); -@import "winduum/tailwindcss/base/defaults.css"; -@import "tailwindcss/base.css"; -@import "tailwindcss/components.css"; -@import "tailwindcss/utilities.css"; -@import "tailwindcss/variants.css"; ``` -Follow the installation steps in [TailwindCSS](https://v3.tailwindcss.com/docs/installation) docs -and include Winduum as a plugin, -see [Config](/docs/base/config#tailwind-css-v3) for more info. - -## PostCSS or LightingCSS -For TailwindCSS `v3` following PostCSS plugins are required. -If you are using `v4` the [LightingCSS](https://lightningcss.dev/) is used out of the box. - -* [`autoprefixer`](https://www.npmjs.com/package/autoprefixer) -* [`tailwindcss`](https://www.npmjs.com/package/tailwindcss) -* [`postcss-nesting`](https://www.npmjs.com/package/postcss-nesting) -* [`postcss-import`](https://www.npmjs.com/package/postcss-import) -* [`postcss-custom-media`](https://www.npmjs.com/package/postcss-custom-media) - -If you are not using TailwindCSS, you can use whatever you want, even no build step! +Or paste the source code to your project and make it your own! + +```css +@import "@/styles/theme/index.css" layer(theme); +@import "@/styles/base/index.css" layer(base); +@import "@/styles/components/button/index.css" layer(utilities); +@import "@/styles/utilities/index.css" layer(utilities); +``` ## Stylelint diff --git a/docs/docs/layers.md b/docs/docs/layers.md deleted file mode 100644 index 47c9c8b..0000000 --- a/docs/docs/layers.md +++ /dev/null @@ -1,37 +0,0 @@ -# Layers - -All component styles are written with low specificity in mind. This ensures that any utility classes have higher specificity. - -You can also leverage [CSS Layers](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers) to have even better control of your specificity. This can be also combined with [TailwindCSS layers](https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer). - -## TailwindCSS v4 - -Future version of TailwindCSS uses layers by default, so no configration is needed. - -## TailwindCSS v3 -If you want to write CSS [per-component](https://tailwindcss.com/docs/adding-custom-styles#layers-and-per-component-css), be aware that here you cannot use TailwindCSS layers. Well you could, but it would have some unfortunate side effects of utility classes leaking into components. You can use layers globally like this. - -```css -@layer winduum-base, winduum-components, winduum-utilities, winduum-variants; - -@import "winduum/src/base/index.css" layer(base); -@import "winduum/src/components/index.css" layer(utilities); -@import "winduum/src/components/index.css" layer(utilities); -@import "winduum/src/utilities/index.css" layer(utilities); - -@layer winduum-base { - @tailwind base; -} - -@layer winduum-components { - @tailwind components; -} - -@layer winduum-utilities { - @tailwind utilities; -} - -@layer winduum-variants { - @tailwind variants; -} -``` diff --git a/docs/docs/utilities/accent.md b/docs/docs/utilities/accent.md index 3d42708..4e13b64 100644 --- a/docs/docs/utilities/accent.md +++ b/docs/docs/utilities/accent.md @@ -1,7 +1,7 @@ # Accent Provides a new TailwindCSS utility class `accent` which extends [Accent](https://tailwindcss.com/docs/accent) utility classe. -## TailwindCSS v4 +## TailwindCSS Include CSS file with the `@utility` at-rule. @@ -11,9 +11,6 @@ Include CSS file with the `@utility` at-rule. @import "winduum/tailwindcss/utilities/accent.css"; ``` -## TailwindCSS v3 -Add plugin via the `tailwind.config.js`, see [Config](/docs/base/config#tailwind-css-v3) for more info. - ## Example diff --git a/docs/docs/utilities/animation.md b/docs/docs/utilities/animation.md index e186e01..d2a0245 100644 --- a/docs/docs/utilities/animation.md +++ b/docs/docs/utilities/animation.md @@ -6,10 +6,9 @@ You should use this together with [Keyframes](/docs/base/keyframes) or use your ### Dependencies -* [tailwindcss](https://tailwindcss.com/) (TailwindCSS v4 @utility) -* [winduum](/docs/base/config.html#tailwind-css-v3) (TailwindCSS v3 plugin) +* [tailwindcss](https://tailwindcss.com/) (TailwindCSS @utility) -## TailwindCSS v4 +## TailwindCSS You can add more via the `@theme` at-rule, see [Config](/docs/base/config#tailwind-css-v4) for more info.
Include CSS file with the `@utility` at-rule. @@ -58,24 +57,4 @@ or use arbitrary value .animation-fade-in { animation-name: fade-in; } -``` - -## TailwindCSS v3 -You can add more via the `tailwind.config.js`, see [Config](/docs/base/config#tailwind-css-v3) for more info. - -### Example -```html -
- Content -
-``` -```css -.animation { - animation-duration: var(--default-animation-duration, var(--default-transition-duration)); - animation-fill-mode: both; -} - -.animation-fade-in { - animation-name: fade-in; -} -``` +``` \ No newline at end of file diff --git a/docs/docs/utilities/divide-gap.md b/docs/docs/utilities/divide-gap.md index fbbc48e..ca2377f 100644 --- a/docs/docs/utilities/divide-gap.md +++ b/docs/docs/utilities/divide-gap.md @@ -1,7 +1,7 @@ # Divide Gap Provides a new TailwindCSS utility classes `divide-gap-x` and `divide-gap-y` for easier way to do gap between [Divide](https://tailwindcss.com/docs/divide-width) utility classes. You can use all values from [Spacing scale](https://tailwindcss.com/docs/customizing-spacing#default-spacing-scale). -## TailwindCSS v4 +## TailwindCSS Include CSS file with the `@utility` at-rule. @@ -11,9 +11,6 @@ Include CSS file with the `@utility` at-rule. @import "winduum/tailwindcss/utilities/divide-gap.css"; ``` -## TailwindCSS v3 -Add plugin via the `tailwind.config.js`, see [Config](/docs/base/config#tailwind-css-v3) for more info. - ## Example From 0322664fb5cd902ce7d78a5d24fd12880cd3161d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubom=C3=ADr=20Bla=C5=BEek?= Date: Thu, 25 Jun 2026 15:58:39 +0200 Subject: [PATCH 02/35] feat: update navigation config with new links, sections, and adjustments --- docs/.vitepress/config.ts | 68 ++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 1f9ae69..8c79eb6 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -107,6 +107,10 @@ export default defineConfig({ { text: 'Tokens', link: '/docs/tokens' + }, + { + text: 'Polyfills', + link: '/docs/polyfills' } ] }, @@ -140,7 +144,7 @@ export default defineConfig({ { text: 'Transitions', link: '/docs/base/transitions' - } + }, ] }, { @@ -222,9 +226,13 @@ export default defineConfig({ text: 'Label', link: '/docs/components/label' }, + // { + // text: 'Link', + // link: '/docs/components/link' + // }, { - text: 'Link', - link: '/docs/components/link' + text: 'Marquee', + link: '/docs/components/marquee' }, { text: 'Notice', @@ -284,7 +292,6 @@ export default defineConfig({ } ] }, - { text: 'Utilities', items: [ @@ -296,10 +303,10 @@ export default defineConfig({ text: 'Animation', link: '/docs/utilities/animation' }, - { - text: 'Container', - link: '/docs/utilities/container' - }, + // { + // text: 'Container', + // link: '/docs/utilities/container' + // }, { text: 'Divide Gap', link: '/docs/utilities/divide-gap' @@ -312,6 +319,22 @@ export default defineConfig({ text: 'Dot', link: '/docs/utilities/dot' }, + { + text: 'Grid', + link: '/docs/utilities/grid' + }, + { + text: 'Link', + link: '/docs/utilities/link' + }, + { + text: 'Position', + link: '/docs/utilities/position' + }, + { + text: 'Ripple', + link: '/docs/utilities/ripple' + }, { text: 'Skeleton', link: '/docs/utilities/skeleton' @@ -324,15 +347,36 @@ export default defineConfig({ text: 'Swap', link: '/docs/utilities/swap' }, - { - text: 'Ripple', - link: '/docs/utilities/ripple' - }, { text: 'Underline', link: '/docs/utilities/underline' + }, + { + text: 'View Transition', + link: '/docs/utilities/view-transition' } ] + }, + { + text: "Variants", + items: [ + { + text: 'Dark', + link: '/docs/variants/dark' + }, + { + text: 'Hocus', + link: '/docs/variants/hocus' + }, + { + text: 'Interest', + link: '/docs/variants/interest' + }, + { + text: 'Scroll State', + link: '/docs/variants/scrolll-state' + }, + ] } ] } From 8204e7bc1bf22dd1403598e440d3fec881edd1a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubom=C3=ADr=20Bla=C5=BEek?= Date: Thu, 25 Jun 2026 16:01:05 +0200 Subject: [PATCH 03/35] docs: refine TailwindCSS details in feature description --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 8c6c86e..80ae723 100644 --- a/docs/index.md +++ b/docs/index.md @@ -37,7 +37,7 @@ features: details: Everything is written in plain CSS and JS, so you can use it with any framework you want. You can also use pre-build components for Vue etc. TailwindCSS is optional, but it's recommended. - icon: 🎨 title: Extends TailwindCSS - details: Adds a plugin for TailwindCSS which adds new handy utilities and CSS properties. You don't even need to use TailwindCSS, but is recommend for full experience. + details: Adds new handy utilities, variants and CSS properties. You don't even need to use TailwindCSS, but is recommend for full experience. - icon: 🚀 title: Small and fast details: Doesn't reinvent the wheel, many components are using existing optimized standards. So the focus is that the final javascript code is minimal! From 4ae47d49d468c7e9bd104b26008fc117cc344bba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubom=C3=ADr=20Bla=C5=BEek?= Date: Thu, 25 Jun 2026 16:37:21 +0200 Subject: [PATCH 04/35] docs: add links for `winduum-elements` and `winduum-stimulus`, update component references and navigation --- docs/.vitepress/config.ts | 16 ++++++++++++++++ docs/docs/about.md | 2 +- docs/docs/components/button.md | 3 ++- docs/docs/components/carousel.md | 2 ++ docs/docs/components/check.md | 2 ++ docs/docs/components/compare.md | 3 ++- docs/docs/components/control.md | 3 ++- docs/docs/components/details.md | 1 - docs/docs/components/dialog.md | 1 - docs/docs/components/drawer.md | 3 ++- docs/docs/components/form.md | 3 ++- docs/docs/components/image.md | 2 ++ docs/docs/components/popover.md | 3 ++- docs/docs/components/range.md | 3 ++- docs/docs/components/tabs.md | 3 ++- docs/docs/components/toast.md | 3 ++- docs/docs/components/toaster.md | 3 ++- docs/docs/index.md | 2 ++ 18 files changed, 45 insertions(+), 13 deletions(-) diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 8c79eb6..6ca3a13 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -69,11 +69,27 @@ export default defineConfig({ text: 'Changelog', link: 'https://github.com/winduum/winduum/blob/main/CHANGELOG.md' }, + { + text: 'v2', + link: 'https://v2--winduum.netlify.app/' + }, { text: 'v1', link: 'https://v1--winduum.netlify.app/' } ] + }, + { + items: [ + { + text: 'Webuum', + link: 'https://webuum.dev' + }, + { + text: 'Vituum', + link: 'https://vituum.dev' + } + ] } ] } diff --git a/docs/docs/about.md b/docs/docs/about.md index 0539f0a..1112a36 100644 --- a/docs/docs/about.md +++ b/docs/docs/about.md @@ -26,7 +26,7 @@ Winduum is **framework-agnostic**, so you are able to create your own components If there is interest, pre-built components may be developed for popular frameworks. Currently, -only [`winduum-vue`](https://www.github.com/winduum/winduum-vue) and [`winduum-react`](https://www.github.com/winduum/winduum-react) are available +only [`winduum-elements`](https://www.github.com/winduum/winduum-elements), [`winduum-stimulus`](https://www.github.com/winduum/winduum-stimulus), [`winduum-vue`](https://www.github.com/winduum/winduum-vue) and [`winduum-react`](https://www.github.com/winduum/winduum-react) are available and most of the components have usage and installation examples in the docs. Want to help? We're open for pull requests! diff --git a/docs/docs/components/button.md b/docs/docs/components/button.md index 8ba321c..50b5345 100644 --- a/docs/docs/components/button.md +++ b/docs/docs/components/button.md @@ -33,9 +33,10 @@ Follow instructions for individual framework usage below * +* +* * * -* ## Examples diff --git a/docs/docs/components/carousel.md b/docs/docs/components/carousel.md index e1d5268..c5ac4d0 100644 --- a/docs/docs/components/carousel.md +++ b/docs/docs/components/carousel.md @@ -20,6 +20,8 @@ Provides a scroll carousel that uses native CSS `scroll-snap` property.
Follow instructions for individual framework usage below * +* +* ## Examples diff --git a/docs/docs/components/check.md b/docs/docs/components/check.md index 9107cbe..4144c3a 100644 --- a/docs/docs/components/check.md +++ b/docs/docs/components/check.md @@ -22,6 +22,8 @@ Check supports `checkbox` and `radio` **input** types Follow instructions for individual framework usage below * +* +* * * diff --git a/docs/docs/components/compare.md b/docs/docs/components/compare.md index e0f4d88..ad6cc53 100644 --- a/docs/docs/components/compare.md +++ b/docs/docs/components/compare.md @@ -15,7 +15,8 @@ Side-by-side comparison slider component. Follow instructions for individual framework usage below * -* +* +* ## Examples diff --git a/docs/docs/components/control.md b/docs/docs/components/control.md index f327c05..e6d10c2 100644 --- a/docs/docs/components/control.md +++ b/docs/docs/components/control.md @@ -15,9 +15,10 @@ Other input types are supported in other components Follow instructions for individual framework usage below * +* +* * * -* ### Usage diff --git a/docs/docs/components/details.md b/docs/docs/components/details.md index 768fe77..6858559 100644 --- a/docs/docs/components/details.md +++ b/docs/docs/components/details.md @@ -48,7 +48,6 @@ document.querySelectorAll('[data-action="toggleDetails"]').forEach(summary => { Follow instructions for individual framework usage below * -* ## Examples diff --git a/docs/docs/components/dialog.md b/docs/docs/components/dialog.md index 74930ba..662d6d0 100644 --- a/docs/docs/components/dialog.md +++ b/docs/docs/components/dialog.md @@ -55,7 +55,6 @@ Follow instructions for individual framework usage below * * * -* ## Example diff --git a/docs/docs/components/drawer.md b/docs/docs/components/drawer.md index cfc8c94..81d3c31 100644 --- a/docs/docs/components/drawer.md +++ b/docs/docs/components/drawer.md @@ -25,7 +25,8 @@ Can be dismissed with touch gestures on touch devices. Follow instructions for individual framework usage below * -* +* +* ## Examples diff --git a/docs/docs/components/form.md b/docs/docs/components/form.md index 524b63c..15de42e 100644 --- a/docs/docs/components/form.md +++ b/docs/docs/components/form.md @@ -14,7 +14,8 @@ For advance form of validation use [VeeValidate](https://vee-validate.logaretm.c Follow instructions for individual framework usage below * -* +* +* ### Usage ::: code-group diff --git a/docs/docs/components/image.md b/docs/docs/components/image.md index db72db2..226df21 100644 --- a/docs/docs/components/image.md +++ b/docs/docs/components/image.md @@ -19,6 +19,8 @@ Default constrains for media elements such as `img`, `video`, `iframe`, `object` Follow instructions for individual framework usage below * +* +* * * diff --git a/docs/docs/components/popover.md b/docs/docs/components/popover.md index 4456471..3c77bd4 100644 --- a/docs/docs/components/popover.md +++ b/docs/docs/components/popover.md @@ -59,9 +59,10 @@ Applicable to `x-popover-content` Follow instructions for individual framework usage below * +* +* * * -* ## Examples diff --git a/docs/docs/components/range.md b/docs/docs/components/range.md index 9ddbbdb..d607c89 100644 --- a/docs/docs/components/range.md +++ b/docs/docs/components/range.md @@ -33,9 +33,10 @@ rangeSlider.addEventListener('input', ({ currentTarget }) => setValue(currentTar Follow instructions for individual framework usage below * +* +* * * -* ## Examples diff --git a/docs/docs/components/tabs.md b/docs/docs/components/tabs.md index 21f79a4..a600bf8 100644 --- a/docs/docs/components/tabs.md +++ b/docs/docs/components/tabs.md @@ -15,7 +15,8 @@ Follow instructions for individual framework usage below * -* +* +* ## Examples diff --git a/docs/docs/components/toast.md b/docs/docs/components/toast.md index 7ead7ef..2d6cede 100644 --- a/docs/docs/components/toast.md +++ b/docs/docs/components/toast.md @@ -52,7 +52,8 @@ document.querySelector('#insertToast').addEventListener('click', async () => { Follow instructions for individual framework usage below * -* +* +* ## Example diff --git a/docs/docs/components/toaster.md b/docs/docs/components/toaster.md index 0a5e7bd..62e8088 100644 --- a/docs/docs/components/toaster.md +++ b/docs/docs/components/toaster.md @@ -16,7 +16,8 @@ Bake your [Toast](/docs/components/toast) and let it fly! You should insert in i Follow instructions for individual framework usage below * -* +* +* ## Example diff --git a/docs/docs/index.md b/docs/docs/index.md index fdd2408..eb6f72a 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -170,6 +170,8 @@ Winduum is **framework-agnostic**, learn more on the [About](/docs/about#framewo Do you need ready to use components? Here are components ready to copy & paste. For now there are only a few, more might come in the future! +* +* * * From 175487fb2c6da3f4fe69c36b083187fd453b8312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubom=C3=ADr=20Bla=C5=BEek?= Date: Thu, 2 Jul 2026 13:50:30 +0200 Subject: [PATCH 05/35] docs: add "Marquee" and "Polyfills" component documentation and examples --- docs/docs/base/transitions.md | 2 +- docs/docs/components/marquee.md | 59 ++++++++++++ docs/docs/polyfills.md | 71 ++++++++++++++ .../pages/components/marquee/default.liquid | 89 ++++++++++++++++++ .../pages/components/marquee/reverse.liquid | 93 +++++++++++++++++++ 5 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 docs/docs/components/marquee.md create mode 100644 docs/docs/polyfills.md create mode 100644 examples/src/pages/components/marquee/default.liquid create mode 100644 examples/src/pages/components/marquee/reverse.liquid diff --git a/docs/docs/base/transitions.md b/docs/docs/base/transitions.md index 8941ece..9713695 100644 --- a/docs/docs/base/transitions.md +++ b/docs/docs/base/transitions.md @@ -1,7 +1,7 @@ # Transitions This activates the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) with cross-document animations.
-CSS properties can be changed via [Config](/docs/base/config/). +CSS properties can be changed via [Config](/docs/base/config). [`src/base/transitions.css`](https://github.com/winduum/winduum/blob/main/src/base/transitions.css) diff --git a/docs/docs/components/marquee.md b/docs/docs/components/marquee.md new file mode 100644 index 0000000..1656b17 --- /dev/null +++ b/docs/docs/components/marquee.md @@ -0,0 +1,59 @@ +# Marquee + +Marquee creates an infinite horizontal loop for logos, partners or other repeated items. It is CSS-only and positions each child on the same motion path using sibling count and sibling index variables. + + + +### Usage + +```css +@import "winduum/src/components/marquee/index.css" layer(utilities); +``` + +Or import the pieces separately if you want to customize the props or keyframes. + +```css +@import "winduum/src/components/marquee/keyframes/default.css" layer(utilities); +@import "winduum/src/components/marquee/default.css" layer(utilities); +``` + +### Variants +* + +### Props +* `--x-marquee-sibling-count` - total number of marquee items +* `--x-marquee-visible-count` - number of visible items used for spacing along the path +* `--x-marquee-inline-size` - inline size of each marquee item +* `--x-marquee-gap` - gap between marquee items +* `--x-marquee-animation-duration` - animation duration, defaults to `30s` +* `--x-marquee-animation-timing-function` - animation timing function, defaults to `linear` +* `--x-marquee-sibling-index` - item index, required as a fallback for browsers without `sibling-index()` + +### Installation +Follow instructions for individual framework usage below. + +* + +## Examples + +### Default + + + +<<< @/public/examples/components/marquee/default.html#body{} + +### Reverse + +Use TailwindCSS arbitrary child variant `*:[animation-direction:reverse]` to move the loop in the opposite direction. + + + +::: code-group +<<< @/public/examples/components/marquee/reverse.html#body{} [html] +::: + +## Accessibility + +Keep only the real set of links focusable. If extra duplicated items are present only to make the loop feel continuous, add `aria-hidden="true"` and `tabindex="-1"` to those duplicates. + +Pause the animation when focus moves inside the marquee so keyboard users can interact with links without the focused item moving away. The examples use `*:group-has-focus-within:[animation-play-state:paused]` on the marquee wrapper. diff --git a/docs/docs/polyfills.md b/docs/docs/polyfills.md new file mode 100644 index 0000000..4271862 --- /dev/null +++ b/docs/docs/polyfills.md @@ -0,0 +1,71 @@ +# Polyfills + +Winduum builds on modern web platform features. Some of them are still experimental or not supported in every browser, so polyfills are opt-in and can be lazy-loaded only when feature detection says they are needed. + +## Install + +Install only the polyfills you actually need for your project. + +```shell +npm install interestfor +``` + +If you use `winduum-elements`, also add the Webuum polyfills used by those elements: + +```shell +npm install invokers-polyfill @webreflection/custom-elements-builtin +``` + +See the [Webuum polyfills docs](https://webuum.dev/docs/polyfills.html) for more details about these Webuum features. + +## Winduum + +Winduum exposes support checks from `winduum/supports`. Use them before loading a polyfill. + +```js +import { supportsInterestFor, supportsTimelineTrigger } from 'winduum/supports' + +if (!supportsInterestFor) { + await import('interestfor/src/interestfor.js') +} + +if (!supportsTimelineTrigger) { + await import('winduum/src/polyfills/timelineTrigger.js') +} +``` + +### Interest Invokers + +The `interestfor` API lets controls declaratively show interest in another element. Winduum uses `supportsInterestFor` to detect native support and can fall back to the [`interestfor`](https://www.npmjs.com/package/interestfor) polyfill. + +### Timeline Trigger + +The `timeline-trigger` feature is used by Winduum animation trigger utilities. Winduum includes an experimental `timelineTrigger` polyfill that observes elements with `timeline-trigger-*` classes and toggles `data-enter` based on the configured entry and exit thresholds. + +## Winduum Elements + +`winduum-elements` builds on top of Webuum, so projects using it need to include Webuum polyfills too when targeting browsers without support for those APIs. + +```js +import { supportsCommand, supportsIs } from 'webuum/supports' +import { supportsInterestFor, supportsTimelineTrigger } from 'winduum/supports' + +if (!supportsCommand) { + const { apply } = await import('invokers-polyfill/fn') + apply() +} + +if (!supportsIs()) { + await import('@webreflection/custom-elements-builtin') +} + +if (!supportsInterestFor) { + await import('interestfor/src/interestfor.js') +} + +if (!supportsTimelineTrigger) { + await import('winduum/src/polyfills/timelineTrigger.js') +} +``` + +The Webuum checks cover the Command API and customized built-in elements. The Winduum checks cover Interest Invokers and the timeline trigger polyfill. diff --git a/examples/src/pages/components/marquee/default.liquid b/examples/src/pages/components/marquee/default.liquid new file mode 100644 index 0000000..7a6e000 --- /dev/null +++ b/examples/src/pages/components/marquee/default.liquid @@ -0,0 +1,89 @@ +{% layout "templates/layout.liquid" %} +{% block %} + +{% endblock %} + +{% block head %} + +{% endblock %} diff --git a/examples/src/pages/components/marquee/reverse.liquid b/examples/src/pages/components/marquee/reverse.liquid new file mode 100644 index 0000000..3af7566 --- /dev/null +++ b/examples/src/pages/components/marquee/reverse.liquid @@ -0,0 +1,93 @@ +{% layout "templates/layout.liquid" %} +{% block %} + +{% endblock %} + +{% block head %} + +{% endblock %} From 5417010bf9102848a84ffcbecca4923081b72687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubom=C3=ADr=20Bla=C5=BEek?= Date: Thu, 2 Jul 2026 16:11:31 +0200 Subject: [PATCH 06/35] docs: fix typos in navigation links and update documentation for Tooltip and animation utilities --- docs/.vitepress/config.ts | 2 +- docs/docs/components/tooltip.md | 13 +- docs/docs/utilities/animation.md | 176 +++++++++++++++++- docs/docs/utilities/grid.md | 82 ++++++++ docs/docs/utilities/link.md | 41 ++++ docs/docs/utilities/position.md | 44 +++++ docs/docs/utilities/view-transition.md | 51 +++++ docs/docs/variants/dark.md | 38 ++++ docs/docs/variants/hocus.md | 51 +++++ docs/docs/variants/interest.md | 55 ++++++ docs/docs/variants/scroll-state.md | 58 ++++++ .../src/pages/components/tooltip/basic.liquid | 2 +- 12 files changed, 602 insertions(+), 11 deletions(-) create mode 100644 docs/docs/utilities/grid.md create mode 100644 docs/docs/utilities/link.md create mode 100644 docs/docs/utilities/position.md create mode 100644 docs/docs/utilities/view-transition.md create mode 100644 docs/docs/variants/dark.md create mode 100644 docs/docs/variants/hocus.md create mode 100644 docs/docs/variants/interest.md create mode 100644 docs/docs/variants/scroll-state.md diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 6ca3a13..22046c2 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -390,7 +390,7 @@ export default defineConfig({ }, { text: 'Scroll State', - link: '/docs/variants/scrolll-state' + link: '/docs/variants/scroll-state' }, ] } diff --git a/docs/docs/components/tooltip.md b/docs/docs/components/tooltip.md index 1e8b64f..d3c37be 100644 --- a/docs/docs/components/tooltip.md +++ b/docs/docs/components/tooltip.md @@ -1,6 +1,8 @@ # Tooltip Tooltip can be used for a little info hint on hover or focus. +It's a pure CSS solution — the tooltip text comes from the `aria-label` attribute and is rendered via the `::before` pseudo-element, so it stays accessible and needs no JavaScript. Placement is controlled with the `tooltip-*` tokens and appearance can be customized via the `--x-tooltip-*` props. + ## Usage @@ -27,11 +29,14 @@ Tooltip can be used for a little info hint on hover or focus. ### Variants * +### Props +* + ### Tokens -* `top` -* `bottom` -* `left` -* `right` +* `tooltip-top` +* `tooltip-bottom` +* `tooltip-left` +* `tooltip-right` ### Installation Follow instructions for individual framework usage below diff --git a/docs/docs/utilities/animation.md b/docs/docs/utilities/animation.md index d2a0245..8c0904b 100644 --- a/docs/docs/utilities/animation.md +++ b/docs/docs/utilities/animation.md @@ -1,15 +1,31 @@ # Animation -Provides a new utility class `animation` and TailwindCSS utility class `animation-*` for `animation-name` property. +A set of utilities for working with CSS animations. Instead of predefined animation classes, Winduum lets you compose animations from small building blocks: -You should use this together with [Keyframes](/docs/base/keyframes) or use your own animation keyframes. +* [`animation`](#base-class) — base class that sets a default `animation-duration` and `animation-fill-mode` +* [`animation-*`](#tailwindcss) — sets `animation-name` from your theme or an arbitrary value +* [`from-*` / `to-*`](#from-to-utilities) — customize the start and end state of the `enter` and `exit` keyframes +* [Animation Timeline](#animation-timeline) — scroll-driven animations with `animation-timeline` +* [Animation Trigger](#animation-trigger) — play animations when an element enters the viewport - +Animations themselves are defined as keyframes — use the ones provided in [Keyframes](/docs/base/keyframes) or define your own. ### Dependencies * [tailwindcss](https://tailwindcss.com/) (TailwindCSS @utility) +## Base class +The `animation` utility class only sets sensible defaults — a default duration and `animation-fill-mode: both` — so the element stays in the final state of its keyframes. It doesn't animate anything on its own, you combine it with an `animation-name` set by the `animation-*` utility below. + + + +```css +.animation { + animation-duration: var(--default-animation-duration, var(--default-transition-duration, 150ms)); + animation-fill-mode: both; +} +``` + ## TailwindCSS -You can add more via the `@theme` at-rule, see [Config](/docs/base/config#tailwind-css-v4) for more info.
+The `animation-*` utility sets the `animation-name` property. It accepts animation names defined in your theme via the `@theme` at-rule (see [Config](/docs/base/config#tailwind-css-v4)) or any arbitrary keyframes name.
Include CSS file with the `@utility` at-rule. @@ -57,4 +73,154 @@ or use arbitrary value .animation-fade-in { animation-name: fade-in; } -``` \ No newline at end of file +``` + +### From / To utilities +Utilities `from-*` and `to-*` set CSS variables that are consumed by the `enter` and `exit` [Keyframes](/docs/base/keyframes). This allows you to customize the starting and ending state of an animation directly in HTML. + +Available utilities: + +* `from-translate-y-*` / `to-translate-y-*` (also negative `-from-translate-y-*` / `-to-translate-y-*`) +* `from-translate-x-*` / `to-translate-x-*` (also negative `-from-translate-x-*` / `-to-translate-x-*`) +* `from-opacity-*` / `to-opacity-*` +* `from-scale-*` / `to-scale-*` +* `from-rotate-*` / `to-rotate-*` + +```html +
+ Content +
+``` +```css +.from-translate-y-4 { + --tw-animation-from-translate-y: calc(var(--spacing) * 4); +} + +.from-opacity-0 { + --tw-animation-from-opacity: 0%; +} +``` + +## Animation Timeline +Utilities for [scroll-driven animations](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_scroll-driven_animations) — `animation-timeline`, `animation-range`, `scroll-timeline`, `view-timeline` and `timeline-scope` properties. + + + +```css +@import "winduum/tailwindcss/utilities/animation-timeline.css"; +``` + +Available utilities: + +* `animation-timeline-scroll` / `animation-timeline-scroll-y` / `animation-timeline-scroll-x` — `animation-timeline: scroll()` +* `animation-timeline-view` — `animation-timeline: view()` +* `animation-timeline-*` — arbitrary `animation-timeline` value (`auto`, `none` or custom timeline name) +* `animation-range-*` — arbitrary `animation-range` value +* `scroll-timeline-y-*` / `scroll-timeline-x-*` / `scroll-timeline-block` — named `scroll-timeline` +* `view-timeline-y-*` / `view-timeline-x-*` / `view-timeline-block` — named `view-timeline` +* `timeline-scope-*` — `timeline-scope` + +### Example +```html +
+ Content +
+``` +```css +.animation-timeline-view { + animation-timeline: view(); +} + +.animation-range-\[entry_0\%_cover_40\%\] { + animation-range: entry 0% cover 40%; +} +``` + +or with a named timeline + +```html +
+
+ Content +
+
+``` + +## Animation Trigger +Utilities for [`animation-trigger`](https://developer.chrome.com/blog/animation-trigger) and `timeline-trigger` properties, allowing you to play animations when an element enters the viewport. + + + +```css +@import "winduum/tailwindcss/utilities/animation-trigger.css"; +``` + +Available utilities: + +* `animation-trigger-enter` — plays the `enter` keyframes once via the `--enter` trigger +* `animation-trigger-*` — arbitrary `animation-name` triggered via a named trigger passed as a modifier, e.g. `animation-trigger-[fade-in]/[--reveal]` +* `timeline-trigger-enter` — defines the `--enter` view timeline trigger on the element +* `timeline-trigger-*` — defines an arbitrary named `timeline-trigger` + +Behavior can be customized via CSS variables: + +* `--tw-animation-duration` — animation duration (default `1.75s`) +* `--tw-animation-timing-function` — easing (default `var(--ease-emphasized)`) +* `--tw-animation-fill-mode` — fill mode (default `both`) +* `--tw-animation-trigger-action` — trigger action (default `play-once`) +* `--tw-timeline-trigger-entry` / `--tw-timeline-trigger-exit` — entry/exit range of the view timeline (default `20%` / `0%`) + +Animations are automatically disabled with `prefers-reduced-motion`. + +### Example +Combine with `from-*` utilities to define the starting state of the `enter` animation: + +```html +

Our key partners

+``` +```css +.animation-trigger-enter { + animation-duration: var(--tw-animation-duration, 1.75s); + animation-timing-function: var(--tw-animation-timing-function, var(--ease-emphasized)); + animation-fill-mode: var(--tw-animation-fill-mode, both); + animation-trigger: --enter var(--tw-animation-trigger-action, play-once); + animation-name: enter; + + @media (prefers-reduced-motion) { + animation: none; + } +} + +.from-translate-y-4 { + --tw-animation-from-translate-y: calc(var(--spacing) * 4); +} + +.timeline-trigger-enter { + timeline-trigger: --enter view() entry var(--tw-timeline-trigger-entry, 20%) exit var(--tw-timeline-trigger-exit, 0%); + trigger-scope: --enter; +} +``` + +or with a custom named trigger and animation + +```html +

Our key partners

+``` +```css +.animation-trigger-\[fade-in\]\/\[--reveal\] { + animation-duration: var(--tw-animation-duration, 1.75s); + animation-timing-function: var(--tw-animation-timing-function, var(--ease-emphasized)); + animation-fill-mode: var(--tw-animation-fill-mode, both); + animation-trigger: --reveal var(--tw-animation-trigger-action, play-once); + animation-name: fade-in; + + @media (prefers-reduced-motion) { + animation: none; + } +} + +.timeline-trigger-\[--reveal\] { + timeline-trigger: --reveal view() entry var(--tw-timeline-trigger-entry, 20%) exit var(--tw-timeline-trigger-exit, 0%); + trigger-scope: --reveal; +} +``` diff --git a/docs/docs/utilities/grid.md b/docs/docs/utilities/grid.md new file mode 100644 index 0000000..da84c22 --- /dev/null +++ b/docs/docs/utilities/grid.md @@ -0,0 +1,82 @@ +# Grid +Utilities that extend TailwindCSS [grid](https://tailwindcss.com/docs/grid-template-columns) with two additions: + +* [`grid-cols-container`](#grid-cols-container) — a container layout built with grid, replacing the classic container class +* [`grid-area-*`](#grid-area) — utilities for the `grid-area` property + +### Dependencies +* [tailwindcss](https://tailwindcss.com/) (TailwindCSS @utility) + +## Grid Cols Container +A modern approach to the classic [Container](https://tailwindcss.com/docs/max-width#container-scale) — instead of wrapping content in a fixed-width element, the parent becomes a grid with named column lines and children are placed into the center column automatically. Inspired by [Kevin Powell](https://youtu.be/c13gpBrnGEw?si=FGoMS9FnWEOYohPi). + +Available column lines: + +* `container` — content width, children are placed here by default +* `container-breakout` — slightly wider than the content width, for elements that should stand out +* `container-full` — full viewport width + +The container is configured via CSS variables — `--container-width` (default `80rem`), `--container-breakout-width` (default `--container-width + 10rem`) and `--container-padding` (default `5vw`). + + + +```css +@import "winduum/tailwindcss/utilities/grid-cols-container.css"; +``` + +### Example +```html + +
Header Full Width
+
Content in container
+
Footer Breakout
+ +``` + +In some cases the classic approach is still handy, you can achieve that easily with `w-[--container]` + +```html +
+ Content +
+``` + +## Grid Area +Utilities for the `grid-area` property — place elements into named or numbered grid areas. + +* `grid-area-full` — `grid-area: 1/-1`, useful for stacking elements on top of each other +* `grid-area-*` — a row number or an arbitrary value, e.g. `grid-area-[banner]` + + + +```css +@import "winduum/tailwindcss/utilities/grid-area.css"; +``` + +### Example +Stack elements on top of each other without absolute positioning: + +```html +
+ +
Caption
+
+``` +```css +.grid-area-full { + grid-area: 1/-1; +} +``` + +or place elements into a named area + +```html +
+
Banner
+
+``` +```css +.grid-area-\[banner\] { + grid-area: banner; +} +``` diff --git a/docs/docs/utilities/link.md b/docs/docs/utilities/link.md new file mode 100644 index 0000000..011236f --- /dev/null +++ b/docs/docs/utilities/link.md @@ -0,0 +1,41 @@ +# Link +Provides a `link` utility class that adds a smooth color transition on hover and focus to interactive elements. It only applies to elements that are actually interactive — links, enabled buttons and elements with `role="button"` — so it's safe to use on a wrapper class. + +The hover color can be customized via the `--link-hover-color` variable and defaults to the current [accent](/docs/utilities/accent) color. + +You can combine it with the [Underline](/docs/utilities/underline) utility for underline animations. + +### Dependencies +* [tailwindcss](https://tailwindcss.com/) (TailwindCSS @utility) + +## TailwindCSS +Include CSS file with the `@utility` at-rule. + + + +```css +@import "winduum/tailwindcss/utilities/link.css"; +``` + +```css +.link { + &:where(:any-link, button:enabled, [role="button"]) { + transition: all var(--default-transition-duration) var(--ease-in-out); + + &:is(:hover, :focus-visible) { + color: var(--link-hover-color, var(--color-accent)); + } + } +} +``` + +### Example +```html +Link +``` + +or with a custom hover color + +```html +Link +``` diff --git a/docs/docs/utilities/position.md b/docs/docs/utilities/position.md new file mode 100644 index 0000000..d5b86dc --- /dev/null +++ b/docs/docs/utilities/position.md @@ -0,0 +1,44 @@ +# Position +Utilities for positioning elements with [CSS Anchor Positioning](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_anchor_positioning) — each utility sets the `position-area` property together with `position-try-fallbacks`, so the element automatically flips to the other side when there is not enough space in the viewport. + +These utilities are used for anchored elements such as [Popover](/docs/components/popover). Each utility also sets a matching `transform-origin` on direct children, so scale/enter animations grow from the anchor side. + +### Dependencies +* [tailwindcss](https://tailwindcss.com/) (TailwindCSS @utility) + +## TailwindCSS +Include CSS file with the `@utility` at-rule. + + + +```css +@import "winduum/tailwindcss/utilities/position.css"; +``` + +Available utilities: + +* `top` / `top-start` / `top-end` — above the anchor, flips to bottom when there is no space +* `bottom` / `bottom-start` / `bottom-end` — below the anchor, flips to top when there is no space +* `left` / `left-start` / `left-end` — before the anchor, flips to right when there is no space +* `right` / `right-start` / `right-end` — after the anchor, flips to left when there is no space + +The base name sets the side, the `-start` / `-end` suffix aligns the element along that side. + +### Example +```html + + + +``` +```css +.bottom-start { + position-area: block-end span-inline-end; + position-try-fallbacks: flip-block; + + > * { + transform-origin: top left; + } +} +``` diff --git a/docs/docs/utilities/view-transition.md b/docs/docs/utilities/view-transition.md new file mode 100644 index 0000000..c9a33a6 --- /dev/null +++ b/docs/docs/utilities/view-transition.md @@ -0,0 +1,51 @@ +# View Transition +Provides a utility class for the [View Transition API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API) — `view-transition-main` sets `view-transition-name: main`, so the element transitions independently from the rest of the page. + +### Dependencies +* [tailwindcss](https://tailwindcss.com/) (TailwindCSS @utility) + +## TailwindCSS +Include CSS file with the `@utility` at-rule. + + + +```css +@import "winduum/tailwindcss/utilities/view-transition.css"; +``` + +```css +.view-transition-main { + view-transition-name: main; +} +``` + +### Example +Enable cross-document view transitions and mark the main content, so only the content transitions between pages while the rest of the layout (header, footer) stays static: + +```css +@view-transition { + navigation: auto; +} +``` + +```html + +
Header
+
+ Content +
+
Footer
+ +``` + +The transition animation can be customized via the `::view-transition-group(main)`, `::view-transition-old(main)` and `::view-transition-new(main)` pseudo-elements together with [Keyframes](/docs/base/keyframes): + +```css +::view-transition-old(main) { + animation-name: fade-out; +} + +::view-transition-new(main) { + animation-name: fade-in; +} +``` diff --git a/docs/docs/variants/dark.md b/docs/docs/variants/dark.md new file mode 100644 index 0000000..cf10476 --- /dev/null +++ b/docs/docs/variants/dark.md @@ -0,0 +1,38 @@ +# Dark +Overrides the default TailwindCSS [dark mode](https://tailwindcss.com/docs/dark-mode) variant to be class-based instead of media query based. The `dark:` variant applies to elements with the `.dark` class and all their descendants, so dark mode can be toggled manually — typically by adding the class to the `` element. + +See [Theme](/docs/base/theme) for the dark color theme itself. + +### Dependencies +* [tailwindcss](https://tailwindcss.com/) (TailwindCSS @variant) + +## TailwindCSS +Include CSS file with the `@variant` at-rule. + + + +```css +@import "winduum/tailwindcss/variants/dark.css"; +``` + +```css +@variant dark (&:where(.dark, .dark *)); +``` + +### Example +```html + + +
+ Content +
+ + +``` +```css +.dark\:bg-black { + &:where(.dark, .dark *) { + background-color: var(--color-black); + } +} +``` diff --git a/docs/docs/variants/hocus.md b/docs/docs/variants/hocus.md new file mode 100644 index 0000000..637c8ce --- /dev/null +++ b/docs/docs/variants/hocus.md @@ -0,0 +1,51 @@ +# Hocus +Provides a `hocus:` variant — a shortcut that applies styles on both `hover` and `focus-visible`, so you don't have to repeat every interactive style twice. + +Unlike a plain `hover:` + `focus:` combination it's also smarter: + +* hover styles only apply on devices that actually support hover (`@media (hover: hover)`), so they don't get stuck on touch screens +* focus styles use `:focus-visible` instead of `:focus`, so they only show for keyboard navigation + +### Dependencies +* [tailwindcss](https://tailwindcss.com/) (TailwindCSS @variant) + +## TailwindCSS +Include CSS file with the `@variant` at-rule. + + + +```css +@import "winduum/tailwindcss/variants/hocus.css"; +``` + +```css +@variant hocus { + @media (hover: hover) { + &:hover { + @slot; + } + } + + &:focus-visible { + @slot; + } +} +``` + +### Example +```html +Link +``` +```css +.hocus\:text-accent { + @media (hover: hover) { + &:hover { + color: var(--color-accent); + } + } + + &:focus-visible { + color: var(--color-accent); + } +} +``` diff --git a/docs/docs/variants/interest.md b/docs/docs/variants/interest.md new file mode 100644 index 0000000..af1d9d1 --- /dev/null +++ b/docs/docs/variants/interest.md @@ -0,0 +1,55 @@ +# Interest +Provides `interest-target:` and `interest-source:` variants for [Interest Invokers](https://open-ui.org/components/interest-invokers.explainer/) — the `interestfor` attribute that lets controls declaratively show interest in another element (hover, focus or long-press), typically used for tooltips and hover cards. + +* `interest-target:` — applies when the element is the target of interest (`:interest-target`) +* `interest-source:` — applies when the element is the source showing interest (`:interest-source`) + +Both variants also match the `.interest-target` / `.interest-source` classes, so they work with the [`interestfor` polyfill](/docs/polyfills#interest-invokers) in browsers without native support. + +### Dependencies +* [tailwindcss](https://tailwindcss.com/) (TailwindCSS @custom-variant) + +## TailwindCSS +Include CSS file with the `@custom-variant` at-rule. + + + +```css +@import "winduum/tailwindcss/variants/interest.css"; +``` + +```css +@custom-variant interest-target { + &:is(:interest-target, .interest-target) { + @slot; + } +} + +@custom-variant interest-source { + &:is(:interest-source, .interest-source) { + @slot; + } +} +``` + +### Example +```html + + +
+ Tooltip content +
+``` +```css +.interest-source\:text-accent { + &:is(:interest-source, .interest-source) { + color: var(--color-accent); + } +} + +.interest-target\:opacity-100 { + &:is(:interest-target, .interest-target) { + opacity: 100%; + } +} +``` diff --git a/docs/docs/variants/scroll-state.md b/docs/docs/variants/scroll-state.md new file mode 100644 index 0000000..03c3e4e --- /dev/null +++ b/docs/docs/variants/scroll-state.md @@ -0,0 +1,58 @@ +# Scroll State +Provides variants for [scroll-state container queries](https://developer.chrome.com/blog/css-scroll-state-queries) — style elements based on the scroll state of their container: whether it can be scrolled, has been scrolled, an item is snapped, or a sticky element is stuck. + +To use these variants, the queried element must be inside a container with `container-type: scroll-state`. The variants then apply to its descendants. + +Available variant groups: + +* `scrollable-*` — whether the container can be scrolled in the given direction: `none`, `top`, `right`, `bottom`, `left`, `x`, `y`, `block`, `inline`, `block-start`, `block-end`, `inline-start`, `inline-end` +* `scrolled-*` — whether the container has been scrolled in the given direction (same values as `scrollable-*`) +* `snapped-*` — whether the element is a scroll-snap target: `none`, `x`, `y`, `block`, `inline`, `both` +* `stuck-*` — whether a `position: sticky` container is currently stuck to the given edge: `none`, `top`, `right`, `bottom`, `left`, `block-start`, `block-end`, `inline-start`, `inline-end` + +### Dependencies +* [tailwindcss](https://tailwindcss.com/) (TailwindCSS @variant) + +## TailwindCSS +Include CSS file with the `@variant` at-rule. + + + +```css +@import "winduum/tailwindcss/variants/scroll-state.css"; +``` + +### Example +Add a shadow to a sticky header once it sticks to the top of the viewport: + +```html +
+ +
+``` +```css +.stuck-top\:shadow-md { + @container scroll-state(stuck: top) { + box-shadow: var(--shadow-md); + } +} +``` + +or highlight the currently snapped item in a carousel + +```html +
    +
  • + +
  • +
+``` +```css +.snapped-x\:scale-100 { + @container scroll-state(snapped: x) { + scale: 100%; + } +} +``` diff --git a/examples/src/pages/components/tooltip/basic.liquid b/examples/src/pages/components/tooltip/basic.liquid index d6b707d..2667112 100644 --- a/examples/src/pages/components/tooltip/basic.liquid +++ b/examples/src/pages/components/tooltip/basic.liquid @@ -1,6 +1,6 @@ {% layout "templates/layout.liquid" %} {% block %} -
+
{% endblock %} From eb88bcb668272af871789e14fc0ee89c2984245f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubom=C3=ADr=20Bla=C5=BEek?= Date: Fri, 3 Jul 2026 12:39:09 +0200 Subject: [PATCH 07/35] docs: expand component documentation, fix links, and update usage examples --- docs/.vitepress/theme/index.ts | 180 ++++--------- docs/docs/base/defaults.md | 11 +- docs/docs/components/button.md | 9 +- docs/docs/components/carousel.md | 204 ++++----------- docs/docs/components/compare.md | 6 +- docs/docs/components/control.md | 2 + docs/docs/components/details.md | 82 ++---- docs/docs/components/dialog.md | 140 ++-------- docs/docs/components/drawer.md | 114 ++++---- docs/docs/components/form.md | 97 +++---- docs/docs/components/heading.md | 3 + docs/docs/components/popover.md | 244 +++++------------- docs/docs/components/tabs.md | 2 +- docs/docs/components/toast.md | 53 ++-- docs/docs/components/toaster.md | 57 +++- docs/docs/grid.md | 2 +- docs/docs/index.md | 2 +- docs/docs/polyfills.md | 7 + docs/docs/utilities/dot.md | 2 +- docs/docs/utilities/ripple.md | 20 +- docs/docs/utilities/spinner.md | 2 +- docs/docs/utilities/swap.md | 19 ++ examples/package-lock.json | 96 ++++++- examples/package.json | 7 +- .../pages/components/carousel/basic.liquid | 24 +- .../src/pages/components/carousel/full.liquid | 84 +++--- .../pages/components/details/accordion.liquid | 36 +-- .../pages/components/details/checkbox.liquid | 14 +- .../pages/components/details/default.liquid | 20 +- .../src/pages/components/drawer/bottom.liquid | 41 ++- .../src/pages/components/drawer/left.liquid | 37 +-- .../src/pages/components/drawer/right.liquid | 37 +-- .../src/pages/components/drawer/top.liquid | 39 ++- .../src/pages/components/popover/api.liquid | 44 +--- .../src/pages/components/popover/basic.liquid | 15 +- .../src/pages/components/popover/hover.liquid | 16 +- examples/src/pages/form-field.liquid | 4 +- examples/src/pages/form.liquid | 2 +- examples/vite.config.js | 1 + package-lock.json | 82 +++++- package.json | 5 +- 41 files changed, 791 insertions(+), 1071 deletions(-) diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index 74ebe16..ee2f909 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -1,8 +1,4 @@ import Theme from 'vitepress/theme' -import { showRipple } from 'winduum/src/utilities/ripple' -import { showToast, closeToast } from 'winduum/src/components/toast' -import { closeToaster } from 'winduum/src/components/toaster' -import { showDrawer, closeDrawer, scrollDrawer, scrollInitDrawer } from "winduum/src/components/drawer" import './styles/vars.css' import 'winduum/dist/main.css' import 'winduum/dist/tailwind.css' @@ -11,7 +7,6 @@ import LinkGh from './components/LinkGh.vue' import ViewSourceGh from './components/ViewSourceGh.vue' import HomeSponsors from './components/HomeSponsors.vue' import UsageInfo from './components/UsageInfo.vue' -import { showDialog, closeDialog } from "winduum/src/components/dialog"; function updateDarkIframes() { if (typeof document !== 'undefined') { @@ -23,135 +18,68 @@ function updateDarkIframes() { } } -function dialogEvent() { - if (typeof document !== 'undefined') { - // @ts-ignore - document.querySelector('#showDialog')?.addEventListener('click', async () => { - showDialog(window.dialogExample) - }) - - window.dialogExample?.querySelector('form')?.addEventListener('submit', (e) => { - e.preventDefault() - closeDialog(window.dialogExample) - }) - - document.querySelector('#showRipple')?.addEventListener('click', (event) => { - showRipple(event) - }) - - document.querySelector('#closeToaster')?.addEventListener(`click`, async () => { - await closeToaster(document.querySelector('.c-toaster')) - }) - - document.querySelector('#showToast:not(.has-events)')?.addEventListener('click', () => { - - if (!document.querySelector('.x-toaster')) { - document.body.insertAdjacentHTML('beforeend', `
    `) - } - - document.querySelector('.x-toaster')?.insertAdjacentHTML('beforeend', ` -
  1. -
    -
    -
    Hello toast
    -
    Amazing toast
    -
    - -
    -
  2. - `) - - showToast(document.querySelector('.x-toaster').children[document.querySelector('.x-toaster').children.length - 1]) - - const closeToastButton = document.querySelectorAll('[data-action="closeToast"]')[document.querySelectorAll('[data-action="closeToast"]').length - 1] - - closeToastButton.addEventListener('click', ({ currentTarget }) => { - closeToast(currentTarget.closest('.x-toast')) - }) - }) - - document.querySelector('#showToast')?.classList.add('has-events') - - if (!document.querySelector('.vp-doc').classList.contains('has-events')) { - document.querySelector('.vp-doc').classList.add('has-events') - - - window.drawerLeftElement?.addEventListener('scroll', ({ target }) => scrollDrawer(target)) - - window.showDrawerLeftElement?.addEventListener('click', async () => { - window.drawerLeftElement.showModal() - - await scrollInitDrawer(window.drawerLeftElement) - - showDrawer(window.drawerLeftElement) - }) - - window.closeDrawerLeftElement?.addEventListener('click', () => closeDrawer(window.drawerLeftElement, window.drawerLeftElement.scrollWidth)) - - - - - window.drawerRightElement?.addEventListener('scroll', ({ target }) => scrollDrawer(target, { - opacityRatio: 0, - scrollOpen: target.scrollWidth - target.clientWidth, - scrollClose: 0 - })) - - window.showDrawerRightElement?.addEventListener('click', async () => { - window.drawerRightElement.showModal() - - await scrollInitDrawer(window.drawerRightElement, 0) +async function initPolyfills() { + // @ts-ignore + if (!('command' in HTMLButtonElement.prototype)) { + const { apply } = await import('invokers-polyfill/fn') + apply() + } +} - showDrawer(window.drawerRightElement, drawerRightElement.scrollWidth) - }) +async function exampleEvents() { + if (typeof document === 'undefined') return - window.closeDrawerRightElement?.addEventListener('click', () => closeDrawer(window.drawerRightElement, 0)) + // dialog side-effect script — closedby fallback + --default-scrollbar-width + await import('winduum/src/components/dialog') + const { showRipple } = await import('winduum/src/utilities/ripple') + const { showToast, closeToast } = await import('winduum/src/components/toast') + const { closeToaster, toasterObserver } = await import('winduum/src/components/toaster') + // @ts-ignore + document.querySelector('#showRipple')?.addEventListener('click', (event) => { + showRipple(event) + }) + document.querySelector('#closeToaster')?.addEventListener(`click`, () => { + closeToaster(document.querySelector('.x-toaster')) + }) - window.drawerBottomElement?.addEventListener('scroll', ({ target }) => scrollDrawer(target, { - opacityRatio: 0, - scrollOpen: target.scrollHeight - target.clientHeight, - scrollClose: 0, - scrollDirection: target.scrollTop, - snapClass: 'snap-y snap-mandatory', - scrollSize: target.scrollHeight - target.clientHeight - })) + document.querySelector('#showToast:not(.has-events)')?.addEventListener('click', () => { - window.showDrawerBottomElement?.addEventListener('click', async () => { - window.drawerBottomElement.showModal() + if (!document.querySelector('.x-toaster')) { + document.body.insertAdjacentHTML('beforeend', `
      `) - await scrollInitDrawer(window.drawerBottomElement, 0, 'top') + const observer = toasterObserver() - showDrawer(window.drawerBottomElement, drawerBottomElement.scrollHeight, 'top') + observer.observe(document.querySelector('.x-toaster'), { + childList: true, }) + } - window.closeDrawerBottomElement?.addEventListener('click', () => closeDrawer(window.drawerBottomElement, 0, 'top')) - - - - window.drawerTopElement?.scroll({ top: drawerTopElement.scrollHeight, behavior: 'instant' }); - window.drawerTopElement?.classList.remove('invisible') - - window.drawerTopElement?.addEventListener('scroll', ({ target }) => scrollDrawer(target, { - snapClass: 'snap-y snap-mandatory', - scrollSize: target.scrollHeight - target.clientHeight, - scrollDirection: target.scrollTop, - scrollOpen: 0, - scrollClose: target.scrollHeight - target.clientHeight - })) - window.showDrawerTopElement?.addEventListener('click', async () => { - window.drawerTopElement.showModal() - - await scrollInitDrawer(window.drawerTopElement, window.drawerTopElement?.scrollHeight, 'top') - - showDrawer(window.drawerTopElement, 0, 'top') - }) + document.querySelector('.x-toaster')?.insertAdjacentHTML('beforeend', ` +
    1. +
      +
      +
      Hello toast
      +
      Amazing toast
      +
      + +
      +
    2. + `) + + showToast(document.querySelector('.x-toaster').children[document.querySelector('.x-toaster').children.length - 1]) + + const closeToastButton = document.querySelectorAll('[data-action="closeToast"]')[document.querySelectorAll('[data-action="closeToast"]').length - 1] + + closeToastButton.addEventListener('click', ({ currentTarget }) => { + // @ts-ignore + closeToast(currentTarget.closest('.x-toast')) + }) + }) - window.closeDrawerTopElement?.addEventListener('click', () => closeDrawer(window.drawerTopElement, drawerTopElement.scrollHeight, 'top')) - } - } + document.querySelector('#showToast')?.classList.add('has-events') } export default { @@ -169,14 +97,15 @@ export default { watch(router.route, () => { setTimeout(() => { updateDarkIframes() - dialogEvent() + exampleEvents() }, 10) }) }, setup() { onMounted(() => { updateDarkIframes() - dialogEvent() + initPolyfills() + exampleEvents() !document.getElementById('icons') && document.body.insertAdjacentHTML('beforeend', ` `) diff --git a/docs/docs/base/defaults.md b/docs/docs/base/defaults.md index 7dd3db1..ba0a810 100644 --- a/docs/docs/base/defaults.md +++ b/docs/docs/base/defaults.md @@ -5,8 +5,15 @@ Default styles or rules applied to certain HTML elements or pseudo-elements. The <<< @/../node_modules/winduum/src/base/defaults.css -For TailwindCSS `v3` there are few rules such as resetting borders -and applying `--tw-content` to all pseudo-elements and zero border to all elements or pseudo-elements. +There is also an extended set of opinionated defaults — block `svg`/`img`, icon styling based on `href` suffixes (`-outline`, `-solid`, ...), unstyled lists and native appearance resets for `number` and `search` inputs. + +[`src/base/defaults-extended.css`](https://github.com/winduum/winduum/blob/main/src/base/defaults-extended.css) + +```css +@import "winduum/src/base/defaults-extended.css" layer(base); +``` + +For TailwindCSS there are few rules such as applying `--tw-content` to all pseudo-elements and zero border to all elements or pseudo-elements. [`tailwindcss/base/defaults.css`](https://github.com/winduum/winduum/blob/main/tailwindcss/base/defaults.css) diff --git a/docs/docs/components/button.md b/docs/docs/components/button.md index 50b5345..6ab4385 100644 --- a/docs/docs/components/button.md +++ b/docs/docs/components/button.md @@ -10,8 +10,8 @@ ``` ### Variants -* -* +* +* ### Props * @@ -21,12 +21,13 @@ * `bordered` * `muted` * `raised` -* `ghosted` +* `ghosted` * `sm` * `lg` * `square` * `circle` -* `fill` +* `fill` +* `spinner` ### Installation diff --git a/docs/docs/components/carousel.md b/docs/docs/components/carousel.md index c5ac4d0..a1e2b4e 100644 --- a/docs/docs/components/carousel.md +++ b/docs/docs/components/carousel.md @@ -1,5 +1,11 @@ # Carousel -Provides a scroll carousel that uses native CSS `scroll-snap` property.
      +Provides a scroll carousel that uses native CSS `scroll-snap` property. + +Since v3, the carousel is CSS-first — scrolling, snapping and even scroll markers can be handled by CSS alone +(see [CSS scroll markers](https://developer.mozilla.org/en-US/docs/Web/CSS/::scroll-marker)). +A small JavaScript layer adds prev/next buttons, marker state and scroll state — ready to use via +[winduum-elements](https://github.com/winduum/winduum-elements/tree/main/components/carousel) or +[winduum-stimulus](https://github.com/winduum/winduum-stimulus/tree/main/components/carousel). @@ -46,183 +52,71 @@ Follow instructions for individual framework usage below ## Javascript API -### `scrollTo` - -* **Type:** `(element: HTMLElement | Element, index: number) => void` -* **Kind:** `sync` +Low-level helpers used by `winduum-elements` and `winduum-stimulus` — you can use them to build your own integration. -Scroll to a snap item by its index. +### `scrollBy` -### `scrollNext` - -* **Type:** `(element: HTMLElement | Element) => void` +* **Type:** `(element: HTMLElement, options: { direction?: number, vertical?: boolean, ratio?: number }) => void` * **Kind:** `sync` -Scroll to the next snap item. +Scrolls the carousel content by a portion of its visible size. +`direction` is `1` (next) or `-1` (prev), `ratio` determines how much of the visible size is scrolled (default `0.85`). -### `scrollPrev` - -* **Type:** `(element: HTMLElement | Element) => void` -* **Kind:** `sync` - -Scroll to a previous snap item. - -### `getItemCount` - -* **Type:** `(element: HTMLElement | Element, scrollWidth: number, mathFloor: boolean) => number` -* **Kind:** `sync` - -Get the number of possible scrolls inside the carousel. +```js +import { scrollBy } from 'winduum/src/components/carousel' +nextElement.addEventListener('click', () => scrollBy(contentElement, { direction: 1 })) +prevElement.addEventListener('click', () => scrollBy(contentElement, { direction: -1 })) +``` -### `observeCarousel` +### `toggleScrollState` -* **Type:** `(element: HTMLElement | Element, options?: ObserveCarouselOptions) => void` +* **Type:** `(element: HTMLElement, options: { prevElement?: HTMLButtonElement, nextElement?: HTMLButtonElement, vertical?: boolean }) => void` * **Kind:** `sync` -Adds an observer for the carousel. Adds properties `_observer` and `_activeIndex` to the DOM of the carousel `element`. - -#### ObserveCarouselOptions - ---- - -##### visibleAttribute - -* **Type:** `string` -* **Default:** `data-visible` - -A class that is added to the carousel items once they are visible. +Updates the carousel scroll state — toggles `data-scroll-start`, `data-scroll-end` and `data-scroll-none` +attributes on the content element and disables the prev/next buttons at the edges. Call it on `scroll`. ---- - -##### observerOptions - -* **Type:** `IntersectionObserverInit` -* **Default:** `{ threshold: 0.5 }` - -Additional [options](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver#options) confugration for the observer. - ---- +```js +contentElement.addEventListener('scroll', () => { + toggleScrollState(contentElement, { prevElement, nextElement }) +}) +``` -### `dragCarousel` +### `setCurrentAttribute` -* **Type:** `(element: HTMLElement | Element, options?: DragCarouselOptions) => void` +* **Type:** `(element: HTMLElement, index: number, attributeName?: string) => void` * **Kind:** `sync` -Adds a mouse dragging capability to the carousel. - -#### DragCarouselOptions - ---- - -##### activeAttribute - -* **Type:** `string` -* **Default:** `data-grabbing` +Marks the child at `index` with the given attribute (default `aria-current`) and removes it from the previous one. ---- +### `setSnappedAttribute` -### `paginationCarousel` - -* **Type:** `(element: HTMLElement | Element, options?: PaginationCarouselOptions) => void` +* **Type:** `(element: HTMLElement, target: HTMLElement, markerGroupElement?: HTMLElement) => void` * **Kind:** `sync` -Inserts pagination indicators for the carousel to the desired element. - -#### PaginationCarouselOptions - ---- - -##### element - -* **Type:** `HTMLElement | Element` -* **Default:** `undefined` - ---- - -##### itemContent - -* **Type:** `string` -* **Default:** `` +Sets `data-snapped` on the currently snapped item and syncs `aria-current` in the marker group. +Designed for the [`scrollsnapchanging`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollsnapchanging_event) event. ---- - -##### activeAttribute - -* **Type:** `string` -* **Default:** `data-active` - ---- - -### `autoplayCarousel` - -* **Type:** `(element: HTMLElement | Element, options?: AutoplayCarouselOptions) => void` -* **Kind:** `sync` - -Adds an autoplay for the carousel. - -#### AutoplayCarouselOptions - ---- - -##### delay - -* **Type:** `number` -* **Default:** `4000` - -Delay in ms. - ---- - -##### pauseElements - -* **Type:** `HTMLElement[] | Element[]` -* **Default:** `[]` - -Which elements should pause the autoplay upon hover. - ---- +```js +contentElement.addEventListener('scrollsnapchanging', (event) => { + setSnappedAttribute(contentElement, event.snapTargetInline ?? event.snapTargetBlock, markerGroupElement) +}) +``` -### `scrollCarousel` +### `scrollToMarker` -* **Type:** `(element: HTMLElement | Element, options?: ScrollCarouselOptions) => void` +* **Type:** `(element: HTMLElement, target: HTMLElement, markerGroupElement: HTMLElement, scrollIntoViewOptions?: ScrollIntoViewOptions) => void` * **Kind:** `sync` -A helper function that updates various carousel states upon scroll. - -#### ScrollCarouselOptions - ---- - -##### observe - -* **Type:** `ObserveCarouselOptions` -* **Default:** `undefined` - ---- - -##### pagination - -* **Type:** `PaginationCarouselOptions` -* **Default:** `{ activeClass: 'active' }` +Scrolls the carousel to the item referenced by a marker (an anchor with `href="#slide-id"`) and updates the marker state. ---- +```js +markerElements.forEach((marker) => { + marker.addEventListener('click', (event) => { + event.preventDefault() -##### progressElement - -* **Type:** `HTMLProgressElement | Element` -* **Default:** `undefined` - ---- - -##### counterMinElement - -* **Type:** `HTMLElement | Element` -* **Default:** `undefined` - ---- - -##### counterMaxElement - -* **Type:** `HTMLElement | Element` -* **Default:** `undefined` + scrollToMarker(contentElement, event.target, markerGroupElement) + }) +}) +``` diff --git a/docs/docs/components/compare.md b/docs/docs/components/compare.md index ad6cc53..9ee5c63 100644 --- a/docs/docs/components/compare.md +++ b/docs/docs/components/compare.md @@ -65,12 +65,14 @@ Follow instructions for individual framework usage below ### setKeyboardStep -* **Type:** `(element: HTMLInputElement, key: string, step?: number) => void` +* **Type:** `(element: HTMLInputElement, key: string, step?: string) => void` * **Kind:** `sync` +* **Default step:** `'10'` ### setMouseStep -* **Type:** `(element: HTMLInputElement, step?: number) => void` +* **Type:** `(element: HTMLInputElement, step?: string) => void` * **Kind:** `sync` +* **Default step:** `'0.1'` diff --git a/docs/docs/components/control.md b/docs/docs/components/control.md index e6d10c2..ac2d1c6 100644 --- a/docs/docs/components/control.md +++ b/docs/docs/components/control.md @@ -36,6 +36,7 @@ Follow instructions for individual framework usage below * * * +* * ### Props @@ -43,6 +44,7 @@ Follow instructions for individual framework usage below * * * +* * ## Examples diff --git a/docs/docs/components/details.md b/docs/docs/components/details.md index 6858559..a9b37f8 100644 --- a/docs/docs/components/details.md +++ b/docs/docs/components/details.md @@ -1,49 +1,32 @@ # Details -An accessible accordion or toggle component for `details` and `summary` elements.
      -Uses small external library `slide-element` for smooth toggle animations. - -It is unstyled by default, so you can apply your own styles. +An accessible accordion or toggle component for `details` and `summary` elements. -### Dependencies - -* [slide-element](https://www.npmjs.com/package/slide-element) - ### Usage ::: code-group -```shell -npm i slide-element +```css +@import "winduum/src/components/details/index.css" layer(utilities); ``` ```html
      - + Show more -
      -
      - Details content -
      +
      + Details content
      ``` -```js -import { toggleDetails } from 'winduum/src/components/details' - -document.querySelectorAll('[data-action="toggleDetails"]').forEach(summary => { - summary.addEventListener('click', event => { - if (event.currentTarget.tagName !== 'INPUT') event.preventDefault() - - toggleDetails(summary) - }) -}) -``` ::: +### Variants +* + ### Installation Follow instructions for individual framework usage below @@ -55,13 +38,12 @@ Follow instructions for individual framework usage below -::: code-group -<<< @/public/examples/components/details/default.html#body{} [html] -<<< @/../examples/src/pages/components/details/default.liquid#js{} [js] -::: +<<< @/public/examples/components/details/default.html#body{} ### Checkbox +You can also control details with a checkbox inside `summary` — only a tiny inline script is needed to sync the checkbox state. + ::: code-group @@ -71,42 +53,8 @@ Follow instructions for individual framework usage below ### Accordion - - -::: code-group -<<< @/public/examples/components/details/accordion.html#body{} [html] -<<< @/../examples/src/pages/components/details/accordion.liquid#js{} [js] -::: - - -## Javascript API - -```typescript -interface DefaultOptions { - selector?: string - summarySelector?: string -} -``` - -### toggleDetails - -* **Type:** `(selector: HTMLInputElement | HTMLElement, options?: DefaultOptions) => Promise` -* **Kind:** `async` - -Toggles a details element, should be added on summary or anywhere inside the details element. - -### showDetails - -* **Type:** `(selector: HTMLInputElement | HTMLElement, options?: DefaultOptions) => Promise` -* **Kind:** `async` - -Shows a details element, should be added on `summary` or anywhere inside the `details` element. - -### closeDetails - -* **Type:** `(selector: HTMLInputElement | HTMLElement, options?: DefaultOptions) => Promise` -* **Kind:** `async` - -Closes a details element, should be added on `summary` or anywhere inside the `details` element. +Exclusive accordions use the native `name` attribute — details elements sharing the same `name` close each other automatically. + +<<< @/public/examples/components/details/accordion.html#body{} diff --git a/docs/docs/components/dialog.md b/docs/docs/components/dialog.md index 662d6d0..f7cee47 100644 --- a/docs/docs/components/dialog.md +++ b/docs/docs/components/dialog.md @@ -1,6 +1,11 @@ # Dialog Modal component that uses native HTML5 `dialog` functionality. +Since v3, dialogs are fully controlled by the web platform — opening and closing is handled with +native [Invoker Commands](https://developer.mozilla.org/en-US/docs/Web/API/Invoker_Commands_API) +(`command` / `commandfor`) and the [`closedby`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog#closedby) +attribute, so no JavaScript API is needed. + ## Usage @@ -43,6 +48,7 @@ document.querySelector('#showDialog').addEventListener('click', () => { ### Variants * * +* ### Props * @@ -59,10 +65,10 @@ Follow instructions for individual framework usage below ## Example
      - +
      - +
      Example dialog

      @@ -108,131 +114,21 @@ Follow instructions for individual framework usage below const dialogMain = ref() - - +```html + ``` -::: - -## JavaScript API -### `showDialog` +## JavaScript -* **Type:** `(selector: HTMLDialogElement, options?: DefaultOptions) => Promise` -* **Kind:** `async` - -Shows an existing ``. It takes a `selector` argument, which is a CSS selector that identifies the dialog DOM element to be displayed. It also takes an options argument, which is an object that specifies how the dialog should be displayed. - -The `closeDialog` event is sent upon closing with the `esc` key or clicking outside the dialog content window. - -#### Example +There is no JavaScript API — dialogs use the native [`HTMLDialogElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement) +interface. If you need to control a dialog programmatically, use the native methods directly ```js -import { showDialog } from 'winduum/src/libraries/dialog' - -document.querySelector('#showDialog').addEventListener('click', async () => { - await showDialog(document.querySelector('#dialogElement')) -}) +document.querySelector('#dialogExample').showModal() +document.querySelector('#dialogExample').close() ``` -
      - -#### `DefaultOptions` - ---- - -##### remove - -* **Type:** `boolean` -* **Default:** `true` - -A boolean that indicates whether the dialog should be removed from the DOM when it is closed. - ---- - -##### closable - -* **Type:** `boolean` -* **Default:** `true` - -A boolean that indicates whenever is dialog closable by clicking outside or with `esc` key. - ---- -##### modal - -* **Type:** `boolean` -* **Default:** `true` - -Determines if the dialog is shown as modal on top-layer. - ---- - -##### openAttribute - -* **Type:** `string` -* **Default:** `data-open` - -A string representing a data attribute that will be added when the dialog is fully visible. - ---- - -##### closedAttribute - -* **Type:** `string` -* **Default:** `data-closed` - -A string representing a data attribute that will be added once the dialog starts closing. - ---- - -##### contentSelector - -* **Type:** `string` -* **Default:** `.x-dialog-content` - -A string representing a CSS selector representing the dialog content - ---- - -##### scrollbarWidthProperty - -* **Type:** `string` -* **Default:** `--default-scrollbar-width` - -A CSS property representing a scrollbar width, when dialog is shown the document scrollbar is hidden, this adds necessary padding. - ---- - -
      - -### `closeDialog` - -* **Type:** `(selector: HTMLDialogElement, options?: DefaultOptions) => Promise` -* **Kind:** `async` - -Closes an existing ``. -It takes a `selector` argument, which is a CSS selector that identifies the dialog DOM element. -It also takes an `options` argument, which is an object that specifies how the dialog should be closed. - -When dialog closes it sends native `close` event you can listen to, -additionally `x-dialog:close` event is sent when dialog animation starts. - -#### Example - -```js -import { closeDialog } from 'winduum/src/components/dialog' - -document.querySelector('#closeDialog').addEventListener('click', async () => { - await closeDialog(document.querySelector('#dialogElement')) -}) -``` +The `winduum/src/components/dialog` side-effect script additionally +* closes an open dialog when clicking its backdrop, based on the `closedby` attribute (fallback for browsers without native `closedby` support) +* keeps `--default-scrollbar-width` on `` updated via a `ResizeObserver`, which the dialog CSS uses to compensate for the hidden page scrollbar diff --git a/docs/docs/components/drawer.md b/docs/docs/components/drawer.md index 81d3c31..33503bd 100644 --- a/docs/docs/components/drawer.md +++ b/docs/docs/components/drawer.md @@ -2,6 +2,12 @@ Provides a scroll drawer that uses native HTML5 `dialog` and CSS `scroll-snap` property.
      Can be dismissed with touch gestures on touch devices. +Since v3 the drawer is opened with native [Invoker Commands](https://developer.mozilla.org/en-US/docs/Web/API/Invoker_Commands_API) +(`command="show-modal"` / `command="request-close"`) and the scroll behavior is driven by the `Drawer` custom element from +[winduum-elements](https://github.com/winduum/winduum-elements/tree/main/components/drawer) +(or the [winduum-stimulus](https://github.com/winduum/winduum-stimulus/tree/main/components/drawer) controller). +Thanks to the `noscript` variant, the drawer degrades gracefully even without JavaScript. + ### Usage @@ -16,6 +22,9 @@ Can be dismissed with touch gestures on touch devices. ### Variants * * +* +* +* ### Props * @@ -105,95 +114,72 @@ Follow instructions for individual framework usage below ## Javascript API +Low-level helpers used by `winduum-elements` and `winduum-stimulus` — you can use them to build your own integration. +All functions take a `placement` of `'left' | 'right' | 'top' | 'bottom'` and operate on the **scroller** element (`.x-drawer-scroller`). + ### `showDrawer` -* **Type:** `(element: HTMLElement | Element, distance: number, direction: 'left' | 'top') => void` -* **Kind:** `sync` +* **Type:** `(element: HTMLElement, placement: 'left' | 'right' | 'top' | 'bottom') => Promise` +* **Kind:** `async` -Scroll the drawer to open state. +Scrolls the drawer scroller to its open state. Resets the scroll position first in browsers without +[`scroll-initial-target`](https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-initial-target) support. +Call it after `dialog.showModal()`. -### `closeDrawer` +```js +import { showDrawer } from 'winduum/src/components/drawer' -* **Type:** `(element: HTMLElement | Element, distance: number, direction: 'left' | 'top') => void` -* **Kind:** `sync` - -Scroll the drawer to closed state. +dialogElement.showModal() +await showDrawer(dialogElement.firstElementChild, 'left') +``` -### `scrollInitDrawer` +### `closeDrawer` -* **Type:** `(element: HTMLElement | Element, distance?: number, direction?: 'left' | 'top') => void` +* **Type:** `(element: HTMLElement, placement: 'left' | 'right' | 'top' | 'bottom') => void` * **Kind:** `sync` -Initializes the scroll position. Call this before `showDrawer` method. +Scrolls the drawer scroller to its closed state — the dismiss animation is handled by scroll snapping, +and the dialog is closed by `drawerObserver` once the content leaves the viewport. ### `scrollDrawer` -* **Type:** `(element: HTMLElement | Element, options: ScrollDrawerOptions) => void` +* **Type:** `(element: HTMLElement, placement: 'left' | 'right' | 'top' | 'bottom', reverse?: boolean, behavior?: 'auto' | 'instant') => void` * **Kind:** `sync` -Sets correct classes and attributes upon scroll. Events `c-drawer:open` and `c-drawer:close` are dispatched upon opening or closing the drawer. - -#### ScrollDrawerOptions - ---- - -##### snapClass - -* **Type:** `string` -* **Default:** `snap-x snap-mandatory` - -A classes that are added for snapping purposes once the drawer is open. - ---- +Scrolls the drawer scroller to the open (or closed, with `reverse: true`) position. -##### opacityProperty +### `drawerEvents` -* **Type:** `string` -* **Default:** `--tw-bg-opacity` - -A CSS property for animating the background opacity upon scroll. - ---- - -##### opacityRatio - -* **Type:** `number` -* **Default:** `1` - -You can either set `1` or `0` depending on the direction the drawer is opened. Right and bottom drawer should be set to `0`. - ---- - -##### scrollOpen - -* **Type:** `number` -* **Default:** `0` - -Scroll position indicating that the drawer is opened. +* **Type:** `(element: HTMLDialogElement, contentElement: HTMLElement, placement: 'left' | 'right' | 'top' | 'bottom', signal?: AbortSignal) => void` +* **Kind:** `sync` ---- +Wires up dialog events — closes the drawer with the scroll animation on `cancel` (Esc) and on click outside the content. -##### scrollClose +### `drawerObserver` -* **Type:** `number` -* **Default:** `element.scrollWidth - element.clientWidth` +* **Type:** `(element: HTMLDialogElement, placement: 'left' | 'right' | 'top' | 'bottom') => IntersectionObserver` +* **Kind:** `sync` -Scroll position indicating that the drawer is closed. +Returns an `IntersectionObserver` that closes the dialog once the drawer content is scrolled/swiped out of view. +Observe the content element with it. ---- +```js +import { drawerObserver } from 'winduum/src/components/drawer' -##### scrollSize +const observer = drawerObserver(dialogElement, 'left') +observer.observe(contentElement) +``` -* **Type:** `number` -* **Default:** `element.scrollWidth - element.clientWidth` +### `drawerProperties` -Maximum scroll size of the drawer. +* **Type:** `(element: HTMLElement, placement: 'left' | 'right' | 'top' | 'bottom') => ['top' | 'left', number, number]` +* **Kind:** `sync` ---- +Returns the scroll axis and the open/closed scroll distances for the given placement. -##### scrollDirection +### `isVerticalDrawer` -* **Type:** `number` -* **Default:** `element.scrollLeft` +* **Type:** `(placement: 'left' | 'right' | 'top' | 'bottom') => boolean` +* **Kind:** `sync` -Current scroll position of the drawer. +Returns `true` for `top` and `bottom` placements. diff --git a/docs/docs/components/form.md b/docs/docs/components/form.md index 15de42e..b63cdcb 100644 --- a/docs/docs/components/form.md +++ b/docs/docs/components/form.md @@ -52,18 +52,21 @@ Follow instructions for individual framework usage below * **Type:** `(event: Event | SubmitEvent, options?: ValidateFormOptions) => void` * **Kind:** `sync` -Validates a form with [checkValidity](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/checkValidity) and [validateField](/docs/components/form#validatefield) events. +Validates a form with [checkValidity](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/checkValidity) +and runs [validateField](/docs/components/form#validatefield) on every field. +On invalid submit it scrolls to and focuses the first invalid element, on valid submit it marks the submitter +with a loading attribute. #### ValidateFormOptions --- -##### validateSelectors +##### validateSelector * **Type:** `string` -* **Default:** `.x-control, .x-check, .x-switch, .x-rating, .x-color` +* **Default:** `.x-field` -Selectors which will be validated. +Selector of field wrappers which will be validated. --- @@ -76,12 +79,21 @@ Additional options for `validateField` --- +##### validateField + +* **Type:** `typeof validateField` +* **Default:** `validateField` + +Override the field validation function. + +--- + ##### submitterLoadingAttribute * **Type:** `string` * **Default:** `data-loading` -Loading class that will be added to a submitter element, e.g., A button. +Loading attribute that will be added to the submitter element (e.g. a button) on valid submit. --- @@ -96,86 +108,71 @@ Scroll options when scrolling to an invalid element. ### `validateField` -* **Type:** `(selector: HTMLElement, options?: ValidateFieldOptions) => void` +* **Type:** `(element: HTMLElement, options?: ValidateFieldOptions) => void` * **Kind:** `sync` -Validates a field. This can be element such as `.x-control`, `x-check` and others that can be validated. It adds validation info message inside `c-field` and validation icon inside `x-control`. -It also adds a `valid`, `invalid` or `active` class to the element. +Validates a single field wrapper (typically `.x-field`). It appends a validation info message +(with `data-validity`) to the field and a validation icon inside `.x-control`. +The message text is resolved from `options.validationMessage`, the `data-validation-message` attribute +on the invalid element, or the native +[`validationMessage`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validationMessage). #### ValidateFieldOptions --- -##### validate -* **Type:** `boolean` -* **Default:** `true` +##### validationMessage +* **Type:** `string` +* **Default:** `undefined` -Only `active` class is added if the element value is not empty. No other validation is done. +Overrides the displayed validation message. --- ##### selector * **Type:** `string` -* **Default:** `input:not([type="hidden"]), textarea, select` - ---- - -##### ignoreMatch -* **Type:** `RegExp` -* **Default:** `/(data-novalidate|readonly)/` +* **Default:** `:is(input:not([type="hidden"]), textarea, select):not([readonly], [data-novalidate])` -Ignores a validation if any of these strings are present in the HTML. +Selector of elements inside the field that are validated. Add `data-novalidate` or `readonly` to skip validation. --- ##### validitySelector * **Type:** `string` -* **Default:** `.validity` - -Selector for dynamically added content in the DOM such us info message or icon. - ---- - -##### infoParentSelector -* **Type:** `string` -* **Default:** `.x-field` +* **Default:** `[data-validity]` ---- - -##### infoSelector -* **Type:** `string` -* **Default:** `.x-info` +Selector for dynamically added content in the DOM, such as the info message or icon — it is removed on re-validation. --- ##### infoContent * **Type:** `string` -* **Default:** `
      ` +* **Default:** `
      ` + +Element appended to the field with the validation message. --- -##### endParentSelector +##### iconParentSelector * **Type:** `string` * **Default:** `.x-control` +Element the validation icon is appended into. + --- -##### endSelector +##### iconSelector * **Type:** `string` * **Default:** `.ms-auto` --- -##### endContent +##### iconContent * **Type:** `string` * **Default:** `
      ` ---- - -##### validAttribute -* **Type:** `string` -* **Default:** `data-valid` +Wrapper element for the validation icon, created inside `iconParentSelector` when missing. --- @@ -185,19 +182,7 @@ Selector for dynamically added content in the DOM such us info message or icon. --- -##### invalidAttribute -* **Type:** `string` -* **Default:** `data-invalid` - ---- - ##### invalidIcon * **Type:** `string` -* **Default:** `` - ---- - -##### activeAttribute -* **Type:** `string` -* **Default:** `data-active` +* **Default:** `` diff --git a/docs/docs/components/heading.md b/docs/docs/components/heading.md index a9799ae..a1541f6 100644 --- a/docs/docs/components/heading.md +++ b/docs/docs/components/heading.md @@ -9,6 +9,9 @@ For common heading styles that you can manage from one component across project. @import "winduum/src/components/heading/index.css" layer(utilities); ``` +### Props +* + ### Tokens * `sm` diff --git a/docs/docs/components/popover.md b/docs/docs/components/popover.md index 3c77bd4..f1eaa75 100644 --- a/docs/docs/components/popover.md +++ b/docs/docs/components/popover.md @@ -1,15 +1,16 @@ # Popover -Popover can be used for dropdowns and other popovers when an element is clicked and focused. +Popover can be used for dropdowns and other popovers when an element is clicked, focused or hovered. You have following types of trigger as an option: -* trigger on focus with CSS `trigger-focus` class -* trigger on hover with CSS `trigger-hover` class -* trigger on click with JS and the `[popover]` attribute +* trigger on click with `command="toggle-popover"` and `commandfor` +* trigger on hover/focus with the [`interestfor`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/interestfor) attribute (see the [Interest](/docs/variants/interest) variant) - - -### Dependencies +Since v3, popovers build entirely on the web platform — the `[popover]` attribute, +[Invoker Commands](https://developer.mozilla.org/en-US/docs/Web/API/Invoker_Commands_API) +(`command="toggle-popover"` / `show-popover` / `hide-popover`) and +[CSS Anchor Positioning](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_anchor_positioning). +No JavaScript is required in browsers with anchor positioning support. -* [floating-ui](https://floating-ui.com/) - for `[popover]` trigger + ## Usage @@ -39,21 +40,17 @@ You have following types of trigger as an option: ### Variants * * - + +### Props +* +* + ### Tokens -Applicable to `x-popover-content` -* `bottom bottom-start` -* `bottom bottom-end` -* `top top-start` -* `top top-end` -* `right right-start` -* `right right-end` -* `left left-start` -* `left left-end` -* `bottom inline-center` -* `top inline-center` -* `right block-center` -* `left block-center` +Positioning of `x-popover` is provided by the [Position](/docs/utilities/position) utilities +* `top` `top-start` `top-end` +* `bottom` `bottom-start` `bottom-end` +* `left` `left-start` `left-end` +* `right` `right-start` `right-end` ### Installation Follow instructions for individual framework usage below @@ -67,199 +64,94 @@ Follow instructions for individual framework usage below ## Examples -### focus-trigger +### Command + +Native [Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API) with +[Invoker Commands](https://developer.mozilla.org/en-US/docs/Web/API/Invoker_Commands_API) — +the popover lives in the [top-layer](https://developer.mozilla.org/en-US/docs/Glossary/Top_layer), gets light-dismiss +(Esc, clicking outside) and keyboard handling for free, without a single line of JavaScript. <<< @/public/examples/components/popover/basic.html#body{} -### hover-trigger +### Interest (hover) + +Shows the popover when the user *shows interest* in the trigger — hover or keyboard focus — via the `interestfor` attribute. +Use the [interestfor](https://www.npmjs.com/package/interestfor) polyfill for browsers without native support. <<< @/public/examples/components/popover/hover.html#body{} -### [popover] +### Positioning fallback -This is using advantages of [Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API) with [floating-ui](https://floating-ui.com/). -It's also backwards compatible as it's leveraging only the `showPopover` and `hidePopover` for the [top-layer](https://developer.mozilla.org/en-US/docs/Glossary/Top_layer) support. - -Popover is placed dynamically upon available space, and auto updates itself when needed. +Same as the command example, but wrapped in the `x-popover` custom element from +[winduum-elements](https://github.com/winduum/winduum-elements/tree/main/components/popover), which applies +the floating-ui positioning fallback in browsers without CSS Anchor Positioning. -<<< @/public/examples/components/popover/api.html#body{} +::: code-group +<<< @/public/examples/components/popover/api.html#body{} [html] +<<< @/../examples/src/pages/components/popover/api.liquid#js{} [js] +::: ## JavaScript API -### `showPopover` - -* **Type:** `(element: HTMLElement | Element, options?: ShowPopoverOptions) => Promise` -* **Kind:** `async` - -#### Example - -```js -import { showPopover, hidePopover } from '/src/components/popover' - -const popoverActionElement = document?.querySelector('[popovertargetaction="show"]') - -popoverActionElement?.addEventListener('click', async (e) => { - e.preventDefault() - - const currentTarget = e.currentTarget - await showPopover(currentTarget, { - placement: 'right-end', - }) -}) - -// close on esc -window.addEventListener('keydown', ({ key }) => { - if (key === 'Escape') { - hidePopover(popoverActionElement) - } -}) - -// outside dismiss -window.addEventListener('click', ({ target }) => { - if (!window.popover?.contains(target) && !popoverActionElement?.isEqualNode(target) && popoverActionElement?.ariaExpanded === 'true') { - hidePopover(popoverActionElement) - } -}) -``` -
      - -#### `ShowPopoverOptions` - ---- - -##### anchorSelector - -* **Type:** `string` -* **Default:** `undefined` - -By default, the anchor selector is the trigger button, you can change this to other selector. - ---- - -##### openAttribute - -* **Type:** `string` -* **Default:** `data-open` +The core popover component needs no JavaScript — use the native +[`showPopover`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/showPopover) / +[`hidePopover`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/hidePopover) / +[`togglePopover`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/togglePopover) methods for programmatic control. -A string representing an attribute that will be added when popover is visible. +Two helpers are exported for the floating-ui positioning fallback (they require [`@floating-ui/dom`](https://floating-ui.com/) as a dependency). +They are used internally by `winduum-elements` and `winduum-stimulus`, but you can use them to build your own integration. ---- +### `computePositionPopover` -##### compute - -* **Type:** `boolean` -* **Default:** `true` - -Determines if the popover should be anchored and computed with `@floating-ui/dom` - ---- - -##### placement - -* **Type:** `Placement` -* **Default:** `undefined` - -Determines [placement](https://floating-ui.com/docs/computePosition#placement) of the popover with `@floating-ui/dom`, also adds a corresponding class to the popover target. - ---- - -##### middleware - -* **Type:** `Array` -* **Default:** `[offset(12 ?? options?.offset), flip(options?.flip), shift({ padding: 8, ...options?.shift })]` - -Customize [middleware](https://floating-ui.com/docs/computePosition#middleware) for `@floating-ui/dom` - ---- - -##### offset - -* **Type:** `OffsetOptions` -* **Default:** `12` - -Customize [offset](https://floating-ui.com/docs/offset#options) options for `@floating-ui/dom` - ---- - -##### flip - -* **Type:** `FlipOptions` -* **Default:** `undefined` - -Customize [flip](https://floating-ui.com/docs/flip#options) options for `@floating-ui/dom` - ---- - -##### shift - -* **Type:** `ShiftOptions` -* **Default:** `undefined` - -Customize [shift](https://floating-ui.com/docs/shift#options) options for `@floating-ui/dom` - ---- - -
      - -### `hidePopover` - -* **Type:** `(element: HTMLElement | Element) => Promise` +* **Type:** `(referenceElement: HTMLElement, floatingElement: HTMLElement, placement: Placement, options?: ComputePositionConfig | boolean) => Promise` * **Kind:** `async` +Computes the popover position with `@floating-ui/dom` and applies it to the floating element. +When native CSS anchor positioning is supported, only the placement class is applied and positioning is left to CSS. +Passing `options: true` enables the built-in `flip()` middleware. + #### Example ```js -import { hidePopover } from '/src/components/popover' +import { computePositionPopover } from 'winduum/src/components/popover' -const popoverActionElement = document?.querySelector('[popovertargetaction="hide"]') +const trigger = document.querySelector('#popoverTrigger') +const popover = document.querySelector('#popoverElement') -popoverActionElement?.addEventListener('click', async (e) => { - e.preventDefault() - - const currentTarget = e.currentTarget - await hidePopover(currentTarget) +popover.addEventListener('toggle', async ({ newState }) => { + if (newState === 'open') { + await computePositionPopover(trigger, popover, 'bottom-start') + } }) ``` -
      -### `togglePopover` +### `autoUpdatePopover` -* **Type:** `(element: HTMLElement | Element, options?: ShowPopoverOptions) => Promise` +* **Type:** `(referenceElement: HTMLElement, floatingElement: HTMLElement, placement: Placement, options?: ComputePositionConfig | boolean) => Promise<() => void>` * **Kind:** `async` +Same as `computePositionPopover`, but keeps the position updated on scroll and resize via floating-ui +[`autoUpdate`](https://floating-ui.com/docs/autoUpdate). Returns a cleanup function — call it when the popover closes. + #### Example ```js -import { togglePopover, hidePopover } from '/src/components/popover' - -const popoverActionElement = document?.querySelector('[popovertargetaction="toggle"]') +import { autoUpdatePopover } from 'winduum/src/components/popover' -popoverActionElement?.addEventListener('click', async (e) => { - e.preventDefault() - - const currentTarget = e.currentTarget - await togglePopover(currentTarget) -}) - -// close on esc -window.addEventListener('keydown', ({ key }) => { - if (key === 'Escape') { - hidePopover(popoverActionElement) - } -}) +let cleanup -// outside dismiss -window.addEventListener('click', ({ target }) => { - if (!window.popover?.contains(target) && !popoverActionElement?.isEqualNode(target) && popoverActionElement?.ariaExpanded === 'true') { - hidePopover(popoverActionElement) +popover.addEventListener('toggle', async ({ newState }) => { + if (newState === 'open') { + cleanup = await autoUpdatePopover(trigger, popover, 'bottom-start') + } else { + cleanup?.() } }) ``` -
      diff --git a/docs/docs/components/tabs.md b/docs/docs/components/tabs.md index a600bf8..8ff03c9 100644 --- a/docs/docs/components/tabs.md +++ b/docs/docs/components/tabs.md @@ -9,7 +9,7 @@ ``` ### Variants -* +* ### Installation Follow instructions for individual framework usage below diff --git a/docs/docs/components/toast.md b/docs/docs/components/toast.md index 2d6cede..d8c4ebb 100644 --- a/docs/docs/components/toast.md +++ b/docs/docs/components/toast.md @@ -10,13 +10,13 @@ Let it bake and fly from your [Toaster](/docs/components/toaster)! @import "winduum/src/components/toast/index.css" layer(utilities); ``` ```js -import { showToast, closeToast } from 'winduum/src/components/toaster' +import { showToast, closeToast } from 'winduum/src/components/toast' document.querySelector('#insertToast').addEventListener('click', async () => { const toaster = document.querySelector('.x-toaster') toaster.insertAdjacentHTML('beforeend', ` -
    3. +
    4. Hello toast
      @@ -32,14 +32,14 @@ document.querySelector('#insertToast').addEventListener('click', async () => { const closeToastButton = document.querySelectorAll('[data-action="closeToast"]')[document.querySelectorAll('[data-action="closeToast"]').length - 1] closeToastButton.addEventListener('click', ({ currentTarget }) => { - closeToast(currentTarget.closest('.c-toast')) + closeToast(currentTarget.closest('.x-toast')) }) }) ``` ```html -
        +
          ``` ::: @@ -48,6 +48,10 @@ document.querySelector('#insertToast').addEventListener('click', async () => { * * +### Props +* +* + ### Installation Follow instructions for individual framework usage below @@ -65,16 +69,16 @@ Follow instructions for individual framework usage below ```html -
            +
              @@ -101,15 +105,15 @@ Follow instructions for individual framework usage below ### `showToast` -* **Type:** `(selector: HTMLElement, options?: ShowToastOptions) => Promise` +* **Type:** `(element: HTMLElement, options?: ShowToastOptions) => Promise` * **Kind:** `async` -Applies an enter animation to existing toast. +Applies an enter animation to existing toast and schedules its auto-hide. #### Example ```js -import { showToast } from 'winduum/src/components/toaster' +import { showToast } from 'winduum/src/components/toast' document.querySelector('#showToast').addEventListener('click', async () => { await showToast(document.querySelector('#toastElement')) @@ -130,15 +134,17 @@ document.querySelector('#showToast').addEventListener('click', async () => { ##### autoHide -* **Type:** `number` -* **Default:** `null` +* **Type:** `number | null` +* **Default:** `7500` + +Time in ms after which the toast closes automatically — the delay scales with the number of toasts in the toaster. Set to `null` to disable. --- ##### heightProperty * **Type:** `string` -* **Default:** `--x-toast-height` +* **Default:** `--x-toast-block-size` --- @@ -147,13 +153,15 @@ document.querySelector('#showToast').addEventListener('click', async () => { * **Type:** `CloseToastOptions` * **Default:** `{}` +Options passed to `closeToast` when the toast auto-hides. + ---
              ### `closeToast` -* **Type:** `(selector: HTMLElement, options?: CloseToastOptions) => Promise` +* **Type:** `(element: HTMLElement, options?: CloseToastOptions) => Promise` * **Kind:** `async` Applies an exit animation to existing toast and removes it from DOM. @@ -161,7 +169,7 @@ Applies an exit animation to existing toast and removes it from DOM. #### Example ```js -import { showToast } from 'winduum/src/components/toaster' +import { closeToast } from 'winduum/src/components/toast' document.querySelector('#closeToast').addEventListener('click', async () => { await closeToast(document.querySelector('#toastElement')) @@ -176,14 +184,21 @@ document.querySelector('#closeToast').addEventListener('click', async () => { ##### closedAttribute -* **Type:** `data-closed` -* **Default:** `out` +* **Type:** `string` +* **Default:** `data-closed` --- ##### heightProperty * **Type:** `string` -* **Default:** `--x-toast-height` +* **Default:** `--x-toast-block-size` --- + +##### remove + +* **Type:** `boolean` +* **Default:** `true` + +Determines whether the toast is removed from the DOM after the exit animation. diff --git a/docs/docs/components/toaster.md b/docs/docs/components/toaster.md index 62e8088..53c4d35 100644 --- a/docs/docs/components/toaster.md +++ b/docs/docs/components/toaster.md @@ -1,17 +1,38 @@ # Toaster Bake your [Toast](/docs/components/toast) and let it fly! You should insert in into your `` +The toaster uses the [Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API) +(`popover="manual"`) so toasts always appear in the [top-layer](https://developer.mozilla.org/en-US/docs/Glossary/Top_layer) — +even above open dialogs. Use `toasterObserver` to show/hide the toaster popover automatically as toasts are added and removed. + ## Usage +::: code-group ```css @import "winduum/src/components/toaster/index.css" layer(utilities); ``` +```html +
                +``` +```js +import { toasterObserver } from 'winduum/src/components/toaster' + +const observer = toasterObserver() + +observer.observe(document.querySelector('.x-toaster'), { + childList: true, +}) +``` +::: ### Variants * +### Props +* + ### Installation Follow instructions for individual framework usage below @@ -19,25 +40,41 @@ Follow instructions for individual framework usage below * * -## Example - -```html -
                  -``` +## JavaScript API ### `closeToaster` -* **Type:** `(selector: HTMLElement, options?: CloseToastOptions) => Promise` -* **Kind:** `async` +* **Type:** `(element: HTMLElement, options?: CloseToastOptions) => void` +* **Kind:** `sync` All toasts are closed at once. #### Example ```js -import { showToast } from 'winduum/src/components/toaster' +import { closeToaster } from 'winduum/src/components/toaster' + +document.querySelector('#closeToaster').addEventListener('click', () => { + closeToaster(document.querySelector('.x-toaster')) +}) +``` + +### `toasterObserver` + +* **Type:** `() => MutationObserver` +* **Kind:** `sync` + +Returns a `MutationObserver` that shows the toaster popover when the first toast is inserted +and hides it when the last toast is removed. Observe the toaster element with `{ childList: true }`. + +#### Example + +```js +import { toasterObserver } from 'winduum/src/components/toaster' + +const observer = toasterObserver() -document.querySelector('#closeToaster').addEventListener('click', async () => { - await closeToaster(document.querySelector('.c-toaster')) +observer.observe(document.querySelector('.x-toaster'), { + childList: true, }) ``` diff --git a/docs/docs/grid.md b/docs/docs/grid.md index 087f137..581d139 100644 --- a/docs/docs/grid.md +++ b/docs/docs/grid.md @@ -8,5 +8,5 @@ It's recommended to use the following TailwindCSS approaches to shape your layou Winduum also provides additional utilities to make things even easier. -* [Container](/docs/utilities/container) +* [Grid](/docs/utilities/grid) * [Divide Gap](/docs/utilities/divide-gap) diff --git a/docs/docs/index.md b/docs/docs/index.md index eb6f72a..e16d2c2 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -15,7 +15,7 @@ See [Trying Winduum Online](#trying-winduum-online) section below to see all pos ### npm ```shell -npm i winduum +npm i winduum@next ``` ### TailwindCSS diff --git a/docs/docs/polyfills.md b/docs/docs/polyfills.md index 4271862..e18b078 100644 --- a/docs/docs/polyfills.md +++ b/docs/docs/polyfills.md @@ -42,6 +42,13 @@ The `interestfor` API lets controls declaratively show interest in another eleme The `timeline-trigger` feature is used by Winduum animation trigger utilities. Winduum includes an experimental `timelineTrigger` polyfill that observes elements with `timeline-trigger-*` classes and toggles `data-enter` based on the configured entry and exit thresholds. +### Other support checks + +`winduum/supports` also exposes checks without a bundled polyfill — useful for your own fallbacks: + +* `supportsAnimationTimeline` — CSS [`animation-timeline`](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timeline) scroll-driven animations +* `supportsScrollInitialTarget` — CSS [`scroll-initial-target`](https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-initial-target), used internally by the [Drawer](/docs/components/drawer) helpers + ## Winduum Elements `winduum-elements` builds on top of Webuum, so projects using it need to include Webuum polyfills too when targeting browsers without support for those APIs. diff --git a/docs/docs/utilities/dot.md b/docs/docs/utilities/dot.md index e4e360c..d186585 100644 --- a/docs/docs/utilities/dot.md +++ b/docs/docs/utilities/dot.md @@ -1,4 +1,4 @@ -# Divide Gap +# Dot Provides a new utility class `dot` for.. well dots! diff --git a/docs/docs/utilities/ripple.md b/docs/docs/utilities/ripple.md index 0fe50da..e6c7ab9 100644 --- a/docs/docs/utilities/ripple.md +++ b/docs/docs/utilities/ripple.md @@ -1,6 +1,6 @@ # Ripple -A material ripple effect that is visible on clicking, you can use it with or without JS by adding `animation-ripple` class. +A material ripple effect that is visible on clicking. Use with [Button](/docs/components/button) or any other component. @@ -9,17 +9,13 @@ Use with [Button](/docs/components/button) or any other component. ::: code-group ```css -@import "winduum/utilities/ripple.css" layer(utilities); +@import "winduum/src/utilities/ripple/index.css" layer(utilities); ``` ```js import { showRipple } from 'winduum/src/utilities/ripple' -document.querySelector('#showRipple').addEventListener('click', (e) => { - showRipple({ - element: e.currentTarget, - x: e.offsetX, - y: e.offsetY - }) +document.querySelector('#showRipple').addEventListener('click', (event) => { + showRipple(event) }) ``` ```vue @@ -48,12 +44,8 @@ document.querySelector('#showRipple').addEventListener('click', (e) => { ```js import { showRipple } from 'winduum/src/utilities/ripple' -document.querySelector('#showRipple').addEventListener('click', (e) => { - showRipple({ - element: e.currentTarget, - x: e.offsetX, - y: e.offsetY - }) +document.querySelector('#showRipple').addEventListener('click', (event) => { + showRipple(event) }) ``` ::: diff --git a/docs/docs/utilities/spinner.md b/docs/docs/utilities/spinner.md index 8c5b88d..d7576f5 100644 --- a/docs/docs/utilities/spinner.md +++ b/docs/docs/utilities/spinner.md @@ -1,4 +1,4 @@ -# Swap +# Spinner Provides a new utility class `spinner` for circular animated spinners. diff --git a/docs/docs/utilities/swap.md b/docs/docs/utilities/swap.md index 18aaa65..c04462d 100644 --- a/docs/docs/utilities/swap.md +++ b/docs/docs/utilities/swap.md @@ -19,3 +19,22 @@ Provides a new utility class `swap` to toggle between elements. <<< @/public/examples/swap-aria.html#body{} [html] <<< @/../examples/src/pages/swap-aria.liquid#js{} [js] ::: + +## Javascript API + +There is also a `Swap` controller available in [winduum-stimulus](https://github.com/winduum/winduum-stimulus/tree/main/utilities/swap). + +### toggleSwap + +* **Type:** `(element: HTMLElement) => void` +* **Kind:** `sync` + +Swaps the `aria-hidden` state between the two child elements of the swap. + +```js +import { toggleSwap } from 'winduum/src/utilities/swap' + +document.querySelector('#swapExample').addEventListener('click', ({ currentTarget }) => { + toggleSwap(currentTarget) +}) +``` diff --git a/examples/package-lock.json b/examples/package-lock.json index 4207c85..9729873 100644 --- a/examples/package-lock.json +++ b/examples/package-lock.json @@ -8,11 +8,14 @@ "@floating-ui/dom": "^1.6.13", "@tailwindcss/vite": "^4.0.0", "@vituum/vite-plugin-liquid": "^1.1.0", - "slide-element": "^2.3.1", + "@webreflection/custom-elements-builtin": "^0.4.1", + "interestfor": "^1.0.0", + "invokers-polyfill": "^1.0.3", "tailwindcss": "^4.0.0", "vite": "^6.0.11", "vituum": "^1.1.1", - "winduum": "^2.2.0-next.5" + "winduum": "^3.0.0-next.7", + "winduum-elements": "^0.0.11" } }, "node_modules/@esbuild/aix-ppc64": { @@ -440,6 +443,15 @@ "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", "license": "MIT" }, + "node_modules/@newlogic-digital/utils-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@newlogic-digital/utils-js/-/utils-js-1.2.0.tgz", + "integrity": "sha512-tObXqpJKB8C9AvHACfCqJZkKHbDAIBTgO9RpMM01Ow/0pxX9G5vB8OSZ2W9eInMA9oB6BYGtPCzvO7MdZ2CWhw==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -974,6 +986,29 @@ "node": "^18.0.0 || >=20.0.0" } }, + "node_modules/@webreflection/custom-elements-attributes": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@webreflection/custom-elements-attributes/-/custom-elements-attributes-0.1.4.tgz", + "integrity": "sha512-uL8msxNYPabss14zx+pxMgr16x/RBKGeMzZQ95UZv5HRQPqs3hK1gNxMYwLvhuJ7aumvbqktfEf2g4waBl13iQ==", + "license": "ISC" + }, + "node_modules/@webreflection/custom-elements-builtin": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@webreflection/custom-elements-builtin/-/custom-elements-builtin-0.4.1.tgz", + "integrity": "sha512-CueKyf4HVvVx/5C458ZvOuI32BbdloJs6iIinf9k/M4POCddL7pR5ciWxHYy7Jd+FVkoMbwoOr+104ATecV51w==", + "license": "ISC", + "dependencies": { + "@webreflection/custom-elements-attributes": "^0.1.4", + "@webreflection/custom-elements-upgrade": "^0.1.4", + "qsa-observer": "^3.0.2" + } + }, + "node_modules/@webreflection/custom-elements-upgrade": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@webreflection/custom-elements-upgrade/-/custom-elements-upgrade-0.1.4.tgz", + "integrity": "sha512-gCRV9bImUc8oR+0N1YE+1etW5qaWpd4lUJeagBZfdZa6WIJ5fnihM1x6ngiKG/ND1kFNlqxE8fDkwJts7pwXBA==", + "license": "ISC" + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -1083,6 +1118,12 @@ "node": ">=0.10" } }, + "node_modules/element-notifier": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/element-notifier/-/element-notifier-1.1.2.tgz", + "integrity": "sha512-GaXwkw/aZ4ZCsmzTDrlchtFmu3k3mruOUcC04Lk7YCQLMWsBPUONaIzczvW3QxxVkTpu8oq3r+muVuD+01b7fA==", + "license": "ISC" + }, "node_modules/enhanced-resolve": { "version": "5.18.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", @@ -1205,6 +1246,18 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/interestfor": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/interestfor/-/interestfor-1.0.8.tgz", + "integrity": "sha512-qYwTmxzDnrosGZX/1lDEOsAv73aYiFKLniN20SS78588WhRMHj8z7u2uFe9QZPIVmkCyIbJwiMQ/85Up7hrseQ==", + "license": "BSD-3-Clause" + }, + "node_modules/invokers-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/invokers-polyfill/-/invokers-polyfill-1.0.3.tgz", + "integrity": "sha512-T8zVavFQu5GlWlpkjghmaCaTx6Wk+9tWwJ2BC4oNsNAnar6AIrvSJQFZUcYDfrxzK9thBIyZvAkeLfdN9hTzGA==", + "license": "MIT" + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1611,6 +1664,15 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/qsa-observer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/qsa-observer/-/qsa-observer-3.0.2.tgz", + "integrity": "sha512-G1qqXYKG9RNpoFROJFGzYew1g76YDJsL5jyjePB8CdU6H9SFWO47WGLlqkuJKr5NKwVAzFl2fmTwqyK/EywxOw==", + "license": "ISC", + "dependencies": { + "element-notifier": "^1.1.2" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -1714,12 +1776,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/slide-element": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/slide-element/-/slide-element-2.3.1.tgz", - "integrity": "sha512-DBDX3fGmrL4lED9PGHv1254sHiQp5KsdeOJ+ohAdU1qOaolAHxYT9Wa5TjW1cw4Oh05Rq2fYpeIp1tFdQBg2Ug==", - "license": "ISC" - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -2307,14 +2363,32 @@ } } }, + "node_modules/webuum": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/webuum/-/webuum-0.2.1.tgz", + "integrity": "sha512-3XfdLSo3IJ/Tz/igRdV5cGLoNZNGLiN9A745ESWuKFW5RUHDd4l4LG5WYgXKeza0Xp7Zdj2ITeKosQLnXIYNpQ==", + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/winduum": { - "version": "2.2.0-next.5", - "resolved": "https://registry.npmjs.org/winduum/-/winduum-2.2.0-next.5.tgz", - "integrity": "sha512-5/qyRhwa9KQbmvKa/9UaDIoLRr/UozXP41LdyJkRAbnc4AyUvRJkN3YuBxxWCHN8j+IPtVDk1MT1qiIRvPPuqQ==", + "version": "3.0.0-next.7", + "resolved": "https://registry.npmjs.org/winduum/-/winduum-3.0.0-next.7.tgz", + "integrity": "sha512-CNuA0yf2XhV9ndSNr8rnkzC0V/tMqmdqInPyMnfvq33jf+C/AUqVS6FaAfum/cvEgnJvV3pud941LG66POasPg==", "engines": { "node": ">=20.0.0", "npm": ">=9.0.0" } + }, + "node_modules/winduum-elements": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/winduum-elements/-/winduum-elements-0.0.11.tgz", + "integrity": "sha512-dT2jt6ofwbbS6Hj6+2MhqPW/aS6Ioa4YwJvwvJkrxoWbbbUOLTcN5w8X+Xkv82qh/3jYbBzT8o8QURitjOUEHg==", + "dependencies": { + "@newlogic-digital/utils-js": "^1.2.0", + "webuum": "^0.2.1", + "winduum": "^3.0.0-next.7" + } } } } diff --git a/examples/package.json b/examples/package.json index 9012dd6..d23f9b4 100644 --- a/examples/package.json +++ b/examples/package.json @@ -3,11 +3,14 @@ "dependencies": { "@vituum/vite-plugin-liquid": "^1.1.0", "@tailwindcss/vite": "^4.0.0", + "@webreflection/custom-elements-builtin": "^0.4.1", + "interestfor": "^1.0.0", + "invokers-polyfill": "^1.0.3", "tailwindcss": "^4.0.0", - "winduum": "^2.2.0-next.5", + "winduum": "^3.0.0-next.7", + "winduum-elements": "^0.0.11", "vituum": "^1.1.1", "vite": "^6.0.11", - "slide-element": "^2.3.1", "@floating-ui/dom": "^1.6.13" } } diff --git a/examples/src/pages/components/carousel/basic.liquid b/examples/src/pages/components/carousel/basic.liquid index 509d2a7..27e8cae 100644 --- a/examples/src/pages/components/carousel/basic.liquid +++ b/examples/src/pages/components/carousel/basic.liquid @@ -1,12 +1,12 @@ {% layout "templates/layout.liquid" %} {% block %} - + {% endblock %} {% block head %} @@ -38,16 +38,14 @@ {% block foot %} {% endblock %} diff --git a/examples/src/pages/components/carousel/full.liquid b/examples/src/pages/components/carousel/full.liquid index 74798c1..15d5de8 100644 --- a/examples/src/pages/components/carousel/full.liquid +++ b/examples/src/pages/components/carousel/full.liquid @@ -1,45 +1,47 @@ {% layout "templates/layout.liquid" %} {% block %} -