Remove animation from home page
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
|||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { formatDate } from "date-fns";
|
import { formatDate } from "date-fns";
|
||||||
import { Code } from "@unsend/ui/src/code";
|
import { Code } from "@unsend/ui/src/code";
|
||||||
|
import { TextWithCopyButton } from "@unsend/ui/src/text-with-copy";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
|
||||||
@@ -236,19 +237,7 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="lg:w-1/2 flex flex-col border rounded-lg p-8">
|
<div className="lg:w-1/2 flex flex-col border rounded-lg p-8">
|
||||||
<div className=" border-l border-dashed flex flex-col gap-8">
|
<div className=" border-l border-dashed flex flex-col gap-8">
|
||||||
<motion.div
|
<div className="flex flex-col gap-4">
|
||||||
initial={{ opacity: 0, y: 20 }}
|
|
||||||
whileInView={{ opacity: 1, y: 0 }}
|
|
||||||
transition={{
|
|
||||||
duration: 0.3,
|
|
||||||
damping: 15,
|
|
||||||
stiffness: 100,
|
|
||||||
type: "spring",
|
|
||||||
delay: 0.3,
|
|
||||||
}}
|
|
||||||
viewport={{ once: true }}
|
|
||||||
className="flex flex-col gap-4"
|
|
||||||
>
|
|
||||||
<div className="flex gap-5 items-start">
|
<div className="flex gap-5 items-start">
|
||||||
<div className=" -ml-2.5">
|
<div className=" -ml-2.5">
|
||||||
<div
|
<div
|
||||||
@@ -274,19 +263,8 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</div>
|
||||||
<motion.div
|
<div>
|
||||||
initial={{ opacity: 0, y: 25 }}
|
|
||||||
whileInView={{ opacity: 1, y: 0 }}
|
|
||||||
transition={{
|
|
||||||
duration: 0.3,
|
|
||||||
damping: 15,
|
|
||||||
stiffness: 100,
|
|
||||||
type: "spring",
|
|
||||||
delay: 0.6,
|
|
||||||
}}
|
|
||||||
viewport={{ once: true }}
|
|
||||||
>
|
|
||||||
<div className="flex gap-5 items-start">
|
<div className="flex gap-5 items-start">
|
||||||
<div className=" -ml-2.5">
|
<div className=" -ml-2.5">
|
||||||
<div
|
<div
|
||||||
@@ -313,7 +291,7 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -337,115 +315,37 @@ export default function Home() {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="lg:w-1/2">
|
<div className="lg:w-1/2">
|
||||||
<motion.div
|
<div className="w-full rounded-lg border">
|
||||||
initial="hidden"
|
|
||||||
whileInView="visible"
|
|
||||||
transition={{
|
|
||||||
duration: 0.3,
|
|
||||||
type: "spring",
|
|
||||||
damping: 13,
|
|
||||||
stiffness: 100,
|
|
||||||
delayChildren: 0.5,
|
|
||||||
staggerChildren: 0.05,
|
|
||||||
delay: 0.3,
|
|
||||||
}}
|
|
||||||
viewport={{ once: true }}
|
|
||||||
className="w-full rounded-lg border"
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, scale: 0.5 },
|
|
||||||
visible: { opacity: 1, scale: 1 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex gap-4 justify-between border-b p-4">
|
<div className="flex gap-4 justify-between border-b p-4">
|
||||||
<motion.div
|
<div className="">
|
||||||
className=""
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, scale: 0.8 },
|
|
||||||
visible: { opacity: 1, scale: 1 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Heading1 />
|
<Heading1 />
|
||||||
</motion.div>
|
</div>
|
||||||
<motion.div
|
<div className="">
|
||||||
className=""
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, scale: 0.8 },
|
|
||||||
visible: { opacity: 1, scale: 1 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Heading2 />
|
<Heading2 />
|
||||||
</motion.div>
|
</div>
|
||||||
<motion.div
|
<div className="">
|
||||||
className=""
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, scale: 0.8 },
|
|
||||||
visible: { opacity: 1, scale: 1 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Heading3 />
|
<Heading3 />
|
||||||
</motion.div>
|
</div>
|
||||||
<motion.div
|
<div className="">
|
||||||
className=""
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, scale: 0.8 },
|
|
||||||
visible: { opacity: 1, scale: 1 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AlignLeft />
|
<AlignLeft />
|
||||||
</motion.div>
|
</div>
|
||||||
<motion.div
|
<div className="">
|
||||||
className=""
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, scale: 0.8 },
|
|
||||||
visible: { opacity: 1, scale: 1 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AlignCenter />
|
<AlignCenter />
|
||||||
</motion.div>
|
</div>
|
||||||
<motion.div
|
<div className="">
|
||||||
className=""
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, scale: 0.8 },
|
|
||||||
visible: { opacity: 1, scale: 1 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AlignRight />
|
<AlignRight />
|
||||||
</motion.div>
|
</div>
|
||||||
<motion.div
|
<div className="">
|
||||||
className=""
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, scale: 0.8 },
|
|
||||||
visible: { opacity: 1, scale: 1 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Bold />
|
<Bold />
|
||||||
</motion.div>
|
</div>
|
||||||
<motion.div
|
<div className="">
|
||||||
className=""
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, scale: 0.8 },
|
|
||||||
visible: { opacity: 1, scale: 1 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Italic />
|
<Italic />
|
||||||
</motion.div>
|
</div>
|
||||||
<motion.div
|
<div className="">
|
||||||
className=""
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, scale: 0.8 },
|
|
||||||
visible: { opacity: 1, scale: 1 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ListOrdered />
|
<ListOrdered />
|
||||||
</motion.div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<motion.div
|
<div className="h-[200px] p-4">
|
||||||
className="h-[200px] p-4"
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, scale: 0.95 },
|
|
||||||
visible: { opacity: 1, scale: 1 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="">
|
<div className="">
|
||||||
<div className="text-xl text-center">Welcome to unsend!</div>
|
<div className="text-xl text-center">Welcome to unsend!</div>
|
||||||
<p className="text-center mt-8">
|
<p className="text-center mt-8">
|
||||||
@@ -453,53 +353,11 @@ export default function Home() {
|
|||||||
Sendgrid and postmark.
|
Sendgrid and postmark.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</div>
|
||||||
</motion.div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-10 flex-col lg:flex-row px-8 lg:px-0">
|
|
||||||
<div className="lg:w-1/2">
|
|
||||||
<div className="flex flex-col gap-3">
|
|
||||||
<DevicePhoneMobileIcon className="h-10 w-10 text-emerald-500" />
|
|
||||||
<p className="text-3xl font-semibold">SMS & Push notification</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="lg:w-1/2">
|
|
||||||
<motion.div
|
|
||||||
initial="hidden"
|
|
||||||
whileInView="visible"
|
|
||||||
transition={{
|
|
||||||
duration: 0.4,
|
|
||||||
type: "spring",
|
|
||||||
damping: 13,
|
|
||||||
stiffness: 100,
|
|
||||||
delayChildren: 0.4,
|
|
||||||
staggerChildren: 0.05,
|
|
||||||
delay: 0.3,
|
|
||||||
}}
|
|
||||||
viewport={{ once: true }}
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, scale: 0.7 },
|
|
||||||
visible: { opacity: 1, scale: 1 },
|
|
||||||
}}
|
|
||||||
className="w-full h-[15rem] rounded-lg border flex justify-center items-center"
|
|
||||||
>
|
|
||||||
<div className="text-3xl">
|
|
||||||
{"Coming soon!".split("").map((l, i) => (
|
|
||||||
<motion.span
|
|
||||||
key={i}
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0 },
|
|
||||||
visible: { opacity: 1 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{l}
|
|
||||||
</motion.span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className=" px-8 lg:px-0 mt-20">
|
<div className=" px-8 lg:px-0 mt-20">
|
||||||
<p className="text-center text-3xl lg:text-6xl ">
|
<p className="text-center text-3xl lg:text-6xl ">
|
||||||
Integrate in minutes
|
Integrate in minutes
|
||||||
@@ -548,7 +406,7 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between mt-20 max-w-5xl mx-auto px-4">
|
<div className="flex justify-between mt-20 max-w-5xl mx-auto px-4">
|
||||||
<div>
|
<div>
|
||||||
Email: <a href="mailto:hello@unsend.dev">hello@unsend.dev</a>
|
<TextWithCopyButton value="hello@unsend.dev" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-8 items-center">
|
<div className="flex gap-8 items-center">
|
||||||
{/* <Link href="https://github.com/unsend-dev/unsend" target="_blank">
|
{/* <Link href="https://github.com/unsend-dev/unsend" target="_blank">
|
||||||
|
@@ -19,8 +19,7 @@ import {
|
|||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@unsend/ui/src/table";
|
} from "@unsend/ui/src/table";
|
||||||
import { Button } from "@unsend/ui/src/button";
|
import { TextWithCopyButton } from "@unsend/ui/src/text-with-copy";
|
||||||
import { CheckIcon, ClipboardCopy } from "lucide-react";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Switch } from "@unsend/ui/src/switch";
|
import { Switch } from "@unsend/ui/src/switch";
|
||||||
import DeleteDomain from "./delete-domain";
|
import DeleteDomain from "./delete-domain";
|
||||||
@@ -90,12 +89,12 @@ export default function DomainItemPage({
|
|||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell className="">MX</TableCell>
|
<TableCell className="">MX</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<InputWithCopyButton
|
<TextWithCopyButton
|
||||||
value={`mail.${domainQuery.data?.subdomain || domainQuery.data?.name}`}
|
value={`mail.${domainQuery.data?.subdomain || domainQuery.data?.name}`}
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="">
|
<TableCell className="">
|
||||||
<InputWithCopyButton
|
<TextWithCopyButton
|
||||||
value={`feedback-smtp.${domainQuery.data?.region}.amazonses.com`}
|
value={`feedback-smtp.${domainQuery.data?.region}.amazonses.com`}
|
||||||
className="w-[200px] overflow-hidden text-ellipsis text-nowrap"
|
className="w-[200px] overflow-hidden text-ellipsis text-nowrap"
|
||||||
/>
|
/>
|
||||||
@@ -114,12 +113,12 @@ export default function DomainItemPage({
|
|||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell className="">TXT</TableCell>
|
<TableCell className="">TXT</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<InputWithCopyButton
|
<TextWithCopyButton
|
||||||
value={`unsend._domainkey.${domainQuery.data?.subdomain || domainQuery.data?.name}`}
|
value={`unsend._domainkey.${domainQuery.data?.subdomain || domainQuery.data?.name}`}
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="">
|
<TableCell className="">
|
||||||
<InputWithCopyButton
|
<TextWithCopyButton
|
||||||
value={`p=${domainQuery.data?.publicKey}`}
|
value={`p=${domainQuery.data?.publicKey}`}
|
||||||
className="w-[200px] overflow-hidden text-ellipsis"
|
className="w-[200px] overflow-hidden text-ellipsis"
|
||||||
/>
|
/>
|
||||||
@@ -135,12 +134,12 @@ export default function DomainItemPage({
|
|||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell className="">TXT</TableCell>
|
<TableCell className="">TXT</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<InputWithCopyButton
|
<TextWithCopyButton
|
||||||
value={`mail.${domainQuery.data?.subdomain || domainQuery.data?.name}`}
|
value={`mail.${domainQuery.data?.subdomain || domainQuery.data?.name}`}
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="">
|
<TableCell className="">
|
||||||
<InputWithCopyButton
|
<TextWithCopyButton
|
||||||
value={`v=spf1 include:amazonses.com ~all`}
|
value={`v=spf1 include:amazonses.com ~all`}
|
||||||
className="w-[200px] overflow-hidden text-ellipsis text-nowrap"
|
className="w-[200px] overflow-hidden text-ellipsis text-nowrap"
|
||||||
/>
|
/>
|
||||||
@@ -156,12 +155,12 @@ export default function DomainItemPage({
|
|||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell className="">TXT</TableCell>
|
<TableCell className="">TXT</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<InputWithCopyButton
|
<TextWithCopyButton
|
||||||
value={`_dmarc.${domainQuery.data?.subdomain || domainQuery.data?.name}`}
|
value={`_dmarc.${domainQuery.data?.subdomain || domainQuery.data?.name}`}
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="">
|
<TableCell className="">
|
||||||
<InputWithCopyButton
|
<TextWithCopyButton
|
||||||
value={`v=DMARC1; p=none;`}
|
value={`v=DMARC1; p=none;`}
|
||||||
className="w-[200px] overflow-hidden text-ellipsis text-nowrap"
|
className="w-[200px] overflow-hidden text-ellipsis text-nowrap"
|
||||||
/>
|
/>
|
||||||
@@ -188,40 +187,6 @@ export default function DomainItemPage({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputWithCopyButton: React.FC<{ value: string; className?: string }> = ({
|
|
||||||
value,
|
|
||||||
className,
|
|
||||||
}) => {
|
|
||||||
const [isCopied, setIsCopied] = React.useState(false);
|
|
||||||
|
|
||||||
const copyToClipboard = async () => {
|
|
||||||
try {
|
|
||||||
await navigator.clipboard.writeText(value);
|
|
||||||
setIsCopied(true);
|
|
||||||
setTimeout(() => setIsCopied(false), 2000); // Reset isCopied to false after 2 seconds
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Failed to copy: ", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={"flex gap-2 items-center group"}>
|
|
||||||
<div className={className}>{value}</div>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
className="hover:bg-transparent p-0 cursor-pointer text-muted-foreground opacity-0 group-hover:opacity-100"
|
|
||||||
onClick={copyToClipboard}
|
|
||||||
>
|
|
||||||
{isCopied ? (
|
|
||||||
<CheckIcon className="h-4 w-4 text-green-500" />
|
|
||||||
) : (
|
|
||||||
<ClipboardCopy className="h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const DomainSettings: React.FC<{ domain: Domain }> = ({ domain }) => {
|
const DomainSettings: React.FC<{ domain: Domain }> = ({ domain }) => {
|
||||||
const updateDomain = api.domain.updateDomain.useMutation();
|
const updateDomain = api.domain.updateDomain.useMutation();
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
|
38
packages/ui/src/text-with-copy.tsx
Normal file
38
packages/ui/src/text-with-copy.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
"use client";
|
||||||
|
import React from "react";
|
||||||
|
import { Button } from "./button";
|
||||||
|
import { CheckIcon, ClipboardCopy } from "lucide-react";
|
||||||
|
|
||||||
|
export const TextWithCopyButton: React.FC<{
|
||||||
|
value: string;
|
||||||
|
className?: string;
|
||||||
|
}> = ({ value, className }) => {
|
||||||
|
const [isCopied, setIsCopied] = React.useState(false);
|
||||||
|
|
||||||
|
const copyToClipboard = async () => {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(value);
|
||||||
|
setIsCopied(true);
|
||||||
|
setTimeout(() => setIsCopied(false), 2000); // Reset isCopied to false after 2 seconds
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Failed to copy: ", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={"flex gap-2 items-center group"}>
|
||||||
|
<div className={className}>{value}</div>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
className="hover:bg-transparent p-0 cursor-pointer text-muted-foreground opacity-0 group-hover:opacity-100"
|
||||||
|
onClick={copyToClipboard}
|
||||||
|
>
|
||||||
|
{isCopied ? (
|
||||||
|
<CheckIcon className="h-4 w-4 text-green-500" />
|
||||||
|
) : (
|
||||||
|
<ClipboardCopy className="h-4 w-4" />
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
Reference in New Issue
Block a user