reshaped 4.3.0-canary.2 → 4.3.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/dist/bundle.cjs +1 -1
- package/dist/components/Tabs/TabsList.js +4 -1
- package/dist/components/Tabs/tests/Tabs.stories.d.ts +1 -0
- package/dist/components/Tabs/tests/Tabs.stories.js +61 -0
- package/dist/hooks/_internal/useFadeSide.d.ts +1 -0
- package/dist/hooks/_internal/useFadeSide.js +9 -7
- package/package.json +3 -3
|
@@ -24,8 +24,11 @@ const TabsList = (props) => {
|
|
|
24
24
|
const { children, className, attributes } = props;
|
|
25
25
|
const { value, itemWidth, variant, name, direction, size, selection, setSelection, elActiveRef, elPrevActiveRef, elScrollableRef, disableSelectionAnimation, } = useTabs();
|
|
26
26
|
const [rtl] = useRTL();
|
|
27
|
-
const fadeSide = useFadeSide(elScrollableRef, { disabled: itemWidth === "equal" });
|
|
28
27
|
const listRef = React.useRef(null);
|
|
28
|
+
const fadeSide = useFadeSide(elScrollableRef, {
|
|
29
|
+
contentRef: listRef,
|
|
30
|
+
disabled: itemWidth === "equal",
|
|
31
|
+
});
|
|
29
32
|
const rootClassNames = classNames(s.root, size && s[`--size-${size}`], direction && s[`--direction-${direction}`], itemWidth && s[`--item-width-${itemWidth}`], variant && s[`--variant-${variant}`], fadeSide && s["--scrollable"], (fadeSide === "start" || fadeSide === "both") && s["--fade-start"], (fadeSide === "end" || fadeSide === "both") && s["--fade-end"], className);
|
|
30
33
|
const selectorClassNames = classNames(s.selector, selection.status === "idle" && s["selector--hidden"], selection.status === "animated" && s["selector--animated"]);
|
|
31
34
|
const handleNextClick = () => {
|
|
@@ -631,3 +631,64 @@ export const testEdgeCaseDom = {
|
|
|
631
631
|
</Example>);
|
|
632
632
|
},
|
|
633
633
|
};
|
|
634
|
+
export const testOverflowResize = {
|
|
635
|
+
name: "test: overflow on size change",
|
|
636
|
+
render: () => {
|
|
637
|
+
const [narrow, setNarrow] = React.useState(false);
|
|
638
|
+
const [longLabel, setLongLabel] = React.useState(false);
|
|
639
|
+
return (<Example>
|
|
640
|
+
<Example.Item title="container width changes without window resize">
|
|
641
|
+
<View gap={3}>
|
|
642
|
+
<View width={narrow ? "200px" : "640px"}>
|
|
643
|
+
<Tabs defaultValue="0">
|
|
644
|
+
<Tabs.List attributes={{ "data-testid": "container-tabs" }}>
|
|
645
|
+
{[...Array(4)].map((_, i) => (<Tabs.Item value={`${i}`} key={i}>
|
|
646
|
+
Item {i}
|
|
647
|
+
</Tabs.Item>))}
|
|
648
|
+
</Tabs.List>
|
|
649
|
+
</Tabs>
|
|
650
|
+
</View>
|
|
651
|
+
<View direction="row">
|
|
652
|
+
<Button onClick={() => setNarrow((v) => !v)}>Toggle container width</Button>
|
|
653
|
+
</View>
|
|
654
|
+
</View>
|
|
655
|
+
</Example.Item>
|
|
656
|
+
|
|
657
|
+
<Example.Item title="content width changes">
|
|
658
|
+
<View gap={3}>
|
|
659
|
+
<View width="200px">
|
|
660
|
+
<Tabs defaultValue="0">
|
|
661
|
+
<Tabs.List attributes={{ "data-testid": "content-tabs" }}>
|
|
662
|
+
<Tabs.Item value="0">Item 0</Tabs.Item>
|
|
663
|
+
<Tabs.Item value="1">
|
|
664
|
+
{longLabel ? "Very long item label that doesn't fit" : "Item 1"}
|
|
665
|
+
</Tabs.Item>
|
|
666
|
+
</Tabs.List>
|
|
667
|
+
</Tabs>
|
|
668
|
+
</View>
|
|
669
|
+
<View direction="row">
|
|
670
|
+
<Button onClick={() => setLongLabel((v) => !v)}>Toggle label length</Button>
|
|
671
|
+
</View>
|
|
672
|
+
</View>
|
|
673
|
+
</Example.Item>
|
|
674
|
+
</Example>);
|
|
675
|
+
},
|
|
676
|
+
play: async ({ canvas }) => {
|
|
677
|
+
const getOverflow = (testId) => {
|
|
678
|
+
const tablist = within(canvas.getByTestId(testId)).getByRole("tablist");
|
|
679
|
+
return getComputedStyle(tablist.parentElement).overflowX;
|
|
680
|
+
};
|
|
681
|
+
const [containerButton, labelButton] = canvas.getAllByRole("button");
|
|
682
|
+
const cases = [
|
|
683
|
+
["container-tabs", containerButton],
|
|
684
|
+
["content-tabs", labelButton],
|
|
685
|
+
];
|
|
686
|
+
for (const [testId, button] of cases) {
|
|
687
|
+
await waitFor(() => expect(getOverflow(testId)).toBe("visible"));
|
|
688
|
+
await userEvent.click(button);
|
|
689
|
+
await waitFor(() => expect(getOverflow(testId)).toBe("auto"));
|
|
690
|
+
await userEvent.click(button);
|
|
691
|
+
await waitFor(() => expect(getOverflow(testId)).toBe("visible"));
|
|
692
|
+
}
|
|
693
|
+
},
|
|
694
|
+
};
|
|
@@ -4,7 +4,7 @@ import { rafThrottle } from "@reshaped/utilities/internal";
|
|
|
4
4
|
import useIsomorphicLayoutEffect from "../../hooks/useIsomorphicLayoutEffect.js";
|
|
5
5
|
import useRTL from "../../hooks/useRTL.js";
|
|
6
6
|
const useFadeSide = (scrollableRef, options = {}) => {
|
|
7
|
-
const { disabled } = options;
|
|
7
|
+
const { contentRef, disabled } = options;
|
|
8
8
|
const [rtl] = useRTL();
|
|
9
9
|
const [fadeSide, setFadeSide] = React.useState(null);
|
|
10
10
|
const updateFade = React.useCallback(() => {
|
|
@@ -12,8 +12,10 @@ const useFadeSide = (scrollableRef, options = {}) => {
|
|
|
12
12
|
if (!elScrollable)
|
|
13
13
|
return;
|
|
14
14
|
const isScrollable = elScrollable.clientWidth < elScrollable.scrollWidth;
|
|
15
|
-
if (!isScrollable)
|
|
15
|
+
if (!isScrollable) {
|
|
16
16
|
setFadeSide(null);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
17
19
|
// scrollLeft in RTL starts from 1 instead of 0, so we compare values using this delta
|
|
18
20
|
const scrollLeft = elScrollable.scrollLeft * (rtl ? -1 : 1);
|
|
19
21
|
const cutOffStart = scrollLeft > 1;
|
|
@@ -32,13 +34,13 @@ const useFadeSide = (scrollableRef, options = {}) => {
|
|
|
32
34
|
if (disabled)
|
|
33
35
|
return;
|
|
34
36
|
const debouncedUpdate = rafThrottle(updateFade);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
const resizeObserver = new ResizeObserver(() => updateFade());
|
|
38
|
+
resizeObserver.observe(elScrollable);
|
|
39
|
+
if (contentRef?.current)
|
|
40
|
+
resizeObserver.observe(contentRef.current);
|
|
39
41
|
elScrollable.addEventListener("scroll", debouncedUpdate);
|
|
40
42
|
return () => {
|
|
41
|
-
|
|
43
|
+
resizeObserver.disconnect();
|
|
42
44
|
elScrollable.removeEventListener("scroll", debouncedUpdate);
|
|
43
45
|
};
|
|
44
46
|
}, [rtl, disabled]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reshaped",
|
|
3
|
-
"version": "4.3.0
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "Professionally crafted design system in React and Figma for building products of any scale and complexity",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
"cssnano": "8.0.2",
|
|
82
82
|
"csstype": "3.2.3",
|
|
83
83
|
"postcss-custom-media": "12.0.1",
|
|
84
|
-
"@reshaped/
|
|
85
|
-
"@reshaped/
|
|
84
|
+
"@reshaped/utilities": "4.3.0",
|
|
85
|
+
"@reshaped/theming": "4.3.0"
|
|
86
86
|
},
|
|
87
87
|
"peerDependencies": {
|
|
88
88
|
"postcss": "^8",
|