[WEB-4729] dev: propel scrollarea (#7748)
* dev: scrollarea added to propel * dev: scrollarea story added * chore: propel config updated * fix: format error
This commit is contained in:
parent
37ce8a9fe6
commit
fbd48c33f5
5 changed files with 192 additions and 0 deletions
|
|
@ -27,6 +27,7 @@
|
|||
"./icons": "./dist/icons/index.js",
|
||||
"./menu": "./dist/menu/index.js",
|
||||
"./popover": "./dist/popover/index.js",
|
||||
"./scrollarea": "./dist/scrollarea/index.js",
|
||||
"./skeleton": "./dist/skeleton/index.js",
|
||||
"./styles/fonts": "./dist/styles/fonts/index.css",
|
||||
"./switch": "./dist/switch/index.js",
|
||||
|
|
|
|||
1
packages/propel/src/scrollarea/index.ts
Normal file
1
packages/propel/src/scrollarea/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from "./scrollarea";
|
||||
100
packages/propel/src/scrollarea/scrollarea.stories.tsx
Normal file
100
packages/propel/src/scrollarea/scrollarea.stories.tsx
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import { ScrollArea } from "./scrollarea";
|
||||
|
||||
const meta: Meta<typeof ScrollArea> = {
|
||||
title: "Components/ScrollArea",
|
||||
component: ScrollArea,
|
||||
parameters: {
|
||||
layout: "padded",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"A customizable scroll area component with multiple size variants, scroll behaviors, and orientations.",
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
orientation: {
|
||||
control: { type: "select" },
|
||||
options: ["vertical", "horizontal"],
|
||||
description: "Orientation of the scrollbar",
|
||||
table: {
|
||||
type: { summary: "ScrollAreaOrientation" },
|
||||
defaultValue: { summary: "vertical" },
|
||||
},
|
||||
},
|
||||
size: {
|
||||
control: { type: "select" },
|
||||
options: ["sm", "md", "lg"],
|
||||
description: "Size variant of the scrollbar",
|
||||
table: {
|
||||
type: { summary: "ScrollAreaSize" },
|
||||
defaultValue: { summary: "md" },
|
||||
},
|
||||
},
|
||||
scrollType: {
|
||||
control: { type: "select" },
|
||||
options: ["always", "scroll", "hover"],
|
||||
description: "When to show the scrollbar",
|
||||
table: {
|
||||
type: { summary: "ScrollAreaScrollType" },
|
||||
defaultValue: { summary: "always" },
|
||||
},
|
||||
},
|
||||
className: {
|
||||
control: { type: "text" },
|
||||
description: "Additional CSS classes",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof ScrollArea>;
|
||||
|
||||
// Sample content components for stories
|
||||
const LongTextContent = () => (
|
||||
<div className="p-4 space-y-4">
|
||||
<h3 className="text-lg font-semibold">Long Text Content</h3>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore
|
||||
magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat.
|
||||
</p>
|
||||
<p>
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
|
||||
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
</p>
|
||||
<p>
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem
|
||||
aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
|
||||
</p>
|
||||
<p>
|
||||
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores
|
||||
eos qui ratione voluptatem sequi nesciunt.
|
||||
</p>
|
||||
<p>
|
||||
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam
|
||||
eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.
|
||||
</p>
|
||||
<p>
|
||||
Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea
|
||||
commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae
|
||||
consequatur.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
// Default story
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
className: "h-64 w-80 border rounded-lg",
|
||||
size: "md",
|
||||
scrollType: "always",
|
||||
orientation: "vertical",
|
||||
},
|
||||
render: (args) => (
|
||||
<ScrollArea {...args}>
|
||||
<LongTextContent />
|
||||
</ScrollArea>
|
||||
),
|
||||
};
|
||||
89
packages/propel/src/scrollarea/scrollarea.tsx
Normal file
89
packages/propel/src/scrollarea/scrollarea.tsx
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import * as React from "react";
|
||||
import { ScrollArea as BaseScrollArea } from "@base-ui-components/react/scroll-area";
|
||||
|
||||
import { cn } from "../utils/classname";
|
||||
|
||||
type ScrollAreaOrientation = "horizontal" | "vertical";
|
||||
type ScrollAreaScrollType = "always" | "scroll" | "hover";
|
||||
type ScrollAreaSize = "sm" | "md" | "lg";
|
||||
|
||||
interface ScrollAreaProps extends React.ComponentProps<typeof BaseScrollArea.Root> {
|
||||
orientation?: ScrollAreaOrientation;
|
||||
scrollType?: ScrollAreaScrollType;
|
||||
size?: ScrollAreaSize;
|
||||
}
|
||||
|
||||
function ScrollArea({ className, children, orientation, scrollType, size = "md", ...props }: ScrollAreaProps) {
|
||||
return (
|
||||
<BaseScrollArea.Root data-slot="scroll-area" className={cn("relative", className)} {...props}>
|
||||
<BaseScrollArea.Viewport
|
||||
data-slot="scroll-area-viewport"
|
||||
className="focus-visible:ring-ring/50 size-full overscroll-contain rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline"
|
||||
>
|
||||
{children}
|
||||
</BaseScrollArea.Viewport>
|
||||
<ScrollBar orientation={orientation} scrollType={scrollType} size={size} />
|
||||
<BaseScrollArea.Corner />
|
||||
</BaseScrollArea.Root>
|
||||
);
|
||||
}
|
||||
|
||||
const horizontalSizeStyles = {
|
||||
sm: "p-[0.112rem] h-2.5",
|
||||
md: "p-[0.112rem] h-3",
|
||||
lg: "p-[0.112rem] h-4",
|
||||
} as const;
|
||||
|
||||
const verticalSizeStyles = {
|
||||
sm: "p-[0.112rem] w-2.5",
|
||||
md: "p-[0.112rem] w-3",
|
||||
lg: "p-[0.112rem] w-4",
|
||||
} as const;
|
||||
|
||||
const thumbSizeStyles = {
|
||||
sm: "before:absolute before:left-1/2 before:top-1/2 before:size-full before:min-h-11 before:min-w-11 before:-translate-x-1/2 before:-translate-y-1/2",
|
||||
md: "before:absolute before:left-1/2 before:top-1/2 before:size-full before:min-h-14 before:min-w-14 before:-translate-x-1/2 before:-translate-y-1/2",
|
||||
lg: "before:absolute before:left-1/2 before:top-1/2 before:size-full before:min-h-17 before:min-w-17 before:-translate-x-1/2 before:-translate-y-1/2",
|
||||
} as const;
|
||||
|
||||
interface ScrollBarProps extends React.ComponentProps<typeof BaseScrollArea.Scrollbar> {
|
||||
scrollType?: ScrollAreaScrollType;
|
||||
size?: ScrollAreaSize;
|
||||
}
|
||||
|
||||
const ScrollBar = React.memo(function ScrollBar({
|
||||
className,
|
||||
orientation = "vertical",
|
||||
scrollType = "always",
|
||||
size = "md",
|
||||
...props
|
||||
}: ScrollBarProps) {
|
||||
return (
|
||||
<BaseScrollArea.Scrollbar
|
||||
data-slot="scroll-area-scrollbar"
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"group/track mr-1 flex justify-center rounded bg-transparent opacity-0 transition-opacity delay-300 ",
|
||||
orientation === "vertical" && verticalSizeStyles[size],
|
||||
orientation === "horizontal" && horizontalSizeStyles[size],
|
||||
scrollType === "always" && "opacity-100",
|
||||
scrollType === "scroll" &&
|
||||
"data-[scrolling]:opacity-100 data-[scrolling]:delay-0 data-[scrolling]:duration-75",
|
||||
scrollType === "hover" && "data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[hovering]:duration-75",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<BaseScrollArea.Thumb
|
||||
data-slot="scroll-area-thumb"
|
||||
className={cn(
|
||||
"relative flex-1 rounded-[10px] bg-custom-scrollbar-neutral group-hover:bg-custom-scrollbar-hover group-active/track:bg-custom-scrollbar-active data-[scrolling]:bg-custom-scrollbar-active",
|
||||
thumbSizeStyles[size]
|
||||
)}
|
||||
/>
|
||||
</BaseScrollArea.Scrollbar>
|
||||
);
|
||||
});
|
||||
|
||||
export { ScrollArea };
|
||||
export type { ScrollAreaProps, ScrollAreaOrientation, ScrollAreaScrollType, ScrollAreaSize };
|
||||
|
|
@ -13,6 +13,7 @@ export default defineConfig({
|
|||
"src/icons/index.ts",
|
||||
"src/menu/index.ts",
|
||||
"src/popover/index.ts",
|
||||
"src/scrollarea/index.ts",
|
||||
"src/skeleton/index.ts",
|
||||
"src/switch/index.ts",
|
||||
"src/table/index.ts",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue