Skip to content

Commit

Permalink
[Feat]: New Component - Animated Scroll Progress (#177)
Browse files Browse the repository at this point in the history
* feat: Added new Component - ScrollProgess

* chore: Added credits section and changed the date in MDX page

* fix: lint and mdx fix

---------

Co-authored-by: Dipesh <dtamangt582@gmail.com>
Co-authored-by: Arghya Das <arghyadasproject@gmail.com>
  • Loading branch information
3 people authored Dec 19, 2024
1 parent e163f07 commit e1c6709
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 1 deletion.
26 changes: 26 additions & 0 deletions __registry__/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ export const Index: Record<string, any> = {
subcategory: "undefined",
chunks: [],
},
"scroll-progress": {
name: "scroll-progress",
type: "registry:ui",
registryDependencies: undefined,
files: ["registry/default/magicui/scroll-progress.tsx"],
component: React.lazy(
() => import("@/registry/default/magicui/scroll-progress.tsx"),
),
source: "",
category: "undefined",
subcategory: "undefined",
chunks: [],
},
"neon-gradient-card": {
name: "neon-gradient-card",
type: "registry:ui",
Expand Down Expand Up @@ -763,6 +776,19 @@ export const Index: Record<string, any> = {
subcategory: "undefined",
chunks: [],
},
"scroll-progress-demo": {
name: "scroll-progress-demo",
type: "registry:example",
registryDependencies: ["scroll-progress"],
files: ["registry/default/example/scroll-progress-demo.tsx"],
component: React.lazy(
() => import("@/registry/default/example/scroll-progress-demo.tsx"),
),
source: "",
category: "undefined",
subcategory: "undefined",
chunks: [],
},
"neon-gradient-card-demo": {
name: "neon-gradient-card-demo",
type: "registry:example",
Expand Down
6 changes: 6 additions & 0 deletions config/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,12 @@ export const docsConfig: DocsConfig = {
items: [],
label: "",
},
{
title: "Scroll Progress",
href: `/docs/components/scroll-progress`,
items: [],
label: "New",
},
],
},
{
Expand Down
50 changes: 50 additions & 0 deletions content/docs/components/scroll-progress.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: Scroll Progress
date: 2024-12-19
description: Animated Scroll Progress for your pages
author: dipesh_the_dev
published: true
---

<ComponentPreview name="scroll-progress-demo" />

## Installation

<Tabs defaultValue="cli">
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">

```bash
npx shadcn@latest add "https://magicui.design/r/scroll-progress"
```

</TabsContent>

<TabsContent value="manual">

<Steps>

<Step>Copy and paste the following code into your project.</Step>

<ComponentSource name="scroll-progress" />

</Steps>

</TabsContent>

</Tabs>

## Props

| Prop | Type | Description | Default |
| --------- | ------ | --------------------------------------------- | ------- |
| className | string | The class name to be applied to the component | - |

The `ScrollProgress` component also accepts all properties of the `HTMLDivElement` type.

## Credits

- Credit to [dipesh_the_dev](https://twitter.com/dipesh_the_dev)
13 changes: 13 additions & 0 deletions public/r/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@
}
]
},
{
"name": "scroll-progress",
"type": "registry:ui",
"dependencies": [
"framer-motion"
],
"files": [
{
"path": "magicui/scroll-progress.tsx",
"type": "registry:ui"
}
]
},
{
"name": "neon-gradient-card",
"type": "registry:ui",
Expand Down
2 changes: 1 addition & 1 deletion public/r/styles/default/bento-grid.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"files": [
{
"path": "magicui/bento-grid.tsx",
"content": "import { ReactNode } from \"react\";\nimport { ArrowRightIcon } from \"@radix-ui/react-icons\";\n\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/button\";\n\nconst BentoGrid = ({\n children,\n className,\n}: {\n children: ReactNode;\n className?: string;\n}) => {\n return (\n <div\n className={cn(\n \"grid w-full auto-rows-[22rem] grid-cols-3 gap-4\",\n className,\n )}\n >\n {children}\n </div>\n );\n};\n\nconst BentoCard = ({\n name,\n className,\n background,\n Icon,\n description,\n href,\n cta,\n}: {\n name: string;\n className: string;\n background: ReactNode;\n Icon: any;\n description: string;\n href: string;\n cta: string;\n}) => (\n <div\n key={name}\n className={cn(\n \"group relative col-span-3 flex flex-col justify-between overflow-hidden rounded-xl\",\n // light styles\n \"bg-white [box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05),0_12px_24px_rgba(0,0,0,.05)]\",\n // dark styles\n \"transform-gpu dark:bg-black dark:[border:1px_solid_rgba(255,255,255,.1)] dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset]\",\n className,\n )}\n >\n <div>{background}</div>\n <div className=\"pointer-events-none z-10 flex transform-gpu flex-col gap-1 p-6 transition-all duration-300 group-hover:-translate-y-10\">\n <Icon className=\"h-12 w-12 origin-left transform-gpu text-neutral-700 transition-all duration-300 ease-in-out group-hover:scale-75\" />\n <h3 className=\"text-xl font-semibold text-neutral-700 dark:text-neutral-300\">\n {name}\n </h3>\n <p className=\"max-w-lg text-neutral-400\">{description}</p>\n </div>\n\n <div\n className={cn(\n \"pointer-events-none absolute bottom-0 flex w-full translate-y-10 transform-gpu flex-row items-center p-4 opacity-0 transition-all duration-300 group-hover:translate-y-0 group-hover:opacity-100\",\n )}\n >\n <Button variant=\"ghost\" asChild size=\"sm\" className=\"pointer-events-auto\">\n <a href={href}>\n {cta}\n <ArrowRightIcon className=\"ml-2 h-4 w-4\" />\n </a>\n </Button>\n </div>\n <div className=\"pointer-events-none absolute inset-0 transform-gpu transition-all duration-300 group-hover:bg-black/[.03] group-hover:dark:bg-neutral-800/10\" />\n </div>\n);\n\nexport { BentoCard, BentoGrid };\n",
"content": "import { ReactNode } from \"react\";\nimport { ArrowRightIcon } from \"@radix-ui/react-icons\";\n\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/button\";\n\ntype BentoGridProps = {\n children: ReactNode;\n className?: string;\n};\n\ntype BentoCardProps = {\n name: string;\n className: string;\n background: ReactNode;\n Icon: any;\n description: string;\n href: string;\n cta: string;\n};\n\nconst BentoGrid = ({ children, className }: BentoGridProps) => {\n return (\n <div\n className={cn(\n \"grid w-full auto-rows-[22rem] grid-cols-3 gap-4\",\n className,\n )}\n >\n {children}\n </div>\n );\n};\n\nconst BentoCard = ({\n name,\n className,\n background,\n Icon,\n description,\n href,\n cta,\n}: BentoCardProps) => (\n <div\n key={name}\n className={cn(\n \"group relative col-span-3 flex flex-col justify-between overflow-hidden rounded-xl\",\n // light styles\n \"bg-white [box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05),0_12px_24px_rgba(0,0,0,.05)]\",\n // dark styles\n \"transform-gpu dark:bg-black dark:[border:1px_solid_rgba(255,255,255,.1)] dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset]\",\n className,\n )}\n >\n <div>{background}</div>\n <div className=\"pointer-events-none z-10 flex transform-gpu flex-col gap-1 p-6 transition-all duration-300 group-hover:-translate-y-10\">\n <Icon className=\"h-12 w-12 origin-left transform-gpu text-neutral-700 transition-all duration-300 ease-in-out group-hover:scale-75\" />\n <h3 className=\"text-xl font-semibold text-neutral-700 dark:text-neutral-300\">\n {name}\n </h3>\n <p className=\"max-w-lg text-neutral-400\">{description}</p>\n </div>\n\n <div\n className={cn(\n \"pointer-events-none absolute bottom-0 flex w-full translate-y-10 transform-gpu flex-row items-center p-4 opacity-0 transition-all duration-300 group-hover:translate-y-0 group-hover:opacity-100\",\n )}\n >\n <Button variant=\"ghost\" asChild size=\"sm\" className=\"pointer-events-auto\">\n <a href={href}>\n {cta}\n <ArrowRightIcon className=\"ml-2 h-4 w-4\" />\n </a>\n </Button>\n </div>\n <div className=\"pointer-events-none absolute inset-0 transform-gpu transition-all duration-300 group-hover:bg-black/[.03] group-hover:dark:bg-neutral-800/10\" />\n </div>\n);\n\nexport { BentoCard, BentoGrid };\n",
"type": "registry:ui",
"target": ""
}
Expand Down
15 changes: 15 additions & 0 deletions public/r/styles/default/scroll-progress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "scroll-progress",
"type": "registry:ui",
"dependencies": [
"framer-motion"
],
"files": [
{
"path": "magicui/scroll-progress.tsx",
"content": "import { cn } from \"@/lib/utils\";\nimport { motion, useScroll, useSpring } from \"framer-motion\";\n\ninterface ScrollProgressProps {\n className?: string;\n}\n\nexport default function ScrollProgress({ className }: ScrollProgressProps) {\n const { scrollYProgress } = useScroll();\n\n const scaleX = useSpring(scrollYProgress, {\n stiffness: 200,\n damping: 50,\n restDelta: 0.001,\n });\n\n return (\n <motion.div\n className={cn(\n \"fixed inset-x-0 top-0 z-[1000] h-1 origin-left bg-gradient-to-r from-[#A97CF8] via-[#F38CB8] to-[#FDCC92]\",\n className,\n )}\n style={{\n scaleX,\n }}\n />\n );\n}\n",
"type": "registry:ui",
"target": ""
}
]
}
20 changes: 20 additions & 0 deletions registry/default/example/scroll-progress-demo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import ScrollProgress from "@/registry/default/magicui/scroll-progress";

const ScrollProgressDemo = () => {
return (
<div className="z-10 rounded-lg border border-gray-200 bg-white p-4">
<ScrollProgress className="top-[65px]" />
<h2 className="pb-4 font-bold">
Note: The scroll progress is shown below the navbar of the page.
</h2>
<p className="pb-4">
Magic UI is a collection of re-usable components that you can copy and
paste into your web apps. It primarily features components, blocks, and
templates geared towards creating landing pages and user-facing
marketing materials.
</p>
</div>
);
};

export default ScrollProgressDemo;
28 changes: 28 additions & 0 deletions registry/default/magicui/scroll-progress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { cn } from "@/lib/utils";
import { motion, useScroll, useSpring } from "framer-motion";

interface ScrollProgressProps {
className?: string;
}

export default function ScrollProgress({ className }: ScrollProgressProps) {
const { scrollYProgress } = useScroll();

const scaleX = useSpring(scrollYProgress, {
stiffness: 200,
damping: 50,
restDelta: 0.001,
});

return (
<motion.div
className={cn(
"fixed inset-x-0 top-0 z-[1000] h-1 origin-left bg-gradient-to-r from-[#A97CF8] via-[#F38CB8] to-[#FDCC92]",
className,
)}
style={{
scaleX,
}}
/>
);
}
6 changes: 6 additions & 0 deletions registry/registry-examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ export const examples: Registry = [
registryDependencies: ["magic-card"],
files: ["example/magic-card-demo.tsx"],
},
{
name: "scroll-progress-demo",
type: "registry:example",
registryDependencies: ["scroll-progress"],
files: ["example/scroll-progress-demo.tsx"],
},
{
name: "neon-gradient-card-demo",
type: "registry:example",
Expand Down
6 changes: 6 additions & 0 deletions registry/registry-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ export const ui: Registry = [
dependencies: ["framer-motion"],
files: ["magicui/magic-card.tsx"],
},
{
name: "scroll-progress",
type: "registry:ui",
dependencies: ["framer-motion"],
files: ["magicui/scroll-progress.tsx"],
},
{
name: "neon-gradient-card",
type: "registry:ui",
Expand Down

0 comments on commit e1c6709

Please sign in to comment.