{"_id":"fluid-tabs","_rev":"4-c9e9c420891942ba46754bc255b1f5f4","name":"fluid-tabs","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.0":{"name":"fluid-tabs","version":"0.1.0","keywords":["fluid-tabs","tabs","tab-bar","tabbed-interface","javascript","zero-dependency"],"author":{"name":"Ewan Howell","email":"ewanhowell5195"},"license":"MIT","_id":"fluid-tabs@0.1.0","maintainers":[{"name":"ewanhowell5195","email":"ewan@ewanhowell.com"}],"homepage":"https://github.com/ewanhowell5195/fluid-tabs#readme","bugs":{"url":"https://github.com/ewanhowell5195/fluid-tabs/issues"},"dist":{"shasum":"9bd1cccbcc324f9505f61a6482159ef91bb3d6ef","tarball":"https://registry.npmjs.org/fluid-tabs/-/fluid-tabs-0.1.0.tgz","fileCount":5,"integrity":"sha512-bOraTK3iBPEPQ9CP3O+AyEK/JfYiOhY7kVQj8vrZIcAutejJ9R9F0Esw3cseSqceBKpuDNIPGgJNKQaubwqCcQ==","signatures":[{"sig":"MEYCIQCBs9nzLkp7AuXGYVmZRS89rYz0qRvs0mBVqN4HznNaowIhAJBpWMJXiHWPQlBvmFDEXJHXLO53GV5XVnR3cavno5IH","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":20649},"main":"./dist/fluid-tabs.min.js","type":"module","style":"./dist/fluid-tabs.min.css","exports":{".":"./dist/fluid-tabs.min.js","./styles.css":"./dist/fluid-tabs.min.css"},"gitHead":"19534b9bb6bd16df79ef2ddd188469556623d51f","scripts":{"build":"node build.js"},"_npmUser":{"name":"ewanhowell5195","email":"ewan@ewanhowell.com"},"repository":{"url":"git+https://github.com/ewanhowell5195/fluid-tabs.git","type":"git"},"_npmVersion":"10.9.7","description":"A lightweight, zero-dependency tabs library with smooth animated indicators, swipe support, and multiple visual styles.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.43.1","clean-css":"^5.3.3"},"_npmOperationalInternal":{"tmp":"tmp/fluid-tabs_0.1.0_1781911401258_0.3297088554817367","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"fluid-tabs","version":"0.1.1","keywords":["fluid-tabs","tabs","tab-bar","tabbed-interface","javascript","zero-dependency"],"author":{"name":"Ewan Howell","email":"ewanhowell5195"},"license":"MIT","_id":"fluid-tabs@0.1.1","maintainers":[{"name":"ewanhowell5195","email":"ewan@ewanhowell.com"}],"homepage":"https://github.com/ewanhowell5195/fluid-tabs#readme","bugs":{"url":"https://github.com/ewanhowell5195/fluid-tabs/issues"},"dist":{"shasum":"fb39bddaf81ef21fcffe0a1db8c8b37e84d9da1d","tarball":"https://registry.npmjs.org/fluid-tabs/-/fluid-tabs-0.1.1.tgz","fileCount":5,"integrity":"sha512-6Sh3aifLk9VnqfdXQkB2ClkSldbLeX2wGTrh4NoL5SvpgNCmRJ+6Z1z4QmJf/jNBoSzFO58PF46bIAlp4zTU3w==","signatures":[{"sig":"MEUCIQCjfIFbiJ6EOH1ZnpQ2qmARlaeOSqQkY4GpcvfzbgShoQIgf/oziMGbG7dRWVNshCazRyrsrJeOw5MlHeo4PPemAKU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":21107},"main":"./dist/fluid-tabs.min.js","type":"module","style":"./dist/fluid-tabs.min.css","exports":{".":"./dist/fluid-tabs.min.js","./styles.css":"./dist/fluid-tabs.min.css"},"gitHead":"a294b5cd494515dfd1408e34d45bdaa02e854eb4","scripts":{"build":"node build.js"},"_npmUser":{"name":"ewanhowell5195","email":"ewan@ewanhowell.com"},"repository":{"url":"git+https://github.com/ewanhowell5195/fluid-tabs.git","type":"git"},"_npmVersion":"10.9.7","description":"A lightweight, zero-dependency tabs library with smooth animated indicators, swipe support, and multiple visual styles.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.43.1","clean-css":"^5.3.3"},"_npmOperationalInternal":{"tmp":"tmp/fluid-tabs_0.1.1_1781912920849_0.7471442068814367","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"fluid-tabs","version":"0.1.2","keywords":["fluid-tabs","tabs","tab-bar","tabbed-interface","javascript","zero-dependency"],"author":{"name":"Ewan Howell","email":"ewanhowell5195"},"license":"MIT","_id":"fluid-tabs@0.1.2","maintainers":[{"name":"ewanhowell5195","email":"ewan@ewanhowell.com"}],"homepage":"https://github.com/ewanhowell5195/fluid-tabs#readme","bugs":{"url":"https://github.com/ewanhowell5195/fluid-tabs/issues"},"dist":{"shasum":"5753443e8a2425e68d33f8a515d62d61358c9899","tarball":"https://registry.npmjs.org/fluid-tabs/-/fluid-tabs-0.1.2.tgz","fileCount":5,"integrity":"sha512-tKzG91B3xKHdrivURG0/RkBJmvEnSQk2p7Xr4gstHdF/Yric/ElMm0omGfRm7zW/m0ySy49WI/C59NVJLqVrvw==","signatures":[{"sig":"MEQCIFsyO1ori2pXsCHekDysDtoCIMpwNYiP/MSAq3vNWepJAiB7fL8UnnGfZTdBFCtsbXxd9NKQVcVdN4eCcWcuJlw8tw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":21196},"main":"./dist/fluid-tabs.min.js","type":"module","style":"./dist/fluid-tabs.min.css","exports":{".":"./dist/fluid-tabs.min.js","./styles.css":"./dist/fluid-tabs.min.css"},"gitHead":"f1afe6b1e806b5a7b1b0d5533b569bd7d1c2b834","scripts":{"build":"node build.js"},"_npmUser":{"name":"ewanhowell5195","email":"ewan@ewanhowell.com"},"repository":{"url":"git+https://github.com/ewanhowell5195/fluid-tabs.git","type":"git"},"_npmVersion":"10.9.7","description":"A lightweight, zero-dependency tabs library with smooth animated indicators, swipe support, and multiple visual styles.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.43.1","clean-css":"^5.3.3"},"_npmOperationalInternal":{"tmp":"tmp/fluid-tabs_0.1.2_1781995369670_0.27954784890161544","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"fluid-tabs","version":"0.1.3","description":"A lightweight, zero-dependency tabs library with smooth animated indicators, swipe support, and multiple visual styles.","author":{"name":"Ewan Howell","email":"ewanhowell5195"},"license":"MIT","type":"module","main":"./dist/fluid-tabs.min.js","style":"./dist/fluid-tabs.min.css","exports":{".":"./dist/fluid-tabs.min.js","./styles.css":"./dist/fluid-tabs.min.css"},"repository":{"type":"git","url":"git+https://github.com/ewanhowell5195/fluid-tabs.git"},"bugs":{"url":"https://github.com/ewanhowell5195/fluid-tabs/issues"},"homepage":"https://github.com/ewanhowell5195/fluid-tabs#readme","scripts":{"build":"node build.js"},"devDependencies":{"clean-css":"^5.3.3","terser":"^5.43.1"},"keywords":["fluid-tabs","tabs","tab-bar","tabbed-interface","javascript","zero-dependency"],"_id":"fluid-tabs@0.1.3","gitHead":"795e49a156892168ec68113373f353e5f468d478","_nodeVersion":"22.22.2","_npmVersion":"10.9.7","dist":{"integrity":"sha512-9HA638XGpKLMNcasZJpULnHt8FnkyFQmDyott7N2H8agi2YVP8JeiHqJ1kSW+PEBoVb12by8MoVHAR70wAu8Bw==","shasum":"7acb502effcfa151aebb5b324dc82fe380c9e4ba","tarball":"https://registry.npmjs.org/fluid-tabs/-/fluid-tabs-0.1.3.tgz","fileCount":5,"unpackedSize":21357,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIB02BNb0A+yLn9Zf8OngwRUn6lUIR86SgHuETafAFAVkAiEA2YtnGpzBWfQnucV4PAILF6oCr0r2FoPdMOb27x/LWCY="}]},"_npmUser":{"name":"ewanhowell5195","email":"ewan@ewanhowell.com"},"directories":{},"maintainers":[{"name":"ewanhowell5195","email":"ewan@ewanhowell.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/fluid-tabs_0.1.3_1787575017523_0.24642906128829867"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-19T23:23:21.216Z","modified":"2026-08-24T12:36:58.134Z","0.1.0":"2026-06-19T23:23:21.392Z","0.1.1":"2026-06-19T23:48:40.991Z","0.1.2":"2026-06-20T22:42:49.792Z","0.1.3":"2026-08-24T12:36:57.985Z"},"bugs":{"url":"https://github.com/ewanhowell5195/fluid-tabs/issues"},"author":{"name":"Ewan Howell","email":"ewanhowell5195"},"license":"MIT","homepage":"https://github.com/ewanhowell5195/fluid-tabs#readme","keywords":["fluid-tabs","tabs","tab-bar","tabbed-interface","javascript","zero-dependency"],"repository":{"type":"git","url":"git+https://github.com/ewanhowell5195/fluid-tabs.git"},"description":"A lightweight, zero-dependency tabs library with smooth animated indicators, swipe support, and multiple visual styles.","maintainers":[{"name":"ewanhowell5195","email":"ewan@ewanhowell.com"}],"readme":"# fluid-tabs\n\nA lightweight, zero-dependency tabs library with a smooth animated indicator, drag/wheel/swipe scrolling, and multiple visual styles.\n\n[![npm version](https://badge.fury.io/js/fluid-tabs.svg)](https://www.npmjs.com/package/fluid-tabs)\n[![jsDelivr](https://data.jsdelivr.com/v1/package/npm/fluid-tabs/badge)](https://www.jsdelivr.com/package/npm/fluid-tabs)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## Features\n\n* No dependencies\n* Three visual styles out of the box: underline, classic tabs, and a sliding segmented control\n* Animated indicator that slides between tabs with an elastic stretch, and a spring \"tease\" on hover\n* Animated content panel that cross-fades and resizes between tabs\n* Too many tabs? They scroll horizontally (drag, wheel, or swipe) with momentum and edge fades. Opt into wrapping instead.\n* Swipe left/right on the content to change tabs on touch\n* Interruptible: click another tab mid-animation and the indicator redirects, no waiting\n* Detached tabs: the bar and its panels don't have to be siblings\n* Fires a `tab-changed` event, and works with plain `.click()`\n* Themeable with a handful of CSS variables\n\n## Quick Start\n\n### Install via npm\n```bash\nnpm install fluid-tabs\n```\n\n```js\nimport \"fluid-tabs/styles.css\"\nimport \"fluid-tabs\"\n```\n\n### Or use via CDN\nhttps://www.jsdelivr.com/package/npm/fluid-tabs\n\n### Add tabs to your HTML\n\n```html\n<div class=\"tab-bar\">\n  <button class=\"tab-bar-button active\" data-tab=\"overview\">Overview</button>\n  <button class=\"tab-bar-button\" data-tab=\"details\">Details</button>\n  <button class=\"tab-bar-button\" data-tab=\"reviews\">Reviews</button>\n</div>\n<div class=\"tab-contents\">\n  <div class=\"tab-content active\" data-tab=\"overview\">Overview content</div>\n  <div class=\"tab-content\" data-tab=\"details\">Details content</div>\n  <div class=\"tab-content\" data-tab=\"reviews\">Reviews content</div>\n</div>\n```\n\nEvery `.tab-bar` on the page is initialised automatically on load - no setup or config required.\n\n* A `.tab-bar` holds the `.tab-bar-button`s.\n* The matching `.tab-contents` holds the `.tab-content` panels.\n* Buttons and panels are paired by `data-tab` - clicking a button shows the panel with the same value.\n* Mark the starting button and panel with `active`.\n\nThe content panel is optional. A `.tab-bar` on its own still animates the indicator and fires `tab-changed` - useful as a filter/segmented control.\n\n## Styles\n\nSet a `tab-style-*` class on both the `.tab-bar` and its matching `.tab-contents`. If you forget it on the panel, the library copies the bar's style onto it as a fallback.\n\n| Class | Style |\n|---|---|\n| *(none)* / `tab-style-buttons` | **Underline** - text tabs with a sliding underline. The default. |\n| `tab-style-tabs` | **Classic tabs** - filled tabs joined to a bordered content panel. |\n| `tab-style-slide` | **Slide** - a pill-shaped segmented control with a sliding knob. |\n\n```html\n<div class=\"tab-bar tab-style-slide\"> … </div>\n<div class=\"tab-contents tab-style-slide\"> … </div>\n```\n\n## Linking the content\n\nThere are three ways a bar finds its panels.\n\n### Adjacent (default)\n\nPut the `.tab-contents` immediately after the `.tab-bar`:\n\n```html\n<div class=\"tab-bar\"> … </div>\n<div class=\"tab-contents\"> … </div>\n```\n\n### Detached\n\nIf the bar and panels can't be siblings, give the bar an `id` and point the contents at it with `data-tab-bar`:\n\n```html\n<div class=\"tab-bar\" id=\"account\"> … </div>\n\n<p>…anything in between…</p>\n\n<div class=\"tab-contents\" data-tab-bar=\"account\"> … </div>\n```\n\n### Standalone\n\nA `.tab-bar` with no matching `.tab-contents` just tracks the active button and fires `tab-changed`.\n\n## Options\n\nBehavioural options are set as data attributes on the `.tab-bar`. Presence is enough - the value is ignored.\n\n| Attribute | Description |\n|---|---|\n| `data-tab-wrap` | Wrap to multiple rows instead of scrolling when the tabs don't fit. |\n| `data-tab-no-swipe` | Disable swipe-to-change on the content panel. |\n\n```html\n<div class=\"tab-bar\" data-tab-wrap> … </div>\n```\n\n## Scrolling &amp; wrapping\n\nWhen there are more tabs than fit, the bar **scrolls** horizontally by default. You can:\n\n* **Drag** it with the mouse or finger (with flick momentum)\n* **Wheel** over it\n* **Swipe** the content panel to step between tabs\n\nA soft fade appears on whichever edge has hidden tabs, and selecting a tab scrolls it into view. Wheel scrolling only kicks in when a gesture *starts* over the bar, so scrolling the page past it isn't hijacked.\n\nAdd `data-tab-wrap` to wrap onto multiple rows instead of scrolling.\n\n## Events\n\nThe bar dispatches a `tab-changed` event when the active tab changes. `event.detail` is the new tab's `data-tab`:\n\n```js\ndocument.querySelector(\".tab-bar\").addEventListener(\"tab-changed\", e => {\n  console.log(\"switched to\", e.detail)\n})\n```\n\n## Programmatic control\n\nSwitch tabs by clicking a button - the library listens for normal clicks:\n\n```js\nconst bar = document.querySelector(\".tab-bar\")\nbar.querySelector('.tab-bar-button[data-tab=\"reviews\"]').click()\n```\n\nEach initialised bar also exposes an `update()` method that re-snaps the indicator and edge fades. It's called automatically on resize; call it yourself if you change the layout in a way a `ResizeObserver` won't catch:\n\n```js\nbar.update()\n```\n\n### Initialising dynamically-added tabs\n\nEvery `.tab-bar` present on load is initialised automatically. If you add tab bars later, call `FluidTabs.init()` to pick up any that aren't initialised yet. It's idempotent - already-initialised bars are skipped. Pass a root element to limit the scan:\n\n```js\nFluidTabs.init()           // scan the whole document\nFluidTabs.init(sectionEl)  // scan within an element\n```\n\n## Theming\n\nThe library ships the structural and default styling it needs. Tweak the look with these CSS variables (shown with their defaults):\n\n| Variable | Default | Description |\n|---|---|---|\n| `--tab-transition-duration` | `.25s` | Duration of every transition (indicator, panel, height). |\n| `--tab-transition-easing` | `cubic-bezier(.4, 0, .2, 1)` | Easing for every transition. |\n| `--tab-slide-lag` | `.333` | Trailing-edge lag of the indicator slide, as a fraction of the duration. `0` removes the elastic stretch. |\n| `--tab-tease-x` | `10px` | How far the indicator stretches toward a hovered tab. |\n| `--tab-fade` | `60px` | Width of the scroll edge fade. |\n\n```css\n.tab-bar {\n  --tab-transition-duration: .2s;\n  --tab-fade: 40px;\n}\n```\n\nColours, radii, and spacing are plain values in the stylesheet - override the `.tab-bar`, `.tab-bar-button`, `.tab-contents`, and `.tab-content` rules to restyle.\n\n### Classes\n\nThese are added by the library and can be targeted with CSS:\n\n| Class | When applied |\n|---|---|\n| `initialised` | On each `.tab-bar` once set up. |\n| `active` | On the current `.tab-bar-button` and its `.tab-content`. |\n| `tab-bar-active` | The indicator element, appended inside each `.tab-bar`. |\n| `tab-bar-wrap` | When `data-tab-wrap` is set. |\n| `tab-bar-dragging` | While the bar is being drag-scrolled. |\n| `tab-bar-fade-start` / `tab-bar-fade-end` | When there are hidden tabs off the start / end edge. |\n| `transitioning` | On `.tab-contents` while a panel change is animating. |\n\n## License\n\nMIT © [Ewan Howell](https://ewanhowell.com/)\n","readmeFilename":"README.md"}