Add new ScrollArea component

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2025-03-16 08:00:46 +00:00
parent 85df833fe3
commit 2a711a9339
8 changed files with 270 additions and 1 deletions
+33
View File
@@ -12,6 +12,7 @@ import { default as React_2 } from 'react';
import * as React_3 from 'react';
import { ReactNode } from 'react';
import { RefAttributes } from 'react';
import { ScrollArea as ScrollArea_2 } from '@base-ui-components/react/scroll-area';
// @public (undocumented)
export type AlignItems = 'stretch' | 'start' | 'center' | 'end';
@@ -827,6 +828,38 @@ export type ResponsivePropDef<T = any> = RegularPropDef<T> & {
responsive: true;
};
// @public (undocumented)
export const ScrollArea: {
Root: React_2.ForwardRefExoticComponent<
Omit<
ScrollArea_2.Root.Props & React_2.RefAttributes<HTMLDivElement>,
'ref'
> &
React_2.RefAttributes<HTMLDivElement>
>;
Viewport: React_2.ForwardRefExoticComponent<
Omit<
ScrollArea_2.Viewport.Props & React_2.RefAttributes<HTMLDivElement>,
'ref'
> &
React_2.RefAttributes<HTMLDivElement>
>;
Scrollbar: React_2.ForwardRefExoticComponent<
Omit<
ScrollArea_2.Scrollbar.Props & React_2.RefAttributes<HTMLDivElement>,
'ref'
> &
React_2.RefAttributes<HTMLDivElement>
>;
Thumb: React_2.ForwardRefExoticComponent<
Omit<
ScrollArea_2.Thumb.Props & React_2.RefAttributes<HTMLDivElement>,
'ref'
> &
React_2.RefAttributes<HTMLDivElement>
>;
};
// @public (undocumented)
export type Space =
| '0.5'
@@ -0,0 +1,68 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { ScrollArea } from './ScrollArea';
import { Text } from '../Text/Text';
const meta = {
title: 'Components/ScrollArea',
component: ScrollArea.Root,
} satisfies Meta<typeof ScrollArea.Root>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
render: () => (
<ScrollArea.Root style={{ width: '24rem', height: '8.5rem' }}>
<ScrollArea.Viewport
style={{ border: '1px solid var(--canon-border)', borderRadius: '4px' }}
>
<div style={{ padding: '0.75rem', paddingRight: '1.5rem' }}>
<Text style={{ paddingBottom: '1rem' }}>
Vernacular architecture is building done outside any academic
tradition, and without professional guidance. It is not a particular
architectural movement or style, but rather a broad category,
encompassing a wide range and variety of building types, with
differing methods of construction, from around the world, both
historical and extant and classical and modern. Vernacular
architecture constitutes 95% of the world's built environment, as
estimated in 1995 by Amos Rapoport, as measured against the small
percentage of new buildings every year designed by architects and
built by engineers.
</Text>
<Text>
This type of architecture usually serves immediate, local needs, is
constrained by the materials available in its particular region and
reflects local traditions and cultural practices. The study of
vernacular architecture does not examine formally schooled
architects, but instead that of the design skills and tradition of
local builders, who were rarely given any attribution for the work.
More recently, vernacular architecture has been examined by
designers and the building industry in an effort to be more energy
conscious with contemporary design and constructionpart of a
broader interest in sustainable design.
</Text>
</div>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar orientation="vertical">
<ScrollArea.Thumb />
</ScrollArea.Scrollbar>
</ScrollArea.Root>
),
};
@@ -0,0 +1,67 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.canon-ScrollAreaRoot {
box-sizing: border-box;
width: 24rem;
height: 8.5rem;
max-width: calc(100vw - 8rem);
}
.canon-ScrollAreaViewport {
height: 100%;
overscroll-behavior: contain;
}
.canon-ScrollAreaContent {
display: flex;
flex-direction: column;
gap: 1rem;
padding-block: 0.75rem;
padding-left: 1rem;
padding-right: 1.5rem;
}
.canon-ScrollAreaScrollbar {
display: flex;
justify-content: center;
background-color: var(--canon-scrollbar);
width: 0.25rem;
border-radius: 0.375rem;
margin: 0.5rem;
opacity: 0;
transition: opacity 150ms 300ms;
&[data-hovering],
&[data-scrolling] {
opacity: 1;
transition-duration: 75ms;
transition-delay: 0ms;
}
&::before {
content: '';
position: absolute;
width: 1.25rem;
height: 100%;
}
}
.canon-ScrollAreaThumb {
width: 100%;
border-radius: inherit;
background-color: var(--canon-scrollbar-thumb);
}
@@ -0,0 +1,75 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { ScrollArea as ScrollAreaPrimitive } from '@base-ui-components/react/scroll-area';
import clsx from 'clsx';
const ScrollAreaRoot = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, ...props }, ref) => (
<ScrollAreaPrimitive.Root
ref={ref}
className={clsx('canon-ScrollAreaRoot', className)}
{...props}
/>
));
ScrollAreaRoot.displayName = ScrollAreaPrimitive.Root.displayName;
const ScrollAreaViewport = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Viewport>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Viewport>
>(({ className, ...props }, ref) => (
<ScrollAreaPrimitive.Viewport
ref={ref}
className={clsx('canon-ScrollAreaViewport', className)}
{...props}
/>
));
ScrollAreaViewport.displayName = ScrollAreaPrimitive.Viewport.displayName;
const ScrollAreaScrollbar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Scrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Scrollbar>
>(({ className, ...props }, ref) => (
<ScrollAreaPrimitive.Scrollbar
ref={ref}
className={clsx('canon-ScrollAreaScrollbar', className)}
{...props}
/>
));
ScrollAreaScrollbar.displayName = ScrollAreaPrimitive.Scrollbar.displayName;
const ScrollAreaThumb = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Thumb>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Thumb>
>(({ className, ...props }, ref) => (
<ScrollAreaPrimitive.Thumb
ref={ref}
className={clsx('canon-ScrollAreaThumb', className)}
{...props}
/>
));
ScrollAreaThumb.displayName = ScrollAreaPrimitive.Thumb.displayName;
/** @public */
export const ScrollArea = {
Root: ScrollAreaRoot,
Viewport: ScrollAreaViewport,
Scrollbar: ScrollAreaScrollbar,
Thumb: ScrollAreaThumb,
};
@@ -0,0 +1,17 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './ScrollArea';
+1
View File
@@ -27,3 +27,4 @@
@import '../components/Input/Input.styles.css';
@import '../components/Field/Field.styles.css';
@import '../components/Link/styles.css';
@import '../components/ScrollArea/ScrollArea.styles.css';
+8 -1
View File
@@ -109,8 +109,10 @@
--canon-border-warning: #e36d05;
--canon-border-success: #53db83;
/* Ring Colors */
/* Special Colors */
--canon-ring: #1f5493;
--canon-scrollbar: #a0a0a03b;
--canon-scrollbar-thumb: #a0a0a0;
}
/* Dark theme tokens */
@@ -153,4 +155,9 @@
--canon-border-danger: #f87a7a;
--canon-border-warning: #e36d05;
--canon-border-success: #53db83;
/* Special Colors */
--canon-ring: #1f5493;
--canon-scrollbar: #3636363a;
--canon-scrollbar-thumb: #575757;
}
+1
View File
@@ -38,6 +38,7 @@ export * from './components/Checkbox';
export * from './components/Table';
export * from './components/Input';
export * from './components/Field';
export * from './components/ScrollArea';
// Types
export * from './types';