Skip to content

Commit

Permalink
Add dark mode support and improve layout consistency across components
Browse files Browse the repository at this point in the history
  • Loading branch information
Precious-Macaulay committed Jan 15, 2025
1 parent b0a672a commit 5515046
Show file tree
Hide file tree
Showing 14 changed files with 885 additions and 926 deletions.
1 change: 1 addition & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ASTRIA_API_KEY=fill your astria api key
1,663 changes: 795 additions & 868 deletions package-lock.json

Large diffs are not rendered by default.

Binary file added public/github-mark-white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/github-mark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/api/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const retrievePrompt = async (tuneId: number, promptId: number): Promise<

export const likePrompt = async (promptId: number) => {
const response = await apiClient.post(`/prompts/${promptId}/like`);
console.log(response);
// console.log(response);
if (response.status === 200 ){
return true;
}
Expand Down
12 changes: 6 additions & 6 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const Navbar: React.FC = () => {
};

return (
<nav className="sticky top-0 h-screen w-20 custom-lg:w-60 flex-col items-center justify-between p-4 bg-none hidden md:flex transition-all duration-300 ease-in-out">
<nav className={`sticky top-0 h-screen w-20 custom-lg:w-60 flex-col items-center justify-between p-4 bg-none hidden md:flex transition-all duration-300 ease-in-out ${location.state?.type !== 'user' && location.state?.type !== 'gallery' ? '' : 'dark:bg-black'}`}>
<div className="flex w-full grow flex-col items-center gap-6">
{/* Logo and brand */}
<div className="flex-shrink-0 my-3 transition-all duration-200 ease-in-out">
Expand All @@ -37,7 +37,7 @@ const Navbar: React.FC = () => {
alt="Logo"
className="h-7 w-7 transition-transform duration-200 hover:scale-110"
/>
<span className="ml-2 text-black text-md font-semibold hidden custom-lg:inline">Astria Imagine</span>
<span className="ml-2 text-black text-md font-semibold hidden custom-lg:inline dark:text-white">Astria Imagine</span>
</Link>
</div>
<div className="flex flex-col text-center item-center w-full py-2 space-y-4">
Expand All @@ -56,11 +56,11 @@ const Navbar: React.FC = () => {
<div className="flex-shrink-0 my-3 transition-all duration-200 ease-in-out">
<Link to="https://github.com/astriaai/imagine" className="flex items-center justify-center md:justify-start" target="_blank" rel="noopener noreferrer">
<img
src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
src={window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? "./github-mark-white.png" : "./github-mark.png"}
alt="GitHub Logo"
className="h-7 w-7 transition-transform duration-200 hover:scale-110"
/>
<span className="ml-2 text-black text-md font-semibold hidden custom-lg:inline">Open Source Code</span>
<span className="ml-2 text-black text-md font-semibold hidden custom-lg:inline dark:text-white">Open Source Code</span>
</Link>
</div>
</footer>
Expand All @@ -77,10 +77,10 @@ const NavLink: React.FC<NavLinkProps> = ({ to, label, Icon, active }) => (
to={to}
className={cn(
'w-fit custom-lg:w-full flex items-center justify-center custom-lg:justify-start px-2 custom-lg:px-3 py-2 rounded-full text-sm font-medium transition-all duration-300 ease-in-out',
active ? 'bg-orange-500 bg-clip-padding backdrop-filter backdrop-blur-sm bg-opacity-10 border text-orange-900' : 'text-gray-700 hover:bg-gray-100 hover:text-black'
active ? 'bg-orange-500 bg-clip-padding backdrop-filter backdrop-blur-sm bg-opacity-10 text-orange-900 dark:text-orange-500 dark:bg-opacity-20' : 'text-gray-700 hover:bg-gray-100 hover:text-black dark:text-white dark:hover:bg-gray-800 dark:hover:text-white',
)}
>
<Icon className="h-5 w-5 transition-transform duration-200 hover:scale-110" strokeWidth={2.5} />
<Icon className="h-5 w-5 transition-transform duration-200 hover:scale-110" strokeWidth={2.5} />
<span className="ml-2 hidden custom-lg:inline">{label}</span>
</Link>
);
Expand Down
84 changes: 57 additions & 27 deletions src/components/PromptCard/ImageGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,42 @@
import React from "react";
import React, { useState } from "react";
import { Skeleton } from "../ui/skeleton";

interface ImageGridProps {
images: string[] | undefined;
images?: string[];
onClick: (index: number) => void;
}

export const ImageGrid: React.FC<ImageGridProps> = ({ images, onClick }) => {
if (!images || images.length === 0) {
export const ImageGrid: React.FC<ImageGridProps> = ({
images = [],
onClick,
}) => {
const [loadedImages, setLoadedImages] = useState<boolean[]>(
Array(images.length).fill(false)
);

const handleImageLoad = (index: number) => {
setLoadedImages((prev) => {
const updated = [...prev];
updated[index] = true;
return updated;
});
};

const getRoundedClass = (index: number, total: number) => {
if (total === 1) return "rounded-md";
if (total === 2) return index === 0 ? "rounded-l-md" : "rounded-r-md";
if (total === 3) return ["rounded-tl-md", "rounded-tr-md", "rounded-b-md"][index];
if (total === 4) return ["", "rounded-tr-md", "rounded-bl-md", "rounded-br-md"][index];
if (total > 4) {
if (index === 0) return "rounded-tl-md";
if (index === 3) return "rounded-tr-md";
if (index === total - 2) return "rounded-bl-md";
if (index === total - 1) return "rounded-br-md";
}
return "";
};

if (!images.length) {
return (
<div className="flex-1 grid grid-cols-2 md:grid-cols-4 gap-2 w-full">
{Array.from({ length: 4 }).map((_, i) => (
Expand All @@ -20,29 +49,30 @@ export const ImageGrid: React.FC<ImageGridProps> = ({ images, onClick }) => {
return (
<div className="flex-1 grid grid-cols-2 md:grid-cols-4 gap-[2px] md:gap-2 w-full">
{images.map((image, i) => (
<div
key={i}
className={`flex items-center w-full justify-center overflow-hidden md:rounded-md
${images.length === 1 ? 'rounded-md' : ''}
${images.length === 2 && i === 0 ? 'rounded-l-md' : ''}
${images.length === 2 && i === 1 ? 'rounded-r-md' : ''}
${images.length > 2 && i === 0 ? 'rounded-tl-md' : ''}
${images.length === 3 && i === 1 ? 'rounded-tr-md' : ''}
${images.length === 3 && i === 2 ? 'rounded-b-md' : ''}
${images.length === 4 && i === 1 ? 'rounded-tr-md' : ''}
${images.length === 4 && i === 2 ? 'rounded-bl-md' : ''}
${images.length === 4 && i === 3 ? 'rounded-br-md' : ''}
${images.length > 4 && i === 3 ? 'rounded-tr-md' : ''}
${images.length > 4 && i === images.length - 2 ? 'rounded-bl-md' : ''}
${images.length > 4 && i === images.length - 1 ? 'rounded-br-md' : ''}`}
>
<img
src={image}
alt={`prompt-${i}`}
className="object-cover w-full h-auto max-h-[900px]"
onClick={() => onClick(i)}
/>
</div>
<div
key={i}
className={`flex items-center w-full justify-center overflow-hidden md:rounded-md ${getRoundedClass(
i,
images.length
)}`}
>
{!loadedImages[i] ? (
loadedImages.some((value) => value) ? (
<Skeleton className="w-full h-full max-h-[900px]" />
) : (
<Skeleton className="w-full h-[250px]" />
)
) : null}
<img
src={image}
alt={`Image ${i + 1} of ${images.length}`}
className={`object-cover w-full h-auto max-h-[900px] ${loadedImages[i] ? "" : "hidden"
}`}
onLoad={() => handleImageLoad(i)}
onError={() => console.warn(`Failed to load image at index ${i}`)}
onClick={() => onClick(i)}
/>
</div>
))}
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/PromptCard/PropertiesDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const displayProperties: DisplayProperty[] = [
export const PropertiesDisplay: React.FC<PropertiesDisplayProps> = ({
prompt,
}) => {
console.log("prompt", { prompt });
// console.log("prompt", { prompt });
return (
<>
{prompt.input_image && (
Expand Down
35 changes: 18 additions & 17 deletions src/components/PromptDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,28 @@ const PromptDetails: React.FC<PromptDetailsProps> = ({ prompt, imageUrl }) => {
if (imageUrl) {
const element = document.createElement("a");
element.href = imageUrl;
element.download = `${prompt?.id || "image"}.png`;
element.download = `${prompt.id}.png`;
element.target = "_blank";
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
};

return (
<div className="hidden md:w-2/5 lg:w-1/3 h-full md:flex flex-col justify-between rounded-xl p-4 shadow-lg bg-white">
<div className="hidden md:w-2/5 lg:w-1/3 h-full md:flex flex-col justify-between rounded-xl p-4 shadow-lg bg-white dark:bg-black">
<div>
<div className="flex mb-2 justify-between items-center">
<h2 className="text-lg font-semibold">{prompt?.id}</h2>
<div className="p-2 flex items-center gap-1">
<div className="p-2 flex items-center gap-1">
<button
className="p-2 rounded-full hover:bg-gray-100"
className="p-2 rounded-full hover:bg-gray-100 group"
onClick={handleDownload}
>
<DownloadIcon className="text-gray-600 w-4 h-4" />
<DownloadIcon className="text-gray-600 dark:text-white group-hover:dark:text-gray-600 w-4 h-4" />
</button>
<button
className={`p-2 rounded-full hover:bg-gray-100 ${isPromptUsed ? "text-green-500" : "text-gray-600"
className={`p-2 rounded-full hover:bg-gray-100 dark:hover:text-gray-600 ${isPromptUsed ? "text-green-500" : "text-gray-600 dark:text-white"
}`}
onClick={() => handleUsePrompt(prompt)}
>
Expand All @@ -58,29 +59,29 @@ const PromptDetails: React.FC<PromptDetailsProps> = ({ prompt, imageUrl }) => {
)}
</button>
<button
className="p-2 rounded-full hover:bg-gray-100"
className="p-2 rounded-full hover:bg-gray-100 group"
onClick={() => handleCopy(prompt)}
>
{isCopied ? (
<>
<CheckIcon className="text-green-500 w-4 h-4" />
</>
<>
<CheckIcon className="text-green-500 w-4 h-4" />
</>
) : (
<>
<CopyIcon className="text-gray-600 w-4 h-4" />
</>
<>
<CopyIcon className="text-gray-600 dark:text-white group-hover:dark:text-gray-600 w-4 h-4" />
</>
)}
</button>
<button
className={`p-2 rounded-full hover:bg-gray-100 ${isLiked ? "text-red-500" : "text-gray-600"
}`}
className={`p-2 rounded-full hover:bg-gray-100 dark:hover:text-gray-600 ${isLiked ? "text-red-500" : "text-gray-600 dark:text-white"
}`}
onClick={toggleLike}
>
<Heart className={`w-4 h-4 ${isLiked ? "fill-current" : ""}`} />
</button>
</div>
</div>
</div>
<p className="overflow-y-auto max-h-48 text-sm text-gray-700 break-words">
<p className="overflow-y-auto max-h-48 text-sm text-gray-700 dark:text-white break-words">
{prompt?.text?.length > 100 ? `${prompt?.text.slice(0, 200)}...` : prompt?.text}
</p>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/PromptForm/ImageUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const ImageUpload: React.FC<ImageUploadProps> = ({ showControls, onImageU
} = useImageUpload();

const { image, urlImage } = usePromptFormStore();
console.log({ image, urlImage });
// console.log({ image, urlImage });
const handleClear = () => {
clearImage();
onImageUpload(null, null);
Expand Down
2 changes: 1 addition & 1 deletion src/components/PromptImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const PromptImage: React.FC<PromptImageProps> = ({ imageUrl, setDisplay }) => {

return (
<div
className="flex-1 relative cursor-zoom-in overflow-hidden pb-12 md:pb-0"
className="flex-1 relative cursor-zoom-in overflow-hidden pb-12 md:pb-0 dark:bg-zinc-900"
onClick={() => setDisplay && setDisplay(true)}
>
<div className="h-full p-6 flex justify-center items-center">
Expand Down
2 changes: 1 addition & 1 deletion src/components/WithLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
<div className="flex w-full justify-around select-text bg-light-mode dark:bg-zinc-900 min-h-screen" >
<Navbar />
<MobileTabNav />
<div className="flex-1 p-1">
<div className="flex-1 py-1 px-2 sm:px-[4rem] md:px-1">
<div className='w-full max-w-7xl mx-auto'>
{children}
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/usePromptForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const usePromptForm = () => {
};

const handlePaste = (event: ClipboardEvent) => {
console.log('handlePaste');
// console.log('handlePaste');
//stop propagation to prevent the default paste behavior
event.preventDefault();
event.stopPropagation();
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Prompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const Prompt: React.FC = () => {

useEffect(() => {
const determinePromptType = async () => {
console.log({ promptType, id, galleryPrompts });
// console.log({ promptType, id, galleryPrompts });
if (!promptType && id) {
setIsLoading(true);
try {
Expand Down Expand Up @@ -123,7 +123,7 @@ const Prompt: React.FC = () => {
<div className="hidden w-full h-screen md:flex flex-col overflow-hidden">
<PromptForm />
<div className="flex-1 p-0 md:p-4 overflow-auto">
<div className="w-full h-full flex flex-col md:flex-row bg-light-mode">
<div className="w-full h-full flex flex-col md:flex-row bg-light-mode dark:bg-zinc-900">
<PromptImage
imageUrl={currentPrompt.images[index]}
setDisplay={setZoomImage}
Expand Down

0 comments on commit 5515046

Please sign in to comment.