Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ScrollArea] Create new ScrollArea component #665

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7d57e20
[ScrollArea] Create new ScrollArea component
atomiks Sep 30, 2024
7d498d2
Updates
atomiks Sep 30, 2024
00e7e25
Exports
atomiks Sep 30, 2024
e2497af
Fix ref timing
atomiks Sep 30, 2024
8101e7f
Handle content resizing and hidden scrollbars
atomiks Sep 30, 2024
ed0681d
Handle pinch-zoom
atomiks Oct 1, 2024
d034a82
Fix RTL handling
atomiks Oct 1, 2024
b6c0fd7
Support inlay scrollbars
atomiks Oct 2, 2024
c729981
Corner logic
atomiks Oct 2, 2024
7dd9d11
Check for ResizeObserver existence
atomiks Oct 3, 2024
d1cc0cf
Refactor into hooks and add tests
atomiks Oct 7, 2024
a27b78e
Adjust tests
atomiks Oct 7, 2024
3501086
Fix tests
atomiks Oct 7, 2024
ff26970
Reverse measurements
atomiks Oct 7, 2024
12d01a9
Fix tests
atomiks Oct 7, 2024
781611a
Parse computed styles
atomiks Oct 7, 2024
c29fadf
Merge branch 'master' into feat/ScrollArea
atomiks Oct 14, 2024
ad05d64
Migrate to new exports
atomiks Oct 14, 2024
dec8458
Fix imports
atomiks Oct 14, 2024
38d38fb
CSS demo fixes
atomiks Oct 14, 2024
71f8515
Fix syntax replace error
atomiks Oct 15, 2024
fa62cdf
Add style hook tests
atomiks Oct 15, 2024
021ae16
Use new context pattern
atomiks Oct 15, 2024
a5cd4e4
Change context error messages
atomiks Oct 15, 2024
ea74699
Hide scrollbars with style tag, support overscroll-behavior, observe …
atomiks Oct 16, 2024
ef7d2f2
Change content wrapper
atomiks Oct 16, 2024
38f4cc8
type dep
atomiks Oct 16, 2024
5b1686c
Undo overscroll demo style
atomiks Oct 16, 2024
e292a1a
Lint
atomiks Oct 16, 2024
21c51cf
Unconditionally preventDefault
atomiks Oct 16, 2024
09cc4c5
Take into account rubber band in Safari
atomiks Oct 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions docs/data/api/scroll-area-corner.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"props": {
"className": { "type": { "name": "union", "description": "func<br>&#124;&nbsp;string" } },
"render": { "type": { "name": "union", "description": "element<br>&#124;&nbsp;func" } }
},
"name": "ScrollAreaCorner",
"imports": [
"import { ScrollArea } from '@base_ui/react/ScrollArea';\nconst ScrollAreaCorner = ScrollArea.Corner;"
],
"classes": [],
"spread": true,
"themeDefaultProps": true,
"muiName": "ScrollAreaCorner",
"forwardsRefTo": "HTMLDivElement",
"filename": "/packages/mui-base/src/ScrollArea/Corner/ScrollAreaCorner.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/react-scroll-area/\">Scroll Area</a></li></ul>",
"cssComponent": false
}
30 changes: 30 additions & 0 deletions docs/data/api/scroll-area-root.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"props": {
"className": { "type": { "name": "union", "description": "func<br>&#124;&nbsp;string" } },
"gutter": {
"type": {
"name": "enum",
"description": "'both-edges'<br>&#124;&nbsp;'none'<br>&#124;&nbsp;'stable'"
},
"default": "'stable'"
},
"render": { "type": { "name": "union", "description": "element<br>&#124;&nbsp;func" } },
"type": {
"type": { "name": "enum", "description": "'inlay'<br>&#124;&nbsp;'overlay'" },
"default": "'overlay'"
}
},
"name": "ScrollAreaRoot",
"imports": [
"import { ScrollArea } from '@base_ui/react/ScrollArea';\nconst ScrollAreaRoot = ScrollArea.Root;"
],
"classes": [],
"spread": true,
"themeDefaultProps": true,
"muiName": "ScrollAreaRoot",
"forwardsRefTo": "HTMLDivElement",
"filename": "/packages/mui-base/src/ScrollArea/Root/ScrollAreaRoot.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/react-scroll-area/\">Scroll Area</a></li></ul>",
"cssComponent": false
}
23 changes: 23 additions & 0 deletions docs/data/api/scroll-area-scrollbar.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"props": {
"className": { "type": { "name": "union", "description": "func<br>&#124;&nbsp;string" } },
"orientation": {
"type": { "name": "enum", "description": "'horizontal'<br>&#124;&nbsp;'vertical'" },
"default": "'vertical'"
},
"render": { "type": { "name": "union", "description": "element<br>&#124;&nbsp;func" } }
},
"name": "ScrollAreaScrollbar",
"imports": [
"import { ScrollArea } from '@base_ui/react/ScrollArea';\nconst ScrollAreaScrollbar = ScrollArea.Scrollbar;"
],
"classes": [],
"spread": true,
"themeDefaultProps": true,
"muiName": "ScrollAreaScrollbar",
"forwardsRefTo": "HTMLDivElement",
"filename": "/packages/mui-base/src/ScrollArea/Scrollbar/ScrollAreaScrollbar.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/react-scroll-area/\">Scroll Area</a></li></ul>",
"cssComponent": false
}
19 changes: 19 additions & 0 deletions docs/data/api/scroll-area-thumb.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"props": {
"className": { "type": { "name": "union", "description": "func<br>&#124;&nbsp;string" } },
"render": { "type": { "name": "union", "description": "element<br>&#124;&nbsp;func" } }
},
"name": "ScrollAreaThumb",
"imports": [
"import { ScrollArea } from '@base_ui/react/ScrollArea';\nconst ScrollAreaThumb = ScrollArea.Thumb;"
],
"classes": [],
"spread": true,
"themeDefaultProps": true,
"muiName": "ScrollAreaThumb",
"forwardsRefTo": "HTMLDivElement",
"filename": "/packages/mui-base/src/ScrollArea/Thumb/ScrollAreaThumb.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/react-scroll-area/\">Scroll Area</a></li></ul>",
"cssComponent": false
}
19 changes: 19 additions & 0 deletions docs/data/api/scroll-area-viewport.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"props": {
"className": { "type": { "name": "union", "description": "func<br>&#124;&nbsp;string" } },
"render": { "type": { "name": "union", "description": "element<br>&#124;&nbsp;func" } }
},
"name": "ScrollAreaViewport",
"imports": [
"import { ScrollArea } from '@base_ui/react/ScrollArea';\nconst ScrollAreaViewport = ScrollArea.Viewport;"
],
"classes": [],
"spread": true,
"themeDefaultProps": true,
"muiName": "ScrollAreaViewport",
"forwardsRefTo": "HTMLDivElement",
"filename": "/packages/mui-base/src/ScrollArea/Viewport/ScrollAreaViewport.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/react-scroll-area/\">Scroll Area</a></li></ul>",
"cssComponent": false
}
118 changes: 118 additions & 0 deletions docs/data/components/scroll-area/ScrollAreaInlay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
'use client';
import * as React from 'react';
import { ScrollArea } from '@base_ui/react/ScrollArea';
import { styled } from '@mui/system';

const data = [
'f47ac10b-58cc-4372-a567-0e02b2c3d479',
'7c9e6679-7425-40de-944b-e07fc1f90ae7',
'550e8400-e29b-41d4-a716-446655440000',
'9b2b38e2-4c7b-4e53-a228-c89c535c5072',
'3fa85f64-5717-4562-b3fc-2c963f66afa6',
'4dfbdfc4-2d0e-4e6c-8bd6-7c8d765f0a1c',
'aa9e5d30-cf2a-4234-bc9b-6a5d965c6a00',
'16fd2706-8baf-433b-82eb-8c7fada847da',
'66ed7a57-e4b7-4b82-8b1e-2a8942f8ec6e',
'f9e87c8f-7b4f-4c7e-bb72-ebe8e2277c5e',
];

export default function ScrollAreaInlay() {
return (
<ScrollAreaRoot type="inlay" gutter="none">
<ScrollAreaViewport>
<div style={{ padding: '10px 20px' }}>
<h3 style={{ margin: '20px 0 10px' }}>User IDs</h3>
<ul
style={{
padding: '10px 20px',
margin: 0,
display: 'flex',
flexDirection: 'column',
gap: 5,
}}
>
{data.map((value) => (
<li key={value} style={{ padding: 5, whiteSpace: 'nowrap' }}>
{value}
</li>
))}
</ul>
</div>
</ScrollAreaViewport>
<ScrollAreaScrollbar>
<ScrollAreaThumb />
</ScrollAreaScrollbar>
<ScrollAreaScrollbar orientation="horizontal">
<ScrollAreaThumb />
</ScrollAreaScrollbar>
<ScrollAreaCorner />
</ScrollAreaRoot>
);
}

const ScrollAreaRoot = styled(ScrollArea.Root)`
width: 250px;
height: 250px;
border-radius: 6px;
background: #f5f5f5;
overflow: hidden;
`;

const ScrollAreaViewport = styled(ScrollArea.Viewport)`
width: 100%;
height: 100%;
scrollbar-width: none;

&::-webkit-scrollbar {
display: none;
}
`;

const ScrollAreaScrollbar = styled(ScrollArea.Scrollbar)`
width: 10px;
height: calc(100% - var(--scroll-area-corner-height));
background: rgb(220 220 220);
box-sizing: border-box;

&[data-orientation='horizontal'] {
width: calc(100% - var(--scroll-area-corner-width));
height: 10px;
}
`;

const ScrollAreaThumb = styled(ScrollArea.Thumb)`
background: rgb(180 180 180);

&[data-orientation='vertical'] {
width: 10px;
height: var(--scroll-area-thumb-height, 0);
}

&[data-orientation='horizontal'] {
width: var(--scroll-area-thumb-width, 0);
height: 10px;
}

&:hover {
background: rgb(150 150 150);
}

&::before {
content: '';
display: block;
position: absolute;
width: 100%;
height: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
min-width: 22px;
min-height: 22px;
}
`;

const ScrollAreaCorner = styled(ScrollArea.Corner)`
width: var(--scroll-area-corner-width, 10px);
height: var(--scroll-area-corner-height, 10px);
background: rgb(220 220 220);
`;
118 changes: 118 additions & 0 deletions docs/data/components/scroll-area/ScrollAreaInlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
'use client';
import * as React from 'react';
import { ScrollArea } from '@base_ui/react/ScrollArea';
import { styled } from '@mui/system';

const data = [
'f47ac10b-58cc-4372-a567-0e02b2c3d479',
'7c9e6679-7425-40de-944b-e07fc1f90ae7',
'550e8400-e29b-41d4-a716-446655440000',
'9b2b38e2-4c7b-4e53-a228-c89c535c5072',
'3fa85f64-5717-4562-b3fc-2c963f66afa6',
'4dfbdfc4-2d0e-4e6c-8bd6-7c8d765f0a1c',
'aa9e5d30-cf2a-4234-bc9b-6a5d965c6a00',
'16fd2706-8baf-433b-82eb-8c7fada847da',
'66ed7a57-e4b7-4b82-8b1e-2a8942f8ec6e',
'f9e87c8f-7b4f-4c7e-bb72-ebe8e2277c5e',
];

export default function ScrollAreaInlay() {
return (
<ScrollAreaRoot type="inlay" gutter="none">
<ScrollAreaViewport>
<div style={{ padding: '10px 20px' }}>
<h3 style={{ margin: '20px 0 10px' }}>User IDs</h3>
<ul
style={{
padding: '10px 20px',
margin: 0,
display: 'flex',
flexDirection: 'column',
gap: 5,
}}
>
{data.map((value) => (
<li key={value} style={{ padding: 5, whiteSpace: 'nowrap' }}>
{value}
</li>
))}
</ul>
</div>
</ScrollAreaViewport>
<ScrollAreaScrollbar>
<ScrollAreaThumb />
</ScrollAreaScrollbar>
<ScrollAreaScrollbar orientation="horizontal">
<ScrollAreaThumb />
</ScrollAreaScrollbar>
<ScrollAreaCorner />
</ScrollAreaRoot>
);
}

const ScrollAreaRoot = styled(ScrollArea.Root)`
width: 250px;
height: 250px;
border-radius: 6px;
background: #f5f5f5;
overflow: hidden;
`;

const ScrollAreaViewport = styled(ScrollArea.Viewport)`
width: 100%;
height: 100%;
scrollbar-width: none;

&::-webkit-scrollbar {
display: none;
}
`;

const ScrollAreaScrollbar = styled(ScrollArea.Scrollbar)`
width: 10px;
height: calc(100% - var(--scroll-area-corner-height));
background: rgb(220 220 220);
box-sizing: border-box;

&[data-orientation='horizontal'] {
width: calc(100% - var(--scroll-area-corner-width));
height: 10px;
}
`;

const ScrollAreaThumb = styled(ScrollArea.Thumb)`
background: rgb(180 180 180);

&[data-orientation='vertical'] {
width: 10px;
height: var(--scroll-area-thumb-height, 0);
}

&[data-orientation='horizontal'] {
width: var(--scroll-area-thumb-width, 0);
height: 10px;
}

&:hover {
background: rgb(150 150 150);
}

&::before {
content: '';
display: block;
position: absolute;
width: 100%;
height: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
min-width: 22px;
min-height: 22px;
}
`;

const ScrollAreaCorner = styled(ScrollArea.Corner)`
width: var(--scroll-area-corner-width, 10px);
height: var(--scroll-area-corner-height, 10px);
background: rgb(220 220 220);
`;
Loading