Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jobs:
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ vars.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
NEXT_PUBLIC_POSTHOG_KEY: ${{ vars.NEXT_PUBLIC_POSTHOG_KEY }}
NEXT_PUBLIC_POSTHOG_HOST: ${{ vars.NEXT_PUBLIC_POSTHOG_HOST }}
NEXT_PUBLIC_PLUNK_API_KEY: ${{ vars.NEXT_PUBLIC_PLUNK_API_KEY }}
run: yarn build
- name: Deploy to Cloudflare Pages
id: deploy
Expand Down
47 changes: 47 additions & 0 deletions animata/widget/calendar-widget.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import CalendarWidget from "@/animata/widget/calendar-widget";
import { Meta, StoryObj } from "@storybook/react";

const meta = {
title: "Widget/Calendar Widget",
component: CalendarWidget,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
argTypes: {
initialSelectedDate: {
control: { type: "number", min: 1, max: 30 },
defaultValue: 1,
},
initialShowEvents: {
control: { type: "boolean" },
defaultValue: true,
},
eventsData: {
control: { type: "object" },
defaultValue: [
{ date: 3, title: "Project Review", time: "10:00 - 11:00 AM" },
{ date: 5, title: "Client Meeting", time: "9:00 - 9:45 AM" },
{ date: 18, title: "Walk", time: "6:00 - 7:00 AM" },
],
},
},
} satisfies Meta<typeof CalendarWidget>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Primary: Story = {
args: {
initialSelectedDate: 1,
initialShowEvents: true,
eventsData: [
{ date: 3, title: "Project Review", time: "10:00 - 11:00 AM" },
{ date: 3, title: "Project discussion", time: "11:00 - 12:00 AM" },
{ date: 5, title: "Client Meeting", time: "9:00 - 9:45 AM" },
{ date: 18, title: "Walk", time: "6:00 - 7:00 AM" },
],
month: 3,
year: 2023,
},
};
154 changes: 154 additions & 0 deletions animata/widget/calendar-widget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import React, { useEffect, useRef, useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { Calendar as CalendarIcon, DotIcon } from "lucide-react";

const monthArray = [
"",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
];

interface EventType {
date: number;
title: string;
time: string;
}

export default function CalendarWidget({
initialSelectedDate = 1,
initialShowEvents = true,
eventsData = [],
month = 1,
year = new Date().getFullYear(),
}: {
initialSelectedDate?: number;
initialShowEvents?: boolean;
eventsData?: EventType[];
month?: number;
year?: number;
}) {
const [selectedDate, setSelectedDate] = useState(initialSelectedDate);
const [showEvents, setShowEvents] = useState(initialShowEvents);
const scrollRef = useRef<HTMLDivElement>(null);

const dates = Array.from({ length: 30 }, (_, i) => i + 1);
const daySymbols = ["S", "M", "T", "W", "T", "F", "S"];

const filteredEvents = eventsData.filter((event: EventType) => event.date === selectedDate);

useEffect(() => {
if (scrollRef.current) {
const selectedElement = scrollRef.current.querySelector(`[data-date="${selectedDate}"]`);
if (selectedElement) {
selectedElement.scrollIntoView({ behavior: "smooth", inline: "center", block: "nearest" });
}
}
}, [selectedDate]);

return (
<motion.div
className="mx-auto max-w-sm rounded-3xl bg-slate-200 shadow-lg"
initial={{ scale: 0.9, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ duration: 0.3 }}
>
<div className="mx-auto max-w-sm rounded-3xl px-6 py-2">
<h2 className="mb-4 text-2xl font-bold">{`${monthArray[month]} ${year}`}</h2>
<div
ref={scrollRef}
className="scrollbar-hide flex items-start space-x-2 overflow-x-auto py-2"
style={{ scrollbarWidth: "none", msOverflowStyle: "none" }}
>
{dates.map((date, index) => (
<motion.button
key={date}
data-date={date}
className="flex w-10 flex-shrink-0 flex-col items-center justify-center gap-y-2 rounded-lg"
onClick={() => {
setSelectedDate(date);
setShowEvents(true);
}}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
<span className="mb-1 text-xs">{daySymbols[(index + 4) % 7]}</span>
<AnimatePresence>
{selectedDate === date ? (
<motion.span
layoutId="highlighted-date"
className="flex h-8 w-8 items-center justify-center rounded-full bg-gray-100 text-black shadow-lg"
transition={{
type: "spring",
stiffness: 300,
damping: 20,
}}
>
{date}
</motion.span>
) : (
<span className="flex h-8 w-8 items-center justify-center">{date}</span>
)}
</AnimatePresence>
<span>
{eventsData.find((alldates: EventType) => alldates.date === date) ? (
<DotIcon />
) : (
""
)}
</span>
</motion.button>
))}
</div>
</div>

<div className="w-full rounded-3xl bg-[#fefefe] px-6 shadow-lg">
<AnimatePresence mode="wait">
{showEvents && (
<motion.div
key="events"
className="scrollbar-hide mt-2 h-[150px] overflow-scroll border-t pt-4"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.2 }}
>
{filteredEvents.length > 0 ? (
filteredEvents.map((event: EventType, index: number) => (
<motion.div
key={index}
className="mb-2 border-b-2 border-slate-200"
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: index * 0.1 }}
>
<h4 className="font-medium">{event.title}</h4>
<p className="text-sm text-gray-500">{event.time}</p>
</motion.div>
))
) : (
<motion.div
className="flex flex-col items-center text-gray-500"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
>
<CalendarIcon className="mb-2 h-8 w-8" />
<p>No Events</p>
</motion.div>
)}
</motion.div>
)}
</AnimatePresence>
</div>
</motion.div>
);
}
13 changes: 6 additions & 7 deletions app/_landing/hero.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Link from "next/link";

import CarbonAds from "@/components/ads";
import { Icons } from "@/components/icons";
import { PageHeaderDescription } from "@/components/page-header";
import { buttonVariants } from "@/components/ui/button";
Expand Down Expand Up @@ -69,19 +70,17 @@ export default function Hero() {
<Pill className="right-12 top-20 -translate-y-1/2 -rotate-6">1000+ stars</Pill>
<Pill className="bottom-12 left-12 -rotate-6">1033+ hours of development</Pill>
<Pill className="right-8 top-1/2 -translate-y-1/2">250+ hours of research</Pill>
<Pill className="bottom-32 left-12 aspect-square -translate-y-full translate-x-full">
<Icons.framerMotion className="size-6" />
</Pill>

<div className="absolute left-12 top-1/2 w-32 -translate-y-1/2">
<CarbonAds />
</div>
<Pill className="bottom-24 right-12 aspect-square -translate-x-full -translate-y-full p-2">
<Icons.tailwind className="size-6" />
</Pill>
<Pill className="bottom-12 right-12 aspect-square translate-x-1/2 translate-y-1/2 p-1">
<Icons.nextJS className="size-12" />
<Icons.framerMotion className="size-6" />
</Pill>
<Pill className="right-12 top-32 aspect-square translate-y-full p-1">
<Icons.yarn className="size-10" />
</Pill>
<Pill className="left-12 top-32 aspect-square translate-y-full p-2">
<Icons.reactJS className="size-8" />
</Pill>
<svg className="hidden">
Expand Down
5 changes: 4 additions & 1 deletion app/docs/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { allDocs } from "contentlayer/generated";
import Balancer from "react-wrap-balancer";

import NavMenu from "@/app/docs/[[...slug]]/nav-menu";
import CarbonAds from "@/components/ads";
import { Mdx } from "@/components/mdx-components";
import { DocsPager } from "@/components/pager";
import { DashboardTableOfContents } from "@/components/toc";
Expand All @@ -18,7 +19,6 @@ import { ChevronRightIcon, ExternalLinkIcon } from "@radix-ui/react-icons";

import "@/styles/mdx.css";
import "@/styles/storybook.css";

interface DocPageProps {
params: {
slug: string[];
Expand Down Expand Up @@ -144,6 +144,9 @@ export default async function DocPage({ params }: DocPageProps) {
)}
</div>
) : null}
<div className="relative w-fit overflow-y-hidden rounded-xl">
<CarbonAds />
</div>
<div className="pb-12">
<Mdx code={doc.body.code} />

Expand Down
4 changes: 2 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import "@/styles/globals.css";

export const metadata: Metadata = {
title: {
default: siteConfig.name,
template: `%s - ${siteConfig.name}`,
default: `Free & Open Source Animated ReactJS Components | ${siteConfig.name}`,
template: "%s | Free & Open Source Animated ReactJS Components",
},
metadataBase: new URL(siteConfig.url),
description: siteConfig.description,
Expand Down
38 changes: 38 additions & 0 deletions components/ads.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"use client";

import { useEffect } from "react";
import { usePathname } from "next/navigation";

export default function CarbonAds() {
const pathname = usePathname();

useEffect(() => {
// Skip loading ads in development environment
if (
typeof window !== "undefined" &&
(window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1")
) {
return;
}

const script = document.createElement("script");
script.src =
"//cdn.carbonads.com/carbon.js?serve=CW7ITK77&placement=animatadesign&format=cover";
script.id = "_carbonads_js";
script.async = true;

const container = document.getElementById("carbon-container");
if (container && !document.getElementById("_carbonads_js")) {
container.appendChild(script);
}

return () => {
const existingScript = document.getElementById("_carbonads_js");
if (existingScript && existingScript.parentNode) {
existingScript.parentNode.removeChild(existingScript);
}
};
}, [pathname]);

return <div id="carbon-container" />;
}
3 changes: 3 additions & 0 deletions content/docs/background/moving-gradient.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ author: harimanok_
```js
theme: {
extend: {
animation: {
"bg-position": "bg-position 3s infinite alternate",
},
keyframes: {
"bg-position": {
"0%": { backgroundPosition: "0% 50%" },
Expand Down
2 changes: 1 addition & 1 deletion content/docs/container/marquee.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ theme: {
from: { transform: "translateY(0)" },
to: { transform: "translateY(calc(-100% - var(--gap)))" },
},
}
},
animation: {
"marquee-horizontal": "marquee-x var(--duration) infinite linear",
"marquee-vertical": "marquee-y var(--duration) linear infinite",
Expand Down
2 changes: 1 addition & 1 deletion content/docs/section/pricing.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Pricing
description: Pricing component that display the pricing options of various plans in an sleek and interactive way
description: Pricing component that displays the pricing options of various plans in a sleek and interactive way
author: SatyamVyas04
---

Expand Down
38 changes: 38 additions & 0 deletions content/docs/widget/calendar-widget.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Calendar Widget
description: calendar widget is calender like widget with smooth animations and cool effects
author: anshu_code
---

<ComponentPreview name="widget-calendar-widget--docs" />

## Installation

<Steps>
<Step>Install dependencies</Step>

```bash
npm install framer-motion lucide-react
```

<Step>Run the following command</Step>

It will create a new file `calendar-widget.tsx` inside the `components/animata/widget` directory.

```bash
mkdir -p components/animata/widget && touch components/animata/widget/calendar-widget.tsx
```

<Step>Paste the code</Step>{" "}

Open the newly created file and paste the following code:

```jsx file=<rootDir>/animata/widget/calendar-widget.tsx

```

</Steps>

## Credits

Built by [Anshuman](https://github.com/anshuman008)
Loading