Update scroll area

This commit is contained in:
Nate Kelley 2025-03-24 12:24:49 -06:00
parent 8663eebce5
commit d305e72b5a
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
7 changed files with 49 additions and 88 deletions

View File

@ -40,20 +40,6 @@ export const Default: Story = {
} }
}; };
export const WithSidebar: Story = {
args: {
children: <TestContent />,
sidebar: <div className="">Sidebar Content</div>
},
decorators: [
(Story) => (
<div className="bg-background-secondary" style={{ height: '600px', width: '100%' }}>
<Story />
</div>
)
]
};
export const NonFloating: Story = { export const NonFloating: Story = {
args: { args: {
children: <TestContent />, children: <TestContent />,
@ -66,14 +52,14 @@ export const WithAppPageLayout: Story = {
sidebar: <div className="">Sidebar Content</div>, sidebar: <div className="">Sidebar Content</div>,
children: ( children: (
<TestContent> <TestContent>
<AppPageLayout header="Page Header"> <AppPageLayout header="Page Header" scrollable>
<div> <>
{Array.from({ length: 30 }, (_, i) => ( {Array.from({ length: 30 }, (_, i) => (
<div key={i} className="p-4"> <div key={i} className="p-4">
List Item {i + 1} - Lorem ipsum dolor sit amet, consectetur adipiscing elit. List Item {i + 1} - Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div> </div>
))} ))}
</div> </>
</AppPageLayout> </AppPageLayout>
</TestContent> </TestContent>
), ),

View File

@ -38,7 +38,7 @@ export const NonScrollable: Story = {
args: { args: {
scrollable: false, scrollable: false,
header: <div className="bg-gray-100">Header Content</div>, header: <div className="bg-gray-100">Header Content</div>,
children: <div className="">Fixed Content</div> children: <div className="h-full w-full border border-red-500 bg-red-100">Fixed Content</div>
} }
}; };

View File

@ -1,5 +1,6 @@
import React, { PropsWithChildren } from 'react'; import React, { PropsWithChildren } from 'react';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { ScrollArea } from '../scroll-area/ScrollArea';
export const AppPageLayoutContent: React.FC< export const AppPageLayoutContent: React.FC<
PropsWithChildren<{ PropsWithChildren<{
@ -7,15 +8,12 @@ export const AppPageLayoutContent: React.FC<
scrollable?: boolean; scrollable?: boolean;
}> }>
> = ({ className = '', children, scrollable = true }) => { > = ({ className = '', children, scrollable = true }) => {
const Selector = scrollable ? ScrollArea : 'main';
const ChildSelector = scrollable ? 'main' : React.Fragment;
return ( return (
<main <Selector className={cn('bg-page-background app-content h-full max-h-[100%] p-0', className)}>
className={cn( <ChildSelector>{children}</ChildSelector>
'app-content-page', </Selector>
'bg-page-background app-content h-full max-h-[100%] overflow-hidden p-0',
scrollable && 'overflow-y-auto',
className
)}>
{children}
</main>
); );
}; };

View File

@ -1,5 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react'; import type { Meta, StoryObj } from '@storybook/react';
import { ScrollArea } from './ScrollArea'; import { ScrollArea, ScrollBar } from './ScrollArea';
import { faker } from '@faker-js/faker';
import Image from 'next/image';
const meta = { const meta = {
title: 'UI/ScrollArea/ScrollArea', title: 'UI/ScrollArea/ScrollArea',
@ -59,61 +61,34 @@ export const TallContent: Story = {
}; };
export const WideContent: Story = { export const WideContent: Story = {
render: () => ( render: () => {
<ScrollArea className="h-[200px] w-[350px] rounded-md border p-4"> const works = Array.from({ length: 50 }, (_, i) => ({
<div className="w-[500px]"> artist: `Artist ${i + 1}`,
<p className="mb-4"> art: faker.image.urlLoremFlickr({ category: 'food', width: 300, height: 400 })
This content is intentionally wider than the container to demonstrate horizontal }));
scrolling. The ScrollArea component will automatically add scrollbars as needed.
</p> return (
<div className="flex space-x-4"> <ScrollArea className="w-96 rounded-md border whitespace-nowrap">
{Array.from({ length: 10 }).map((_, i) => ( <div className="flex w-max space-x-4 p-4">
<div {works.map((artwork) => (
key={i} <figure key={artwork.artist} className="shrink-0">
className="flex h-20 w-20 flex-shrink-0 items-center justify-center rounded-md bg-gray-200"> <div className="overflow-hidden rounded-md">
{i + 1} <Image
</div> src={artwork.art}
alt={`Photo by ${artwork.artist}`}
className="aspect-[3/4] h-fit w-fit object-cover"
width={300}
height={400}
/>
</div>
<figcaption className="text-muted-foreground pt-2 text-xs">
Photo by <span className="text-foreground font-semibold">{artwork.artist}</span>
</figcaption>
</figure>
))} ))}
</div> </div>
</div> <ScrollBar orientation="horizontal" />
</ScrollArea> </ScrollArea>
) );
}; }
export const CustomHeight: Story = {
render: () => (
<ScrollArea className="h-[400px] w-[350px] rounded-md border p-4">
<div>
<p className="mb-4 text-lg font-semibold">Taller Scroll Area</p>
{Array.from({ length: 20 }).map((_, i) => (
<p key={i} className="mb-4">
Paragraph {i + 1}: Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
))}
</div>
</ScrollArea>
)
};
export const NestedContent: Story = {
render: () => (
<ScrollArea className="h-[300px] w-[400px] rounded-md border p-4">
<div>
<h3 className="mb-4 text-lg font-semibold">Nested Content Example</h3>
<div className="mb-4">
<p className="mb-2">Main content area with some text.</p>
<div className="rounded-md border p-2">
<h4 className="mb-2 font-medium">Nested Section</h4>
<p>This is nested content inside the scroll area.</p>
</div>
</div>
{Array.from({ length: 10 }).map((_, i) => (
<div key={i} className="mb-4">
<h4 className="mb-1 font-medium">Section {i + 1}</h4>
<p>Additional content for demonstrating scrolling behavior.</p>
</div>
))}
</div>
</ScrollArea>
)
}; };

View File

@ -13,7 +13,9 @@ const ScrollArea = React.forwardRef<
ref={ref} ref={ref}
className={cn('relative overflow-hidden', className)} className={cn('relative overflow-hidden', className)}
{...props}> {...props}>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]"> <ScrollAreaPrimitive.Viewport
className="h-full w-full rounded-[inherit]"
id="scroll-area-viewport">
{children} {children}
</ScrollAreaPrimitive.Viewport> </ScrollAreaPrimitive.Viewport>
<ScrollBar /> <ScrollBar />

View File

@ -10,6 +10,7 @@ import {
useUpdateDashboardConfig useUpdateDashboardConfig
} from '@/api/buster_rest/dashboards'; } from '@/api/buster_rest/dashboards';
import { useDashboardContentStore } from '@/context/Dashboards'; import { useDashboardContentStore } from '@/context/Dashboards';
import { ScrollArea } from '@/components/ui/scroll-area';
export const DashboardViewDashboardController: React.FC<DashboardViewProps> = ({ export const DashboardViewDashboardController: React.FC<DashboardViewProps> = ({
dashboardId, dashboardId,
@ -24,7 +25,7 @@ export const DashboardViewDashboardController: React.FC<DashboardViewProps> = ({
const dashboard = dashboardResponse?.dashboard; const dashboard = dashboardResponse?.dashboard;
return ( return (
<div className="flex h-full flex-col space-y-3 overflow-y-auto p-10"> <ScrollArea className="flex h-full flex-col space-y-3 p-10">
<DashboardEditTitles <DashboardEditTitles
onUpdateDashboard={onUpdateDashboard} onUpdateDashboard={onUpdateDashboard}
dashboardId={dashboardId} dashboardId={dashboardId}
@ -40,6 +41,6 @@ export const DashboardViewDashboardController: React.FC<DashboardViewProps> = ({
onOpenAddContentModal={onOpenAddContentModal} onOpenAddContentModal={onOpenAddContentModal}
readOnly={readOnly} readOnly={readOnly}
/> />
</div> </ScrollArea>
); );
}; };

View File

@ -6,8 +6,7 @@
} }
} }
.scroll-shadow-container { #scroll-area-viewport {
@apply relative overflow-y-auto;
scroll-timeline-name: --scrollShadowContainer; scroll-timeline-name: --scrollShadowContainer;
.scroll-header { .scroll-header {