@helloimjolopez-pathway/pathway-tokens 5.4.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -19
- package/components/scrollbar/scrollbar.jsx +184 -0
- package/components/sidenav/sidenav.jsx +866 -0
- package/dist/breakpoints.css +11 -0
- package/dist/layout-contextual.css +36 -0
- package/dist/layout-responsive.css +32 -0
- package/dist/layout.css +48 -0
- package/dist/motion.css +23 -0
- package/dist/primitives.css +358 -0
- package/dist/themes/light.css +175 -0
- package/dist/themes/midnight.css +175 -0
- package/dist/tokens.js +8943 -69506
- package/dist/tokens.json +3099 -10657
- package/dist/type.css +49 -0
- package/package.json +51 -8
- package/dist/tokens.css +0 -2648
package/README.md
CHANGED
|
@@ -2,43 +2,105 @@
|
|
|
2
2
|
|
|
3
3
|
Design system for Ministry Brands Amplify. Tokens + components + specifications, all versioned in one place, with Storybook deployed from `main`.
|
|
4
4
|
|
|
5
|
+
> **Looking for the tokens?** → **[TOKENS.md](TOKENS.md)** — where the CSS lives, which
|
|
6
|
+
> of the 267 names you may use, and what to link in what order.
|
|
7
|
+
|
|
5
8
|
## Using the tokens
|
|
6
9
|
|
|
7
|
-
The
|
|
10
|
+
**The colour contract is 169 names. Your full working vocabulary is 267.**
|
|
11
|
+
|
|
12
|
+
That is the number worth knowing, because adding up every declaration in the token
|
|
13
|
+
folder gives 966 and the retired `tokens.css` used to emit 2,338. Neither is the
|
|
14
|
+
contract. The difference is that primitives ship but are not named, and the modes share
|
|
15
|
+
one name set rather than each having their own.
|
|
16
|
+
|
|
17
|
+
| | Count | Name these? |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| Colour (`themes/light.css`, `themes/midnight.css` — same names) | **169** | Yes |
|
|
20
|
+
| Type scale (`type.css`) | 41 | Yes |
|
|
21
|
+
| Spacing, radii, borders (`layout.css`) | 40 | Yes |
|
|
22
|
+
| Motion (`motion.css`) | 17 | Yes |
|
|
23
|
+
| Sheet and TopNav padding (`layout-responsive.css`) | 6 | Yes |
|
|
24
|
+
| Breakpoints (`breakpoints.css`) | 5 | Yes |
|
|
25
|
+
| **Working vocabulary** | **267** | |
|
|
26
|
+
| Raw ramps (`primitives.css`) | 350 | **No** — but you must load it |
|
|
27
|
+
| Component metrics (`layout-contextual.css`) | 26 | This repo's components |
|
|
28
|
+
|
|
29
|
+
**The CSS lives in [`src/tokens/`](src/tokens/), and that folder has its own README**
|
|
30
|
+
covering load order, theming, the primitives question and the traps. Read it before
|
|
31
|
+
wiring anything up. The published package carries the same guidance in `dist/README.md`,
|
|
32
|
+
plus `dist/contract.json` listing every consumable name if you want to lint against it.
|
|
33
|
+
|
|
34
|
+
### Install
|
|
8
35
|
|
|
9
36
|
```bash
|
|
10
37
|
npm install @helloimjolopez-pathway/pathway-tokens
|
|
11
38
|
```
|
|
12
39
|
|
|
13
|
-
|
|
14
|
-
// CSS custom properties — import once in your app entry point
|
|
15
|
-
import "@helloimjolopez-pathway/pathway-tokens/css";
|
|
40
|
+
NuGet: `Pathway.DesignTokens`.
|
|
16
41
|
|
|
17
|
-
|
|
42
|
+
```js
|
|
43
|
+
// Every stylesheet is a named subpath export. primitives.css MUST come first —
|
|
44
|
+
// the themes resolve through it, so without it all colour resolves to nothing
|
|
45
|
+
// and the page renders unstyled with no console error.
|
|
46
|
+
import "@helloimjolopez-pathway/pathway-tokens/primitives.css";
|
|
47
|
+
import "@helloimjolopez-pathway/pathway-tokens/themes/light.css";
|
|
48
|
+
import "@helloimjolopez-pathway/pathway-tokens/themes/midnight.css";
|
|
49
|
+
import "@helloimjolopez-pathway/pathway-tokens/type.css";
|
|
50
|
+
import "@helloimjolopez-pathway/pathway-tokens/layout.css";
|
|
51
|
+
import "@helloimjolopez-pathway/pathway-tokens/layout-responsive.css";
|
|
52
|
+
import "@helloimjolopez-pathway/pathway-tokens/motion.css";
|
|
53
|
+
import "@helloimjolopez-pathway/pathway-tokens/breakpoints.css";
|
|
54
|
+
|
|
55
|
+
// JS token object, and the raw DTCG JSON for tooling
|
|
18
56
|
import tokens from "@helloimjolopez-pathway/pathway-tokens";
|
|
19
|
-
|
|
20
|
-
// Raw DTCG JSON (for tooling)
|
|
21
57
|
import tokenJson from "@helloimjolopez-pathway/pathway-tokens/json";
|
|
58
|
+
import contract from "@helloimjolopez-pathway/pathway-tokens/contract.json";
|
|
22
59
|
```
|
|
23
60
|
|
|
24
|
-
|
|
61
|
+
There is deliberately no single `/css` entry point. One combined file was what
|
|
62
|
+
`tokens.css` used to be: it emitted every token times every mode with the mode baked
|
|
63
|
+
into the property name, 2,338 custom properties, and it is the reason this system read
|
|
64
|
+
as too granular to adopt. Retired 2026-09-03 and not coming back.
|
|
65
|
+
|
|
66
|
+
### Without a bundler
|
|
25
67
|
|
|
26
68
|
```html
|
|
27
|
-
|
|
69
|
+
<!-- primitives first: the themes reference these via var(), so this must load -->
|
|
70
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/helloimjolopez-collab/pathway-ds@main/src/tokens/primitives.css" />
|
|
71
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/helloimjolopez-collab/pathway-ds@main/src/tokens/themes/light.css" />
|
|
72
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/helloimjolopez-collab/pathway-ds@main/src/tokens/themes/midnight.css" />
|
|
73
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/helloimjolopez-collab/pathway-ds@main/src/tokens/type.css" />
|
|
74
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/helloimjolopez-collab/pathway-ds@main/src/tokens/layout.css" />
|
|
75
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/helloimjolopez-collab/pathway-ds@main/src/tokens/layout-responsive.css" />
|
|
76
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/helloimjolopez-collab/pathway-ds@main/src/tokens/motion.css" />
|
|
77
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/helloimjolopez-collab/pathway-ds@main/src/tokens/breakpoints.css" />
|
|
28
78
|
```
|
|
29
79
|
|
|
30
|
-
|
|
80
|
+
`@main` tracks the latest. Pin a tag instead if you need a fixed version.
|
|
81
|
+
|
|
82
|
+
### Using a token
|
|
31
83
|
|
|
32
84
|
```css
|
|
33
|
-
.
|
|
34
|
-
background: var(--semantic-color-
|
|
35
|
-
color: var(--semantic-color-
|
|
85
|
+
.card {
|
|
86
|
+
background: var(--semantic-color-fill-surface-sheet);
|
|
87
|
+
color: var(--semantic-color-foreground-static-neutral-strong);
|
|
88
|
+
border: var(--semantic-layout-units-borderwidth-base) solid
|
|
89
|
+
var(--semantic-color-stroke-static-neutral-base);
|
|
90
|
+
border-radius: var(--semantic-layout-units-cornerradius-medium);
|
|
36
91
|
}
|
|
37
92
|
```
|
|
38
93
|
|
|
39
|
-
|
|
94
|
+
One name carries both modes. Set `data-theme="midnight"` on `<html>` to flip the page,
|
|
95
|
+
or on any element to flip just that subtree. Never write a mode into a property name —
|
|
96
|
+
`--semantic-color-light-mode-*` resolves to nothing.
|
|
97
|
+
|
|
98
|
+
### Can I use a primitive?
|
|
40
99
|
|
|
41
|
-
|
|
100
|
+
Yes, and nothing stops you. But `Primitive: Color` has exactly one mode, so a primitive
|
|
101
|
+
holds one value forever and will **not** respond to `data-theme`. Reach for one only
|
|
102
|
+
when you specifically want a fixed value. Full reasoning in
|
|
103
|
+
[`src/tokens/README.md`](src/tokens/README.md).
|
|
42
104
|
|
|
43
105
|
## Layout
|
|
44
106
|
|
|
@@ -57,7 +119,7 @@ pathway-ds/
|
|
|
57
119
|
│ ├── figma-export/ Raw Figma export (sync target)
|
|
58
120
|
│ └── pathway-design-tokens.json W3C DTCG format
|
|
59
121
|
├── src/
|
|
60
|
-
│ ├── tokens/ Built output (
|
|
122
|
+
│ ├── tokens/ Built output (the 8-file contract + tokens.js)
|
|
61
123
|
│ └── stories/ Storybook sources
|
|
62
124
|
│ ├── Primitives/ Token primitives (Color, Typography, Units)
|
|
63
125
|
│ ├── Semantics/ Semantic tokens (light/dark, layout, typography)
|
|
@@ -65,7 +127,6 @@ pathway-ds/
|
|
|
65
127
|
├── .storybook/
|
|
66
128
|
├── .github/workflows/ Token sync · component sync · Storybook deploy
|
|
67
129
|
├── scripts/ Token sync/audit/fix + component build scripts
|
|
68
|
-
└── storybook/ Built Storybook output (deployed by CI)
|
|
69
130
|
```
|
|
70
131
|
|
|
71
132
|
## Governance — where things live
|
|
@@ -74,7 +135,7 @@ pathway-ds/
|
|
|
74
135
|
|---|---|
|
|
75
136
|
| Published token package | [`@helloimjolopez-pathway/pathway-tokens`](https://www.npmjs.com/package/@helloimjolopez-pathway/pathway-tokens) |
|
|
76
137
|
| Token values | [`tokens/pathway-design-tokens.json`](tokens/pathway-design-tokens.json) (source-of-truth, synced from Figma) |
|
|
77
|
-
| Built CSS consumed by Storybook | [`src/tokens
|
|
138
|
+
| Built CSS consumed by Storybook | the eight files in [`src/tokens/`](src/tokens/) (auto-regenerated by Style Dictionary) |
|
|
78
139
|
| Component geometry, tokens, accessibility rules | [`components/<name>/<name>-spec.md`](components/) |
|
|
79
140
|
| Component reference implementation | [`components/<name>/<name>.html`](components/) |
|
|
80
141
|
| How a component appears in Storybook | [`src/stories/Library/<Name>/`](src/stories/Library/) |
|
|
@@ -87,7 +148,7 @@ Three workflows in `.github/workflows/`:
|
|
|
87
148
|
|
|
88
149
|
1. **`sync-tokens.yml`** — fires when `tokens/figma-export/**` changes. Normalises the Figma export into the W3C DTCG JSON and commits `tokens/pathway-design-tokens.json`.
|
|
89
150
|
2. **`sync-component.yml`** — fires when `components/sidenav/sidenav.html` changes. Regenerates the `sidenav-figmamake.html` variant and commits it.
|
|
90
|
-
3. **`deploy-
|
|
151
|
+
3. **`deploy-pages.yml`** — fires on every push to `main`. Builds Style Dictionary and Storybook fresh and deploys a clean `_site` artifact through the official Pages actions. Nothing is committed back to `main`. (`deploy-storybook.yml` is the retired predecessor, kept manual-only; it committed 14MB of build output per push.)
|
|
91
152
|
|
|
92
153
|
Source of truth is always the repo on `main`; Storybook is a downstream artifact.
|
|
93
154
|
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrollable — Pathway Design System
|
|
3
|
+
*
|
|
4
|
+
* A reusable overlay-scrollbar wrapper. Hides the native OS scrollbar entirely and renders
|
|
5
|
+
* one custom liquid-glass thumb so scrolling looks and behaves IDENTICALLY on macOS, Windows,
|
|
6
|
+
* iOS, and Android (native scrollbars can't be made consistent — this sidesteps them).
|
|
7
|
+
*
|
|
8
|
+
* Behaviour (see components/scrollbar/scrollbar-spec.md):
|
|
9
|
+
* - Thumb height is PROPORTIONAL to content: (viewport / total) × track, floored at 28px.
|
|
10
|
+
* - Reveal: appears while scrolling, fades ~900ms after; also appears when the MOUSE is near
|
|
11
|
+
* the right-edge bar (so it can be grabbed). It does NOT appear from hovering the panel.
|
|
12
|
+
* - Drag: MOUSE only, via a wider invisible grab strip (the 6px thumb alone is hard to hit).
|
|
13
|
+
* - Touch: passive — the bar just shows position; you scroll by swiping content. The grab
|
|
14
|
+
* strip is disabled on touch devices via a `(hover: none)` rule.
|
|
15
|
+
* - Keyboard / a11y: the content scrolls natively (arrows, PageUp/Down, Home/End, Space); the
|
|
16
|
+
* thumb is decorative (`aria-hidden`) and never the only scroll mechanism.
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* <Scrollable style={{ flex: 1, minHeight: 0 }}>…tall content…</Scrollable>
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import React, { useRef, useState, useEffect, useCallback } from "react";
|
|
23
|
+
|
|
24
|
+
// ─── TOKENS ──────────────────────────────────────────────────────────────────
|
|
25
|
+
// Every colour + unit resolves through a SEMANTIC Pathway token — no primitives,
|
|
26
|
+
// no hardcoded hex/px. Motion uses the --motion-* tokens (durations/easings from design-system-spec §2).
|
|
27
|
+
export const SCROLL = {
|
|
28
|
+
thumbWidth: "var(--semantic-layout-units-padding-xtight)", // 6px — visible thumb thickness
|
|
29
|
+
thumbRadius: "var(--semantic-layout-units-cornerradius-full)", // fully-rounded pill
|
|
30
|
+
thumbMin: 28, // px — min thumb length (grab-target floor); JS layout math
|
|
31
|
+
gutter: "var(--semantic-layout-units-padding-xxxtight)", // 2px — inset from the right edge
|
|
32
|
+
grabZone: 16, // px — invisible mouse grab strip (wider than the 6px thumb so it's catchable)
|
|
33
|
+
thumbRest: "var(--semantic-color-scrim-faint)", // black 16% — faint overlay (rest)
|
|
34
|
+
thumbHover: "var(--semantic-color-scrim-light)", // black 30% — hover/drag
|
|
35
|
+
thumbBlur: "blur(8px) saturate(180%)",
|
|
36
|
+
// Hairline glass edge: semantic white at 35% via color-mix.
|
|
37
|
+
thumbEdge: "inset 0 0 0 0.5px color-mix(in srgb, var(--semantic-color-fill-static-neutral-faint) 35%, transparent)",
|
|
38
|
+
// Asymmetric fade, motion-token driven: snappy appear (200ms decelerate glide-in), graceful fade-out (380ms).
|
|
39
|
+
fadeIn: "opacity var(--motion-duration-3) var(--motion-easing-decelerate), background var(--motion-duration-3) var(--motion-easing-standard)",
|
|
40
|
+
fadeOut: "opacity var(--motion-duration-5) var(--motion-easing-standard)",
|
|
41
|
+
idleHideMs: 500, // hide the thumb this long after scrolling stops / mouse leaves the bar
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Injected once: hide the native bar on the opt-in class, and disable the mouse grab strip on
|
|
45
|
+
// touch devices so finger-swipes scroll the content underneath (the thumb stays a passive indicator).
|
|
46
|
+
if (typeof document !== "undefined" && !document.getElementById("pds-scrollable-base")) {
|
|
47
|
+
const s = document.createElement("style");
|
|
48
|
+
s.id = "pds-scrollable-base";
|
|
49
|
+
s.textContent =
|
|
50
|
+
".pds-scrollable__view{scrollbar-width:none;-ms-overflow-style:none}" +
|
|
51
|
+
".pds-scrollable__view::-webkit-scrollbar{width:0;height:0;display:none}" +
|
|
52
|
+
"@media (hover: none){.pds-scrollable__grab{pointer-events:none!important}}";
|
|
53
|
+
document.head.appendChild(s);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function Scrollable({ children, className = "", style = {}, viewClassName = "", viewStyle = {} }) {
|
|
57
|
+
const viewRef = useRef(null);
|
|
58
|
+
const dragRef = useRef(null);
|
|
59
|
+
const idleRef = useRef(null);
|
|
60
|
+
const nearRef = useRef(false); // mouse currently near the right-edge bar
|
|
61
|
+
const [thumb, setThumb] = useState({ h: 0, top: 0, show: false });
|
|
62
|
+
const [active, setActive] = useState(false); // thumb visible (scrolling, near-bar, or dragging)
|
|
63
|
+
const [hot, setHot] = useState(false); // mouse over / dragging the grab strip
|
|
64
|
+
|
|
65
|
+
// Thumb height is PROPORTIONAL to content; floored at thumbMin. Position maps the floored
|
|
66
|
+
// thumb across the full track so it still reaches top and bottom exactly.
|
|
67
|
+
const recompute = useCallback(() => {
|
|
68
|
+
const el = viewRef.current;
|
|
69
|
+
if (!el) return;
|
|
70
|
+
const { scrollHeight, clientHeight, scrollTop } = el;
|
|
71
|
+
if (scrollHeight <= clientHeight + 1) { setThumb(t => (t.show ? { ...t, show: false } : t)); return; }
|
|
72
|
+
const h = Math.max(SCROLL.thumbMin, (clientHeight / scrollHeight) * clientHeight);
|
|
73
|
+
const top = (scrollTop / (scrollHeight - clientHeight)) * (clientHeight - h);
|
|
74
|
+
setThumb({ h, top, show: true });
|
|
75
|
+
}, []);
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
recompute();
|
|
79
|
+
const el = viewRef.current;
|
|
80
|
+
if (!el || typeof ResizeObserver === "undefined") return;
|
|
81
|
+
const ro = new ResizeObserver(recompute);
|
|
82
|
+
ro.observe(el);
|
|
83
|
+
Array.from(el.children).forEach(c => ro.observe(c));
|
|
84
|
+
return () => ro.disconnect();
|
|
85
|
+
}, [children, recompute]);
|
|
86
|
+
|
|
87
|
+
const scheduleHide = () => {
|
|
88
|
+
clearTimeout(idleRef.current);
|
|
89
|
+
idleRef.current = setTimeout(() => {
|
|
90
|
+
if (!dragRef.current && !nearRef.current) setActive(false);
|
|
91
|
+
}, SCROLL.idleHideMs);
|
|
92
|
+
};
|
|
93
|
+
const wake = () => { setActive(true); scheduleHide(); }; // reveal while scrolling
|
|
94
|
+
const onScroll = () => { recompute(); wake(); };
|
|
95
|
+
|
|
96
|
+
// Edge-proximity reveal (mouse): show the bar when the cursor is within grabZone of the right
|
|
97
|
+
// edge, so it can be grabbed — but NOT from hovering the rest of the panel.
|
|
98
|
+
const onMouseMove = (e) => {
|
|
99
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
100
|
+
if (rect.right - e.clientX <= SCROLL.grabZone) {
|
|
101
|
+
nearRef.current = true; setActive(true); clearTimeout(idleRef.current);
|
|
102
|
+
} else if (nearRef.current) {
|
|
103
|
+
nearRef.current = false; scheduleHide();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const onMouseLeave = () => { nearRef.current = false; if (!dragRef.current) scheduleHide(); };
|
|
107
|
+
|
|
108
|
+
// Drag (mouse only). The grab strip carries this; the visual thumb is decorative.
|
|
109
|
+
const onGrabDown = (e) => {
|
|
110
|
+
e.preventDefault();
|
|
111
|
+
const el = viewRef.current;
|
|
112
|
+
if (!el) return;
|
|
113
|
+
dragRef.current = { startY: e.clientY, startTop: el.scrollTop };
|
|
114
|
+
setHot(true); setActive(true); clearTimeout(idleRef.current);
|
|
115
|
+
const onMove = (ev) => {
|
|
116
|
+
const { scrollHeight, clientHeight } = el;
|
|
117
|
+
const h = Math.max(SCROLL.thumbMin, (clientHeight / scrollHeight) * clientHeight);
|
|
118
|
+
const ratio = (scrollHeight - clientHeight) / (clientHeight - h);
|
|
119
|
+
el.scrollTop = dragRef.current.startTop + (ev.clientY - dragRef.current.startY) * ratio;
|
|
120
|
+
};
|
|
121
|
+
const onUp = () => {
|
|
122
|
+
dragRef.current = null; setHot(false);
|
|
123
|
+
document.removeEventListener("mousemove", onMove);
|
|
124
|
+
document.removeEventListener("mouseup", onUp);
|
|
125
|
+
wake();
|
|
126
|
+
};
|
|
127
|
+
document.addEventListener("mousemove", onMove);
|
|
128
|
+
document.addEventListener("mouseup", onUp);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const barTop = thumb.top, barH = thumb.h;
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<div
|
|
135
|
+
className={`pds-scrollable ${className}`}
|
|
136
|
+
style={{ position: "relative", minHeight: 0, ...style }}
|
|
137
|
+
onMouseMove={onMouseMove}
|
|
138
|
+
onMouseLeave={onMouseLeave}
|
|
139
|
+
>
|
|
140
|
+
<div
|
|
141
|
+
ref={viewRef}
|
|
142
|
+
className={`pds-scrollable__view ${viewClassName}`}
|
|
143
|
+
onScroll={onScroll}
|
|
144
|
+
style={{ height: "100%", overflowY: "auto", overflowX: "hidden", ...viewStyle }}
|
|
145
|
+
>
|
|
146
|
+
{children}
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
{thumb.show && (
|
|
150
|
+
<>
|
|
151
|
+
{/* Visual thumb — decorative, never intercepts pointer events. */}
|
|
152
|
+
<div
|
|
153
|
+
aria-hidden="true"
|
|
154
|
+
style={{
|
|
155
|
+
position: "absolute", top: barTop, right: SCROLL.gutter,
|
|
156
|
+
width: SCROLL.thumbWidth, height: barH, borderRadius: SCROLL.thumbRadius,
|
|
157
|
+
background: hot ? SCROLL.thumbHover : SCROLL.thumbRest,
|
|
158
|
+
backdropFilter: SCROLL.thumbBlur, WebkitBackdropFilter: SCROLL.thumbBlur,
|
|
159
|
+
boxShadow: SCROLL.thumbEdge,
|
|
160
|
+
opacity: active ? 1 : 0, transition: active ? SCROLL.fadeIn : SCROLL.fadeOut,
|
|
161
|
+
pointerEvents: "none", zIndex: 5,
|
|
162
|
+
}}
|
|
163
|
+
/>
|
|
164
|
+
{/* Invisible mouse grab strip — wider than the thumb so it's catchable; disabled on
|
|
165
|
+
touch via the (hover:none) rule so finger-swipes scroll the content beneath. */}
|
|
166
|
+
<div
|
|
167
|
+
aria-hidden="true"
|
|
168
|
+
className="pds-scrollable__grab"
|
|
169
|
+
onMouseDown={onGrabDown}
|
|
170
|
+
onMouseEnter={() => setHot(true)}
|
|
171
|
+
onMouseLeave={() => setHot(false)}
|
|
172
|
+
style={{
|
|
173
|
+
position: "absolute", top: barTop, right: 0,
|
|
174
|
+
width: SCROLL.grabZone, height: barH,
|
|
175
|
+
pointerEvents: active ? "auto" : "none", zIndex: 6, background: "transparent",
|
|
176
|
+
}}
|
|
177
|
+
/>
|
|
178
|
+
</>
|
|
179
|
+
)}
|
|
180
|
+
</div>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export default Scrollable;
|