Showing preview only (603K chars total). Download the full file or copy to clipboard to get everything.
Repository: hiteshchoudhary/devui
Branch: main
Commit: 1a21d47a1fb6
Files: 82
Total size: 572.3 KB
Directory structure:
gitextract_hoj68ou7/
├── .eslintrc.json
├── .gitignore
├── README.md
├── next.config.js
├── package.json
├── postcss.config.js
├── prettier.config.js
├── src/
│ ├── app/
│ │ ├── about-us/
│ │ │ └── page.tsx
│ │ ├── globals.css
│ │ ├── layout.tsx
│ │ ├── page.tsx
│ │ └── templates/
│ │ ├── [id]/
│ │ │ └── page.tsx
│ │ └── page.tsx
│ ├── components/
│ │ ├── common/
│ │ │ ├── Button.tsx
│ │ │ ├── MainNavbar.tsx
│ │ │ ├── MobileNavbar.tsx
│ │ │ └── Select.tsx
│ │ ├── lib/
│ │ │ ├── CodePreviewer.tsx
│ │ │ ├── CodeSnippetRenderer.tsx
│ │ │ ├── PreviewCard.tsx
│ │ │ └── WidthHandler.tsx
│ │ └── templates/
│ │ ├── authentication/
│ │ │ ├── forgot-password.jsx
│ │ │ ├── index.ts
│ │ │ ├── login.jsx
│ │ │ └── register.jsx
│ │ ├── chat/
│ │ │ ├── chat-screen.jsx
│ │ │ ├── create-group-chat.jsx
│ │ │ ├── create-normal-chat.jsx
│ │ │ ├── empty-chats.jsx
│ │ │ ├── group-information.jsx
│ │ │ ├── index.ts
│ │ │ ├── login.jsx
│ │ │ └── register.jsx
│ │ ├── social-media/
│ │ │ ├── bookmark-posts.jsx
│ │ │ ├── change-password.jsx
│ │ │ ├── edit-profile.jsx
│ │ │ ├── index.ts
│ │ │ ├── login.jsx
│ │ │ ├── my-profile.jsx
│ │ │ ├── post-detail.jsx
│ │ │ ├── post-listing.jsx
│ │ │ ├── register.jsx
│ │ │ └── user-profile.jsx
│ │ ├── todo/
│ │ │ ├── empty-todos.jsx
│ │ │ ├── index.ts
│ │ │ └── todos.jsx
│ │ └── youtube/
│ │ ├── change-password.jsx
│ │ ├── channel-empty-playlist.jsx
│ │ ├── channel-empty-subscribed.jsx
│ │ ├── channel-empty-tweet.jsx
│ │ ├── channel-empty-video.jsx
│ │ ├── channel-playlist-videos.jsx
│ │ ├── channel-playlist.jsx
│ │ ├── channel-subscribed.jsx
│ │ ├── channel-tweets.jsx
│ │ ├── channel-video-list.jsx
│ │ ├── dashboard.jsx
│ │ ├── data.jsx
│ │ ├── delete-video.jsx
│ │ ├── edit-channel-info.jsx
│ │ ├── edit-personal-info.jsx
│ │ ├── edit-video.jsx
│ │ ├── empty-videos.jsx
│ │ ├── index.ts
│ │ ├── login.jsx
│ │ ├── mychannel-empty-tweet.jsx
│ │ ├── mychannel-empty-video.jsx
│ │ ├── mychannel-tweets.jsx
│ │ ├── privacy-policy.jsx
│ │ ├── register.jsx
│ │ ├── terms-and-conditions.jsx
│ │ ├── upload-video.jsx
│ │ ├── uploaded-video.jsx
│ │ ├── uploading-video.jsx
│ │ ├── video-cards.jsx
│ │ ├── video-detail.jsx
│ │ └── video-list.jsx
│ ├── types/
│ │ └── utils.ts
│ └── utils/
│ ├── index.ts
│ └── screens.tsx
├── tailwind.config.ts
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .eslintrc.json
================================================
{
"extends": "next/core-web-vitals",
"rules": {
// next no-img-element
"@next/next/no-img-element": "off"
}
}
================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
================================================
FILE: README.md
================================================
# DevUI
A complete front end solution for learners
================================================
FILE: next.config.js
================================================
/** @type {import('next').NextConfig} */
const nextConfig = {
images: { domains: ["via.placeholder.com"] },
};
module.exports = nextConfig;
================================================
FILE: package.json
================================================
{
"name": "devui",
"description": "Common app templates in plain HTML and TailwindCSS",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@headlessui/react": "^1.7.17",
"@heroicons/react": "^2.0.18",
"@types/node": "20.5.6",
"@types/react": "18.2.21",
"@types/react-dom": "18.2.7",
"@uiw/codemirror-extensions-langs": "^4.21.11",
"@uiw/codemirror-themes-all": "^4.21.11",
"@uiw/react-codemirror": "^4.21.11",
"autoprefixer": "10.4.15",
"eslint": "8.47.0",
"eslint-config-next": "13.4.19",
"next": "13.4.19",
"postcss": "8.4.28",
"react": "18.2.0",
"react-dom": "18.2.0",
"tailwindcss": "3.3.3",
"typescript": "5.2.2"
},
"devDependencies": {
"@types/prettier": "^3.0.0",
"prettier": "^3.0.2",
"prettier-plugin-tailwindcss": "^0.5.3"
}
}
================================================
FILE: postcss.config.js
================================================
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
================================================
FILE: prettier.config.js
================================================
module.exports = {
plugins: ["prettier-plugin-tailwindcss"],
};
================================================
FILE: src/app/about-us/page.tsx
================================================
import React from "react";
const AboutUs = () => {
return <div>AboutUs</div>;
};
export default AboutUs;
================================================
FILE: src/app/globals.css
================================================
@tailwind base;
@tailwind components;
@tailwind utilities;
.resizing,
.resizing * {
@apply !cursor-ew-resize !select-none;
}
.resizing .iframe-overlay {
display: block !important;
}
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.CodeMirror__Main__Editor {
@apply overflow-hidden rounded-md;
}
.CodeMirror__Main__Editor .cm-scroller {
@apply rounded-md px-4 py-2 pb-0;
}
================================================
FILE: src/app/layout.tsx
================================================
import MainNavbar from "@/components/common/MainNavbar";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "DevUI | For learners",
description: "Common app templates in plain HTML and TailwindCSS",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={`${inter.className} bg-dark text-white`}>
<MainNavbar />
<main className="mx-auto max-w-[85rem] p-4 lg:p-6">{children}</main>
</body>
</html>
);
}
================================================
FILE: src/app/page.tsx
================================================
import Button from "@/components/common/Button";
import {
CodeBracketSquareIcon,
LifebuoyIcon,
} from "@heroicons/react/24/outline";
import Image from "next/image";
import Link from "next/link";
export default function Home() {
return (
<section aria-labelledby="hero-banner">
<div className="flex flex-col items-start gap-4">
<Image src="/hero.svg" alt="Hero" width={250} height={100} />
<h1 className="font-heading text-3xl font-bold leading-[1.1] md:text-5xl lg:text-7xl">
A complete front end solution for learners
</h1>
<p className="max-w-[42rem] leading-normal text-gray-300 sm:text-xl sm:leading-8">
DevUI is a comprehensive and easy-to-use open-source UI templates
library ( powered by <strong>TailwindCSS</strong>) designed to
enhance your productivity as a learner
</p>
<div className="mt-2 flex space-x-2">
<Link href="/templates">
<Button StartIcon={CodeBracketSquareIcon}>View templates</Button>
</Link>
<a
href="https://github.com/hiteshchoudhary/devui"
target="_blank"
rel="noreferrer"
>
<Button StartIcon={LifebuoyIcon}>Contribute</Button>
</a>
</div>
</div>
</section>
);
}
================================================
FILE: src/app/templates/[id]/page.tsx
================================================
"use client";
import Select from "@/components/common/Select";
import CodePreviewer from "@/components/lib/CodePreviewer";
import { SelectOptionType } from "@/types/utils";
import { applications, getComponentByAppPageId } from "@/utils/screens";
import { useParams } from "next/navigation";
import { useEffect, useState } from "react";
const TemplateDetails = () => {
const { id } = useParams();
const [loadingUi, setLoadingUi] = useState(true);
const [selectedPageUI, setSelectedPageUI] = useState<SelectOptionType | null>(
null,
);
const [app, setApp] = useState<(typeof applications)[0] | null>(null);
useEffect(() => {
if (!applications) return;
const _app = applications.find((app) => app.id === id) || applications[0];
setApp(_app);
setSelectedPageUI(_app.pages[0]); // set 1st page as default selected page
setLoadingUi(false);
}, [applications]);
if (loadingUi) return <h1>Loading screens...</h1>;
return (
<div>
<Select
options={app?.pages || []}
label="Select a page UI"
value={selectedPageUI}
setValue={setSelectedPageUI}
/>
<div className="w-full">
<CodePreviewer title={selectedPageUI?.name || "DevUI Screen"}>
{getComponentByAppPageId(app?.id || "", selectedPageUI?.id || "")}
</CodePreviewer>
</div>
</div>
);
};
export default TemplateDetails;
================================================
FILE: src/app/templates/page.tsx
================================================
"use client";
import Button from "@/components/common/Button";
import { applications } from "@/utils/screens";
import {
ChevronDoubleRightIcon,
RectangleGroupIcon,
} from "@heroicons/react/24/outline";
import Link from "next/link";
const Templates = () => {
return (
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
{applications.map((application, i) => {
return (
<main key={i} className="py-6 md:px-4">
<div className="mx-auto grid max-w-4xl grid-cols-1">
<div className="relative col-start-1 row-start-1 flex flex-col-reverse bg-gradient-to-t from-black/100 via-black/0 p-3">
<h1 className="mt-1 text-lg font-semibold text-white">
{application.name}
</h1>
<p className="text-sm font-medium leading-4 text-white">
{application.subtitle}
</p>
</div>
<div className="col-start-1 col-end-3 row-start-1 grid items-end justify-end gap-4 border border-gray-700">
<img
src={application.cover}
alt=""
className="w-full object-cover"
loading="lazy"
/>
</div>
<dl className="row-start-2 mt-2 inline-flex items-center text-sm font-medium text-gray-200">
<dd className="inline-flex items-center gap-1">
<RectangleGroupIcon className="-mt-0.5 h-5 w-5" />
{application.pages?.length || 0} Screens
</dd>
</dl>
<div className="col-start-1 row-start-3 mt-2 self-center">
<Link href={`/templates/${application.id}`}>
<Button EndIcon={ChevronDoubleRightIcon}>View Screens</Button>
</Link>
</div>
<p className="col-start-1 mt-4 text-sm leading-6">
{application.description}
</p>
</div>
</main>
);
})}
</div>
);
};
export default Templates;
================================================
FILE: src/components/common/Button.tsx
================================================
import { TailwindIconType } from "@/types/utils";
import React from "react";
const Button: React.FC<
React.ButtonHTMLAttributes<HTMLButtonElement> & {
StartIcon?: TailwindIconType;
EndIcon?: TailwindIconType;
}
> = ({ StartIcon, EndIcon, children, ...props }) => {
return (
<button
type="button"
className="inline-flex items-center gap-x-1.5 rounded-md bg-white px-3 py-2.5 text-sm font-semibold text-gray-950 shadow-sm hover:bg-gray-200 active:bg-gray-300 disabled:bg-slate-500"
{...props}
>
{StartIcon ? (
<StartIcon className="-ml-0.5 h-5 w-5" aria-hidden="true" />
) : null}
{children}
{EndIcon ? (
<EndIcon className="-mr-0.5 h-5 w-5" aria-hidden="true" />
) : null}
</button>
);
};
export default Button;
================================================
FILE: src/components/common/MainNavbar.tsx
================================================
"use client";
import { classNames } from "@/utils";
import { CodeBracketSquareIcon } from "@heroicons/react/20/solid";
import { Bars3BottomLeftIcon, XMarkIcon } from "@heroicons/react/24/outline";
import Link from "next/link";
import React, { useState } from "react";
import { MobileNavbar } from "./MobileNavbar";
const items = [
{
title: "Home",
href: "/",
},
{
title: "Templates",
href: "/templates",
},
{
title: "About us",
href: "/about-us",
},
];
const MainNavbar = () => {
const [showMobileMenu, setShowMobileMenu] = useState<boolean>(false);
return (
<header className="border-slate-800e bg-dark sticky top-0 z-40 border-b-2 border-gray-700">
<div className="mx-auto flex h-20 max-w-[85rem] items-center justify-between p-4 lg:p-6">
<div className="flex gap-6 md:gap-10">
<Link href="/" className="hidden items-center space-x-2 md:flex">
<CodeBracketSquareIcon className="h-7 w-7 text-white" />
<span className="font-heading hidden text-xl font-extrabold sm:inline-block">
DevUI
</span>
</Link>
{items?.length ? (
<nav className="hidden gap-6 md:flex">
{items?.map((item, index) => (
<Link
key={index}
href={item.href}
className={classNames(
"flex items-center text-lg font-semibold transition-colors sm:text-sm",
)}
>
{item.title}
</Link>
))}
</nav>
) : null}
<button
className="flex items-center space-x-2 md:hidden"
onClick={() => setShowMobileMenu(!showMobileMenu)}
>
{showMobileMenu ? (
<XMarkIcon className="h-5 w-5 text-white" />
) : (
<Bars3BottomLeftIcon className="h-5 w-5 text-white" />
)}
<span className="font-heading text-xl font-extrabold sm:inline-block">
DevUI
</span>
</button>
{showMobileMenu && items && <MobileNavbar items={items} />}
</div>
</div>
</header>
);
};
export default MainNavbar;
================================================
FILE: src/components/common/MobileNavbar.tsx
================================================
import * as React from "react";
import Link from "next/link";
import { CodeBracketSquareIcon } from "@heroicons/react/20/solid";
import { classNames } from "@/utils";
interface MobileNavProps {
items: {
title: string;
href: string;
}[];
}
export function MobileNavbar({ items }: MobileNavProps) {
return (
<div
className={classNames(
"animate-in slide-in-from-bottom-80 fixed inset-0 top-16 z-50 grid h-[calc(100vh-4rem)] grid-flow-row auto-rows-max overflow-auto p-6 pb-32 shadow-md md:hidden",
)}
>
<div className="text-popover-foreground relative z-20 grid gap-6 rounded-md bg-dark p-4 shadow-md shadow-gray-700">
<Link href="/" className="flex items-center space-x-2">
<CodeBracketSquareIcon className="h-7 w-7 text-white" />
<span className="font-bold">DevUI</span>
</Link>
<nav className="grid grid-flow-row auto-rows-max text-sm">
{items.map((item, index) => (
<Link
key={index}
href={item.href}
className={classNames(
"flex w-full items-center rounded-md p-2 text-sm font-medium hover:underline",
)}
>
{item.title}
</Link>
))}
</nav>
</div>
</div>
);
}
================================================
FILE: src/components/common/Select.tsx
================================================
"use client";
import { SelectOptionType } from "@/types/utils";
import { classNames } from "@/utils";
import { Combobox } from "@headlessui/react";
import { CheckIcon, ChevronUpDownIcon } from "@heroicons/react/20/solid";
import React, { useState } from "react";
interface SelectProps {
label: string;
options: SelectOptionType[];
value: SelectOptionType | null;
setValue: (val: { id: string; name: string }) => void;
}
const Select: React.FC<SelectProps> = ({ label, options, value, setValue }) => {
const [query, setQuery] = useState("");
const filteredOptions =
query === ""
? options
: options.filter((option) => {
return option.name.toLowerCase().includes(query.toLowerCase());
});
return (
<Combobox as="div" value={value} onChange={setValue}>
<Combobox.Label className="block text-sm font-medium leading-6">
{label}
</Combobox.Label>
<div className="relative mt-2">
<Combobox.Button className="w-full">
<Combobox.Input
className="peer block w-full rounded-md border border-gray-700 bg-transparent px-6 py-4 text-base/6 text-white ring-4 ring-transparent transition focus:border-white focus:outline-none focus:ring-white/5 group-first:rounded-t-2xl group-last:rounded-b-2xl"
onChange={(event) => setQuery(event.target.value)}
displayValue={(option: any) => option?.name}
/>
</Combobox.Button>
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none">
<ChevronUpDownIcon
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</Combobox.Button>
<Combobox.Options className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-gray-900 py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
{filteredOptions.map((option) => (
<Combobox.Option
key={option.id}
value={option}
className={({ active }) =>
classNames(
"relative cursor-default select-none py-2 pl-8 pr-4 text-white",
active ? "bg-slate-600" : "",
)
}
>
{({ active }) => (
<>
<span
className={classNames(
"block truncate capitalize",
option.id === value?.id ? "font-semibold" : "",
)}
>
{option.name}
</span>
{option.id === value?.id && (
<span
className={classNames(
"absolute inset-y-0 left-0 flex items-center pl-1.5",
active ? "text-white" : "text-gray-200",
)}
>
<CheckIcon className="h-5 w-5" aria-hidden="true" />
</span>
)}
</>
)}
</Combobox.Option>
))}
</Combobox.Options>
</div>
</Combobox>
);
};
export default Select;
================================================
FILE: src/components/lib/CodePreviewer.tsx
================================================
import { renderHTMLFromJSX } from "@/utils";
import { CheckCircleIcon } from "@heroicons/react/20/solid";
import {
CodeBracketIcon,
DocumentDuplicateIcon,
EyeIcon,
} from "@heroicons/react/24/outline";
import React, { useState } from "react";
import CodeSnippetRenderer from "./CodeSnippetRenderer";
import PreviewCard from "./PreviewCard";
interface CodePreviewerProps {
title: string;
children: React.ReactElement;
}
const CodePreviewer: React.FC<CodePreviewerProps> = ({ children, title }) => {
const [previewMode, setPreviewMode] = useState(true);
const [codeCopied, setCodeCopied] = useState(false);
const copyToClipboard = () => {
const codeToCopy = renderHTMLFromJSX(children);
navigator.clipboard.writeText(codeToCopy);
setCodeCopied(true);
setTimeout(() => {
setCodeCopied(false);
}, 4000);
};
return (
<div className="my-8 md:my-12 lg:my-14">
<div className="flex flex-col justify-between md:flex-row md:items-center">
<div className="mb-4 flex flex-row items-center space-x-4 md:mb-0">
<h3 className=" font-sans font-semibold md:mb-0">{title}</h3>
</div>
<div className="flex items-center space-x-4">
{/* Buttons */}
<div className="">
<span className="isolate inline-flex rounded-md shadow-sm">
<button
onClick={() => setPreviewMode(true)}
type="button"
className="relative inline-flex items-center rounded-l-md bg-gray-800 px-2 py-2 ring-1 ring-inset ring-gray-500 hover:bg-gray-700 focus:z-10"
>
<span className="sr-only">UI preview</span>
<span className="flex items-center space-x-2 text-sm font-semibold text-gray-200">
<EyeIcon className="h-4 w-4" />
<span>Preview</span>
</span>
</button>
<button
onClick={() => setPreviewMode(false)}
type="button"
className="relative -ml-px inline-flex items-center rounded-r-md bg-gray-800 px-2 py-2 ring-1 ring-inset ring-gray-500 hover:bg-gray-700 focus:z-10"
>
<span className="sr-only">Code snippet</span>
<span className="flex items-center space-x-2 text-sm font-semibold text-gray-200">
<CodeBracketIcon className="h-4 w-4" />
<span>Code</span>
</span>
</button>
</span>
</div>
<button
onClick={() => {
if (codeCopied) return;
copyToClipboard();
}}
className="cursor-pointer rounded-md p-2 hover:bg-gray-700 active:bg-gray-600"
>
{codeCopied ? (
<CheckCircleIcon className="h-5 w-5 text-green-600" />
) : (
<DocumentDuplicateIcon className="h-5 w-5" />
)}
</button>
</div>
</div>
<div className="mt-4 w-full">
{previewMode ? (
<PreviewCard>{children}</PreviewCard>
) : (
<CodeSnippetRenderer codeSnippet={renderHTMLFromJSX(children)} />
)}
</div>
</div>
);
};
export default CodePreviewer;
================================================
FILE: src/components/lib/CodeSnippetRenderer.tsx
================================================
import { langs } from "@uiw/codemirror-extensions-langs";
import * as themes from "@uiw/codemirror-themes-all";
import CodeMirror from "@uiw/react-codemirror";
import * as parserBabel from "prettier/parser-babel";
import * as parserHtml from "prettier/parser-html";
import prettier from "prettier/standalone";
import React, { useEffect, useState } from "react";
const DEFAULT_BASE_SETUP = {
foldGutter: false,
highlightActiveLine: false,
highlightActiveLineGutter: false,
indentOnInput: true,
lineNumbers: false,
syntaxHighlighting: true,
tabSize: 4,
};
interface CodeSnippetRendererProps {
codeSnippet: string;
}
const CodeSnippetRenderer: React.FC<CodeSnippetRendererProps> = ({
codeSnippet,
}) => {
const [code, setCode] = useState("");
const formatCode = async () => {
try {
const formattedCode = await prettier.format(codeSnippet, {
parser: "html",
plugins: [parserHtml, parserBabel],
semi: false,
printWidth: 200,
tabWidth: 2,
bracketSameLine: true,
singleAttributePerLine: true,
htmlWhitespaceSensitivity: "ignore",
});
setCode(formattedCode);
} catch (error) {
console.error("Error while formatting the code: \n", error);
setCode(codeSnippet);
}
};
useEffect(() => {
formatCode();
}, [codeSnippet]);
return (
<div className="relative min-h-min w-full rounded-md border-2 border-gray-700 pb-0">
<CodeMirror
className={"CodeMirror__Main__Editor"}
theme={themes["githubDark"]}
value={code}
extensions={[langs.html()]}
readOnly={true}
style={{
fontSize: "14px",
}}
basicSetup={{
...DEFAULT_BASE_SETUP,
}}
indentWithTab
/>
</div>
);
};
export default CodeSnippetRenderer;
================================================
FILE: src/components/lib/PreviewCard.tsx
================================================
import { classNames, renderHTMLFromJSX } from "@/utils";
import { useEffect, useRef, useState } from "react";
import WidthHandler from "./WidthHandler";
interface PreviewCardProps {
className?: string;
children: React.ReactElement;
}
const PreviewCard = ({ children, className }: PreviewCardProps) => {
const editorRef = useRef<HTMLDivElement>(null);
const [containerWidth, setContainerWidth] = useState("100%");
const [maxWidth, setMaxWidth] = useState<number | null>(null);
useEffect(() => {
if (!editorRef.current || maxWidth) return; // once set don't set max width again
setMaxWidth(editorRef.current?.clientWidth);
}, [editorRef]);
return (
<div
ref={editorRef}
className={classNames(
"relative mx-auto min-h-[865px] overflow-visible rounded-md border-2 border-gray-700",
className || "",
)}
style={{
width: containerWidth || "100%",
}}
>
<WidthHandler
innerRef={editorRef}
onChange={(width) => {
setContainerWidth(`${width}px`);
}}
maxWidth={maxWidth || 1440}
/>
{/*
// ! Reason to use iframe instead on any normal div is to avoid interference of devui parent project's styling and classes with the example's styling an classes
// ! using iframe will isolate the examples from devui's parent application code.
*/}
<div
className={classNames(
"iframe-overlay absolute inset-0 z-20 mx-auto hidden h-full min-h-[865px] w-full overflow-auto rounded-md",
)}
></div>
<iframe
className={classNames(
"z-10 mx-auto min-h-[865px] w-full overflow-auto rounded-md",
)}
srcDoc={`
<script src="https://cdn.tailwindcss.com"></script>
${renderHTMLFromJSX(children)}`}
></iframe>
</div>
);
};
export default PreviewCard;
================================================
FILE: src/components/lib/WidthHandler.tsx
================================================
import React, { RefObject, useEffect, useRef } from "react";
export const DEFAULT_WIDTHS = {
minWidth: 360,
};
interface Props {
innerRef: RefObject<HTMLDivElement>;
onChange: (width: number) => void;
maxWidth: number;
}
const edgeCase = (
value: number,
min: number,
max: number,
): [number, boolean] => {
if (value < min) {
return [min, false];
}
if (value > max) {
return [max, false];
}
return [value, true];
};
const WidthHandler: React.FC<Props> = ({ innerRef, onChange, maxWidth }) => {
const { minWidth } = DEFAULT_WIDTHS;
const startX = useRef<number | null>(null);
const startWidth = useRef<number | null>(null);
useEffect(() => {
const handleMouseMove = (e: MouseEvent) => {
if (!startX.current || !startWidth.current) return;
const delta = e.pageX - startX.current; // leftOrRight === 'left' ? startX - e.pageX : (startX - e.pageX) * -1
const calculated = startWidth.current + delta * window.devicePixelRatio;
const [newWidth, isChanging] = edgeCase(calculated, minWidth, maxWidth);
if (isChanging) {
onChange(newWidth);
}
};
window.addEventListener("mousemove", handleMouseMove);
return () => window.removeEventListener("mousemove", handleMouseMove);
}, [innerRef, maxWidth, minWidth, onChange]);
useEffect(() => {
const handleMouseUp = () => {
startX.current = null;
document.body.classList.remove("resizing");
};
window.addEventListener("mouseup", handleMouseUp);
return () => window.removeEventListener("mouseup", handleMouseUp);
}, []);
return (
<div
onMouseDown={(e) => {
document.body.classList.add("resizing");
startX.current = e.pageX;
startWidth.current = innerRef.current
? innerRef.current.clientWidth
: 0;
}}
role="separator"
aria-orientation="vertical"
aria-valuemin={minWidth}
aria-valuemax={maxWidth}
className="absolute -right-4 top-1/2 z-30 flex h-14 w-2 cursor-ew-resize rounded-md bg-slate-600"
></div>
);
};
export default WidthHandler;
================================================
FILE: src/components/templates/authentication/forgot-password.jsx
================================================
import React from "react";
const ForgotPassword = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto w-full max-w-full bg-[#121212] p-6 text-white lg:px-10">
<h1>DevUI</h1>
</header>
<div className="mx-auto flex w-full items-stretch justify-between gap-10">
<div className="mt-20 flex w-full flex-col items-start justify-start p-6 md:w-1/2 lg:px-10">
<div className="w-full">
<h1 className="mb-2 text-5xl font-extrabold text-white">
Forgot password?
</h1>
<p className="text-xs text-slate-400">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Maxime
eius, aliquid autem numquam iure sint perspiciatis voluptatum
soluta fugiat.
</p>
</div>
<div className="my-14 flex w-full flex-col items-start justify-start gap-4">
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Email</label>
<input
placeholder="Enter an email..."
autoComplete="false"
type="email"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<button className="w-full bg-[#ae7aff] p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Start recovery
</button>
<p className="my-14 text-sm font-light text-white">
Already registered?{" "}
<span className="cursor-pointer font-bold hover:underline">
Sign in to your account
</span>
</p>
</div>
</div>
<div className="fixed right-0 z-20 hidden h-screen w-1/2 md:block">
<img
className="h-full w-full object-cover"
src="https://images.pexels.com/photos/1144275/pexels-photo-1144275.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="register_image"
/>
</div>
</div>
</div>
);
};
export default ForgotPassword;
================================================
FILE: src/components/templates/authentication/index.ts
================================================
import Register from "./register";
import Login from "./login";
import ForgotPassword from "./forgot-password";
const Authentication = { Register, Login, ForgotPassword };
export default Authentication;
================================================
FILE: src/components/templates/authentication/login.jsx
================================================
import React from "react";
const Login = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto w-full max-w-full bg-[#121212] p-6 text-white lg:px-10">
<h1>DevUI</h1>
</header>
<div className="mx-auto flex w-full items-stretch justify-between gap-10">
<div className="mt-20 flex w-full flex-col items-start justify-start p-6 md:w-1/2 lg:px-10">
<div className="w-full">
<h1 className="mb-2 text-5xl font-extrabold text-white">Log in</h1>
<p className="text-xs text-slate-400">
Before we start, please log into your account
</p>
</div>
<div className="my-14 flex w-full flex-col items-start justify-start gap-4">
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Username</label>
<input
placeholder="Enter a username..."
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Password</label>
<input
placeholder="Enter a password..."
autoComplete="false"
type="password"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="inline-flex w-full items-center justify-between">
<div className="mr-4 flex items-center">
<input
type="checkbox"
id="checkbox-1"
name="checkbox-1"
className="absolute h-6 w-6 cursor-pointer opacity-0 [&:checked+div]:bg-green-500 [&:checked+div_svg]:block"
/>
<div className="mr-2 flex h-6 w-6 flex-shrink-0 items-center justify-center border-[1px] border-white bg-transparent focus-within:border-white">
<svg
className="pointer-events-none hidden h-3 w-3 fill-current text-white"
version="1.1"
viewBox="0 0 17 12"
xmlns="http://www.w3.org/2000/svg"
>
<g fill="none" fillRule="evenodd">
<g
transform="translate(-9 -11)"
fill="#000000"
fillRule="nonzero"
>
<path d="m25.576 11.414c0.56558 0.55188 0.56558 1.4439 0 1.9961l-9.404 9.176c-0.28213 0.27529-0.65247 0.41385-1.0228 0.41385-0.37034 0-0.74068-0.13855-1.0228-0.41385l-4.7019-4.588c-0.56584-0.55188-0.56584-1.4442 0-1.9961 0.56558-0.55214 1.4798-0.55214 2.0456 0l3.679 3.5899 8.3812-8.1779c0.56558-0.55214 1.4798-0.55214 2.0456 0z" />
</g>
</g>
</svg>
</div>
<div className="ml-3 text-sm leading-6">
<label
htmlFor="checkbox-1"
className="text-sm font-medium text-white"
>
Remember me
</label>
</div>
</div>
<p className="cursor-pointer text-sm text-white hover:underline">
Forgot password?
</p>
</div>
<button className="w-full bg-[#ae7aff] p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Log in
</button>
<div className="mx-auto my-3 flex w-full max-w-md items-center justify-center gap-4 text-white">
<hr className="w-full border-[0.1px] border-white" />
<p className="text-sm">OR</p>
<hr className="w-full border-[0.1px] border-white" />
</div>
<button className="inline-flex w-full items-center justify-center gap-3 border-[1px] border-white bg-black p-3 text-center text-white">
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
viewBox="0 0 24 24"
width="24"
>
<path
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
fill="#4285F4"
/>
<path
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
fill="#34A853"
/>
<path
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
fill="#FBBC05"
/>
<path
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
fill="#EA4335"
/>
<path d="M1 1h22v22H1z" fill="none" />
</svg>{" "}
Login with Google
</button>
<button className="inline-flex w-full items-center justify-center gap-3 border-[1px] border-white bg-black p-3 text-center text-white">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="#ffffff"
>
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
</svg>
Login with GitHub
</button>
<p className="my-14 text-sm font-light text-white">
Don't have an account?{" "}
<span className="cursor-pointer font-bold hover:underline">
Create an account
</span>
</p>
</div>
</div>
<div className="fixed right-0 z-20 hidden h-screen w-1/2 md:block">
<img
className="h-full w-full object-cover"
src="https://images.pexels.com/photos/1144275/pexels-photo-1144275.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="register_image"
/>
</div>
</div>
</div>
);
};
export default Login;
================================================
FILE: src/components/templates/authentication/register.jsx
================================================
const Register = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto w-full max-w-full bg-[#121212] p-6 text-white lg:px-10">
<h1>DevUI</h1>
</header>
<div className="mx-auto flex w-full items-stretch justify-between gap-10">
<div className="mt-20 flex w-full flex-col items-start justify-start p-6 md:w-1/2 lg:px-10">
<div className="w-full">
<h1 className="mb-2 text-5xl font-extrabold text-white">
Register
</h1>
<p className="text-xs text-slate-400">
Before we start, please create your account
</p>
</div>
<div className="my-14 flex w-full flex-col items-start justify-start gap-4">
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">First name</label>
<input
placeholder="Enter a first name..."
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Last name</label>
<input
placeholder="Enter a last name..."
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Email</label>
<input
placeholder="Enter an email..."
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Username</label>
<input
placeholder="Enter a username..."
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Password</label>
<input
placeholder="Enter a password..."
autoComplete="false"
type="password"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="mr-4 flex items-center">
<input
type="checkbox"
id="checkbox-1"
name="checkbox-1"
className="absolute h-6 w-6 cursor-pointer opacity-0 [&:checked+div]:bg-green-500 [&:checked+div_svg]:block"
/>
<div className="mr-2 flex h-6 w-6 flex-shrink-0 items-center justify-center border-[1px] border-white bg-transparent focus-within:border-white">
<svg
className="pointer-events-none hidden h-3 w-3 fill-current text-white"
version="1.1"
viewBox="0 0 17 12"
xmlns="http://www.w3.org/2000/svg"
>
<g fill="none" fillRule="evenodd">
<g
transform="translate(-9 -11)"
fill="#000000"
fillRule="nonzero"
>
<path d="m25.576 11.414c0.56558 0.55188 0.56558 1.4439 0 1.9961l-9.404 9.176c-0.28213 0.27529-0.65247 0.41385-1.0228 0.41385-0.37034 0-0.74068-0.13855-1.0228-0.41385l-4.7019-4.588c-0.56584-0.55188-0.56584-1.4442 0-1.9961 0.56558-0.55214 1.4798-0.55214 2.0456 0l3.679 3.5899 8.3812-8.1779c0.56558-0.55214 1.4798-0.55214 2.0456 0z" />
</g>
</g>
</svg>
</div>
<div className="ml-3 text-sm leading-6">
<label
htmlFor="checkbox-1"
className="text-sm font-medium text-white"
>
You will get emails on new features and releases
</label>
</div>
</div>
<div className="mr-4 flex items-center">
<input
type="checkbox"
id="checkbox-2"
name="checkbox-2"
className="absolute h-6 w-6 cursor-pointer opacity-0 [&:checked+div]:bg-green-500 [&:checked+div_svg]:block"
/>
<div className="mr-2 flex h-6 w-6 flex-shrink-0 items-center justify-center border-[1px] border-white bg-transparent focus-within:border-white">
<svg
className="pointer-events-none hidden h-3 w-3 fill-current text-white"
version="1.1"
viewBox="0 0 17 12"
xmlns="http://www.w3.org/2000/svg"
>
<g fill="none" fillRule="evenodd">
<g
transform="translate(-9 -11)"
fill="#000000"
fillRule="nonzero"
>
<path d="m25.576 11.414c0.56558 0.55188 0.56558 1.4439 0 1.9961l-9.404 9.176c-0.28213 0.27529-0.65247 0.41385-1.0228 0.41385-0.37034 0-0.74068-0.13855-1.0228-0.41385l-4.7019-4.588c-0.56584-0.55188-0.56584-1.4442 0-1.9961 0.56558-0.55214 1.4798-0.55214 2.0456 0l3.679 3.5899 8.3812-8.1779c0.56558-0.55214 1.4798-0.55214 2.0456 0z" />
</g>
</g>
</svg>
</div>
<div className="ml-3 text-sm leading-6">
<label
htmlFor="checkbox-2"
className="text-sm font-medium text-white"
>
I agree to the terms and conditions
</label>
</div>
</div>
<button className="w-full bg-[#ae7aff] p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Create Account
</button>
<p className="my-14 text-sm font-light text-white">
Already registered?{" "}
<span className="cursor-pointer font-bold hover:underline">
Sign in to your account
</span>
</p>
</div>
</div>
<div className="fixed right-0 z-20 hidden h-screen w-1/2 md:block">
<img
className="h-full w-full object-cover"
src="https://images.pexels.com/photos/1144275/pexels-photo-1144275.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="register_image"
/>
</div>
</div>
</div>
);
};
export default Register;
================================================
FILE: src/components/templates/chat/chat-screen.jsx
================================================
import React from "react";
import { PaperAirplaneIcon, PlusCircleIcon } from "@heroicons/react/20/solid";
import {
Bars3BottomLeftIcon,
BellIcon,
EllipsisVerticalIcon,
FaceSmileIcon,
FunnelIcon,
MagnifyingGlassIcon,
PaperClipIcon,
ShareIcon,
} from "@heroicons/react/24/outline";
import { classNames } from "@/utils";
const chatListDummyData = [
{
avatar:
"https://images.pexels.com/photos/18096595/pexels-photo-18096595/free-photo-of-music-on-street.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "Jane Smith",
lastMessage:
"Hi there! How have you been? It's been a while since we last caught up. Let's plan to meet up soon.",
dateTime: "2 hours ago",
},
{
avatar:
"https://images.pexels.com/photos/18094275/pexels-photo-18094275.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "Alice Smith",
lastMessage:
"How's it going on your end? I heard you had an exciting trip last week. Tell me all about it!",
dateTime: "4 hours ago",
},
{
avatar:
"https://images.pexels.com/photos/13847652/pexels-photo-13847652.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "Bob Johnson",
lastMessage:
"What's for dinner tonight? I'm craving some Italian food. Any recommendations?",
dateTime: "Yesterday",
},
{
avatar:
"https://images.pexels.com/photos/13847596/pexels-photo-13847596.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "Emily Davis",
lastMessage:
"Can you help me with this coding problem? I'm stuck on it for hours now.",
dateTime: "2 days ago",
},
{
avatar:
"https://images.pexels.com/photos/7775636/pexels-photo-7775636.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "Michael Wilson",
lastMessage:
"See you tomorrow at the park. Don't forget to bring your running shoes!",
dateTime: "2 weeks ago",
},
{
avatar:
"https://images.pexels.com/photos/18107025/pexels-photo-18107025/free-photo-of-man-reading-newspaper.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "Sophia Anderson",
lastMessage:
"I miss you so much! It's been ages since we hung out. Let's plan something soon.",
dateTime: "2 weeks ago",
},
{
avatar:
"https://images.pexels.com/photos/7775640/pexels-photo-7775640.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "Liam Brown",
lastMessage:
"Let's meet up for coffee. I have some exciting news to share with you!",
dateTime: "3 weeks ago",
},
{
avatar:
"https://images.pexels.com/photos/18096595/pexels-photo-18096595/free-photo-of-music-on-street.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "Olivia Lee",
lastMessage:
"I have some big news! Guess what? I'm getting married next month!",
dateTime: "4 weeks ago",
},
{
avatar:
"https://images.pexels.com/photos/7775636/pexels-photo-7775636.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "Noah White",
lastMessage:
"How's the weather there? I'm planning a weekend hike and hoping for good weather.",
dateTime: "1 month ago",
},
{
avatar:
"https://images.pexels.com/photos/13847596/pexels-photo-13847596.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "Ava Garcia",
lastMessage:
"Good morning! Did you catch the sunrise today? It was breathtaking.",
dateTime: "2 months ago",
},
{
avatar:
"https://images.pexels.com/photos/7775640/pexels-photo-7775640.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "Ethan Martinez",
lastMessage:
"Let's go for a long walk by the beach this evening. The weather is perfect.",
dateTime: "3 months ago",
},
{
avatar:
"https://images.pexels.com/photos/18107025/pexels-photo-18107025/free-photo-of-man-reading-newspaper.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "Mia Jones",
lastMessage:
"Happy birthday! I hope you have an amazing day filled with joy and surprises.",
dateTime: "4 months ago",
},
{
avatar:
"https://images.pexels.com/photos/7775640/pexels-photo-7775640.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
fullName: "James Harris",
lastMessage:
"What's new with you lately? I've been swamped with work, but I miss our chats.",
dateTime: "5 months ago",
},
];
const chatMessagesDummyData = [
{
fullName: "Dan Abramov",
message:
"I'm good too, just catching up on some reading and enjoying the weather outside.",
time: "5 minutes ago",
isOwnMessage: true,
hasAttachments: true,
avatar:
"https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Jane Smith",
message: "That sounds lovely! What book are you currently reading?",
time: "10 minutes ago",
isOwnMessage: false,
avatar:
"https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Dan Abramov",
message:
"I'm reading 'The Great Gatsby' by F. Scott Fitzgerald. It's a classic!",
time: "15 minutes ago",
isOwnMessage: true,
avatar:
"https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Jane Smith",
message: "Oh, I've heard great things about that book. Enjoy your reading!",
time: "20 minutes ago",
isOwnMessage: false,
avatar:
"https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Dan Abramov",
message: "Thanks! It's such a beautifully written novel.",
time: "25 minutes ago",
isOwnMessage: true,
avatar:
"https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Dan Abramov",
message:
"I can't wait to see what happens next in the series. It's been so captivating!",
time: "45 minutes ago",
isOwnMessage: true,
avatar:
"https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Jane Smith",
message:
"I completely understand. It's always exciting when a series keeps you hooked.",
time: "50 minutes ago",
isOwnMessage: false,
avatar:
"https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Dan Abramov",
message:
"Absolutely! Well, I should get back to work now. Catch up with you later!",
time: "55 minutes ago",
isOwnMessage: true,
avatar:
"https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Dan Abramov",
message: "Sounds like a plan! Let's do it!",
time: "18 hours ago",
isOwnMessage: true,
avatar:
"https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Jane Smith",
message: "Count me in too!",
time: "19 hours ago",
isOwnMessage: false,
avatar:
"https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Dan Abramov",
message: "Great! I'll make a reservation then.",
time: "20 hours ago",
isOwnMessage: true,
avatar:
"https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Jane Smith",
message: "Awesome! Looking forward to it.",
time: "21 hours ago",
isOwnMessage: false,
avatar:
"https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Dan Abramov",
message: "Catch up with you later!",
time: "22 hours ago",
isOwnMessage: true,
avatar:
"https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Jane Smith",
message: "Sure thing! Take care!",
time: "23 hours ago",
isOwnMessage: false,
avatar:
"https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Jane Smith",
message: "That's the spirit! Keep up the good work.",
time: "6 days ago",
isOwnMessage: false,
hasAttachments: true,
avatar:
"https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
];
const dummyAttachments = [
"https://images.pexels.com/photos/18094275/pexels-photo-18094275.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
"https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
"https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
];
const ChatScreen = () => {
return (
<div className="bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-full items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">Inbox</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<span className="relative">
<BellIcon className="h-6 w-6 text-white md:h-8 md:w-8" />
<span className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full bg-red-500 p-1 text-sm text-white md:h-5 md:w-5 md:text-base">
4
</span>
</span>
<div className="h-11 w-11 rounded-full border-2 border-white">
<img
src="https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="avatar"
className="h-10 w-10 rounded-full object-cover"
/>
</div>
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
<PlusCircleIcon className="mr-2 h-5 w-5" /> Create a chat
</button>
</div>
</header>
<div className="mt-[77px] flex h-[calc(100vh-77px)] w-full items-center justify-center overflow-hidden p-0 md:mt-[83px] md:h-[calc(100vh-83px)]">
<button
className="peer fixed h-full w-full md:hidden"
aria-label="mobile-chatlist-toggler"
aria-details="Remove when using in your project. Following button is only to toggle chatlist sidebar"
></button>
<div className="fixed right-full top-[77px] z-10 h-full w-full border-white bg-[#121212] transition-all duration-300 ease-in-out peer-focus:right-0 md:static md:block md:w-[30%] md:border-r-[1px]">
<div className="flex w-full items-center justify-start gap-2 border-b-[1px] border-white p-4">
<input
placeholder="Search chat..."
className="w-full bg-transparent px-2 text-white !outline-none placeholder:text-gray-500 md:px-4"
/>
<button className="inline-flex h-7 w-7 flex-shrink-0 items-center justify-center border-[1px] border-white p-1 md:h-10 md:w-10">
<MagnifyingGlassIcon className="h-5 w-5 text-white" />
</button>
<button className="hidden h-10 w-10 flex-shrink-0 items-center justify-center border-[1px] border-white p-1 md:inline-flex">
<FunnelIcon className="h-5 w-5 text-white" />
</button>
</div>
<ul className="flex h-[calc(100%-140px)] w-full flex-col items-start justify-start divide-y-[1px] divide-white overflow-y-auto md:h-[calc(100%-73px)]">
{chatListDummyData.map((item, i) => {
return (
<li
className="w-full cursor-pointer p-4 hover:bg-[#232323] md:p-6"
key={i}
>
<div className="flex w-full items-start justify-start gap-3 md:gap-4">
<img
className="flex aspect-square h-10 w-10 flex-shrink-0 rounded-full object-cover"
src={item.avatar}
alt="avatar"
/>
<div className="flex w-full flex-col items-start justify-start gap-1 truncate text-ellipsis">
<div className="flex w-full items-center justify-between text-[10px] md:text-xs">
<p className="text-gray-400">{item.fullName}</p>
<p className="text-gray-400">{item.dateTime}</p>
</div>
<p className="text-xs text-white md:text-sm">
{item.lastMessage}
</p>
</div>
</div>
</li>
);
})}
</ul>
</div>
<div className="h-full w-full md:w-[70%]">
<div className="flex w-full items-center justify-between gap-2 border-b-[1px] border-white p-4">
<div className="flex w-full items-center justify-start gap-3">
<button className="inline-flex h-7 w-7 flex-shrink-0 items-center justify-center border-[1px] border-white p-1 md:hidden md:h-10 md:w-10">
<Bars3BottomLeftIcon className="h-5 w-5 text-white" />
</button>
<img
className="flex aspect-square h-10 w-10 flex-shrink-0 rounded-full object-cover"
src="https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="avatar"
/>
<p className="font-semibold text-white">Jane smith</p>
</div>
<div className="flex items-center justify-end gap-4">
<button className="hidden h-10 w-10 flex-shrink-0 items-center justify-center border-[1px] border-white p-1 md:inline-flex">
<ShareIcon className="h-5 w-5 text-white" />
</button>
<button className="inline-flex h-7 w-7 flex-shrink-0 items-center justify-center border-[1px] border-white p-1 md:h-10 md:w-10">
<EllipsisVerticalIcon className="h-5 w-5 text-white" />
</button>
</div>
</div>
<div className="relative h-[calc(100vh-150px)] w-full p-0 md:h-[calc(100vh-158px)] md:p-4">
<div className="flex h-[calc(100%-53px)] w-full flex-col-reverse gap-8 overflow-y-auto px-2 py-4 md:h-[calc(100%-90px)] md:p-0">
<div
className={
"flex min-w-[150px] max-w-[80%] items-start justify-start gap-2 text-white md:max-w-[70%]"
}
>
<img
className="flex aspect-square h-7 w-7 flex-shrink-0 rounded-full object-cover md:h-10 md:w-10"
src={
"https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
}
alt="avatar"
/>
<div className="flex w-full max-w-[70%] flex-col gap-2">
<p className="text-xs">Jane Smith</p>
<div
className={
"relative w-fit bg-[#343434] p-3 text-sm after:absolute after:left-0 after:top-0 after:border-r-[15px] after:border-t-[15px] after:border-r-transparent after:border-t-[#121212]"
}
>
<div className="flex w-full items-center justify-center gap-1.5 px-3 py-1">
<span className="h-2 w-2 animate-pulse rounded-full bg-gray-300"></span>
<span className="h-2 w-2 animate-pulse rounded-full bg-gray-300"></span>
<span className="h-2 w-2 animate-pulse rounded-full bg-gray-300"></span>
</div>
</div>
</div>
</div>
{chatMessagesDummyData.map((message, i) => {
return (
<div
className={classNames(
"flex min-w-[150px] max-w-[80%] items-start justify-start gap-2 text-white md:max-w-[70%]",
message.isOwnMessage
? "ml-auto flex-row-reverse"
: "mr-0",
)}
key={i}
>
<img
className="flex aspect-square h-7 w-7 flex-shrink-0 rounded-full object-cover md:h-10 md:w-10"
src={message.avatar}
alt="avatar"
/>
<div
className={classNames(
"flex w-full flex-col gap-1 md:gap-2",
message.isOwnMessage ? "items-end justify-end" : "",
)}
>
<p className="text-[10px] md:text-xs">
{message.fullName}
<span className="ml-2 text-gray-400">
{message.time}
</span>
</p>
<div
className={classNames(
"relative w-fit p-2 text-xs after:absolute after:top-0 after:border-t-[15px] after:border-t-[#121212] md:p-3 md:text-sm",
message.isOwnMessage
? "bg-[#ae7aff] after:right-0 after:border-l-[15px] after:border-l-transparent"
: "bg-[#343434] after:left-0 after:border-r-[15px] after:border-r-transparent",
)}
>
{message.message}
</div>
{message?.hasAttachments ? (
<div
className={classNames(
"grid w-full grid-cols-2 items-start justify-start gap-1 md:max-w-[90%] md:gap-2",
message.isOwnMessage ? "ml-auto" : "",
)}
>
{dummyAttachments.map((img, i) => {
return (
<img
key={i}
className="flex aspect-video w-full flex-shrink-0 object-cover"
src={img}
alt="avatar"
/>
);
})}
</div>
) : null}
</div>
</div>
);
})}
</div>
<div className="sticky top-full flex w-full items-center justify-start gap-1 border-t-[1px] border-white px-4 py-2 md:gap-4 md:border-[1px] md:shadow-[5px_5px_0px_0px_#4f4e4e]">
<img
className="hidden aspect-square h-5 w-5 flex-shrink-0 rounded-full object-cover md:flex md:h-10 md:w-10"
src="https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="avatar"
/>
<input
placeholder="Message..."
className="w-full bg-transparent p-2 text-sm text-white !outline-none placeholder:text-gray-500 md:p-4 md:text-base"
/>
<button className="hidden h-5 w-5 flex-shrink-0 items-center justify-center p-1 md:flex md:h-10 md:w-10">
<FaceSmileIcon className="h-6 w-6 text-white" />
</button>
<button className="flex h-7 w-7 flex-shrink-0 items-center justify-center p-1 md:h-10 md:w-10">
<PaperClipIcon className="h-6 w-6 text-white" />
</button>
<button className="flex h-7 w-7 flex-shrink-0 items-center justify-center bg-[#ae7aff] p-1 md:h-10 md:w-10">
<PaperAirplaneIcon className="h-6 w-6 text-black" />
</button>
</div>
</div>
</div>
</div>
</div>
);
};
export default ChatScreen;
================================================
FILE: src/components/templates/chat/create-group-chat.jsx
================================================
import {
BellIcon,
PlusCircleIcon,
XMarkIcon,
} from "@heroicons/react/24/outline";
import React from "react";
const selectedUsers = [
{
name: "John Smith",
avatar:
"https://images.pexels.com/photos/18096595/pexels-photo-18096595/free-photo-of-music-on-street.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
name: "Emily Gardener",
avatar:
"https://images.pexels.com/photos/18094275/pexels-photo-18094275.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
name: "Olivia Root",
avatar:
"https://images.pexels.com/photos/13847652/pexels-photo-13847652.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
name: "John Denny",
avatar:
"https://images.pexels.com/photos/13847596/pexels-photo-13847596.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
name: "Emily Rose",
avatar:
"https://images.pexels.com/photos/7775636/pexels-photo-7775636.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
];
const CreateGroupChat = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-[85rem] items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">Inbox</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<span className="relative">
<BellIcon className="h-6 w-6 text-white md:h-8 md:w-8" />
<span className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full bg-red-500 p-1 text-sm text-white md:h-5 md:w-5 md:text-base">
4
</span>
</span>
<div className="h-11 w-11 rounded-full border-2 border-white">
<img
src="https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="avatar"
className="h-10 w-10 rounded-full object-cover"
/>
</div>
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
<PlusCircleIcon className="mr-2 h-5 w-5" /> Create a chat
</button>
</div>
</header>
<div
className="relative z-10"
aria-labelledby="modal-title"
role="dialog"
aria-modal="true"
>
<div className="fixed inset-0 bg-[#121212] bg-opacity-75 transition-opacity" />
<div className="fixed inset-0 z-10 w-screen overflow-y-auto">
<div className="flex min-h-full items-end justify-center p-0 text-center md:items-center md:p-2">
<div className="relative w-full transform overflow-hidden border-t-[1px] border-white bg-[#121212] text-left text-white transition-all md:my-8 md:w-full md:max-w-5xl md:border-[1px]">
<div className="flex items-center justify-between border-b-[1px] border-white p-4">
<p className="text-xl font-bold">Create a Group</p>
<XMarkIcon className="h-6 w-6 text-white" role="button" />
</div>
<div className="flex w-full flex-col gap-4 p-4 md:gap-6 md:p-6">
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Group name</label>
<input
placeholder="Enter group name..."
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">
Select a user
</label>
<div className="w-full border-[1px] border-white pr-4">
<select
placeholder="Select a user..."
autoComplete="false"
className="w-full bg-[#121212] py-4 pl-4 text-white placeholder:text-gray-500 focus:outline-none"
>
<option value="0">John Doe</option>
<option value="1">Jane Doe</option>
<option value="2">Mark Smith</option>
<option value="3">Tiger Woods</option>
</select>
</div>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">
Added participants
</label>
<div className="flex w-full flex-wrap items-center justify-start gap-4">
{selectedUsers.map((user) => {
return (
<div
className="flex w-fit items-center justify-between gap-2 border-[1px] border-white px-2 py-1.5"
key={user.name}
>
<img
alt="avatar"
className="flex h-6 w-6 flex-shrink-0 rounded-full object-cover"
src={user.avatar}
/>
<p className="text-sm text-white">{user.name}</p>
<button className="flex flex-shrink-0 items-center justify-center">
<XMarkIcon className="h-4 w-4 text-white" />
</button>
</div>
);
})}
</div>
</div>
<div className="flex w-full flex-col items-center justify-end gap-4 md:flex-row md:gap-6">
<button className="w-full bg-red-500 p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Cancel
</button>
<button className="w-full bg-[#ae7aff] p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Create
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default CreateGroupChat;
================================================
FILE: src/components/templates/chat/create-normal-chat.jsx
================================================
import {
BellIcon,
PlusCircleIcon,
XMarkIcon,
} from "@heroicons/react/24/outline";
import React from "react";
const CreateOneOnOneChat = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-[85rem] items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">Inbox</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<span className="relative">
<BellIcon className="h-6 w-6 text-white md:h-8 md:w-8" />
<span className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full bg-red-500 p-1 text-sm text-white md:h-5 md:w-5 md:text-base">
4
</span>
</span>
<div className="h-11 w-11 rounded-full border-2 border-white">
<img
src="https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="avatar"
className="h-10 w-10 rounded-full object-cover"
/>
</div>
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
<PlusCircleIcon className="mr-2 h-5 w-5" /> Create a chat
</button>
</div>
</header>
<div
className="relative z-10"
aria-labelledby="modal-title"
role="dialog"
aria-modal="true"
>
<div className="fixed inset-0 bg-[#121212] bg-opacity-75 transition-opacity" />
<div className="fixed inset-0 z-10 w-screen overflow-y-auto">
<div className="flex min-h-full items-end justify-center p-0 text-center md:items-center md:p-2">
<div className="relative w-full transform overflow-hidden border-t-[1px] border-white bg-[#121212] text-left text-white transition-all md:my-8 md:w-full md:max-w-5xl md:border-[1px]">
<div className="flex items-center justify-between border-b-[1px] border-white p-4">
<p className="text-xl font-bold">Create Chat</p>
<XMarkIcon className="h-6 w-6 text-white" role="button" />
</div>
<div className="flex w-full flex-col gap-4 p-4 md:gap-6 md:p-6">
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">
Select a user
</label>
<div className="w-full border-[1px] border-white pr-4">
<select
placeholder="Select a user..."
autoComplete="false"
className="w-full bg-[#121212] py-4 pl-4 text-white placeholder:text-gray-500 focus:outline-none"
>
<option value="0">John Doe</option>
<option value="1">Jane Doe</option>
<option value="2">Mark Smith</option>
<option value="3">Tiger Woods</option>
</select>
</div>
</div>
<div className="flex w-full flex-col items-center justify-end gap-4 md:flex-row md:gap-6">
<button className="w-full bg-red-500 p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Cancel
</button>
<button className="w-full bg-[#ae7aff] p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Start Chatting
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default CreateOneOnOneChat;
================================================
FILE: src/components/templates/chat/empty-chats.jsx
================================================
import React from "react";
import { PlusCircleIcon } from "@heroicons/react/20/solid";
import { BellIcon, InboxIcon } from "@heroicons/react/24/outline";
const EmptyChats = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-full items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">Inbox</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<span className="relative">
<BellIcon className="h-6 w-6 text-white md:h-8 md:w-8" />
<span className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full bg-red-500 p-1 text-sm text-white md:h-5 md:w-5 md:text-base">
4
</span>
</span>
<div className="h-11 w-11 rounded-full border-2 border-white">
<img
src="https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="avatar"
className="h-10 w-10 rounded-full object-cover"
/>
</div>
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
<PlusCircleIcon className="mr-2 h-5 w-5" /> Create a chat
</button>
</div>
</header>
<div className="flex h-full min-h-screen w-full flex-col items-center justify-center px-4 text-center">
<div className="flex flex-col items-center justify-center gap-4 text-white">
<InboxIcon className="h-20 w-20 text-white md:h-28 md:w-28" />
<h1 className="text-4xl font-extrabold md:text-6xl">
No chats found?
</h1>
<p className="max-w-sm text-xs text-gray-200 md:text-sm">
Try to initiate chat with your saved contacts by clicking the button
below
</p>
</div>
<button className="mt-14 inline-flex w-max items-center bg-[#ae7aff] p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
<PlusCircleIcon className="mr-2 h-5 w-5 text-[#121212]" /> Create a
chat
</button>
</div>
</div>
);
};
export default EmptyChats;
================================================
FILE: src/components/templates/chat/group-information.jsx
================================================
import { TrashIcon, UserMinusIcon, XMarkIcon } from "@heroicons/react/20/solid";
import {
BellIcon,
ExclamationTriangleIcon,
PencilIcon,
PlusCircleIcon,
UserGroupIcon,
} from "@heroicons/react/24/outline";
import React from "react";
const participants = [
{
fullName: "Eva Brown",
email: "eva.brown@example.com",
avatar:
"https://images.pexels.com/photos/18096595/pexels-photo-18096595/free-photo-of-music-on-street.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "John Doe",
email: "john.doe@example.com",
avatar:
"https://images.pexels.com/photos/18094275/pexels-photo-18094275.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Jane Smith",
email: "jane.smith@example.com",
avatar:
"https://images.pexels.com/photos/13847652/pexels-photo-13847652.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Alice Johnson",
email: "alice.johnson@example.com",
avatar:
"https://images.pexels.com/photos/13847596/pexels-photo-13847596.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Bob Wilson",
email: "bob.wilson@example.com",
avatar:
"https://images.pexels.com/photos/7775636/pexels-photo-7775636.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "Eva Brown",
email: "eva.brown@example.com",
avatar:
"https://images.pexels.com/photos/18107025/pexels-photo-18107025/free-photo-of-man-reading-newspaper.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
{
fullName: "David Lee",
email: "david.lee@example.com",
avatar:
"https://images.pexels.com/photos/7775640/pexels-photo-7775640.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
},
];
const GroupChatInfo = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-[85rem] items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">Inbox</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<span className="relative">
<BellIcon className="h-6 w-6 text-white md:h-8 md:w-8" />
<span className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full bg-red-500 p-1 text-sm text-white md:h-5 md:w-5 md:text-base">
4
</span>
</span>
<div className="h-11 w-11 rounded-full border-2 border-white">
<img
src="https://images.pexels.com/photos/18148932/pexels-photo-18148932/free-photo-of-bench-city-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="avatar"
className="h-10 w-10 rounded-full object-cover"
/>
</div>
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
<PlusCircleIcon className="mr-2 h-5 w-5" /> Create a chat
</button>
</div>
</header>
<div className="flex h-full min-h-screen w-full flex-col items-center justify-center px-4 text-center">
<div className="fixed inset-0 z-10 bg-[#121212] bg-opacity-75 transition-opacity" />
<aside className="fixed right-0 z-20 h-screen w-full translate-x-0 overflow-y-auto bg-[#121212] p-4 transition-all duration-200 ease-in-out peer-focus:translate-x-0 md:w-1/2 md:border-l-[1px] md:border-l-white md:p-6">
<div className="mb-6 flex items-center justify-between">
<p className="text-lg font-semibold text-white md:text-xl md:font-bold">
About Group
</p>
<XMarkIcon
className="h-5 w-5 text-white md:h-6 md:w-6"
role="button"
/>
</div>
<div className="flex flex-col items-center justify-start gap-4 text-center">
<div className="flex w-14 flex-shrink-0 items-center justify-center md:w-24">
<img
className="flex h-14 w-14 flex-shrink-0 rounded-full object-cover outline outline-8 outline-[#121212] md:h-24 md:w-24"
alt="avatar"
src={participants[0]?.avatar}
/>
<img
className="-ml-10 flex h-14 w-14 flex-shrink-0 rounded-full object-cover outline outline-8 outline-[#121212] md:h-24 md:w-24"
alt="avatar"
src={participants[1]?.avatar}
/>
<img
className="-ml-10 flex h-14 w-14 flex-shrink-0 rounded-full object-cover outline outline-8 outline-[#121212] md:h-24 md:w-24"
alt="avatar"
src={participants[2]?.avatar}
/>
<p className="ml-2 text-sm text-white md:text-base">+4</p>
</div>
<h1 className="truncate text-2xl font-extrabold text-white md:text-4xl">
CodeCrafters Alliance
</h1>
<span className="text-sm text-gray-400">7 Participants</span>
</div>
<hr className="mx-auto my-8 w-[90%] border-[1px] border-dashed border-gray-500" />
<p className="mb-2 inline-flex items-center text-left text-white">
<UserGroupIcon className="mr-2 h-5 w-5" /> Group participants
</p>
<ul className="mb-4 flex w-full flex-col items-start justify-start divide-y-[0.1px] divide-white">
{participants.map((user, i) => {
return (
<li
className="flex w-full items-center justify-start gap-2 py-4 pr-4"
key={i}
>
<img
className="flex h-10 w-10 flex-shrink-0 rounded-full object-cover md:h-14 md:w-14"
src={user.avatar}
alt="avatar"
/>
<div className="flex flex-col items-start justify-start text-left text-white">
<p className="inline-flex items-center text-sm font-semibold md:text-base">
{user.fullName}
{i === 1 ? (
<span className="ml-2 border-[1px] border-white px-1.5 py-0.5 text-[8px] text-white md:text-[10px]">
ADMIN
</span>
) : null}
</p>
<span className="text-xs text-gray-500 md:text-sm">
{user.email}
</span>
</div>
<button className="ml-auto inline-flex aspect-square items-center bg-red-500 p-3 text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
<UserMinusIcon className="h-5 w-5" />
</button>
</li>
);
})}
</ul>
<div className="flex w-full flex-col gap-4">
<button className="inline-flex w-full items-center justify-center bg-[#ae7aff] p-2 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
<PencilIcon className="mr-2 h-5 w-5" /> Update Group
</button>
<button className="inline-flex w-full items-center justify-center bg-red-500 p-2 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
<TrashIcon className="mr-2 h-5 w-5" /> Delete Group
</button>
<button className="inline-flex w-full items-center justify-center bg-red-500 p-2 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
<ExclamationTriangleIcon className="mr-2 h-5 w-5" /> Exit Group
</button>
</div>
</aside>
</div>
</div>
);
};
export default GroupChatInfo;
================================================
FILE: src/components/templates/chat/index.ts
================================================
import EmptyChats from "./empty-chats";
import ChatScreen from "./chat-screen";
import CreateGroupChat from "./create-group-chat";
import CreateOneOnOneChat from "./create-normal-chat";
import GroupInfo from "./group-information";
import Register from "./register";
import Login from "./login";
const Chat = {
EmptyChats,
ChatScreen,
CreateGroupChat,
CreateOneOnOneChat,
GroupInfo,
Register,
Login,
};
export default Chat;
================================================
FILE: src/components/templates/chat/login.jsx
================================================
const SocialLogin = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-full items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">Login</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
Register
</button>
</div>
</header>
<div className="mx-auto flex w-full items-stretch justify-between gap-10">
<div className="fixed left-0 top-0 hidden h-screen w-0 bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 md:block md:w-1/3"></div>
<div className="ml-auto mt-28 flex w-full flex-col items-start justify-start p-6 sm:max-w-4xl md:w-2/3 lg:px-10">
<div className="w-full">
<h1 className="mb-3 text-5xl font-extrabold text-white">Login</h1>
<p className="text-xs text-slate-400">
Login to access your account
</p>
</div>
<div className="my-14 flex w-full flex-col items-start justify-start gap-4">
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">
Username or email
</label>
<input
placeholder="Enter a username or email..."
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Password</label>
<input
placeholder="Enter a password..."
autoComplete="false"
type="password"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="mr-4 flex items-center">
<input
type="checkbox"
id="checkbox-2"
name="checkbox-2"
className="absolute h-6 w-6 cursor-pointer opacity-0 [&:checked+div]:bg-green-500 [&:checked+div_svg]:block"
/>
<div className="mr-2 flex h-6 w-6 flex-shrink-0 items-center justify-center border-[1px] border-white bg-transparent focus-within:border-white">
<svg
className="pointer-events-none hidden h-3 w-3 fill-current text-white"
version="1.1"
viewBox="0 0 17 12"
xmlns="http://www.w3.org/2000/svg"
>
<g fill="none" fillRule="evenodd">
<g
transform="translate(-9 -11)"
fill="#000000"
fillRule="nonzero"
>
<path d="m25.576 11.414c0.56558 0.55188 0.56558 1.4439 0 1.9961l-9.404 9.176c-0.28213 0.27529-0.65247 0.41385-1.0228 0.41385-0.37034 0-0.74068-0.13855-1.0228-0.41385l-4.7019-4.588c-0.56584-0.55188-0.56584-1.4442 0-1.9961 0.56558-0.55214 1.4798-0.55214 2.0456 0l3.679 3.5899 8.3812-8.1779c0.56558-0.55214 1.4798-0.55214 2.0456 0z" />
</g>
</g>
</svg>
</div>
<div className="ml-3 text-sm leading-6">
<label
htmlFor="checkbox-2"
className="text-sm font-medium text-white"
>
Remember me
</label>
</div>
</div>
<button className="w-full bg-[#ae7aff] p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Log in
</button>
<div className="mx-auto my-3 flex w-full max-w-md items-center justify-center gap-4 text-white">
<hr className="w-full border-[0.1px] border-white" />
<p className="text-sm">OR</p>
<hr className="w-full border-[0.1px] border-white" />
</div>
<button className="inline-flex w-full items-center justify-center gap-3 border-[1px] border-white bg-black p-3 text-center text-white">
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
viewBox="0 0 24 24"
width="24"
>
<path
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
fill="#4285F4"
/>
<path
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
fill="#34A853"
/>
<path
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
fill="#FBBC05"
/>
<path
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
fill="#EA4335"
/>
<path d="M1 1h22v22H1z" fill="none" />
</svg>{" "}
Login with Google
</button>
<button className="inline-flex w-full items-center justify-center gap-3 border-[1px] border-white bg-black p-3 text-center text-white">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="#ffffff"
>
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
</svg>
Login with GitHub
</button>
<p className="text-sm font-light text-white">
Don't have an account?{" "}
<span className="cursor-pointer font-bold hover:underline">
Create an account
</span>
</p>
</div>
</div>
</div>
</div>
);
};
export default SocialLogin;
================================================
FILE: src/components/templates/chat/register.jsx
================================================
import { PlusIcon } from "@heroicons/react/24/outline";
const SocialRegister = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-full items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">Register</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
Login
</button>
</div>
</header>
<div className="mx-auto flex w-full items-stretch justify-between gap-10">
<div className="fixed left-0 top-0 hidden h-screen w-0 bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 md:block md:w-1/3"></div>
<div className="ml-auto mt-28 flex w-full flex-col items-start justify-start p-6 sm:max-w-4xl md:w-2/3 lg:px-10">
<div className="w-full text-center">
<h1 className="mb-3 text-5xl font-extrabold text-white">
Register
</h1>
<p className="text-xs text-slate-400">
Before we chat, please create your account
</p>
</div>
<div className="my-14 flex w-full flex-col items-start justify-start gap-4">
<div className="flex w-full items-center justify-center">
<input id="avatar-input-1" hidden type="file" />
<label
htmlFor="avatar-input-1"
className="relative flex aspect-square h-24 w-24 cursor-pointer items-center justify-center overflow-visible rounded-full border-4 border-[#ae7aff] p-1"
>
<div className="flex h-full w-full items-center justify-center rounded-full">
<PlusIcon className="h-8 w-8 text-white" />
</div>
<span className="absolute bottom-0 right-0 flex aspect-square h-5 w-5 items-center justify-center rounded-full bg-[#ae7aff] p-1">
<PlusIcon className="h-3 w-3 text-black" />
</span>
</label>
</div>
<div className="mt-10 flex w-full flex-col items-center justify-between gap-4 md:flex-row">
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">First name</label>
<input
placeholder="Enter a first name..."
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Last name</label>
<input
placeholder="Enter a last name..."
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Username</label>
<input
placeholder="Enter a username..."
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Email</label>
<input
placeholder="Enter an email..."
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Password</label>
<input
placeholder="Enter a password..."
autoComplete="false"
type="password"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="mr-4 flex items-center">
<input
type="checkbox"
id="checkbox-2"
name="checkbox-2"
className="absolute h-6 w-6 cursor-pointer opacity-0 [&:checked+div]:bg-green-500 [&:checked+div_svg]:block"
/>
<div className="mr-2 flex h-6 w-6 flex-shrink-0 items-center justify-center border-[1px] border-white bg-transparent focus-within:border-white">
<svg
className="pointer-events-none hidden h-3 w-3 fill-current text-white"
version="1.1"
viewBox="0 0 17 12"
xmlns="http://www.w3.org/2000/svg"
>
<g fill="none" fillRule="evenodd">
<g
transform="translate(-9 -11)"
fill="#000000"
fillRule="nonzero"
>
<path d="m25.576 11.414c0.56558 0.55188 0.56558 1.4439 0 1.9961l-9.404 9.176c-0.28213 0.27529-0.65247 0.41385-1.0228 0.41385-0.37034 0-0.74068-0.13855-1.0228-0.41385l-4.7019-4.588c-0.56584-0.55188-0.56584-1.4442 0-1.9961 0.56558-0.55214 1.4798-0.55214 2.0456 0l3.679 3.5899 8.3812-8.1779c0.56558-0.55214 1.4798-0.55214 2.0456 0z" />
</g>
</g>
</svg>
</div>
<div className="ml-3 text-sm leading-6">
<label
htmlFor="checkbox-2"
className="text-sm font-medium text-white"
>
I agree to the terms and conditions
</label>
</div>
</div>
<button className="w-full bg-[#ae7aff] p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Create Account
</button>
<p className="text-sm font-light text-white">
Already registered?{" "}
<span className="cursor-pointer font-bold hover:underline">
Sign in to your account
</span>
</p>
</div>
</div>
</div>
</div>
);
};
export default SocialRegister;
================================================
FILE: src/components/templates/social-media/bookmark-posts.jsx
================================================
import React from "react";
import {
BellIcon,
BookmarkIcon,
EllipsisVerticalIcon,
HeartIcon,
LinkIcon,
MagnifyingGlassIcon,
} from "@heroicons/react/24/outline";
import {
ChatBubbleOvalLeftEllipsisIcon,
PlusCircleIcon,
ShareIcon,
} from "@heroicons/react/24/solid";
const posts = [
{
id: 1,
authorImage:
"https://images.pexels.com/photos/18264716/pexels-photo-18264716.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Mystical Wanderer",
createdOn: "15 minutes ago",
text: "Uncovering ancient secrets and mystical wonders. The journey is the destination. 🔮🌟 #MythologyQuest",
images: [],
likeCount: 46,
commentCount: 13,
bookmarked: true,
liked: true,
},
{
id: 2,
authorImage:
"https://images.pexels.com/photos/13847596/pexels-photo-13847596.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Aqua Explorer",
createdOn: "1 hour ago",
text: "Swimming with the dolphins today, and it was magical! 🐬🌊 #OceanAdventure",
images: [
"https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
],
likeCount: 102,
commentCount: 18,
bookmarked: true,
liked: false,
},
{
id: 3,
authorImage:
"https://images.pexels.com/photos/7775637/pexels-photo-7775637.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Solar Flare ",
createdOn: "59 minutes ago",
text: "Harnessing the power of the sun for a brighter future. ☀️🔋 #SolarEnergy",
images: [
"https://images.pexels.com/photos/18107025/pexels-photo-18107025/free-photo-of-man-reading-newspaper.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
"https://images.pexels.com/photos/18148933/pexels-photo-18148933/free-photo-of-city-road-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
"https://images.pexels.com/photos/18148937/pexels-photo-18148937/free-photo-of-city-road-traffic-landscape.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
],
likeCount: 802,
commentCount: 99,
bookmarked: true,
liked: true,
},
{
id: 4,
authorImage:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Aurora Starlight",
createdOn: "17 hours ago",
text: "Embracing the lunar magic tonight. The full moon is my muse. 🌕🌌 #MoonlightDreams",
images: [],
likeCount: 420,
commentCount: 20,
bookmarked: true,
liked: false,
link: {
image:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
title: "Aurora Starlight",
caption: "Digital artist | Creative mind | Color magician 🎨🖌️🖼️",
url: "https://www.aurorastarry.com/",
},
},
{
id: 5,
authorImage:
"https://images.pexels.com/photos/3532553/pexels-photo-3532553.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Nova Sparks",
createdOn: "1 day ago",
text: "💡 Tech Poll: Which emerging technology excites you the most?",
images: [],
likeCount: 207,
commentCount: 63,
bookmarked: true,
liked: false,
poll: [
{
name: "Artificial Intelligence",
},
{
name: "Virtual Reality",
},
{
name: "Quantum Computing",
},
{
name: "5G Connectivity",
},
],
},
{
id: 6,
authorImage:
"https://images.pexels.com/photos/569314/pexels-photo-569314.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Zen Garden",
createdOn: "7 days ago",
text: "🧘♂️ Mindfulness Poll: Which mindfulness practice resonates with you the most?",
images: [],
likeCount: 97,
commentCount: 13,
liked: true,
bookmarked: true,
poll: [
{
name: "Meditation",
votePercentage: 30,
},
{
name: "Yoga",
selected: true,
votePercentage: 33,
},
{
name: "Deep Breathing",
votePercentage: 27,
},
{
name: "Tai Chi",
votePercentage: 20,
},
],
},
{
id: 7,
authorImage:
"https://images.pexels.com/photos/1739942/pexels-photo-1739942.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Pixel Painter",
createdOn: "1 months ago",
text: "🎨 Art Poll: What's your preferred art medium for creating masterpieces?",
images: [],
likeCount: 99,
commentCount: 13,
bookmarked: true,
liked: false,
poll: [
{
name: "Acrylic Paint",
votePercentage: 20,
},
{
name: "Watercolor",
votePercentage: 19,
},
{
name: "Digital Art",
votePercentage: 18,
},
{
name: "Charcoal Sketching",
votePercentage: 43,
},
],
},
];
const BookmarkPosts = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-full items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">My Profile</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<span className="relative">
<MagnifyingGlassIcon className="h-8 w-8" />
</span>
<span className="relative">
<BellIcon className="h-8 w-8 text-white" />
<span className="absolute right-1 top-0 flex h-2.5 w-2.5 items-center justify-center rounded-full bg-green-500 p-1 text-white"></span>
</span>
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
<PlusCircleIcon className="mr-2 h-5 w-5" /> Create new
</button>
</div>
</header>
<div className="mt-[65px] grid grid-cols-12 gap-4 pb-8 pt-0 sm:px-4 sm:pt-8 md:mt-[83px] lg:px-10">
{/* Empty */}
<aside className="col-span-12 text-white md:col-span-5 lg:col-span-4 xl:col-span-3">
{/* Profile Card */}
<div className="sticky top-[100px] border-b border-white p-4 sm:border">
<img
className="mb-3 flex aspect-square h-16 w-16 rounded-full border-2 border-[#ae7aff] object-cover"
src="https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
alt="avatar"
/>
<h2 className="mb-1 font-bold">Aurora Starlight</h2>
<p className="text-sm">
Night owl | Moon enthusiast | Wanderlust 🌕🌙🌎
</p>
<hr className="my-4 h-[1px] w-full" />
<div className="mb-4">
<h3 className="mb-1 font-bold">Short Bio</h3>
<p className="text-sm">
Immersed in the enchanting world of the night, captivated by the
moon's allure, and constantly seeking new adventures around
the globe. 🌕🌙🌎
</p>
</div>
<div className="mb-4 text-sm">
<h3 className="mb-1 font-bold">Public link</h3>
<button className="block text-[#ae7aff] hover:underline">
starryaurora@gmail.com
</button>
<button className="block break-all text-[#ae7aff] hover:underline">
https://www.aurorastarry.com/
</button>
</div>
<p className="mb-4 flex gap-x-4">
<span className="inline-block">
<span className="font-bold">13.5k </span>
<span className="text-sm text-gray-400">Followers</span>
</span>
<span className="inline-block">
<span className="font-bold">204 </span>
<span className="text-sm text-gray-400">Following</span>
</span>
</p>
<button className="inline-flex w-max items-center bg-[#ae7aff] px-4 py-2 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Edit Profile
</button>
</div>
</aside>
<section className="col-span-12 text-white md:col-span-7 lg:col-span-5 xl:col-span-6">
<div className="sticky top-[82px] z-10 mt-[1px] bg-[#121212] pb-4 before:absolute before:inset-x-0 before:bottom-full before:h-[17px] before:bg-[#121212] md:top-[100px] md:mt-0">
<ul className="no-scrollbar flex w-full overflow-x-auto px-4 sm:px-0">
<li className="mr-2 inline-block shrink-0">
<button className="inline-block px-6 py-1.5 hover:bg-[#2c2c2c]">
Posts
</button>
</li>
<li className="mr-2 inline-block shrink-0">
<button className="inline-block px-6 py-1.5 hover:bg-[#2c2c2c]">
Edit profile
</button>
</li>
<li className="mr-2 inline-block shrink-0">
<button className="inline-block px-6 py-1.5 hover:bg-[#2c2c2c]">
Change password
</button>
</li>
<li className="mr-2 inline-block shrink-0">
<button className="inline-block bg-[#2c2c2c] px-6 py-1.5">
Bookmarked
</button>
</li>
</ul>
</div>
{/* Post Lists */}
{posts.map((post) => (
<div
key={post.id}
className="relative mb-2 w-full last:mb-0 sm:mb-4"
>
<div className="flex border-b border-t border-white p-4 text-white sm:border-l sm:border-r">
{/* Author Profile */}
<div className="h-10 w-10 shrink-0 sm:h-12 sm:w-12">
<img
src={post.authorImage}
alt={post.authorName}
className="h-full w-full rounded-full object-cover"
/>
</div>
{/* Center-Right Content */}
<div className="pl-4 pt-1">
{/* Post Metadata */}
<div className="mb-2 flex items-center gap-x-2">
<div className="w-full">
<h2 className="inline-block font-bold">
{post.authorName}
</h2>
<span className="ml-2 inline-block text-sm text-gray-400">
{post.createdOn}
</span>
</div>
<button className="ml-auto shrink-0 hover:text-[#ae7aff]">
<EllipsisVerticalIcon className="h-5 w-5" />
</button>
</div>
{/* Post Text */}
<p className="mb-4 text-sm sm:text-base">{post.text}</p>
{/* Post Images */}
{post.images.length > 0 && (
<div className="mb-4 grid grid-cols-[repeat(auto-fit,_minmax(200px,_1fr))] gap-4">
{post.images.map((image, i) => (
<img
key={image}
src={image}
alt={`attachment-${i}`}
className="rounded-md"
/>
))}
</div>
)}
{/* Link Preview */}
{post.link && (
<div className="group mb-4 border opacity-95 hover:opacity-100">
<div className="max-h-52 overflow-hidden">
<img
src={post.link.image}
alt={post.link.title}
className="object-cover"
/>
</div>
{/* Link Content */}
<div className="p-4">
<h3 className="mb-2 font-bold">{post.link.title}</h3>
<p className="mb-3 text-sm">{post.link.caption}</p>
<span className="inline-flex items-center gap-x-2 break-all text-sm text-[#ae7aff] no-underline group-hover:underline">
<LinkIcon className="h-4 w-4 shrink-0" />
{post.link.url}
</span>
</div>
</div>
)}
{/* Polls */}
{post.poll &&
post.poll.map((option) => (
<button
key={option?.name}
className={`relative z-[1] mb-4 inline-flex w-full items-center gap-x-4 border p-4 before:absolute before:inset-y-0 before:left-0 before:z-[-1] before:w-[var(--data-vote-percentage)] last:mb-0 ${
option?.votePercentage && option?.votePercentage >= 0
? ""
: "hover:bg-[#ae7aff] hover:text-black focus:border-[#ae7aff] focus:bg-[#ae7aff] focus:text-black"
} ${
option?.selected
? "before:bg-[#ae7aff]"
: "before:bg-gray-400/10"
}
`}
disabled={Boolean(option?.votePercentage)}
style={{
"--data-vote-percentage": `${
option?.votePercentage || 0
}%`,
}}
>
{option?.name}{" "}
{option?.votePercentage && (
<span className="ml-auto shrink-0 text-sm">
{option.votePercentage}%
</span>
)}
</button>
))}
{/* Post Actions Buttons */}
<div className="flex gap-x-4">
{/* Like Button */}
<button
className={`group inline-flex items-center gap-x-1 outline-none after:content-[attr(data-like-count)] focus:after:content-[attr(data-like-count-alt)] ${
post.liked
? "text-[#ae7aff] focus:text-inherit"
: "hover:text-[#ae7aff] focus:text-[#ae7aff]"
}`}
data-like-count={post.likeCount}
data-like-count-alt={
post.liked ? post.likeCount - 1 : post.likeCount + 1
}
>
<HeartIcon
className={`h-5 w-5 ${
post.liked
? "fill-[#ae7aff] group-focus:fill-none"
: "group-focus:fill-[#ae7aff]"
}`}
/>
</button>
{/* Comment Button */}
<button className="inline-flex items-center gap-x-1 outline-none hover:text-[#ae7aff]">
<ChatBubbleOvalLeftEllipsisIcon className="h-5 w-5" />
<span>{post.commentCount}</span>
</button>
{/* Share and Bookmarked Button */}
<div className="ml-auto">
<button className="mr-2 inline-flex items-center gap-x-1 outline-none hover:text-[#ae7aff]">
<ShareIcon className="h-5 w-5" />
</button>
<button
className={`group inline-flex items-center gap-x-1 outline-none hover:text-[#ae7aff] ${
post.bookmarked
? "focus:text-white"
: "focus:text-[#ae7aff]"
}`}
>
<BookmarkIcon
className={`h-5 w-5 ${
post.bookmarked
? "fill-[#ae7aff] text-[#ae7aff] group-focus:fill-none group-focus:text-inherit"
: "group-focus:fill-[#ae7aff]"
}`}
/>
</button>
</div>
</div>
</div>
</div>
</div>
))}
</section>
{/* Trending Topics */}
<aside className="hidden text-white lg:col-span-3 lg:block">
<div className="sticky top-[100px] border p-4">
<h2 className="mb-4 font-bold"># Trending Hashtags</h2>
<ul className="list-disc pl-4">
{["javascript", "typescript", "java", "python", "golang"].map(
(hashtag) => (
<li key={hashtag}>
<button className="hover:text-[#ae7aff]">#{hashtag}</button>
</li>
),
)}
</ul>
</div>
</aside>
</div>
</div>
);
};
export default BookmarkPosts;
================================================
FILE: src/components/templates/social-media/change-password.jsx
================================================
import React from "react";
import { BellIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import { PlusCircleIcon } from "@heroicons/react/24/solid";
const ChangePassword = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-full items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">My Profile</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<span className="relative">
<MagnifyingGlassIcon className="h-8 w-8" />
</span>
<span className="relative">
<BellIcon className="h-8 w-8 text-white" />
<span className="absolute right-1 top-0 flex h-2.5 w-2.5 items-center justify-center rounded-full bg-green-500 p-1 text-white"></span>
</span>
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
<PlusCircleIcon className="mr-2 h-5 w-5" /> Create new
</button>
</div>
</header>
<div className="mt-[65px] grid grid-cols-12 gap-4 pb-8 pt-0 sm:px-4 sm:pt-8 md:mt-[83px] lg:px-10">
{/* Empty */}
<aside className="col-span-12 text-white md:col-span-5 lg:col-span-4 xl:col-span-3">
{/* Profile Card */}
<div className="sticky top-[100px] border-b border-white p-4 sm:border">
<img
className="mb-3 flex aspect-square h-16 w-16 rounded-full border-2 border-[#ae7aff] object-cover"
src="https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
alt="avatar"
/>
<h2 className="mb-1 font-bold">Aurora Starlight</h2>
<p className="text-sm">
Night owl | Moon enthusiast | Wanderlust 🌕🌙🌎
</p>
<hr className="my-4 h-[1px] w-full" />
<div className="mb-4">
<h3 className="mb-1 font-bold">Short Bio</h3>
<p className="text-sm">
Immersed in the enchanting world of the night, captivated by the
moon's allure, and constantly seeking new adventures around
the globe. 🌕🌙🌎
</p>
</div>
<div className="mb-4 text-sm">
<h3 className="mb-1 font-bold">Public link</h3>
<button className="block text-[#ae7aff] hover:underline">
starryaurora@gmail.com
</button>
<button className="block break-all text-[#ae7aff] hover:underline">
https://www.aurorastarry.com/
</button>
</div>
<p className="mb-4 flex gap-x-4">
<span className="inline-block">
<span className="font-bold">13.5k </span>
<span className="text-sm text-gray-400">Followers</span>
</span>
<span className="inline-block">
<span className="font-bold">204 </span>
<span className="text-sm text-gray-400">Following</span>
</span>
</p>
<button className="inline-flex w-max items-center bg-[#ae7aff] px-4 py-2 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Edit Profile
</button>
</div>
</aside>
<section className="col-span-12 text-white md:col-span-7 lg:col-span-5 xl:col-span-6">
<div className="sticky top-[82px] z-10 mt-[1px] bg-[#121212] pb-4 before:absolute before:inset-x-0 before:bottom-full before:h-[17px] before:bg-[#121212] md:top-[100px] md:mt-0">
<ul className="no-scrollbar flex w-full overflow-x-auto px-4 sm:px-0">
<li className="mr-2 inline-block shrink-0">
<button className="inline-block px-6 py-1.5 hover:bg-[#2c2c2c]">
Posts
</button>
</li>
<li className="mr-2 inline-block shrink-0">
<button className="inline-block px-6 py-1.5 hover:bg-[#2c2c2c]">
Edit profile
</button>
</li>
<li className="mr-2 inline-block shrink-0">
<button className="inline-block bg-[#2c2c2c] px-6 py-1.5">
Change password
</button>
</li>
<li className="mr-2 inline-block shrink-0">
<button className="inline-block px-6 py-1.5 hover:bg-[#2c2c2c]">
Bookmarked
</button>
</li>
</ul>
</div>
{/* Change Password Form */}
<div className="mb-4 mt-8 flex flex-wrap gap-y-4 p-4 md:p-0">
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Old password</label>
<input
placeholder="Enter old password"
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
type="password"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">New password</label>
<input
placeholder="Enter new password"
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
type="password"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Confirm password</label>
<input
placeholder="Enter confirm password"
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
type="password"
/>
</div>
<button className="w-full bg-[#ae7aff] p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Change Password
</button>
</div>
</section>
{/* Trending Topics */}
<aside className="hidden text-white lg:col-span-3 lg:block">
<div className="sticky top-[100px] border p-4">
<h2 className="mb-4 font-bold"># Trending Hashtags</h2>
<ul className="list-disc pl-4">
{["javascript", "typescript", "java", "python", "golang"].map(
(hashtag) => (
<li key={hashtag}>
<button className="hover:text-[#ae7aff]">#{hashtag}</button>
</li>
),
)}
</ul>
</div>
</aside>
</div>
</div>
);
};
export default ChangePassword;
================================================
FILE: src/components/templates/social-media/edit-profile.jsx
================================================
import React from "react";
import { BellIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import { PlusCircleIcon } from "@heroicons/react/24/solid";
import { PencilIcon } from "@heroicons/react/20/solid";
const EditProfile = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-full items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">My Profile</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<span className="relative">
<MagnifyingGlassIcon className="h-8 w-8" />
</span>
<span className="relative">
<BellIcon className="h-8 w-8 text-white" />
<span className="absolute right-1 top-0 flex h-2.5 w-2.5 items-center justify-center rounded-full bg-green-500 p-1 text-white"></span>
</span>
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
<PlusCircleIcon className="mr-2 h-5 w-5" /> Create new
</button>
</div>
</header>
<div className="mt-[65px] grid grid-cols-12 gap-4 pb-8 pt-0 sm:px-4 sm:pt-8 md:mt-[83px] lg:px-10">
{/* Empty */}
<aside className="col-span-12 text-white md:col-span-5 lg:col-span-4 xl:col-span-3">
{/* Profile Card */}
<div className="sticky top-[100px] border-b border-white p-4 sm:border">
<img
className="mb-3 flex aspect-square h-16 w-16 rounded-full border-2 border-[#ae7aff] object-cover"
src="https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
alt="avatar"
/>
<h2 className="mb-1 font-bold">Aurora Starlight</h2>
<p className="text-sm">
Night owl | Moon enthusiast | Wanderlust 🌕🌙🌎
</p>
<hr className="my-4 h-[1px] w-full" />
<div className="mb-4">
<h3 className="mb-1 font-bold">Short Bio</h3>
<p className="text-sm">
Immersed in the enchanting world of the night, captivated by the
moon's allure, and constantly seeking new adventures around
the globe. 🌕🌙🌎
</p>
</div>
<div className="mb-4 text-sm">
<h3 className="mb-1 font-bold">Public link</h3>
<button className="block text-[#ae7aff] hover:underline">
starryaurora@gmail.com
</button>
<button className="block break-all text-[#ae7aff] hover:underline">
https://www.aurorastarry.com/
</button>
</div>
<p className="mb-4 flex gap-x-4">
<span className="inline-block">
<span className="font-bold">13.5k </span>
<span className="text-sm text-gray-400">Followers</span>
</span>
<span className="inline-block">
<span className="font-bold">204 </span>
<span className="text-sm text-gray-400">Following</span>
</span>
</p>
<button className="inline-flex w-max items-center bg-[#ae7aff] px-4 py-2 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Edit Profile
</button>
</div>
</aside>
<section className="col-span-12 text-white md:col-span-7 lg:col-span-5 xl:col-span-6">
<div className="sticky top-[82px] z-10 mt-[1px] bg-[#121212] pb-4 before:absolute before:inset-x-0 before:bottom-full before:h-[17px] before:bg-[#121212] md:top-[100px] md:mt-0">
<ul className="no-scrollbar flex w-full overflow-x-auto px-4 sm:px-0">
<li className="mr-2 inline-block shrink-0">
<button className="inline-block px-6 py-1.5 hover:bg-[#2c2c2c]">
Posts
</button>
</li>
<li className="mr-2 inline-block shrink-0">
<button className="inline-block bg-[#2c2c2c] px-6 py-1.5">
Edit profile
</button>
</li>
<li className="mr-2 inline-block shrink-0">
<button className="inline-block px-6 py-1.5 hover:bg-[#2c2c2c]">
Change password
</button>
</li>
<li className="mr-2 inline-block shrink-0">
<button className="inline-block px-6 py-1.5 hover:bg-[#2c2c2c]">
Bookmarked
</button>
</li>
</ul>
</div>
{/* Edit profile Form */}
<div className="mb-4 mt-8 flex flex-wrap gap-y-4 p-4 md:p-0">
<div className="flex w-full items-center justify-center">
<input id="avatar-input-1" hidden type="file" />
<label
htmlFor="avatar-input-1"
className="relative flex aspect-square h-24 w-24 cursor-pointer items-center justify-center overflow-visible rounded-full border-4 border-[#ae7aff] p-1"
>
<img
alt="avatar-inp"
src="https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
className="h-full w-full rounded-full object-cover"
/>
<span className="absolute bottom-0 right-0 flex aspect-square h-5 w-5 items-center justify-center rounded-full bg-[#ae7aff] p-1">
<PencilIcon className="h-3 w-3 text-black" />
</span>
</label>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2 xl:w-1/2 xl:pr-2">
<label className="text-xs text-slate-200">First name</label>
<input
placeholder="Enter first name"
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
defaultValue="Aurora"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2 xl:w-1/2 xl:pl-2">
<label className="text-xs text-slate-200">Last name</label>
<input
placeholder="Enter last name"
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
defaultValue="Starlight"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Email</label>
<input
placeholder="Enter email"
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
defaultValue="starryaurora@gmail.com"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Username</label>
<input
placeholder="Enter username"
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
defaultValue="starryaurora"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Tagline</label>
<input
placeholder="Enter tagline"
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
defaultValue="Night owl | Moon enthusiast | Wanderlust 🌕🌙🌎"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Short Bio</label>
<textarea
placeholder="Enter short bio"
autoComplete="false"
className="w-full resize-none border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
defaultValue="Immersed in the enchanting world of the night, captivated by the
moon's allure, and constantly seeking new adventures around the
globe. 🌕🌙🌎"
></textarea>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Portfolio URL</label>
<input
placeholder="Enter url"
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
defaultValue="https://www.aurorastarry.com/"
type="url"
/>
</div>
<button className="w-full bg-[#ae7aff] p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Edit profile
</button>
</div>
</section>
{/* Trending Topics */}
<aside className="hidden text-white lg:col-span-3 lg:block">
<div className="sticky top-[100px] border p-4">
<h2 className="mb-4 font-bold"># Trending Hashtags</h2>
<ul className="list-disc pl-4">
{["javascript", "typescript", "java", "python", "golang"].map(
(hashtag) => (
<li key={hashtag}>
<button className="hover:text-[#ae7aff]">#{hashtag}</button>
</li>
),
)}
</ul>
</div>
</aside>
</div>
</div>
);
};
export default EditProfile;
================================================
FILE: src/components/templates/social-media/index.ts
================================================
import PostListing from "./post-listing";
import PostDetail from "./post-detail";
import UserProfile from "./user-profile";
import MyProfile from "./my-profile";
import EditProfile from "./edit-profile";
import ChangePassword from "./change-password";
import BookmarkedPosts from "./bookmark-posts";
import Register from "./register";
import Login from "./login";
const SocialMedia = {
PostListing,
PostDetail,
UserProfile,
MyProfile,
EditProfile,
ChangePassword,
BookmarkedPosts,
Register,
Login,
};
export default SocialMedia;
================================================
FILE: src/components/templates/social-media/login.jsx
================================================
const SocialLogin = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-full items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">Login</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
Register
</button>
</div>
</header>
<div className="mx-auto flex w-full items-stretch justify-between gap-10">
<div className="mx-auto mt-28 flex w-full flex-col items-start justify-start p-6 sm:max-w-4xl lg:px-10">
<div className="w-full text-center">
<h1 className="mb-3 text-5xl font-extrabold text-white">Login</h1>
<p className="text-xs text-slate-400">
Login to access your account
</p>
</div>
<div className="my-14 flex w-full flex-col items-start justify-start gap-4">
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">
Username or email
</label>
<input
placeholder="Enter a username or email..."
autoComplete="false"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="flex w-full flex-col items-start justify-start gap-2">
<label className="text-xs text-slate-200">Password</label>
<input
placeholder="Enter a password..."
autoComplete="false"
type="password"
className="w-full border-[1px] border-white bg-black p-4 text-white placeholder:text-gray-500"
/>
</div>
<div className="mr-4 flex items-center">
<input
type="checkbox"
id="checkbox-2"
name="checkbox-2"
className="absolute h-6 w-6 cursor-pointer opacity-0 [&:checked+div]:bg-green-500 [&:checked+div_svg]:block"
/>
<div className="mr-2 flex h-6 w-6 flex-shrink-0 items-center justify-center border-[1px] border-white bg-transparent focus-within:border-white">
<svg
className="pointer-events-none hidden h-3 w-3 fill-current text-white"
version="1.1"
viewBox="0 0 17 12"
xmlns="http://www.w3.org/2000/svg"
>
<g fill="none" fillRule="evenodd">
<g
transform="translate(-9 -11)"
fill="#000000"
fillRule="nonzero"
>
<path d="m25.576 11.414c0.56558 0.55188 0.56558 1.4439 0 1.9961l-9.404 9.176c-0.28213 0.27529-0.65247 0.41385-1.0228 0.41385-0.37034 0-0.74068-0.13855-1.0228-0.41385l-4.7019-4.588c-0.56584-0.55188-0.56584-1.4442 0-1.9961 0.56558-0.55214 1.4798-0.55214 2.0456 0l3.679 3.5899 8.3812-8.1779c0.56558-0.55214 1.4798-0.55214 2.0456 0z" />
</g>
</g>
</svg>
</div>
<div className="ml-3 text-sm leading-6">
<label
htmlFor="checkbox-2"
className="text-sm font-medium text-white"
>
Remember me
</label>
</div>
</div>
<button className="w-full bg-[#ae7aff] p-3 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Log in
</button>
<div className="mx-auto my-3 flex w-full max-w-md items-center justify-center gap-4 text-white">
<hr className="w-full border-[0.1px] border-white" />
<p className="text-sm">OR</p>
<hr className="w-full border-[0.1px] border-white" />
</div>
<button className="inline-flex w-full items-center justify-center gap-3 border-[1px] border-white bg-black p-3 text-center text-white">
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
viewBox="0 0 24 24"
width="24"
>
<path
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
fill="#4285F4"
/>
<path
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
fill="#34A853"
/>
<path
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
fill="#FBBC05"
/>
<path
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
fill="#EA4335"
/>
<path d="M1 1h22v22H1z" fill="none" />
</svg>{" "}
Login with Google
</button>
<button className="inline-flex w-full items-center justify-center gap-3 border-[1px] border-white bg-black p-3 text-center text-white">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="#ffffff"
>
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
</svg>
Login with GitHub
</button>
<p className="text-sm font-light text-white">
Don't have an account?{" "}
<span className="cursor-pointer font-bold hover:underline">
Create an account
</span>
</p>
</div>
</div>
</div>
</div>
);
};
export default SocialLogin;
================================================
FILE: src/components/templates/social-media/my-profile.jsx
================================================
import React from "react";
import {
BellIcon,
BookmarkIcon,
EllipsisVerticalIcon,
HeartIcon,
LinkIcon,
MagnifyingGlassIcon,
} from "@heroicons/react/24/outline";
import {
ChatBubbleOvalLeftEllipsisIcon,
PlusCircleIcon,
ShareIcon,
} from "@heroicons/react/24/solid";
const posts = [
{
id: 1,
authorImage:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Aurora Starlight",
createdOn: "15 minutes ago",
text: "Uncovering ancient secrets and mystical wonders. The journey is the destination. 🔮🌟 #MythologyQuest",
images: [],
likeCount: 46,
commentCount: 13,
bookmarked: false,
liked: true,
},
{
id: 2,
authorImage:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Aurora Starlight",
createdOn: "1 hour ago",
text: "Swimming with the dolphins today, and it was magical! 🐬🌊 #OceanAdventure",
images: [
"https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
],
likeCount: 102,
commentCount: 18,
bookmarked: true,
liked: false,
},
{
id: 3,
authorImage:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Aurora Starlight",
createdOn: "59 minutes ago",
text: "Harnessing the power of the sun for a brighter future. ☀️🔋 #SolarEnergy",
images: [
"https://images.pexels.com/photos/18107025/pexels-photo-18107025/free-photo-of-man-reading-newspaper.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
"https://images.pexels.com/photos/18148933/pexels-photo-18148933/free-photo-of-city-road-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
"https://images.pexels.com/photos/18148937/pexels-photo-18148937/free-photo-of-city-road-traffic-landscape.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
],
likeCount: 802,
commentCount: 99,
bookmarked: true,
liked: true,
},
{
id: 4,
authorImage:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Aurora Starlight",
createdOn: "17 hours ago",
text: "Embracing the lunar magic tonight. The full moon is my muse. 🌕🌌 #MoonlightDreams",
images: [],
likeCount: 420,
commentCount: 20,
bookmarked: false,
liked: false,
link: {
image:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
title: "Aurora Starlight",
caption: "Digital artist | Creative mind | Color magician 🎨🖌️🖼️",
url: "https://www.aurorastarry.com/",
},
},
{
id: 5,
authorImage:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Aurora Starlight",
createdOn: "1 day ago",
text: "💡 Tech Poll: Which emerging technology excites you the most?",
images: [],
likeCount: 207,
commentCount: 63,
bookmarked: false,
liked: false,
poll: [
{
name: "Artificial Intelligence",
},
{
name: "Virtual Reality",
},
{
name: "Quantum Computing",
},
{
name: "5G Connectivity",
},
],
},
{
id: 6,
authorImage:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Aurora Starlight",
createdOn: "7 days ago",
text: "🧘♂️ Mindfulness Poll: Which mindfulness practice resonates with you the most?",
images: [],
likeCount: 97,
commentCount: 13,
liked: true,
bookmarked: false,
poll: [
{
name: "Meditation",
votePercentage: 30,
},
{
name: "Yoga",
selected: true,
votePercentage: 33,
},
{
name: "Deep Breathing",
votePercentage: 27,
},
{
name: "Tai Chi",
votePercentage: 20,
},
],
},
{
id: 7,
authorImage:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Aurora Starlight",
createdOn: "1 months ago",
text: "🎨 Art Poll: What's your preferred art medium for creating masterpieces?",
images: [],
likeCount: 99,
commentCount: 13,
bookmarked: true,
liked: false,
poll: [
{
name: "Acrylic Paint",
votePercentage: 20,
},
{
name: "Watercolor",
votePercentage: 19,
},
{
name: "Digital Art",
votePercentage: 18,
},
{
name: "Charcoal Sketching",
votePercentage: 43,
},
],
},
];
const Profile = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-full items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">My Profile</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<span className="relative">
<MagnifyingGlassIcon className="h-8 w-8" />
</span>
<span className="relative">
<BellIcon className="h-8 w-8 text-white" />
<span className="absolute right-1 top-0 flex h-2.5 w-2.5 items-center justify-center rounded-full bg-green-500 p-1 text-white"></span>
</span>
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
<PlusCircleIcon className="mr-2 h-5 w-5" /> Create new
</button>
</div>
</header>
<div className="mt-[65px] grid grid-cols-12 gap-4 pb-8 pt-0 sm:px-4 sm:pt-8 md:mt-[83px] lg:px-10">
{/* Empty */}
<aside className="col-span-12 text-white md:col-span-5 lg:col-span-4 xl:col-span-3">
{/* Profile Card */}
<div className="sticky top-[100px] border-b border-white p-4 sm:border">
<img
className="mb-3 flex aspect-square h-16 w-16 rounded-full border-2 border-[#ae7aff] object-cover"
src="https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
alt="avatar"
/>
<h2 className="mb-1 font-bold">Aurora Starlight</h2>
<p className="text-sm">
Night owl | Moon enthusiast | Wanderlust 🌕🌙🌎
</p>
<hr className="my-4 h-[1px] w-full" />
<div className="mb-4">
<h3 className="mb-1 font-bold">Short Bio</h3>
<p className="text-sm">
Immersed in the enchanting world of the night, captivated by the
moon's allure, and constantly seeking new adventures around
the globe. 🌕🌙🌎
</p>
</div>
<div className="mb-4 text-sm">
<h3 className="mb-1 font-bold">Public link</h3>
<button className="block text-[#ae7aff] hover:underline">
starryaurora@gmail.com
</button>
<button className="block break-all text-[#ae7aff] hover:underline">
https://www.aurorastarry.com/
</button>
</div>
<p className="mb-4 flex gap-x-4">
<span className="inline-block">
<span className="font-bold">13.5k </span>
<span className="text-sm text-gray-400">Followers</span>
</span>
<span className="inline-block">
<span className="font-bold">204 </span>
<span className="text-sm text-gray-400">Following</span>
</span>
</p>
<button className="inline-flex w-max items-center bg-[#ae7aff] px-4 py-2 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
Edit Profile
</button>
</div>
</aside>
<section className="col-span-12 text-white md:col-span-7 lg:col-span-5 xl:col-span-6">
<div className="sticky top-[82px] z-10 mt-[1px] bg-[#121212] pb-4 before:absolute before:inset-x-0 before:bottom-full before:h-[17px] before:bg-[#121212] md:top-[100px] md:mt-0">
<ul className="no-scrollbar flex w-full overflow-x-auto px-4 sm:px-0">
<li className="mr-2 inline-block shrink-0">
<button className="inline-block bg-[#2c2c2c] px-6 py-1.5">
Posts
</button>
</li>
<li className="mr-2 inline-block shrink-0">
<button className="inline-block px-6 py-1.5 hover:bg-[#2c2c2c]">
Edit profile
</button>
</li>
<li className="mr-2 inline-block shrink-0">
<button className="inline-block px-6 py-1.5 hover:bg-[#2c2c2c]">
Change password
</button>
</li>
<li className="mr-2 inline-block shrink-0">
<button className="inline-block px-6 py-1.5 hover:bg-[#2c2c2c]">
Bookmarked
</button>
</li>
</ul>
</div>
{/* Post Lists */}
{posts.map((post) => (
<div
key={post.id}
className="relative mb-2 w-full last:mb-0 sm:mb-4"
>
<div className="flex border-b border-t border-white p-4 text-white sm:border-l sm:border-r">
{/* Author Profile */}
<div className="h-10 w-10 shrink-0 sm:h-12 sm:w-12">
<img
src={post.authorImage}
alt={post.authorName}
className="h-full w-full rounded-full object-cover"
/>
</div>
{/* Center-Right Content */}
<div className="pl-4 pt-1">
{/* Post Metadata */}
<div className="mb-2 flex items-center gap-x-2">
<div className="w-full">
<h2 className="inline-block font-bold">
{post.authorName}
</h2>
<span className="ml-2 inline-block text-sm text-gray-400">
{post.createdOn}
</span>
</div>
<button className="ml-auto shrink-0 hover:text-[#ae7aff]">
<EllipsisVerticalIcon className="h-5 w-5" />
</button>
</div>
{/* Post Text */}
<p className="mb-4 text-sm sm:text-base">{post.text}</p>
{/* Post Images */}
{post.images.length > 0 && (
<div className="mb-4 grid grid-cols-[repeat(auto-fit,_minmax(200px,_1fr))] gap-4">
{post.images.map((image, i) => (
<img
key={image}
src={image}
alt={`attachment-${i}`}
className="rounded-md"
/>
))}
</div>
)}
{/* Link Preview */}
{post.link && (
<div className="group mb-4 border opacity-95 hover:opacity-100">
<div className="max-h-52 overflow-hidden">
<img
src={post.link.image}
alt={post.link.title}
className="object-cover"
/>
</div>
{/* Link Content */}
<div className="p-4">
<h3 className="mb-2 font-bold">{post.link.title}</h3>
<p className="mb-3 text-sm">{post.link.caption}</p>
<span className="inline-flex items-center gap-x-2 break-all text-sm text-[#ae7aff] no-underline group-hover:underline">
<LinkIcon className="h-4 w-4 shrink-0" />
{post.link.url}
</span>
</div>
</div>
)}
{/* Polls */}
{post.poll &&
post.poll.map((option) => (
<button
key={option?.name}
className={`relative z-[1] mb-4 inline-flex w-full items-center gap-x-4 border p-4 before:absolute before:inset-y-0 before:left-0 before:z-[-1] before:w-[var(--data-vote-percentage)] last:mb-0 ${
option?.votePercentage && option?.votePercentage >= 0
? ""
: "hover:bg-[#ae7aff] hover:text-black focus:border-[#ae7aff] focus:bg-[#ae7aff] focus:text-black"
} ${
option?.selected
? "before:bg-[#ae7aff]"
: "before:bg-gray-400/10"
}
`}
disabled={Boolean(option?.votePercentage)}
style={{
"--data-vote-percentage": `${
option?.votePercentage || 0
}%`,
}}
>
{option?.name}{" "}
{option?.votePercentage && (
<span className="ml-auto shrink-0 text-sm">
{option.votePercentage}%
</span>
)}
</button>
))}
{/* Post Actions Buttons */}
<div className="flex gap-x-4">
{/* Like Button */}
<button
className={`group inline-flex items-center gap-x-1 outline-none after:content-[attr(data-like-count)] focus:after:content-[attr(data-like-count-alt)] ${
post.liked
? "text-[#ae7aff] focus:text-inherit"
: "hover:text-[#ae7aff] focus:text-[#ae7aff]"
}`}
data-like-count={post.likeCount}
data-like-count-alt={
post.liked ? post.likeCount - 1 : post.likeCount + 1
}
>
<HeartIcon
className={`h-5 w-5 ${
post.liked
? "fill-[#ae7aff] group-focus:fill-none"
: "group-focus:fill-[#ae7aff]"
}`}
/>
</button>
{/* Comment Button */}
<button className="inline-flex items-center gap-x-1 outline-none hover:text-[#ae7aff]">
<ChatBubbleOvalLeftEllipsisIcon className="h-5 w-5" />
<span>{post.commentCount}</span>
</button>
{/* Share and Bookmarked Button */}
<div className="ml-auto">
<button className="mr-2 inline-flex items-center gap-x-1 outline-none hover:text-[#ae7aff]">
<ShareIcon className="h-5 w-5" />
</button>
<button
className={`group inline-flex items-center gap-x-1 outline-none hover:text-[#ae7aff] ${
post.bookmarked
? "focus:text-white"
: "focus:text-[#ae7aff]"
}`}
>
<BookmarkIcon
className={`h-5 w-5 ${
post.bookmarked
? "fill-[#ae7aff] text-[#ae7aff] group-focus:fill-none group-focus:text-inherit"
: "group-focus:fill-[#ae7aff]"
}`}
/>
</button>
</div>
</div>
</div>
</div>
</div>
))}
</section>
{/* Trending Topics */}
<aside className="hidden text-white lg:col-span-3 lg:block">
<div className="sticky top-[100px] border p-4">
<h2 className="mb-4 font-bold"># Trending Hashtags</h2>
<ul className="list-disc pl-4">
{["javascript", "typescript", "java", "python", "golang"].map(
(hashtag) => (
<li key={hashtag}>
<button className="hover:text-[#ae7aff]">#{hashtag}</button>
</li>
),
)}
</ul>
</div>
</aside>
</div>
</div>
);
};
export default Profile;
================================================
FILE: src/components/templates/social-media/post-detail.jsx
================================================
import React from "react";
import {
BellIcon,
BookmarkIcon,
EllipsisVerticalIcon,
FaceSmileIcon,
HeartIcon,
LinkIcon,
MagnifyingGlassIcon,
PlusIcon,
} from "@heroicons/react/24/outline";
import {
ChatBubbleOvalLeftEllipsisIcon,
PaperAirplaneIcon,
PlusCircleIcon,
ShareIcon,
ChatBubbleLeftRightIcon,
} from "@heroicons/react/24/solid";
const post = {
id: 1,
authorImage:
"https://images.pexels.com/photos/7775637/pexels-photo-7775637.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Solar Flare ",
createdOn: "59 minutes ago",
text: "Harnessing the power of the sun for a brighter future. ☀️🔋 #SolarEnergy",
images: [
"https://images.pexels.com/photos/18107025/pexels-photo-18107025/free-photo-of-man-reading-newspaper.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
"https://images.pexels.com/photos/18148933/pexels-photo-18148933/free-photo-of-city-road-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
"https://images.pexels.com/photos/18148937/pexels-photo-18148937/free-photo-of-city-road-traffic-landscape.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
],
likeCount: 802,
commentCount: 99,
liked: true,
bookmarked: true,
comments: [
{
id: 1,
authorImage:
"https://images.pexels.com/photos/3532554/pexels-photo-3532554.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Isabella Andrews",
createdOn: "58 minutes ago",
text: "Such an important mission! How can individuals contribute to this solar revolution, Solar Flare?",
images: [
"https://images.pexels.com/photos/18148936/pexels-photo-18148936.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
],
likeCount: 420,
commentCount: 20,
liked: false,
bookmarked: true,
replies: [
{
id: 1,
authorImage:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Aurora Starlight",
createdOn: "55 minutes ago",
text: "Embracing the lunar magic tonight. The full moon is my muse. 🌕🌌 #MoonlightDreams",
images: [],
likeCount: 10,
commentCount: 2,
liked: true,
bookmarked: false,
replies: [],
},
],
},
{
id: 2,
authorImage:
"https://images.pexels.com/photos/1092422/pexels-photo-1092422.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Daniel Greenfield",
createdOn: "45 minutes ago",
text: "Absolutely love your commitment to clean energy, Solar Flare! Keep up the great work! 💚♻️",
images: [
"https://images.pexels.com/photos/1114619/pexels-photo-1114619.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
],
likeCount: 45,
liked: false,
bookmarked: false,
commentCount: 0,
replies: [],
},
{
id: 3,
authorImage:
"https://images.pexels.com/photos/998716/pexels-photo-998716.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Matthew Advocate",
createdOn: "30 minutes ago",
text: "Your efforts are helping us move towards a sustainable future. Kudos, Solar Flare! 🌞🌱",
images: [
"https://images.pexels.com/photos/998714/pexels-photo-998714.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
],
liked: false,
bookmarked: false,
likeCount: 60,
commentCount: 2,
replies: [
{
id: 1,
authorImage:
"https://images.pexels.com/photos/909489/pexels-photo-909489.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Sophia Innovator",
createdOn: "28 minutes ago",
text: "Every ray of sunshine counts! Have you considered integrating solar in urban spaces, Solar Flare?",
images: [],
likeCount: 2,
commentCount: 1,
liked: true,
bookmarked: true,
replies: [],
},
{
id: 2,
authorImage:
"https://images.pexels.com/photos/909487/pexels-photo-909487.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Michael Tech",
createdOn: "2 minutes ago",
text: "Your dedication to solar energy is inspiring, Solar Flare! Are there any upcoming projects we can look forward to?",
images: [],
liked: true,
bookmarked: true,
likeCount: 1,
commentCount: 0,
replies: [],
},
],
},
{
id: 4,
authorImage:
"https://images.pexels.com/photos/909483/pexels-photo-909483.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Samuel Eco",
createdOn: "45 seconds ago",
text: "You're doing incredible work for the environment, Solar Flare. 💪🌿 Let's all go solar!",
images: [],
likeCount: 9,
commentCount: 1,
replies: [],
liked: false,
bookmarked: false,
},
],
};
const PostDetail = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-50 mx-auto flex w-full max-w-full items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">View Post</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<span className="relative">
<MagnifyingGlassIcon className="h-8 w-8" />
</span>
<span className="relative">
<BellIcon className="h-8 w-8 text-white" />
<span className="absolute right-1 top-0 flex h-2.5 w-2.5 items-center justify-center rounded-full bg-green-500 p-1 text-white"></span>
</span>
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
<PlusCircleIcon className="mr-2 h-5 w-5" /> Create new
</button>
</div>
</header>
<div className="mt-[65px] grid grid-cols-12 gap-4 pb-8 pt-0 sm:px-4 sm:pt-8 md:mt-[83px] lg:px-10">
{/* Profile */}
<aside className="hidden text-white md:col-span-4 md:block lg:col-span-3">
<div className="sticky top-[100px] border p-4">
<img
className="mb-3 flex aspect-square h-16 w-16 flex-shrink-0 rounded-full object-cover"
src="https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
alt="avatar"
/>
<h2>Aurora Starlight</h2>
<p className="text-sm">
<button className="hover:text-[#ae7aff]">
starryaurora@gmail.com
</button>
</p>
<hr className="my-2 h-[1px] w-full" />
<p className="mb-4">
Night owl | Moon enthusiast | Wanderlust 🌕🌙🌎
</p>
<button className="inline-flex w-max items-center bg-[#ae7aff] px-4 py-2 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
View Profile
</button>
</div>
</aside>
<section className="col-span-12 border-b border-t border-white sm:border-l sm:border-r md:col-span-8 lg:col-span-6">
{/* Post Card */}
<div className="flex border-b border-white p-4 text-white last:border-none">
{/* Author Profile */}
<div className="h-10 w-10 shrink-0 sm:h-12 sm:w-12">
<img
src={post.authorImage}
alt={post.authorName}
className="h-full w-full rounded-full object-cover"
/>
</div>
{/* Center-Right Content */}
<div className="pl-4 pt-1">
{/* Post Metadata */}
<div className="mb-2 flex items-center gap-x-2">
<div className="w-full">
<h2 className="inline-block font-bold">{post.authorName}</h2>
<span className="ml-2 inline-block text-sm text-gray-400">
{post.createdOn}
</span>
</div>
<button className="ml-auto shrink-0 hover:text-[#ae7aff]">
<EllipsisVerticalIcon className="h-5 w-5" />
</button>
</div>
{/* Post Text */}
<p className="mb-4 text-sm sm:text-base">{post.text}</p>
{/* Post Images */}
{post.images.length > 0 && (
<div className="mb-4 grid grid-cols-[repeat(auto-fit,_minmax(200px,_1fr))] gap-4">
{post.images.map((image, i) => (
<img
key={image}
src={image}
alt={`attachment-${i}`}
className="rounded-md"
/>
))}
</div>
)}
{/* Link Preview */}
{post.link && (
<div className="group mb-4 border opacity-95 hover:opacity-100">
<div className="max-h-52 overflow-hidden">
<img
src={post.link.image}
alt={post.link.title}
className="object-cover"
/>
</div>
{/* Link Content */}
<div className="p-4">
<h3 className="mb-2 font-bold">{post.link.title}</h3>
<p className="mb-3 text-sm">{post.link.caption}</p>
<span className="inline-flex items-center gap-x-2 break-all text-sm text-[#ae7aff] no-underline group-hover:underline">
<LinkIcon className="h-4 w-4 shrink-0" />
{post.link.url}
</span>
</div>
</div>
)}
{/* Post Actions Buttons */}
<div className="flex gap-x-4">
{/* Like Button */}
<button
className={`group inline-flex items-center gap-x-1 outline-none after:content-[attr(data-like-count)] focus:after:content-[attr(data-like-count-alt)] ${
post.liked
? "text-[#ae7aff] focus:text-inherit"
: "hover:text-[#ae7aff] focus:text-[#ae7aff]"
}`}
data-like-count={post.likeCount}
data-like-count-alt={
post.liked ? post.likeCount - 1 : post.likeCount + 1
}
>
<HeartIcon
className={`h-5 w-5 ${
post.liked
? "fill-[#ae7aff] group-focus:fill-none"
: "group-focus:fill-[#ae7aff]"
}`}
/>
</button>
{/* Comment Button */}
<button className="inline-flex items-center gap-x-1 outline-none hover:text-[#ae7aff]">
<ChatBubbleOvalLeftEllipsisIcon className="h-5 w-5" />
<span>{post.commentCount}</span>
</button>
{/* Share and bookmarked Button */}
<div className="ml-auto">
<button className="mr-2 inline-flex items-center gap-x-1 outline-none hover:text-[#ae7aff]">
<ShareIcon className="h-5 w-5" />
</button>
<button
className={`group inline-flex items-center gap-x-1 outline-none hover:text-[#ae7aff] ${
post.bookmarked
? "focus:text-white"
: "focus:text-[#ae7aff]"
}`}
>
<BookmarkIcon
className={`h-5 w-5 ${
post.bookmarked
? "fill-[#ae7aff] text-[#ae7aff] group-focus:fill-none group-focus:text-inherit"
: "group-focus:fill-[#ae7aff]"
}`}
/>
</button>
</div>
</div>
</div>
</div>
{/* Add Comment Form */}
<div className="flex w-full items-center justify-start border-b border-white px-4 py-2 last:border-none">
<img
className="flex aspect-square h-10 w-10 shrink-0 rounded-full object-cover"
src="https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
alt="avatar"
/>
<input
placeholder="Comment..."
className="w-full bg-transparent p-2 text-white !outline-none placeholder:text-gray-500 md:p-4"
/>
<div className="flex gap-x-1 sm:gap-x-2">
<button className="flex shrink-0 items-center justify-center p-1">
<FaceSmileIcon className="w-6 text-white" />
</button>
<button className="flex shrink-0 items-center justify-center p-1">
<PlusIcon className="w-6 text-white" />
</button>
<button className="flex shrink-0 items-center justify-center bg-[#ae7aff] p-1">
<PaperAirplaneIcon className="w-6 text-black" />
</button>
</div>
</div>
{/* Post Comments */}
{post.comments.map((comment) => (
<div
className="relative border-b border-white last:border-none"
key={comment.id}
>
<div className="flex p-4 text-white">
{/* Author Profile */}
<div
className={`relative shrink-0 before:absolute before:left-1/2 before:top-[30px] before:z-[5] before:h-full before:w-[1px] ${
comment.replies.length > 0
? "before:bg-white"
: "before:bg-transparent"
}`}
>
<div className="relative z-10 h-10 w-10 sm:h-12 sm:w-12">
<img
src={comment.authorImage}
alt={comment.authorName}
className="h-full w-full rounded-full object-cover"
/>
</div>
</div>
{/* Center-Right Content */}
<div className="pl-4 pt-1">
{/* Post Metadata */}
<div className="mb-2 flex items-center gap-x-2">
<div className="w-full">
<h2 className="inline-block font-bold">
{comment.authorName}
</h2>
<span className="ml-2 inline-block text-sm text-gray-400">
{comment.createdOn}
</span>
</div>
<button className="ml-auto shrink-0 hover:text-[#ae7aff]">
<EllipsisVerticalIcon className="h-5 w-5" />
</button>
</div>
{/* Post Text */}
<p className="mb-4 text-sm sm:text-base">{comment.text}</p>
{/* Post Images */}
{comment.images.length > 0 && (
<div className="mb-4 grid grid-cols-[repeat(auto-fit,_minmax(200px,_1fr))] gap-4">
{comment.images.map((image, i) => (
<img
key={image}
src={image}
alt={`attachment-${i}`}
className="rounded-md"
/>
))}
</div>
)}
{/* Post Actions Buttons */}
<div className="flex gap-x-4">
{/* Like Button */}
<button
className={`group inline-flex items-center gap-x-1 outline-none after:content-[attr(data-like-count)] focus:after:content-[attr(data-like-count-alt)] ${
comment.liked
? "text-[#ae7aff] focus:text-inherit"
: "hover:text-[#ae7aff] focus:text-[#ae7aff]"
}`}
data-like-count={comment.likeCount}
data-like-count-alt={
comment.liked
? comment.likeCount - 1
: comment.likeCount + 1
}
>
<HeartIcon
className={`h-5 w-5 ${
comment.liked
? "fill-[#ae7aff] group-focus:fill-none"
: "group-focus:fill-[#ae7aff]"
}`}
/>
</button>
{/* Comment Button */}
<button className="inline-flex items-center gap-x-1 outline-none hover:text-[#ae7aff]">
<ChatBubbleLeftRightIcon className="h-5 w-5" />
<span>{comment.commentCount}</span>
</button>
</div>
</div>
</div>
{/* Nested Comments */}
{comment.replies.map((comment) => (
<div key={comment.id} className="flex p-4 text-white">
{/* Author Profile */}
<div className="h-10 w-10 shrink-0 sm:h-12 sm:w-12">
<img
src={comment.authorImage}
alt={comment.authorName}
className="h-full w-full rounded-full object-cover"
/>
</div>
{/* Center-Right Content */}
<div className="pl-4 pt-1">
{/* Post Metadata */}
<div className="mb-2 flex items-center gap-x-2">
<div className="w-full">
<h2 className="inline-block font-bold">
{comment.authorName}
</h2>
<span className="ml-2 inline-block text-sm text-gray-400">
{comment.createdOn}
</span>
</div>
<button className="ml-auto shrink-0 hover:text-[#ae7aff]">
<EllipsisVerticalIcon className="h-5 w-5" />
</button>
</div>
{/* Post Text */}
<p className="mb-4 text-sm sm:text-base">{comment.text}</p>
{/* Post Images */}
{comment.images.length > 0 && (
<div className="mb-4 grid grid-cols-[repeat(auto-fit,_minmax(200px,_1fr))] gap-4">
{comment.images.map((image, i) => (
<img
key={image}
src={image}
alt={`attachment-${i}`}
className="rounded-md"
/>
))}
</div>
)}
{/* Post Actions Buttons */}
<div className="flex gap-x-4">
{/* Like Button */}
<button
className={`group inline-flex items-center gap-x-1 outline-none after:content-[attr(data-like-count)] focus:after:content-[attr(data-like-count-alt)] ${
comment.liked
? "text-[#ae7aff] focus:text-inherit"
: "hover:text-[#ae7aff] focus:text-[#ae7aff]"
}`}
data-like-count={comment.likeCount}
data-like-count-alt={
comment.liked
? comment.likeCount - 1
: comment.likeCount + 1
}
>
<HeartIcon
className={`h-5 w-5 ${
comment.liked
? "fill-[#ae7aff] group-focus:fill-none"
: "group-focus:fill-[#ae7aff]"
}`}
/>
</button>
</div>
</div>
</div>
))}
</div>
))}
</section>
{/* Trending Topics */}
<aside className="hidden text-white lg:col-span-3 lg:block">
<div className="sticky top-[100px] border p-4">
<h2 className="mb-4 font-bold"># Trending Hashtags</h2>
<ul className="list-disc pl-4">
{["javascript", "typescript", "java", "python", "golang"].map(
(hashtag) => (
<li key={hashtag}>
<button className="hover:text-[#ae7aff]">#{hashtag}</button>
</li>
),
)}
</ul>
</div>
</aside>
</div>
</div>
);
};
export default PostDetail;
================================================
FILE: src/components/templates/social-media/post-listing.jsx
================================================
import React from "react";
import {
BellIcon,
BookmarkIcon,
EllipsisVerticalIcon,
FaceSmileIcon,
HeartIcon,
LinkIcon,
MagnifyingGlassIcon,
PlusIcon,
} from "@heroicons/react/24/outline";
import {
ChatBubbleOvalLeftEllipsisIcon,
PaperAirplaneIcon,
PlusCircleIcon,
ShareIcon,
} from "@heroicons/react/24/solid";
const posts = [
{
id: 1,
authorImage:
"https://images.pexels.com/photos/18264716/pexels-photo-18264716.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Mystical Wanderer",
createdOn: "15 minutes ago",
text: "Uncovering ancient secrets and mystical wonders. The journey is the destination. 🔮🌟 #MythologyQuest",
images: [],
likeCount: 46,
commentCount: 13,
bookmarked: false,
liked: true,
},
{
id: 2,
authorImage:
"https://images.pexels.com/photos/13847596/pexels-photo-13847596.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Aqua Explorer",
createdOn: "1 hour ago",
text: "Swimming with the dolphins today, and it was magical! 🐬🌊 #OceanAdventure",
images: [
"https://images.pexels.com/photos/18107024/pexels-photo-18107024/free-photo-of-an-old-city-view.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
],
likeCount: 102,
commentCount: 18,
bookmarked: true,
liked: false,
},
{
id: 3,
authorImage:
"https://images.pexels.com/photos/7775637/pexels-photo-7775637.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Solar Flare ",
createdOn: "59 minutes ago",
text: "Harnessing the power of the sun for a brighter future. ☀️🔋 #SolarEnergy",
images: [
"https://images.pexels.com/photos/18107025/pexels-photo-18107025/free-photo-of-man-reading-newspaper.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
"https://images.pexels.com/photos/18148933/pexels-photo-18148933/free-photo-of-city-road-man-people.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
"https://images.pexels.com/photos/18148937/pexels-photo-18148937/free-photo-of-city-road-traffic-landscape.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
],
likeCount: 802,
commentCount: 99,
bookmarked: true,
liked: true,
},
{
id: 4,
authorImage:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Aurora Starlight",
createdOn: "17 hours ago",
text: "Embracing the lunar magic tonight. The full moon is my muse. 🌕🌌 #MoonlightDreams",
images: [],
likeCount: 420,
commentCount: 20,
bookmarked: false,
liked: false,
link: {
image:
"https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
title: "Aurora Starlight",
caption: "Digital artist | Creative mind | Color magician 🎨🖌️🖼️",
url: "https://www.aurorastarry.com/",
},
},
{
id: 5,
authorImage:
"https://images.pexels.com/photos/3532553/pexels-photo-3532553.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Nova Sparks",
createdOn: "1 day ago",
text: "💡 Tech Poll: Which emerging technology excites you the most?",
images: [],
likeCount: 207,
commentCount: 63,
bookmarked: false,
liked: false,
poll: [
{
name: "Artificial Intelligence",
},
{
name: "Virtual Reality",
},
{
name: "Quantum Computing",
},
{
name: "5G Connectivity",
},
],
},
{
id: 6,
authorImage:
"https://images.pexels.com/photos/569314/pexels-photo-569314.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Zen Garden",
createdOn: "7 days ago",
text: "🧘♂️ Mindfulness Poll: Which mindfulness practice resonates with you the most?",
images: [],
likeCount: 97,
commentCount: 13,
liked: true,
bookmarked: false,
poll: [
{
name: "Meditation",
votePercentage: 30,
},
{
name: "Yoga",
selected: true,
votePercentage: 33,
},
{
name: "Deep Breathing",
votePercentage: 27,
},
{
name: "Tai Chi",
votePercentage: 20,
},
],
},
{
id: 7,
authorImage:
"https://images.pexels.com/photos/1739942/pexels-photo-1739942.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
authorName: "Pixel Painter",
createdOn: "1 months ago",
text: "🎨 Art Poll: What's your preferred art medium for creating masterpieces?",
images: [],
likeCount: 99,
commentCount: 13,
bookmarked: true,
liked: false,
poll: [
{
name: "Acrylic Paint",
votePercentage: 20,
},
{
name: "Watercolor",
votePercentage: 19,
},
{
name: "Digital Art",
votePercentage: 18,
},
{
name: "Charcoal Sketching",
votePercentage: 43,
},
],
},
];
const PostListing = () => {
return (
<div className="min-h-screen bg-[#121212]">
<header className="fixed top-0 z-10 mx-auto flex w-full max-w-full items-center justify-between border-b-[1px] border-b-slate-300 bg-[#121212] p-4 text-white lg:px-10">
<h1 className="text-xl font-extrabold md:text-3xl">All Posts</h1>
<div className="flex w-max flex-shrink-0 items-center justify-end gap-6">
<span className="relative">
<MagnifyingGlassIcon className="h-8 w-8" />
</span>
<span className="relative">
<BellIcon className="h-8 w-8 text-white" />
<span className="absolute right-1 top-0 flex h-2.5 w-2.5 items-center justify-center rounded-full bg-green-500 p-1 text-white"></span>
</span>
<button className="hidden w-max items-center justify-center border-[1px] border-white p-3 text-center font-bold text-white md:inline-flex">
<PlusCircleIcon className="mr-2 h-5 w-5" /> Create new
</button>
</div>
</header>
<div className="mt-[65px] grid grid-cols-12 gap-4 pb-8 pt-0 sm:px-4 sm:pt-8 md:mt-[83px] lg:px-10">
{/* Profile */}
<aside className="hidden text-white md:col-span-4 md:block lg:col-span-3">
<div className="sticky top-[100px] border p-4">
<img
className="mb-3 flex aspect-square h-16 w-16 flex-shrink-0 rounded-full object-cover"
src="https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
alt="avatar"
/>
<h2>Aurora Starlight</h2>
<p className="text-sm">
<button className="hover:text-[#ae7aff]">
starryaurora@gmail.com
</button>
</p>
<hr className="my-2 h-[1px] w-full" />
<p className="mb-4">
Night owl | Moon enthusiast | Wanderlust 🌕🌙🌎
</p>
<button className="inline-flex w-max items-center bg-[#ae7aff] px-4 py-2 text-center font-bold text-black shadow-[5px_5px_0px_0px_#4f4e4e] transition-all duration-150 ease-in-out active:translate-x-[5px] active:translate-y-[5px] active:shadow-[0px_0px_0px_0px_#4f4e4e]">
View Profile
</button>
</div>
</aside>
<section className="col-span-12 md:col-span-8 lg:col-span-6">
{/* Create Post Form */}
<div className="mb-2 flex w-full items-center justify-start border-b border-t border-white px-4 py-2 sm:mb-6 sm:border-l sm:border-r sm:shadow-[5px_5px_0px_0px_#4f4e4e]">
<img
className="flex aspect-square h-10 w-10 shrink-0 rounded-full object-cover"
src="https://images.pexels.com/photos/7775642/pexels-photo-7775642.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
alt="avatar"
/>
<input
placeholder="Type to add something"
className="w-full bg-transparent p-2 text-white !outline-none placeholder:text-gray-500 md:p-4"
/>
<div className="flex gap-x-1 sm:gap-x-2">
<button className="flex shrink-0 items-center justify-center p-1">
<FaceSmileIcon className="w-6 text-white" />
</button>
<button className="flex shrink-0 items-center justify-center p-1">
<PlusIcon className="w-6 text-white" />
</button>
<button className="flex shrink-0 items-center justify-center bg-[#ae7aff] p-1">
<PaperAirplaneIcon className="w-6 text-black" />
</button>
</div>
</div>
{/* Post Lists */}
{posts.map((post) => (
<div
key={post.id}
className="relative mb-2 w-full last:mb-0 sm:mb-4"
>
<div className="flex border-b border-t border-white p-4 text-white sm:border-l sm:border-r">
{/* Author Profile */}
<div className="h-10 w-10 shrink-0 sm:h-12 sm:w-12">
<img
src={post.authorImage}
alt={post.authorName}
className="h-full w-full rounded-full object-cover"
/>
</div>
{/* Center-Right Content */}
<div className="pl-4 pt-1">
{/* Post Metadata */}
<div className="mb-2 flex items-center gap-x-2">
<div className="w-full">
<h2 className="inline-block font-bold">
{post.authorName}
</h2>
<span className="ml-2 inline-block text-sm text-gray-400">
{post.createdOn}
</span>
</div>
<button className="ml-auto shrink-0 hover:text-[#ae7aff]">
<EllipsisVerticalIcon className="h-5 w-5" />
</button>
</div>
{/* Post Text */}
<p className="mb-4 text-sm sm:text-base">{post.text}</p>
{/* Post Images */}
{post.images.length > 0 && (
<div className="mb-4 grid grid-cols-[repeat(auto-fit,_minmax(200px,_1fr))] gap-4">
{post.images.map((image, i) => (
<img
key={image}
src={image}
alt={`attachment-${i}`}
className="rounded-md"
/>
))}
</div>
)}
{/* Link Preview */}
{post.link && (
<div className="group mb-4 border opacity-95 hover:opacity-100">
<div className="max-h-52 overflow-hidden">
<img
src={post.link.image}
gitextract_hoj68ou7/ ├── .eslintrc.json ├── .gitignore ├── README.md ├── next.config.js ├── package.json ├── postcss.config.js ├── prettier.config.js ├── src/ │ ├── app/ │ │ ├── about-us/ │ │ │ └── page.tsx │ │ ├── globals.css │ │ ├── layout.tsx │ │ ├── page.tsx │ │ └── templates/ │ │ ├── [id]/ │ │ │ └── page.tsx │ │ └── page.tsx │ ├── components/ │ │ ├── common/ │ │ │ ├── Button.tsx │ │ │ ├── MainNavbar.tsx │ │ │ ├── MobileNavbar.tsx │ │ │ └── Select.tsx │ │ ├── lib/ │ │ │ ├── CodePreviewer.tsx │ │ │ ├── CodeSnippetRenderer.tsx │ │ │ ├── PreviewCard.tsx │ │ │ └── WidthHandler.tsx │ │ └── templates/ │ │ ├── authentication/ │ │ │ ├── forgot-password.jsx │ │ │ ├── index.ts │ │ │ ├── login.jsx │ │ │ └── register.jsx │ │ ├── chat/ │ │ │ ├── chat-screen.jsx │ │ │ ├── create-group-chat.jsx │ │ │ ├── create-normal-chat.jsx │ │ │ ├── empty-chats.jsx │ │ │ ├── group-information.jsx │ │ │ ├── index.ts │ │ │ ├── login.jsx │ │ │ └── register.jsx │ │ ├── social-media/ │ │ │ ├── bookmark-posts.jsx │ │ │ ├── change-password.jsx │ │ │ ├── edit-profile.jsx │ │ │ ├── index.ts │ │ │ ├── login.jsx │ │ │ ├── my-profile.jsx │ │ │ ├── post-detail.jsx │ │ │ ├── post-listing.jsx │ │ │ ├── register.jsx │ │ │ └── user-profile.jsx │ │ ├── todo/ │ │ │ ├── empty-todos.jsx │ │ │ ├── index.ts │ │ │ └── todos.jsx │ │ └── youtube/ │ │ ├── change-password.jsx │ │ ├── channel-empty-playlist.jsx │ │ ├── channel-empty-subscribed.jsx │ │ ├── channel-empty-tweet.jsx │ │ ├── channel-empty-video.jsx │ │ ├── channel-playlist-videos.jsx │ │ ├── channel-playlist.jsx │ │ ├── channel-subscribed.jsx │ │ ├── channel-tweets.jsx │ │ ├── channel-video-list.jsx │ │ ├── dashboard.jsx │ │ ├── data.jsx │ │ ├── delete-video.jsx │ │ ├── edit-channel-info.jsx │ │ ├── edit-personal-info.jsx │ │ ├── edit-video.jsx │ │ ├── empty-videos.jsx │ │ ├── index.ts │ │ ├── login.jsx │ │ ├── mychannel-empty-tweet.jsx │ │ ├── mychannel-empty-video.jsx │ │ ├── mychannel-tweets.jsx │ │ ├── privacy-policy.jsx │ │ ├── register.jsx │ │ ├── terms-and-conditions.jsx │ │ ├── upload-video.jsx │ │ ├── uploaded-video.jsx │ │ ├── uploading-video.jsx │ │ ├── video-cards.jsx │ │ ├── video-detail.jsx │ │ └── video-list.jsx │ ├── types/ │ │ └── utils.ts │ └── utils/ │ ├── index.ts │ └── screens.tsx ├── tailwind.config.ts └── tsconfig.json
SYMBOL INDEX (13 symbols across 9 files)
FILE: src/app/layout.tsx
function RootLayout (line 13) | function RootLayout({
FILE: src/app/page.tsx
function Home (line 9) | function Home() {
FILE: src/components/common/MobileNavbar.tsx
type MobileNavProps (line 6) | interface MobileNavProps {
function MobileNavbar (line 13) | function MobileNavbar({ items }: MobileNavProps) {
FILE: src/components/common/Select.tsx
type SelectProps (line 8) | interface SelectProps {
FILE: src/components/lib/CodePreviewer.tsx
type CodePreviewerProps (line 12) | interface CodePreviewerProps {
FILE: src/components/lib/CodeSnippetRenderer.tsx
constant DEFAULT_BASE_SETUP (line 9) | const DEFAULT_BASE_SETUP = {
type CodeSnippetRendererProps (line 19) | interface CodeSnippetRendererProps {
FILE: src/components/lib/PreviewCard.tsx
type PreviewCardProps (line 5) | interface PreviewCardProps {
FILE: src/components/lib/WidthHandler.tsx
constant DEFAULT_WIDTHS (line 3) | const DEFAULT_WIDTHS = {
type Props (line 7) | interface Props {
FILE: src/types/utils.ts
type TailwindIconType (line 1) | type TailwindIconType = React.ForwardRefExoticComponent<
type SelectOptionType (line 8) | type SelectOptionType = {
Condensed preview — 82 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (616K chars).
[
{
"path": ".eslintrc.json",
"chars": 123,
"preview": "{\n \"extends\": \"next/core-web-vitals\",\n \"rules\": {\n // next no-img-element\n \"@next/next/no-img-element\": \"off\"\n "
},
{
"path": ".gitignore",
"chars": 368,
"preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
},
{
"path": "README.md",
"chars": 52,
"preview": "# DevUI\n\nA complete front end solution for learners\n"
},
{
"path": "next.config.js",
"chars": 143,
"preview": "/** @type {import('next').NextConfig} */\nconst nextConfig = {\n images: { domains: [\"via.placeholder.com\"] },\n};\n\nmodule"
},
{
"path": "package.json",
"chars": 959,
"preview": "{\n \"name\": \"devui\",\n \"description\": \"Common app templates in plain HTML and TailwindCSS\",\n \"version\": \"0.1.0\",\n \"pri"
},
{
"path": "postcss.config.js",
"chars": 82,
"preview": "module.exports = {\n plugins: {\n tailwindcss: {},\n autoprefixer: {},\n },\n}\n"
},
{
"path": "prettier.config.js",
"chars": 66,
"preview": "module.exports = {\n plugins: [\"prettier-plugin-tailwindcss\"],\n};\n"
},
{
"path": "src/app/about-us/page.tsx",
"chars": 109,
"preview": "import React from \"react\";\n\nconst AboutUs = () => {\n return <div>AboutUs</div>;\n};\n\nexport default AboutUs;\n"
},
{
"path": "src/app/globals.css",
"chars": 390,
"preview": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n.resizing,\n.resizing * {\n @apply !cursor-ew-resize !select-"
},
{
"path": "src/app/layout.tsx",
"chars": 668,
"preview": "import MainNavbar from \"@/components/common/MainNavbar\";\nimport type { Metadata } from \"next\";\nimport { Inter } from \"ne"
},
{
"path": "src/app/page.tsx",
"chars": 1335,
"preview": "import Button from \"@/components/common/Button\";\nimport {\n CodeBracketSquareIcon,\n LifebuoyIcon,\n} from \"@heroicons/re"
},
{
"path": "src/app/templates/[id]/page.tsx",
"chars": 1401,
"preview": "\"use client\";\nimport Select from \"@/components/common/Select\";\nimport CodePreviewer from \"@/components/lib/CodePreviewer"
},
{
"path": "src/app/templates/page.tsx",
"chars": 2114,
"preview": "\"use client\";\n\nimport Button from \"@/components/common/Button\";\nimport { applications } from \"@/utils/screens\";\nimport {"
},
{
"path": "src/components/common/Button.tsx",
"chars": 805,
"preview": "import { TailwindIconType } from \"@/types/utils\";\nimport React from \"react\";\n\nconst Button: React.FC<\n React.ButtonHTML"
},
{
"path": "src/components/common/MainNavbar.tsx",
"chars": 2270,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport { CodeBracketSquareIcon } from \"@heroicons/react/20/solid\";\ni"
},
{
"path": "src/components/common/MobileNavbar.tsx",
"chars": 1317,
"preview": "import * as React from \"react\";\nimport Link from \"next/link\";\nimport { CodeBracketSquareIcon } from \"@heroicons/react/20"
},
{
"path": "src/components/common/Select.tsx",
"chars": 3248,
"preview": "\"use client\";\nimport { SelectOptionType } from \"@/types/utils\";\nimport { classNames } from \"@/utils\";\nimport { Combobox "
},
{
"path": "src/components/lib/CodePreviewer.tsx",
"chars": 3283,
"preview": "import { renderHTMLFromJSX } from \"@/utils\";\nimport { CheckCircleIcon } from \"@heroicons/react/20/solid\";\nimport {\n Cod"
},
{
"path": "src/components/lib/CodeSnippetRenderer.tsx",
"chars": 1844,
"preview": "import { langs } from \"@uiw/codemirror-extensions-langs\";\nimport * as themes from \"@uiw/codemirror-themes-all\";\nimport C"
},
{
"path": "src/components/lib/PreviewCard.tsx",
"chars": 1891,
"preview": "import { classNames, renderHTMLFromJSX } from \"@/utils\";\nimport { useEffect, useRef, useState } from \"react\";\nimport Wid"
},
{
"path": "src/components/lib/WidthHandler.tsx",
"chars": 2111,
"preview": "import React, { RefObject, useEffect, useRef } from \"react\";\n\nexport const DEFAULT_WIDTHS = {\n minWidth: 360,\n};\n\ninter"
},
{
"path": "src/components/templates/authentication/forgot-password.jsx",
"chars": 2380,
"preview": "import React from \"react\";\n\nconst ForgotPassword = () => {\n return (\n <div className=\"min-h-screen bg-[#121212]\">\n "
},
{
"path": "src/components/templates/authentication/index.ts",
"chars": 205,
"preview": "import Register from \"./register\";\nimport Login from \"./login\";\nimport ForgotPassword from \"./forgot-password\";\n\nconst A"
},
{
"path": "src/components/templates/authentication/login.jsx",
"chars": 7439,
"preview": "import React from \"react\";\n\nconst Login = () => {\n return (\n <div className=\"min-h-screen bg-[#121212]\">\n <head"
},
{
"path": "src/components/templates/authentication/register.jsx",
"chars": 7301,
"preview": "const Register = () => {\n return (\n <div className=\"min-h-screen bg-[#121212]\">\n <header className=\"fixed top-0"
},
{
"path": "src/components/templates/chat/chat-screen.jsx",
"chars": 21551,
"preview": "import React from \"react\";\nimport { PaperAirplaneIcon, PlusCircleIcon } from \"@heroicons/react/20/solid\";\nimport {\n Bar"
},
{
"path": "src/components/templates/chat/create-group-chat.jsx",
"chars": 6822,
"preview": "import {\n BellIcon,\n PlusCircleIcon,\n XMarkIcon,\n} from \"@heroicons/react/24/outline\";\nimport React from \"react\";\n\nco"
},
{
"path": "src/components/templates/chat/create-normal-chat.jsx",
"chars": 4234,
"preview": "import {\n BellIcon,\n PlusCircleIcon,\n XMarkIcon,\n} from \"@heroicons/react/24/outline\";\nimport React from \"react\";\n\nco"
},
{
"path": "src/components/templates/chat/empty-chats.jsx",
"chars": 2576,
"preview": "import React from \"react\";\nimport { PlusCircleIcon } from \"@heroicons/react/20/solid\";\nimport { BellIcon, InboxIcon } fr"
},
{
"path": "src/components/templates/chat/group-information.jsx",
"chars": 8425,
"preview": "import { TrashIcon, UserMinusIcon, XMarkIcon } from \"@heroicons/react/20/solid\";\nimport {\n BellIcon,\n ExclamationTrian"
},
{
"path": "src/components/templates/chat/index.ts",
"chars": 439,
"preview": "import EmptyChats from \"./empty-chats\";\nimport ChatScreen from \"./chat-screen\";\nimport CreateGroupChat from \"./create-gr"
},
{
"path": "src/components/templates/chat/login.jsx",
"chars": 7392,
"preview": "const SocialLogin = () => {\n return (\n <div className=\"min-h-screen bg-[#121212]\">\n <header className=\"fixed to"
},
{
"path": "src/components/templates/chat/register.jsx",
"chars": 6878,
"preview": "import { PlusIcon } from \"@heroicons/react/24/outline\";\n\nconst SocialRegister = () => {\n return (\n <div className=\"m"
},
{
"path": "src/components/templates/social-media/bookmark-posts.jsx",
"chars": 17642,
"preview": "import React from \"react\";\nimport {\n BellIcon,\n BookmarkIcon,\n EllipsisVerticalIcon,\n HeartIcon,\n LinkIcon,\n Magni"
},
{
"path": "src/components/templates/social-media/change-password.jsx",
"chars": 7430,
"preview": "import React from \"react\";\nimport { BellIcon, MagnifyingGlassIcon } from \"@heroicons/react/24/outline\";\nimport { PlusCir"
},
{
"path": "src/components/templates/social-media/edit-profile.jsx",
"chars": 10510,
"preview": "import React from \"react\";\nimport { BellIcon, MagnifyingGlassIcon } from \"@heroicons/react/24/outline\";\nimport { PlusCir"
},
{
"path": "src/components/templates/social-media/index.ts",
"chars": 549,
"preview": "import PostListing from \"./post-listing\";\nimport PostDetail from \"./post-detail\";\nimport UserProfile from \"./user-profil"
},
{
"path": "src/components/templates/social-media/login.jsx",
"chars": 7246,
"preview": "const SocialLogin = () => {\n return (\n <div className=\"min-h-screen bg-[#121212]\">\n <header className=\"fixed to"
},
{
"path": "src/components/templates/social-media/my-profile.jsx",
"chars": 17652,
"preview": "import React from \"react\";\nimport {\n BellIcon,\n BookmarkIcon,\n EllipsisVerticalIcon,\n HeartIcon,\n LinkIcon,\n Magni"
},
{
"path": "src/components/templates/social-media/post-detail.jsx",
"chars": 21755,
"preview": "import React from \"react\";\nimport {\n BellIcon,\n BookmarkIcon,\n EllipsisVerticalIcon,\n FaceSmileIcon,\n HeartIcon,\n "
},
{
"path": "src/components/templates/social-media/post-listing.jsx",
"chars": 16617,
"preview": "import React from \"react\";\nimport {\n BellIcon,\n BookmarkIcon,\n EllipsisVerticalIcon,\n FaceSmileIcon,\n HeartIcon,\n "
},
{
"path": "src/components/templates/social-media/register.jsx",
"chars": 7136,
"preview": "import { PlusIcon } from \"@heroicons/react/24/outline\";\n\nconst SocialRegister = () => {\n return (\n <div className=\"m"
},
{
"path": "src/components/templates/social-media/user-profile.jsx",
"chars": 16438,
"preview": "import React from \"react\";\nimport {\n BellIcon,\n BookmarkIcon,\n EllipsisVerticalIcon,\n HeartIcon,\n LinkIcon,\n Magni"
},
{
"path": "src/components/templates/todo/empty-todos.jsx",
"chars": 1746,
"preview": "import React from \"react\";\nimport { PlusCircleIcon } from \"@heroicons/react/20/solid\";\nimport { InboxIcon } from \"@heroi"
},
{
"path": "src/components/templates/todo/index.ts",
"chars": 141,
"preview": "import TodosList from \"./todos\";\nimport EmptyTodos from \"./empty-todos\";\n\nconst Todo = {\n TodosList,\n EmptyTodos,\n};\n\n"
},
{
"path": "src/components/templates/todo/todos.jsx",
"chars": 5502,
"preview": "import { PlusCircleIcon } from \"@heroicons/react/20/solid\";\nimport { PencilIcon, TrashIcon } from \"@heroicons/react/24/o"
},
{
"path": "src/components/templates/youtube/change-password.jsx",
"chars": 10413,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport { MagnifyingGlassIcon, XCircleIcon"
},
{
"path": "src/components/templates/youtube/channel-empty-playlist.jsx",
"chars": 8963,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n MagnifyingGlassIcon,\n UserPlu"
},
{
"path": "src/components/templates/youtube/channel-empty-subscribed.jsx",
"chars": 9058,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n MagnifyingGlassIcon,\n UserPlu"
},
{
"path": "src/components/templates/youtube/channel-empty-tweet.jsx",
"chars": 9007,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n MagnifyingGlassIcon,\n UserPlu"
},
{
"path": "src/components/templates/youtube/channel-empty-video.jsx",
"chars": 8978,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n MagnifyingGlassIcon,\n PlayIco"
},
{
"path": "src/components/templates/youtube/channel-playlist-videos.jsx",
"chars": 10288,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport { MagnifyingGlassIcon, XCircleIcon } from \"@heroicons/react/2"
},
{
"path": "src/components/templates/youtube/channel-playlist.jsx",
"chars": 10756,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n MagnifyingGlassIcon,\n UserPlu"
},
{
"path": "src/components/templates/youtube/channel-subscribed.jsx",
"chars": 10566,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n MagnifyingGlassIcon,\n UserPlu"
},
{
"path": "src/components/templates/youtube/channel-tweets.jsx",
"chars": 11333,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n HandThumbDownIcon,\n HandThumb"
},
{
"path": "src/components/templates/youtube/channel-video-list.jsx",
"chars": 9467,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n MagnifyingGlassIcon,\n UserPlu"
},
{
"path": "src/components/templates/youtube/dashboard.jsx",
"chars": 10020,
"preview": "\"use client\";\nimport {\n EyeIcon,\n HeartIcon,\n MagnifyingGlassIcon,\n PencilIcon,\n PlusIcon,\n TrashIcon,\n UserIcon,"
},
{
"path": "src/components/templates/youtube/data.jsx",
"chars": 46031,
"preview": "export const logo = (\n <svg\n style={{ width: \"100%\" }}\n viewBox=\"0 0 63 64\"\n fill=\"none\"\n xmlns=\"http://www"
},
{
"path": "src/components/templates/youtube/delete-video.jsx",
"chars": 11385,
"preview": "\"use client\";\nimport {\n EyeIcon,\n HeartIcon,\n MagnifyingGlassIcon,\n PencilIcon,\n PlusIcon,\n TrashIcon,\n UserIcon,"
},
{
"path": "src/components/templates/youtube/edit-channel-info.jsx",
"chars": 20364,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n ClockIcon,\n ListBulletIcon,\n "
},
{
"path": "src/components/templates/youtube/edit-personal-info.jsx",
"chars": 11642,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n CloudArrowUpIcon,\n EnvelopeIc"
},
{
"path": "src/components/templates/youtube/edit-video.jsx",
"chars": 13243,
"preview": "\"use client\";\nimport {\n EyeIcon,\n HeartIcon,\n MagnifyingGlassIcon,\n PencilIcon,\n PlusIcon,\n TrashIcon,\n UserIcon,"
},
{
"path": "src/components/templates/youtube/empty-videos.jsx",
"chars": 5813,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport {\n MagnifyingGlassIcon,\n PlayIcon,\n XCircleIcon,\n} from \"@"
},
{
"path": "src/components/templates/youtube/index.ts",
"chars": 1975,
"preview": "import EmptyVideos from \"./empty-videos\";\nimport VideoCards from \"./video-cards\";\nimport VideoList from \"./video-list\";\n"
},
{
"path": "src/components/templates/youtube/login.jsx",
"chars": 869,
"preview": "import React from \"react\";\nimport { logo } from \"./data\";\n\nconst Login = () => {\n return (\n <div className=\"h-screen"
},
{
"path": "src/components/templates/youtube/mychannel-empty-tweet.jsx",
"chars": 9673,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n EllipsisHorizontalIcon,\n Face"
},
{
"path": "src/components/templates/youtube/mychannel-empty-video.jsx",
"chars": 9018,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n MagnifyingGlassIcon,\n PencilI"
},
{
"path": "src/components/templates/youtube/mychannel-tweets.jsx",
"chars": 11999,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n EllipsisHorizontalIcon,\n Face"
},
{
"path": "src/components/templates/youtube/privacy-policy.jsx",
"chars": 12398,
"preview": "import React from \"react\";\nimport { XCircleIcon } from \"@heroicons/react/24/outline\";\nimport { siteNavItems, logo } from"
},
{
"path": "src/components/templates/youtube/register.jsx",
"chars": 875,
"preview": "import React from \"react\";\nimport { logo } from \"./data\";\n\nconst Register = () => {\n return (\n <div className=\"h-scr"
},
{
"path": "src/components/templates/youtube/terms-and-conditions.jsx",
"chars": 12462,
"preview": "import React from \"react\";\nimport { XCircleIcon } from \"@heroicons/react/24/outline\";\nimport { siteNavItems, logo } from"
},
{
"path": "src/components/templates/youtube/upload-video.jsx",
"chars": 12233,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n ArrowUpTrayIcon,\n MagnifyingG"
},
{
"path": "src/components/templates/youtube/uploaded-video.jsx",
"chars": 10967,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n FilmIcon,\n MagnifyingGlassIco"
},
{
"path": "src/components/templates/youtube/uploading-video.jsx",
"chars": 12370,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n FilmIcon,\n MagnifyingGlassIco"
},
{
"path": "src/components/templates/youtube/video-cards.jsx",
"chars": 6867,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport { MagnifyingGlassIcon, XCircleIcon"
},
{
"path": "src/components/templates/youtube/video-detail.jsx",
"chars": 18253,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport {\n CheckIcon,\n FolderPlusIcon,\n "
},
{
"path": "src/components/templates/youtube/video-list.jsx",
"chars": 7692,
"preview": "\"use client\";\nimport { classNames } from \"@/utils\";\nimport React from \"react\";\nimport { MagnifyingGlassIcon, XCircleIcon"
},
{
"path": "src/types/utils.ts",
"chars": 290,
"preview": "export type TailwindIconType = React.ForwardRefExoticComponent<\n Omit<React.SVGProps<SVGSVGElement>, \"ref\"> & {\n tit"
},
{
"path": "src/utils/index.ts",
"chars": 328,
"preview": "import { ReactElement } from \"react\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\n\nexport const classNames "
},
{
"path": "src/utils/screens.tsx",
"chars": 8718,
"preview": "import Authentication from \"@/components/templates/authentication\";\nimport Chat from \"@/components/templates/chat\";\nimpo"
},
{
"path": "tailwind.config.ts",
"chars": 394,
"preview": "import type { Config } from \"tailwindcss\";\n\nconst config: Config = {\n content: [\n \"./src/pages/**/*.{js,ts,jsx,tsx,m"
},
{
"path": "tsconfig.json",
"chars": 708,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"es5\",\n \"lib\": [\n \"dom\",\n \"dom.iterable\",\n \"esnext\"\n ],\n "
}
]
About this extraction
This page contains the full source code of the hiteshchoudhary/devui GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 82 files (572.3 KB), approximately 154.9k tokens, and a symbol index with 13 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.