From 0e24b7ad84a17f1fff47a1e86c3d1af1e5ff9070 Mon Sep 17 00:00:00 2001 From: Bartosz Cylwik Date: Wed, 26 Apr 2023 15:54:39 +0200 Subject: [PATCH 1/4] add scrollbar component --- demo/sites/methods/scrollbar.html | 275 +++++++++++++++++++++ index.html | 357 ++++++++++++++-------------- src/js/index.es.js | 2 + src/js/index.umd.js | 3 + src/js/methods/perfect-scrollbar.js | 273 +++++++++++++++++++++ 5 files changed, 734 insertions(+), 176 deletions(-) create mode 100644 demo/sites/methods/scrollbar.html create mode 100644 src/js/methods/perfect-scrollbar.js diff --git a/demo/sites/methods/scrollbar.html b/demo/sites/methods/scrollbar.html new file mode 100644 index 000000000..d17f95dff --- /dev/null +++ b/demo/sites/methods/scrollbar.html @@ -0,0 +1,275 @@ + + + + + + + + Scrollbar + + + + + + + + + + + + + + + + +
+
+
+
+ +

Basic example

+
+ Wild Landscape +
+ +
+
+
+ +

Options

+ +

JavaScript init

+
+ Wild Landscape +
+ +
+
+
+ +

Data attributes

+
+ ... +
+ +
+
+
+ +

Colors example

+
+ ... +
+ +
+
+
+ +

Events

+ +
+ +
+ +
+ Wild Landscape +
+ +
+
+
+ + + + + + +
+ + + + + + + + + + + + diff --git a/index.html b/index.html index bb780e0a7..fe60b852b 100644 --- a/index.html +++ b/index.html @@ -51,885 +51,890 @@

Your sites:

Animations Buttons Colors Cards Badges Button Group Alerts List Group Tables Accordion Carousel Chips Dropdown Gallery Headings Headers Images Modal Paragraphs Popover Progress Toast Tooltip Breadcrumbs Footer Pills Tabs Spinners Navbar Inputs File input Checkbox Radio Switch Form templates Search Range Select Textarea Input group Offcanvas Rating Icons Typography Collapse Notification Link Mask Avatar Ripple Datepicker Timepicker Stepper Timeline Sidenav Hover effects Video carousel Scrollspy Social buttons Video Jumbotron Scroll button Login form Register form Placeholder Dividers Figures Shadows Images Masks Pagination Charts + Scrollbar
Intro 1 Intro 2 Intro 3 Pricing 1 Pricing 2 Pricing 3 Newsletter 1 Newsletter 2 Newsletter 3 Stats 1 Stats 2 Stats 3 Headers 1 Headers 2 Headers 3 News 1 News 2 News 3 Features 1 Features 2 Features 3 Contact 1 Contact 2 Contact 3 Contact 4 Contact 5 Contact 6 Contact 7 Contact 8 Faq 1 Faq 2 Faq 3 Faq 4 Faq 5 cta 1 cta 2 cta 3 Team 1 Team 2 Team 3 Logo clouds 1 Logo clouds 2 Logo clouds 3 Testimonials 0 Testimonials 1 Testimonials 2 Testimonials 3 Content 1 Content 2 Content 3 Banners 1 Banners 2 Banners 3 Mega menu 1 Mega menu 2 Mega menu 3 Mega menu 4 Mega menu 5 Mega menu 6 Projects 1 Projects 2 Projects 3 Admin navigation 1 Admin navigation 2 Admin navigation 3 Admin forms 1 Admin forms 2 Admin forms 3 Admin stats 1 Admin stats 2 Admin stats 3 Admin tables 1 Admin tables 2 Admin tables 3 Admin charts 1 Admin charts 2 Admin charts 3 Admin maps 1 Admin maps 2 Admin maps 3 Admin complex 1 Admin complex 2 Admin complex 3 Hero 1 Hero 2 Hero 3 Hero 4 Hero 5 Hero 6 Hero 7 Hero 8 Hero 9 Hero 10 Hero 11 Hero 12 content 1 content 2 content 3 content 4 content 5 content 6 content 7 content 8 content 9
diff --git a/src/js/index.es.js b/src/js/index.es.js index 8b860cfb3..206d4aab1 100644 --- a/src/js/index.es.js +++ b/src/js/index.es.js @@ -32,6 +32,7 @@ import Select from "./forms/select"; import ChipsInput from "./components/chips"; import Chip from "./components/chips/chip"; import Chart from "./data/chart/charts"; +import PerfectScrollbar from "./methods/perfect-scrollbar"; import initTE from "./autoinit/index"; export { @@ -58,5 +59,6 @@ export { Stepper, Input, Chart, + PerfectScrollbar, initTE, }; diff --git a/src/js/index.umd.js b/src/js/index.umd.js index f86b948fb..f40dd29b4 100644 --- a/src/js/index.umd.js +++ b/src/js/index.umd.js @@ -32,6 +32,7 @@ import Select from "./forms/select"; import ChipsInput from "./components/chips"; import Chip from "./components/chips/chip"; import Chart from "./data/chart/charts"; +import PerfectScrollbar from "./methods/perfect-scrollbar"; import initTE from "./autoinit/index"; const te = { @@ -57,6 +58,7 @@ const te = { Sidenav, Stepper, Input, + PerfectScrollbar, Chart, }; @@ -86,5 +88,6 @@ export { Stepper, Input, Chart, + PerfectScrollbar, initTE, }; diff --git a/src/js/methods/perfect-scrollbar.js b/src/js/methods/perfect-scrollbar.js new file mode 100644 index 000000000..da24e59d6 --- /dev/null +++ b/src/js/methods/perfect-scrollbar.js @@ -0,0 +1,273 @@ +/* eslint-disable no-restricted-globals */ +import PerfectScrollbar from "perfect-scrollbar"; + +import { getjQuery, typeCheckConfig, onDOMContentLoaded } from "../util/index"; +import Data from "../dom/data"; +import Manipulator from "../dom/manipulator"; +import EventHandler from "../dom/event-handler"; +import SelectorEngine from "../dom/selector-engine"; + +const NAME = "perfectScrollbar"; +const CLASSNAME_PS = "perfect-scrollbar"; +const DATA_KEY = "te.perfectScrollbar"; +const TE_NAME = "te"; +const PS_NAME = "ps"; + +const EVENTS = [ + { te: `scrollX.${TE_NAME}.${PS_NAME}`, ps: "ps-scroll-x" }, + { te: `scrollY.${TE_NAME}.${PS_NAME}`, ps: "ps-scroll-y" }, + { te: `scrollUp.${TE_NAME}.${PS_NAME}`, ps: "ps-scroll-up" }, + { te: `scrollDown.${TE_NAME}.${PS_NAME}`, ps: "ps-scroll-down" }, + { te: `scrollLeft.${TE_NAME}.${PS_NAME}`, ps: "ps-scroll-left" }, + { te: `scrollRight.${TE_NAME}.${PS_NAME}`, ps: "ps-scroll-right" }, + { te: `scrollXEnd.${TE_NAME}.${PS_NAME}`, ps: "ps-x-reach-end" }, + { te: `scrollYEnd.${TE_NAME}.${PS_NAME}`, ps: "ps-y-reach-end" }, + { te: `scrollXStart.${TE_NAME}.${PS_NAME}`, ps: "ps-x-reach-start" }, + { te: `scrollYStart.${TE_NAME}.${PS_NAME}`, ps: "ps-y-reach-start" }, +]; + +const PERFECT_SCROLLBAR_INIT = "data-te-perfect-scrollbar-init"; + +const Default = { + handlers: ["click-rail", "drag-thumb", "keyboard", "wheel", "touch"], + wheelSpeed: 1, + wheelPropagation: true, + swipeEasing: true, + minScrollbarLength: null, + maxScrollbarLength: null, + scrollingThreshold: 1000, + useBothWheelAxes: false, + suppressScrollX: false, + suppressScrollY: false, + scrollXMarginOffset: 0, + scrollYMarginOffset: 0, +}; + +const DefaultType = { + handlers: "(string|array)", + wheelSpeed: "number", + wheelPropagation: "boolean", + swipeEasing: "boolean", + minScrollbarLength: "(number|null)", + maxScrollbarLength: "(number|null)", + scrollingThreshold: "number", + useBothWheelAxes: "boolean", + suppressScrollX: "boolean", + suppressScrollY: "boolean", + scrollXMarginOffset: "number", + scrollYMarginOffset: "number", +}; + +const DefaultClasses = { + ps: "group/ps overflow-hidden [overflow-anchor:none] touch-none", + railX: + "group/x absolute bottom-0 h-[0.9375rem] hidden opacity-0 transition-[background-color,_opacity] duration-200 ease-linear motion-reduce:transition-none z-[1035] group-[&.ps--active-x]/ps:block group-[&.ps--active-x]/ps:bg-transparent group-hover/ps:opacity-60 group-focus/ps:opacity-60 group-[&.ps--scrolling-x]/ps:opacity-60 hover:!opacity-90 hover:!bg-[#eee] focus:!opacity-90 focus:!bg-[#eee] [&.ps--clicking]:!opacity-90 [&.ps--clicking]:!bg-[#eee] outline-none", + railXThumb: + "absolute bottom-0.5 rounded-md h-1.5 opacity-0 group-hover/ps:opacity-100 group-focus/ps:opacity-100 group-active/ps:opacity-100 bg-[#aaa] [transition:background-color_.2s_linear,_height_.2s_ease-in-out] group-hover/x:bg-[#999] group-hover/x:h-[11px] group-focus/x:bg-[#999] group-focus/x:h-[0.6875rem] group-[&.ps--clicking]/x:bg-[#999] group-[&.ps--clicking]/x:h-[11px] outline-none", + railY: + "group/y absolute right-0 w-[0.9375rem] hidden opacity-0 transition-[background-color,_opacity] duration-200 ease-linear motion-reduce:transition-none z-[1035] group-[&.ps--active-y]/ps:block group-[&.ps--active-y]/ps:bg-transparent group-hover/ps:opacity-60 group-focus/ps:opacity-60 group-[&.ps--scrolling-y]/ps:opacity-60 hover:!opacity-90 hover:!bg-[#eee] focus:!opacity-90 focus:!bg-[#eee] [&.ps--clicking]:!opacity-90 [&.ps--clicking]:!bg-[#eee] outline-none", + railYThumb: + "absolute right-0.5 rounded-md w-1.5 opacity-0 group-hover/ps:opacity-100 group-focus/ps:opacity-100 group-active/ps:opacity-100 bg-[#aaa] [transition:background-color_.2s_linear,_width_.2s_ease-in-out] group-hover/y:bg-[#999] group-hover/y:w-[11px] group-focus/y:bg-[#999] group-focus/y:w-[0.6875rem] group-[&.ps--clicking]/y:bg-[#999] group-[&.ps--clicking]/y:w-[11px] outline-none", +}; + +const DefaultClassesType = { + ps: "string", + railX: "string", + railXThumb: "string", + railY: "string", + railYThumb: "string", +}; + +class PerfectScrollbars { + constructor(element, options = {}, classes = {}) { + this._element = element; + this._options = this._getConfig(options); + this._classes = this._getClasses(classes); + this.perfectScrollbar = null; + + if (this._element) { + Data.setData(element, DATA_KEY, this); + Manipulator.addClass(this._element, CLASSNAME_PS); + } + + this.init(); + } + + // Getters + static get NAME() { + return NAME; + } + + _getConfig(config) { + const dataAttributes = Manipulator.getDataAttributes(this._element); + + if (dataAttributes.handlers !== undefined) { + dataAttributes.handlers = dataAttributes.handlers.split(" "); + } + + config = { + ...Default, + ...dataAttributes, + ...config, + }; + + typeCheckConfig(NAME, config, DefaultType); + return config; + } + + _getClasses(classes) { + const dataAttributes = Manipulator.getDataClassAttributes(this._element); + + classes = { + ...DefaultClasses, + ...dataAttributes, + ...classes, + }; + + typeCheckConfig(NAME, classes, DefaultClassesType); + + return classes; + } + + // Public + dispose() { + Data.removeData(this._element, DATA_KEY); + this._element = null; + this._dataAttrOptions = null; + this._options = null; + this.perfectScrollbar.destroy(); + this.removeEvent(EVENTS); + this.perfectScrollbar = null; + } + + init() { + this.perfectScrollbar = new PerfectScrollbar(this._element, this._options); + this._addPerfectScrollbarStyles(); + this.perfectScrollbar.update(); + this._initEvents(EVENTS); + } + + update() { + return this.perfectScrollbar.update(); + } + + _initEvents(events = []) { + events.forEach(({ ps, te }) => + EventHandler.on(this._element, ps, (e) => + EventHandler.trigger(this._element, te, { e }) + ) + ); + } + + _addPerfectScrollbarStyles() { + const classes = [ + { ps: "ps__rail-x", te: this._classes.railX }, + { ps: "ps__rail-y", te: this._classes.railY }, + { ps: "ps__thumb-x", te: this._classes.railXThumb }, + { ps: "ps__thumb-y", te: this._classes.railYThumb }, + ]; + + classes.forEach((item) => { + const container = SelectorEngine.findOne(`.${item.ps}`, this._element); + Manipulator.addClass(container, item.te); + if (item.ps.includes("rail-x")) { + console.log(); + container.style.transform = `translateY(calc(-100% + ${getComputedStyle( + this._element + ).getPropertyValue("height")}))`; + } + if (item.ps.includes("rail-y")) { + container.style.transform = `translateX(calc(-100% + ${getComputedStyle( + this._element + ).getPropertyValue("width")}))`; + } + + Manipulator.removeClass( + SelectorEngine.findOne(`.${item.ps}`, this._element), + item.ps + ); + }); + Manipulator.addClass(this._element, this._classes.ps); + Manipulator.removeClass(this._element, "ps"); + } + + removeEvent(event) { + let filter = []; + + if (typeof event === "string") { + filter = EVENTS.filter(({ te }) => te === event); + } + + filter.forEach(({ ps, te }) => { + EventHandler.off(this._element, ps); + EventHandler.off(this._element, te); + }); + } + + // Static + + static jQueryInterface(config) { + return this.each(function () { + let data = Data.getData(this, DATA_KEY); + const _config = typeof config === "object" && config; + + if (!data && /dispose|hide/.test(config)) { + return; + } + + if (!data) { + data = new PerfectScrollbars(this, _config); + } + + if (typeof config === "string") { + if (typeof data[config] === "undefined") { + throw new TypeError(`No method named "${config}"`); + } + + data[config](); + } + }); + } + + static getInstance(element) { + return Data.getData(element, DATA_KEY); + } + + static getOrCreateInstance(element, config = {}) { + return ( + this.getInstance(element) || + new this(element, typeof config === "object" ? config : null) + ); + } +} + +SelectorEngine.find(`[${PERFECT_SCROLLBAR_INIT}]`).forEach((scroll) => { + let instance = PerfectScrollbars.getInstance(scroll); + if (!instance) { + instance = new PerfectScrollbars(scroll); + } + return instance; +}); + +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + * add .perfectScrollbar to jQuery only if jQuery is present + */ + +onDOMContentLoaded(() => { + const $ = getjQuery(); + + if ($) { + const JQUERY_NO_CONFLICT = $.fn[NAME]; + $.fn[NAME] = PerfectScrollbars.jQueryInterface; + $.fn[NAME].Constructor = PerfectScrollbars; + $.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT; + return PerfectScrollbars.jQueryInterface; + }; + } +}); + +export default PerfectScrollbars; From c8b3b2b678e5389ab60a2565a96534e5169f9990 Mon Sep 17 00:00:00 2001 From: Bartosz Cylwik Date: Wed, 28 Jun 2023 15:02:13 +0200 Subject: [PATCH 2/4] Update scrollbar code + add documentation --- demo/sites/methods/scrollbar.html | 16 +- .../docs/standard/methods/scrollbar/a-ss.html | 21 + .../docs/standard/methods/scrollbar/a.html | 882 ++++++++++++++++++ .../standard/methods/scrollbar/index-js.html | 60 ++ .../standard/methods/scrollbar/index-ss.html | 20 + .../standard/methods/scrollbar/index.html | 765 +++++++++++++++ site/static/search.json | 9 + src/js/methods/perfect-scrollbar.js | 68 +- 8 files changed, 1822 insertions(+), 19 deletions(-) create mode 100644 site/content/docs/standard/methods/scrollbar/a-ss.html create mode 100644 site/content/docs/standard/methods/scrollbar/a.html create mode 100644 site/content/docs/standard/methods/scrollbar/index-js.html create mode 100644 site/content/docs/standard/methods/scrollbar/index-ss.html create mode 100644 site/content/docs/standard/methods/scrollbar/index.html diff --git a/demo/sites/methods/scrollbar.html b/demo/sites/methods/scrollbar.html index d17f95dff..1b8b6a23e 100644 --- a/demo/sites/methods/scrollbar.html +++ b/demo/sites/methods/scrollbar.html @@ -224,14 +224,14 @@ scrollColors, {}, { - railX: - "group/x absolute bottom-0 h-[0.9375rem] hidden opacity-0 transition-[background-color,_opacity] duration-200 ease-linear motion-reduce:transition-none z-[1035] group-[&.ps--active-x]/ps:block group-[&.ps--active-x]/ps:!bg-[#90ee90] group-hover/ps:opacity-60 group-focus/ps:opacity-60 group-[&.ps--scrolling-x]/ps:opacity-60 hover:!opacity-90 hover:!bg-[#eee] focus:!opacity-90 focus:!bg-[#eee] [&.ps--clicking]:!opacity-90 [&.ps--clicking]:!bg-[#eee] outline-none", - railXThumb: - "absolute bottom-0.5 rounded-md h-1.5 opacity-0 group-hover/ps:opacity-100 group-focus/ps:opacity-100 group-active/ps:opacity-100 !bg-[#006400] [transition:background-color_.2s_linear,_height_.2s_ease-in-out] group-hover/x:bg-[#999] group-hover/x:h-[11px] group-focus/x:bg-[#999] group-focus/x:h-[0.6875rem] group-[&.ps--clicking]/x:bg-[#999] group-[&.ps--clicking]/x:h-[11px] outline-none", - railY: - "group/y absolute right-0 w-[0.9375rem] hidden opacity-0 transition-[background-color,_opacity] duration-200 ease-linear motion-reduce:transition-none z-[1035] group-[&.ps--active-y]/ps:block group-[&.ps--active-y]/ps:!bg-[#90ee90] group-hover/ps:opacity-60 group-focus/ps:opacity-60 group-[&.ps--scrolling-y]/ps:opacity-60 hover:!opacity-90 hover:!bg-[#eee] focus:!opacity-90 focus:!bg-[#eee] [&.ps--clicking]:!opacity-90 [&.ps--clicking]:!bg-[#eee] outline-none", - railYThumb: - "absolute right-0.5 rounded-md w-1.5 opacity-0 group-hover/ps:opacity-100 group-focus/ps:opacity-100 group-active/ps:opacity-100 !bg-[#006400] [transition:background-color_.2s_linear,_width_.2s_ease-in-out] group-hover/y:bg-[#999] group-hover/y:w-[11px] group-focus/y:bg-[#999] group-focus/y:w-[0.6875rem] group-[&.ps--clicking]/y:bg-[#999] group-[&.ps--clicking]/y:w-[11px] outline-none", + railXColors: + "group-[&.ps--active-x]/ps:!bg-[#90ee90] hover:!bg-[#eee] focus:!bg-[#eee] [&.ps--clicking]:!bg-[#eee]", + railXThumbColors: + "!bg-[#006400] group-hover/x:bg-[#999] group-focus/x:bg-[#999] group-[&.ps--clicking]/x:bg-[#999]", + railYColors: + "group-[&.ps--active-y]/ps:!bg-[#90ee90] hover:!bg-[#eee] focus:!bg-[#eee] [&.ps--clicking]:!bg-[#eee]", + railYThumbColors: + "!bg-[#006400] group-hover/y:bg-[#999] group-focus/y:bg-[#999] group-[&.ps--clicking]/y:bg-[#999]", } ); diff --git a/site/content/docs/standard/methods/scrollbar/a-ss.html b/site/content/docs/standard/methods/scrollbar/a-ss.html new file mode 100644 index 000000000..f5cddf86e --- /dev/null +++ b/site/content/docs/standard/methods/scrollbar/a-ss.html @@ -0,0 +1,21 @@ +--- +--- + +
  • + Import +
  • +
  • + Usage +
  • +
  • + Options +
  • +
  • + Classes +
  • +
  • + Methods +
  • +
  • + Events +
  • diff --git a/site/content/docs/standard/methods/scrollbar/a.html b/site/content/docs/standard/methods/scrollbar/a.html new file mode 100644 index 000000000..9e0a1494b --- /dev/null +++ b/site/content/docs/standard/methods/scrollbar/a.html @@ -0,0 +1,882 @@ +--- +--- + + +
    + +
    + +

    + Import +

    + +

    + Importing components depends on how your application works. If you intend + to use the Tailwind Elements ES format, you must first import + the component and then initialize it with the initTE method. + If you are going to use the UMD format, just import the + tw-elements package. +

    + + + {{< twsnippet/no-demo id="api-example41" >}} + + +
    + + +
    + + +
    + +

    + Usage +

    + +

    Via data attributes

    + +

    + Add the data-te-perfect-scrollbar-init attribute to the + clickable element to apply the ripple effect. For ES format, you must + first import and call the initTE method. +

    + + + {{< twsnippet/no-demo id="api-example1" >}} + + + +

    Via JavaScript

    + + + {{< twsnippet/no-demo id="api-example2" >}} + + + +
    + +
    + + +
    + +

    + Options +

    + +

    + Options can be passed via data attributes or JavaScript. For data + attributes, append the option name to data-te-, as in + data-te-wheel-speed="2". +

    + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Name + + Type + + Default + Description
    + handlers + + String[] + + ['click-rail', 'drag-thumb', 'keyboard', 'wheel', + 'touch'] + + It is a list of handlers to scroll the element. +
    + wheelSpeed + + Number + + 1 + + The scroll speed applied to mousewheel event. +
    + wheelPropagation + + Boolean + + true + + If this option is true, when the scroll reaches the end of + the side, mousewheel event will be propagated to parent + element. +
    + swipeEasing + + Boolean + + true + + If this option is true, swipe scrolling will be eased. +
    + minScrollbarLength + + Number | null + + null + + When set to an integer value, the thumb part of the + scrollbar will not shrink below that number of pixels. +
    + maxScrollbarLength + + Number | null + + null + + When set to an integer value, the thumb part of the + scrollbar will not expand over that number of pixels. +
    + scrollingThreshold + + Number + + 1000 + + This sets threshold for ps--scrolling-x and ps--scrolling-y + classes to remain. In the default CSS, they make scrollbars + shown regardless of hover state. The unit is millisecond. +
    + suppressScrollX + + Boolean + + false + + When set to true, the scrollbar in X-axis will not be + available, regardless of the content width. +
    + suppressScrollY + + Boolean + + false + + When set to true, the scroll bar in Y-axis will not be + available, regardless of the content height. +
    + scrollXMarginOffset + + Number + + 0 + + The number of pixels the content width can surpass the + container width without enabling the X-axis scroll bar. + Allows some "wiggle room" or "offset break", so that X-axis + scroll bar is not enabled just because of a few pixels. +
    + scrollYMarginOffset + + Number + + 0 + + The number of pixels the content width can surpass the + container width without enabling the Y-axis scroll bar. + Allows some "wiggle room" or "offset break", so that Y-axis + scroll bar is not enabled just because of a few pixels. +
    +
    +
    +
    +
    +
    + + +
    + + +
    + +

    + Classes +

    + +

    + Custom classes can be passed via data attributes or JavaScript. For data + attributes, append the class name to + data-te-class, as in data-te-class-ps="". +

    + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Name + + Default + Description
    + ps + + group/ps overflow-hidden [overflow-anchor:none] touch-none + + Sets styles for perfect scrollbar wrapper. +
    + railX + + group/x absolute bottom-0 h-[0.9375rem] hidden opacity-0 + transition-[background-color,_opacity] duration-200 + ease-linear motion-reduce:transition-none z-[1035] + group-[&.ps--active-x]/ps:block group-hover/ps:opacity-60 + group-focus/ps:opacity-60 + group-[&.ps--scrolling-x]/ps:opacity-60 hover:!opacity-90 + focus:!opacity-90 [&.ps--clicking]:!opacity-90 outline-none + + Adds styles for horizontal scrollbar rail. +
    + railXColors + + group-[&.ps--active-x]/ps:bg-transparent hover:!bg-[#eee] + focus:!bg-[#eee] [&.ps--clicking]:!bg-[#eee] + dark:hover:!bg-[#555] dark:focus:!bg-[#555] + dark:[&.ps--clicking]:!bg-[#555] + + Adds styles for horizontal scrollbar rail. Decides the color + of the x rail. +
    + railXThumb + + absolute bottom-0.5 rounded-md h-1.5 + group-focus/ps:opacity-100 group-active/ps:opacity-100 + [transition:background-color_.2s_linear,_height_.2s_ease-in-out] + group-hover/x:h-[11px] group-focus/x:h-[0.6875rem] + group-[&.ps--clicking]/x:bg-[#999] + group-[&.ps--clicking]/x:h-[11px] outline-none + + Adds styles for horizontal scrollbar thumb. +
    + railXThumbColors + + bg-[#aaa] group-hover/x:bg-[#999] group-focus/x:bg-[#999] + + Adds styles for horizontal scrollbar thumb. Decides the + color of the x thumb. +
    + railY + + group/y absolute right-0 w-[0.9375rem] hidden opacity-0 + transition-[background-color,_opacity] duration-200 + ease-linear motion-reduce:transition-none z-[1035] + group-[&.ps--active-y]/ps:block group-hover/ps:opacity-60 + group-focus/ps:opacity-60 + group-[&.ps--scrolling-y]/ps:opacity-60 hover:!opacity-90 + focus:!opacity-90 [&.ps--clicking]:!opacity-90 outline-none + + Adds styles for vertical scrollbar rail. +
    + railYColors + + group-[&.ps--active-y]/ps:bg-transparent hover:!bg-[#eee] + focus:!bg-[#eee] [&.ps--clicking]:!bg-[#eee] + dark:hover:!bg-[#555] dark:focus:!bg-[#555] + dark:[&.ps--clicking]:!bg-[#555] + + Adds styles for vertical scrollbar rail. Decides the color + of the y rail. +
    + railYThumb + + absolute right-0.5 rounded-md w-1.5 + group-focus/ps:opacity-100 group-active/ps:opacity-100 + [transition:background-color_.2s_linear,_width_.2s_ease-in-out,_opacity] + group-hover/y:w-[11px] group-focus/y:w-[0.6875rem] + group-[&.ps--clicking]/y:w-[11px] outline-none + + Adds styles for vertical scrollbar thumb. +
    + railYThumbColors + + bg-[#aaa] group-hover/y:bg-[#999] group-focus/y:bg-[#999] + group-[&.ps--clicking]/y:bg-[#999] + + Adds styles for vertical scrollbar thumb. Decides the color + of the y thumb. +
    +
    +
    +
    +
    +
    + + +
    + + +
    + +

    + Methods +

    + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Method + + Description + Example
    + dispose + + Destroy PerfectScrollbar instance. + + myPs.dispose() +
    + getInstance + + Static method which allows you to get the perfect scrollbar + instance associated to a DOM element. + + PerfectScrollbar.getInstance(myPs) +
    + getOrCreateInstance + + Static method which returns the perfect scrollbar instance + associated to a DOM element or create a new one in case it + wasn't initialized. + + PerfectScrollbar.getOrCreateInstance(myPs) +
    + update + + Update PerfectScrollbar + + myPs.update() +
    +
    +
    +
    +
    + + + {{< twsnippet/no-demo id="api-example3" >}} + + +
    + + + +
    + +

    + Events +

    + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Event type + Description
    + scrollX.te.ps + + This event fires when the x-axis is scrolled in either + direction. +
    + scrollY.te.ps + + This event fires when the y-axis is scrolled in either + direction. +
    + scrollUp.te.ps + + This event fires when scrolling upwards. +
    + scrollDown.te.ps + + This event fires when scrolling downwards. +
    + scrollLeft.te.ps + + This event fires when scrolling to the left. +
    + scrollRight.te.ps + + This event fires when scrolling to the right. +
    + scrollYStart.te.ps + + This event fires when scrolling reaches the start of the + y-axis. +
    + scrollXStart.te.ps + + This event fires when scrolling reaches the start of the + x-axis. +
    + scrollXEnd.te.ps + + This event fires when scrolling reaches the end of the + x-axis. +
    + scrollYEnd.te.ps + + This event fires when scrolling reaches the end of the + y-axis (useful for infinite scroll). +
    +
    +
    +
    +
    + + + {{< twsnippet/no-demo id="api-example6" >}} + + + +
    +
    diff --git a/site/content/docs/standard/methods/scrollbar/index-js.html b/site/content/docs/standard/methods/scrollbar/index-js.html new file mode 100644 index 000000000..ec40597dd --- /dev/null +++ b/site/content/docs/standard/methods/scrollbar/index-js.html @@ -0,0 +1,60 @@ +--- +--- + + diff --git a/site/content/docs/standard/methods/scrollbar/index-ss.html b/site/content/docs/standard/methods/scrollbar/index-ss.html new file mode 100644 index 000000000..0e08abbb1 --- /dev/null +++ b/site/content/docs/standard/methods/scrollbar/index-ss.html @@ -0,0 +1,20 @@ +--- +--- + +
  • + Basic example +
  • +
  • Options
  • +
  • + JavaScript init +
  • +
  • + Data attributes +
  • +
  • + Colors example +
  • +
  • Events
  • +
  • + Related resources +
  • diff --git a/site/content/docs/standard/methods/scrollbar/index.html b/site/content/docs/standard/methods/scrollbar/index.html new file mode 100644 index 000000000..ebe7bacc3 --- /dev/null +++ b/site/content/docs/standard/methods/scrollbar/index.html @@ -0,0 +1,765 @@ +--- +title: "Scrollbar" +date: 2023-03-07T16:00:58+02:00 +draft: false +main_title: "Tailwind Scrollbar method" +subheading: "Tailwind CSS Scrollbar" +seo_title: "Tailwind CSS Scrollbar - Free Examples & Tutorial" +description: "Scrollbar method which allows you to create a custom scrollbar." +image: "https://tecdn.b-cdn.net/img/docs/methods/ripple.webp" +video: "https://www.youtube.com/watch?v=-GmnyjgI4Jc&ab_channel=Keepcoding" +url: "/docs/standard/methods/scrollbar/" +menu: + methods: + name: "Scrollbar" +autoinits: "Scrollbar" +--- + + +
    + +

    + Basic example +

    + +

    + Scrollbar is initialized automatically when you add + data-te-perfect-scrollbar-init attribute to your container. +

    + + + {{< twsnippet/demo id="example1">}} +
    +
    + Wild Landscape +
    +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +
    + + + +
    + +

    + Options +

    +
    + + + +
    + +

    + JavaScript init +

    + +

    + You can easily init scrollbar with JavaScript. You have to invoke + PerfectScrollbar() or te.PerfectScrollbar() if you + are using UMD format and include options within that. +

    + + {{< twsnippet/demo id="example6" >}} +
    +
    + Wild Landscape +
    +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Data attributes +

    + +

    + You can easily init scrollbar with options with + data-te-attributes. You have to add + data-te-perfect-scrollbar-init to your wrapper. If you want add + options with data-te-attr you have to add for example + data-te-suppress-scroll-x="true" to your container. +

    + + {{< twsnippet/demo id="example7" >}} +
    +
    + ... +
    +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Colors example +

    + +

    + Scrollbar's thumb and rail's colors can be customized by changing the + default classes we add to them. Change the classes of the Scrollbar element + that you would like to edit: railXColors, + railXThumbColors, railYColors or + railYThumbColors. Visit the API section to see the default + classes for those elements. +

    + + {{< twsnippet/demo id="example8" >}} +
    +
    + ... +
    +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Events +

    + +

    PerfectScrollbar dispatches custom events.

    + +
      +
    • ScrollX
    • +
    • ScrollY
    • +
    • ScrollUp
    • +
    • ScrollDown
    • +
    • ScrollLeft
    • +
    • ScrollRight
    • +
    • ScrollXEnd
    • +
    • ScrollYEnd
    • +
    • ScrollXStart
    • +
    • ScrollYStart
    • +
    + +

    Example

    + +
    + +
    + + {{< twsnippet/demo id="example9" >}} +
    +
    + Wild Landscape +
    + + + + + + +
    + {{< /twsnippet/demo >}} + + + +
    + + +
    + +
    + + + +
    diff --git a/site/static/search.json b/site/static/search.json index 969bd31ba..24322d462 100644 --- a/site/static/search.json +++ b/site/static/search.json @@ -769,6 +769,15 @@ "ripple": 1 } }, + { + "href": "/docs/standard/methods/scrollbar/", + "name": "Scrollbar", + "keywords": ["scrollbar", "scroll", "bar"], + "category": "Methods", + "priority": { + "scrollbar": 1 + } + }, { "href": "/docs/standard/designblocks/hero-sections/", "name": "Hero sections", diff --git a/src/js/methods/perfect-scrollbar.js b/src/js/methods/perfect-scrollbar.js index da24e59d6..93c6305b0 100644 --- a/src/js/methods/perfect-scrollbar.js +++ b/src/js/methods/perfect-scrollbar.js @@ -1,3 +1,14 @@ +/* +-------------------------------------------------------------------------- +Tailwind Elements is an open-source UI kit of advanced components for TailwindCSS. +Copyright © 2023 MDBootstrap.com + +Unless a custom, individually assigned license has been granted, this program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +In addition, a custom license may be available upon request, subject to the terms and conditions of that license. Please contact tailwind@mdbootstrap.com for more information on obtaining a custom license. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +-------------------------------------------------------------------------- +*/ + /* eslint-disable no-restricted-globals */ import PerfectScrollbar from "perfect-scrollbar"; @@ -61,21 +72,32 @@ const DefaultType = { const DefaultClasses = { ps: "group/ps overflow-hidden [overflow-anchor:none] touch-none", railX: - "group/x absolute bottom-0 h-[0.9375rem] hidden opacity-0 transition-[background-color,_opacity] duration-200 ease-linear motion-reduce:transition-none z-[1035] group-[&.ps--active-x]/ps:block group-[&.ps--active-x]/ps:bg-transparent group-hover/ps:opacity-60 group-focus/ps:opacity-60 group-[&.ps--scrolling-x]/ps:opacity-60 hover:!opacity-90 hover:!bg-[#eee] focus:!opacity-90 focus:!bg-[#eee] [&.ps--clicking]:!opacity-90 [&.ps--clicking]:!bg-[#eee] outline-none", + "group/x absolute bottom-0 h-[0.9375rem] hidden opacity-0 transition-[background-color,_opacity] duration-200 ease-linear motion-reduce:transition-none z-[1035] group-[&.ps--active-x]/ps:block group-hover/ps:opacity-60 group-focus/ps:opacity-60 group-[&.ps--scrolling-x]/ps:opacity-60 hover:!opacity-90 focus:!opacity-90 [&.ps--clicking]:!opacity-90 outline-none", + railXColors: + "group-[&.ps--active-x]/ps:bg-transparent hover:!bg-[#eee] focus:!bg-[#eee] [&.ps--clicking]:!bg-[#eee] dark:hover:!bg-[#555] dark:focus:!bg-[#555] dark:[&.ps--clicking]:!bg-[#555]", railXThumb: - "absolute bottom-0.5 rounded-md h-1.5 opacity-0 group-hover/ps:opacity-100 group-focus/ps:opacity-100 group-active/ps:opacity-100 bg-[#aaa] [transition:background-color_.2s_linear,_height_.2s_ease-in-out] group-hover/x:bg-[#999] group-hover/x:h-[11px] group-focus/x:bg-[#999] group-focus/x:h-[0.6875rem] group-[&.ps--clicking]/x:bg-[#999] group-[&.ps--clicking]/x:h-[11px] outline-none", + "absolute bottom-0.5 rounded-md h-1.5 group-focus/ps:opacity-100 group-active/ps:opacity-100 [transition:background-color_.2s_linear,_height_.2s_ease-in-out] group-hover/x:h-[11px] group-focus/x:h-[0.6875rem] group-[&.ps--clicking]/x:bg-[#999] group-[&.ps--clicking]/x:h-[11px] outline-none", + railXThumbColors: "bg-[#aaa] group-hover/x:bg-[#999] group-focus/x:bg-[#999]", railY: - "group/y absolute right-0 w-[0.9375rem] hidden opacity-0 transition-[background-color,_opacity] duration-200 ease-linear motion-reduce:transition-none z-[1035] group-[&.ps--active-y]/ps:block group-[&.ps--active-y]/ps:bg-transparent group-hover/ps:opacity-60 group-focus/ps:opacity-60 group-[&.ps--scrolling-y]/ps:opacity-60 hover:!opacity-90 hover:!bg-[#eee] focus:!opacity-90 focus:!bg-[#eee] [&.ps--clicking]:!opacity-90 [&.ps--clicking]:!bg-[#eee] outline-none", + "group/y absolute right-0 w-[0.9375rem] hidden opacity-0 transition-[background-color,_opacity] duration-200 ease-linear motion-reduce:transition-none z-[1035] group-[&.ps--active-y]/ps:block group-hover/ps:opacity-60 group-focus/ps:opacity-60 group-[&.ps--scrolling-y]/ps:opacity-60 hover:!opacity-90 focus:!opacity-90 [&.ps--clicking]:!opacity-90 outline-none", + railYColors: + "group-[&.ps--active-y]/ps:bg-transparent hover:!bg-[#eee] focus:!bg-[#eee] [&.ps--clicking]:!bg-[#eee] dark:hover:!bg-[#555] dark:focus:!bg-[#555] dark:[&.ps--clicking]:!bg-[#555]", railYThumb: - "absolute right-0.5 rounded-md w-1.5 opacity-0 group-hover/ps:opacity-100 group-focus/ps:opacity-100 group-active/ps:opacity-100 bg-[#aaa] [transition:background-color_.2s_linear,_width_.2s_ease-in-out] group-hover/y:bg-[#999] group-hover/y:w-[11px] group-focus/y:bg-[#999] group-focus/y:w-[0.6875rem] group-[&.ps--clicking]/y:bg-[#999] group-[&.ps--clicking]/y:w-[11px] outline-none", + "absolute right-0.5 rounded-md w-1.5 group-focus/ps:opacity-100 group-active/ps:opacity-100 [transition:background-color_.2s_linear,_width_.2s_ease-in-out,_opacity] group-hover/y:w-[11px] group-focus/y:w-[0.6875rem] group-[&.ps--clicking]/y:w-[11px] outline-none", + railYThumbColors: + "bg-[#aaa] group-hover/y:bg-[#999] group-focus/y:bg-[#999] group-[&.ps--clicking]/y:bg-[#999]", }; const DefaultClassesType = { ps: "string", railX: "string", + railXColors: "string", railXThumb: "string", + railXThumbColors: "string", railY: "string", + railYColors: "string", railYThumb: "string", + railYThumbColors: "string", }; class PerfectScrollbars { @@ -161,22 +183,46 @@ class PerfectScrollbars { _addPerfectScrollbarStyles() { const classes = [ - { ps: "ps__rail-x", te: this._classes.railX }, - { ps: "ps__rail-y", te: this._classes.railY }, - { ps: "ps__thumb-x", te: this._classes.railXThumb }, - { ps: "ps__thumb-y", te: this._classes.railYThumb }, + { + ps: "ps__rail-x", + te: this._classes.railX, + teColor: this._classes.railXColors, + }, + { + ps: "ps__rail-y", + te: this._classes.railY, + teColor: this._classes.railYColors, + }, + { + ps: "ps__thumb-x", + te: this._classes.railXThumb, + teColor: this._classes.railXThumbColors, + }, + { + ps: "ps__thumb-y", + te: this._classes.railYThumb, + teColor: this._classes.railYThumbColors, + }, ]; classes.forEach((item) => { const container = SelectorEngine.findOne(`.${item.ps}`, this._element); + + // check if the perfect scrollbar package styles have been imported + const shouldTransform = + getComputedStyle(container).getPropertyValue("right") === "auto"; + Manipulator.addClass(container, item.te); - if (item.ps.includes("rail-x")) { - console.log(); + Manipulator.addClass(container, item.teColor); + + // prettier-ignore + if (shouldTransform && classes[0].te.includes("bottom") && item.ps.includes("rail-x")) { container.style.transform = `translateY(calc(-100% + ${getComputedStyle( this._element ).getPropertyValue("height")}))`; } - if (item.ps.includes("rail-y")) { + // prettier-ignore + if (shouldTransform && classes[1].te.includes("right") && item.ps.includes("rail-y")) { container.style.transform = `translateX(calc(-100% + ${getComputedStyle( this._element ).getPropertyValue("width")}))`; From 86eb414360f5874e97925491d53f51f8c96afc47 Mon Sep 17 00:00:00 2001 From: Bartosz Cylwik Date: Thu, 29 Jun 2023 09:38:21 +0200 Subject: [PATCH 3/4] Add Scrollbar component to autoinits --- src/js/autoinit/index.js | 8 +++++++ src/js/methods/perfect-scrollbar.js | 33 +---------------------------- 2 files changed, 9 insertions(+), 32 deletions(-) diff --git a/src/js/autoinit/index.js b/src/js/autoinit/index.js index 96f0ad927..31f0761be 100644 --- a/src/js/autoinit/index.js +++ b/src/js/autoinit/index.js @@ -12,6 +12,9 @@ import { import { chartsCallback } from "./chartsInit"; +// key => component NAME constant +// name => component exported by name + const defaultInitSelectors = { alert: { name: "Alert", @@ -48,6 +51,11 @@ const defaultInitSelectors = { selector: "[data-te-input-wrapper-init]", isToggler: false, }, + perfectScrollbar: { + name: "PerfectScrollbar", + selector: "[data-te-perfect-scrollbar-init]", + isToggler: false, + }, scrollspy: { name: "ScrollSpy", selector: "[data-te-spy='scroll']", diff --git a/src/js/methods/perfect-scrollbar.js b/src/js/methods/perfect-scrollbar.js index 93c6305b0..1fde514e1 100644 --- a/src/js/methods/perfect-scrollbar.js +++ b/src/js/methods/perfect-scrollbar.js @@ -12,7 +12,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY /* eslint-disable no-restricted-globals */ import PerfectScrollbar from "perfect-scrollbar"; -import { getjQuery, typeCheckConfig, onDOMContentLoaded } from "../util/index"; +import { typeCheckConfig } from "../util/index"; import Data from "../dom/data"; import Manipulator from "../dom/manipulator"; import EventHandler from "../dom/event-handler"; @@ -37,8 +37,6 @@ const EVENTS = [ { te: `scrollYStart.${TE_NAME}.${PS_NAME}`, ps: "ps-y-reach-start" }, ]; -const PERFECT_SCROLLBAR_INIT = "data-te-perfect-scrollbar-init"; - const Default = { handlers: ["click-rail", "drag-thumb", "keyboard", "wheel", "touch"], wheelSpeed: 1, @@ -287,33 +285,4 @@ class PerfectScrollbars { } } -SelectorEngine.find(`[${PERFECT_SCROLLBAR_INIT}]`).forEach((scroll) => { - let instance = PerfectScrollbars.getInstance(scroll); - if (!instance) { - instance = new PerfectScrollbars(scroll); - } - return instance; -}); - -/** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - * add .perfectScrollbar to jQuery only if jQuery is present - */ - -onDOMContentLoaded(() => { - const $ = getjQuery(); - - if ($) { - const JQUERY_NO_CONFLICT = $.fn[NAME]; - $.fn[NAME] = PerfectScrollbars.jQueryInterface; - $.fn[NAME].Constructor = PerfectScrollbars; - $.fn[NAME].noConflict = () => { - $.fn[NAME] = JQUERY_NO_CONFLICT; - return PerfectScrollbars.jQueryInterface; - }; - } -}); - export default PerfectScrollbars; From 2f9511e617d1c971f27f6d554c920f1aa9c77a96 Mon Sep 17 00:00:00 2001 From: Bartosz Cylwik Date: Fri, 30 Jun 2023 09:47:05 +0200 Subject: [PATCH 4/4] Fix scroll. position issue + remove old from docs --- .../docs/standard/methods/scrollbar/a.html | 18 +++ .../standard/methods/scrollbar/index.html | 2 +- .../partials/footer/footer-scripts.html | 3 +- site/layouts/partials/head/head.html | 1 - site/static/css/perfect-scrollbar.css | 125 ------------------ site/static/js/perfect-scrollbar.min.js | 20 --- src/js/methods/perfect-scrollbar.js | 118 ++++++++++------- src/js/navigation/sidenav.js | 5 +- 8 files changed, 93 insertions(+), 199 deletions(-) delete mode 100644 site/static/css/perfect-scrollbar.css delete mode 100644 site/static/js/perfect-scrollbar.min.js diff --git a/site/content/docs/standard/methods/scrollbar/a.html b/site/content/docs/standard/methods/scrollbar/a.html index 9e0a1494b..8c06943b7 100644 --- a/site/content/docs/standard/methods/scrollbar/a.html +++ b/site/content/docs/standard/methods/scrollbar/a.html @@ -362,6 +362,24 @@

    Via JavaScript

    scroll bar is not enabled just because of a few pixels. + + + positionRight + + + Boolean + + + true + + + Changes the sides of scrollbar rails + + diff --git a/site/content/docs/standard/methods/scrollbar/index.html b/site/content/docs/standard/methods/scrollbar/index.html index ebe7bacc3..3bbc75876 100644 --- a/site/content/docs/standard/methods/scrollbar/index.html +++ b/site/content/docs/standard/methods/scrollbar/index.html @@ -12,7 +12,7 @@ menu: methods: name: "Scrollbar" -autoinits: "Scrollbar" +autoinits: "PerfectScrollbar" --- diff --git a/site/layouts/partials/footer/footer-scripts.html b/site/layouts/partials/footer/footer-scripts.html index 3eab0c8ab..6e3d3e705 100644 --- a/site/layouts/partials/footer/footer-scripts.html +++ b/site/layouts/partials/footer/footer-scripts.html @@ -5,7 +5,6 @@ -