[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",
|
"./icons": "./dist/icons/index.js",
|
||||||
"./menu": "./dist/menu/index.js",
|
"./menu": "./dist/menu/index.js",
|
||||||
"./popover": "./dist/popover/index.js",
|
"./popover": "./dist/popover/index.js",
|
||||||
|
"./scrollarea": "./dist/scrollarea/index.js",
|
||||||
"./skeleton": "./dist/skeleton/index.js",
|
"./skeleton": "./dist/skeleton/index.js",
|
||||||
"./styles/fonts": "./dist/styles/fonts/index.css",
|
"./styles/fonts": "./dist/styles/fonts/index.css",
|
||||||
"./switch": "./dist/switch/index.js",
|
"./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/icons/index.ts",
|
||||||
"src/menu/index.ts",
|
"src/menu/index.ts",
|
||||||
"src/popover/index.ts",
|
"src/popover/index.ts",
|
||||||
|
"src/scrollarea/index.ts",
|
||||||
"src/skeleton/index.ts",
|
"src/skeleton/index.ts",
|
||||||
"src/switch/index.ts",
|
"src/switch/index.ts",
|
||||||
"src/table/index.ts",
|
"src/table/index.ts",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue