From 5f38ec8e73eeab095688c2fd395aaee5ec3621c7 Mon Sep 17 00:00:00 2001 From: Hemant <133942800+hk2166@users.noreply.github.com> Date: Mon, 2 Mar 2026 00:54:23 +0530 Subject: [PATCH 1/3] added a hovered state to FAQItems with onMouseEnter and changed the BG color for better visibility --- package-lock.json | 4 ++-- src/Pages/FaqPage/FAQ.tsx | 43 +++++++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index a4a057d..58df27c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "PictoPy", - "version": "0.0.0", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "PictoPy", - "version": "0.0.0", + "version": "1.0.0", "dependencies": { "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.1.0", diff --git a/src/Pages/FaqPage/FAQ.tsx b/src/Pages/FaqPage/FAQ.tsx index 6bd921f..d9b157e 100644 --- a/src/Pages/FaqPage/FAQ.tsx +++ b/src/Pages/FaqPage/FAQ.tsx @@ -93,38 +93,51 @@ interface FAQItemProps { function FAQItem({ question, answer, isOpen, onClick, index, icon }: FAQItemProps) { const contentRef = useRef(null); + const [hovered, setHovered] = useState(false); return ( @@ -180,4 +193,4 @@ function BackgroundAnimation({ darkMode }: { darkMode: boolean }) { ); -} +} \ No newline at end of file From f9e1746736b51ac4d6395d59724d3a98203015b0 Mon Sep 17 00:00:00 2001 From: Hemant <133942800+hk2166@users.noreply.github.com> Date: Mon, 2 Mar 2026 01:02:54 +0530 Subject: [PATCH 2/3] fix: improve button hover contrast to meet WCAG 2.1 AA standards --- src/Pages/Landing page/Home1.tsx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Pages/Landing page/Home1.tsx b/src/Pages/Landing page/Home1.tsx index a605326..07946f9 100644 --- a/src/Pages/Landing page/Home1.tsx +++ b/src/Pages/Landing page/Home1.tsx @@ -2,7 +2,6 @@ import { motion } from "framer-motion"; import { useEffect, useRef, useState } from "react"; const ShuffleHero = () => { - // Function to scroll to downloads section const scrollToDownloads = () => { const downloadsSection = document.getElementById('downloads-section'); if (downloadsSection) { @@ -44,7 +43,7 @@ const ShuffleHero = () => {
- {/* Download button - scrolls to downloads section */} + {/* Download button */} { transition={{ duration: 0.5, delay: 0.6 }} whileHover={{ scale: 1.03 }} whileTap={{ scale: 0.98 }} - className="bg-gradient-to-r from-yellow-500 to-green-500 text-white font-medium py-2 px-6 rounded transition-all shadow-sm hover:shadow-md" + className="bg-gradient-to-r from-yellow-500 to-green-500 hover:from-yellow-600 hover:to-green-600 text-white font-semibold py-2 px-6 rounded transition-all shadow-sm hover:shadow-md" > Download - {/* View Docs button - links to documentation */} + {/* View Docs button - fixed contrast on hover */} { transition={{ duration: 0.5, delay: 0.7 }} whileHover={{ scale: 1.03 }} whileTap={{ scale: 0.98 }} - className="border border-slate-300 dark:border-slate-600 text-slate-700 dark:text-slate-200 font-medium py-2 px-6 rounded transition-all hover:border-teal-500 hover:text-teal-500" + className="border border-slate-300 dark:border-slate-600 text-slate-700 dark:text-slate-200 font-semibold py-2 px-6 rounded transition-all hover:bg-teal-600 hover:border-teal-600 hover:text-white dark:hover:bg-teal-600 dark:hover:border-teal-600 dark:hover:text-white" > View Docs @@ -185,13 +184,11 @@ const ShuffleGrid = () => { useEffect(() => { shuffleSquares(); - return () => clearTimeout(timeoutRef.current); }, []); const shuffleSquares = () => { setSquares(generateSquares()); - timeoutRef.current = setTimeout(shuffleSquares, 3000); }; @@ -202,4 +199,4 @@ const ShuffleGrid = () => { ); }; -export default ShuffleHero; +export default ShuffleHero; \ No newline at end of file From b5ffdc87a5013668f39f66a9f5a5be60d630d76a Mon Sep 17 00:00:00 2001 From: Hemant <133942800+hk2166@users.noreply.github.com> Date: Mon, 2 Mar 2026 01:13:20 +0530 Subject: [PATCH 3/3] feat(footer): expand footer with AOSSIE info and multi-column layout --- src/Pages/Footer/Footer.tsx | 230 +++++++++++++++++++++++++++---- src/Pages/Landing page/Home1.tsx | 85 +++++++----- 2 files changed, 252 insertions(+), 63 deletions(-) diff --git a/src/Pages/Footer/Footer.tsx b/src/Pages/Footer/Footer.tsx index ae4b766..29f2055 100644 --- a/src/Pages/Footer/Footer.tsx +++ b/src/Pages/Footer/Footer.tsx @@ -1,38 +1,218 @@ -import type React from "react" -import { FaDiscord } from 'react-icons/fa' // Import Discord icon from React Icons +import type React from "react"; +import { motion } from "framer-motion"; +import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa"; +import { ExternalLink } from "lucide-react"; + +const fadeUp = { + hidden: { opacity: 0, y: 20 }, + visible: (i: number) => ({ + opacity: 1, + y: 0, + transition: { duration: 0.5, delay: i * 0.1 }, + }), +}; const Footer: React.FC = () => { + const year = new Date().getFullYear(); + return ( -
-
-
- {/* Left-aligned PictoPy text */} -
-

+

+ {/* Main grid */} +
+
+ {/* Column 1 — PictoPy brand */} + +

PictoPy +

+

+ A privacy-first, AI-powered desktop gallery application built with + Tauri, React, and Rust — keeping your data entirely on your + device.

-
- - {/* Right-aligned Discord Icon and "Made with love" text */} - + + + {/* Column 2 — About AOSSIE */} + +

+ About AOSSIE +

+

+ + Australian Open Source Software Innovation and Education + (AOSSIE) + {" "} + is an Australian not-for-profit umbrella organisation for + open-source projects. AOSSIE mentors students and contributors + through programs like Google Summer of Code and Outreachy, + fostering innovation in open-source software across the globe. +

+ + aossie.org + + +
+ + {/* Column 3 — Quick Links */} + +

+ Quick Links +

+
    + {[ + { + label: "Documentation", + href: "https://aossie-org.github.io/PictoPy/", + }, + { + label: "Releases", + href: "https://github.com/AOSSIE-Org/PictoPy/releases", + }, + { + label: "Issue Tracker", + href: "https://github.com/AOSSIE-Org/PictoPy/issues", + }, + { + label: "Contributing Guide", + href: "https://github.com/AOSSIE-Org/PictoPy/blob/main/CONTRIBUTING.md", + }, + { + label: "AOSSIE Projects", + href: "https://aossie.org/#projects", + }, + { + label: "Google Summer of Code", + href: "https://summerofcode.withgoogle.com/", + }, + ].map(({ label, href }) => ( +
  • + + {label} + +
  • + ))} +
+
+ + {/* Column 4 — Community */} + +

+ Community +

+

+ Join our community to report bugs, request features, chat with + contributors, and follow AOSSIE's open-source journey. +

+ +
+
-
- {/* You can add any content here if needed */} + {/* Bottom bar */} +
+
+

+ {`© ${year} `} + + {"AOSSIE"} + + { + ". PictoPy is open-source software released under the MIT License." + } +

+

+ {"Made with ♥ by the "} + + {"AOSSIE Team"} + +

- ) -} + ); +}; -export default Footer +export default Footer; diff --git a/src/Pages/Landing page/Home1.tsx b/src/Pages/Landing page/Home1.tsx index 07946f9..c6f5caf 100644 --- a/src/Pages/Landing page/Home1.tsx +++ b/src/Pages/Landing page/Home1.tsx @@ -1,13 +1,20 @@ import { motion } from "framer-motion"; -import { useEffect, useRef, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; + +const SHUFFLE_INTERVAL = 3000; + +interface SquareItem { + id: number; + src: string; +} const ShuffleHero = () => { const scrollToDownloads = () => { - const downloadsSection = document.getElementById('downloads-section'); + const downloadsSection = document.getElementById("downloads-section"); if (downloadsSection) { downloadsSection.scrollIntoView({ - behavior: 'smooth', - block: 'start', + behavior: "smooth", + block: "start", }); } }; @@ -15,7 +22,7 @@ const ShuffleHero = () => { return (
- { > INTELLIGENT GALLERY MANAGEMENT - - { > PictoPy - - - Advanced desktop gallery application powered by Tauri, React, and Rust with a Python backend for intelligent image analysis and seamless management. + Advanced desktop gallery application powered by Tauri, React, and Rust + with a Python backend for intelligent image analysis and seamless + management. - +
- {/* Download button */} - { > Download - - {/* View Docs button - fixed contrast on hover */} - { ); }; -const shuffle = (array: (typeof squareData)[0][]) => { - let currentIndex = array.length, - randomIndex; +const shuffle = (array: SquareItem[]): SquareItem[] => { + const result = [...array]; + let currentIndex = result.length; - while (currentIndex != 0) { - randomIndex = Math.floor(Math.random() * currentIndex); + while (currentIndex !== 0) { + const randomIndex = Math.floor(Math.random() * currentIndex); currentIndex--; - - [array[currentIndex], array[randomIndex]] = [ - array[randomIndex], - array[currentIndex], + [result[currentIndex], result[randomIndex]] = [ + result[randomIndex], + result[currentIndex], ]; } - return array; + return result; }; -const squareData = [ +const squareData: SquareItem[] = [ { id: 1, src: "https://images.unsplash.com/photo-1547347298-4074fc3086f0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1740&q=80", @@ -173,30 +179,33 @@ const generateSquares = () => { style={{ backgroundImage: `url(${sq.src})`, backgroundSize: "cover", + backgroundPosition: "center", }} > )); }; const ShuffleGrid = () => { - const timeoutRef = useRef(null); + const timeoutRef = useRef | null>(null); const [squares, setSquares] = useState(generateSquares()); - useEffect(() => { - shuffleSquares(); - return () => clearTimeout(timeoutRef.current); + const shuffleSquares = useCallback(() => { + setSquares(generateSquares()); + timeoutRef.current = setTimeout(shuffleSquares, SHUFFLE_INTERVAL); }, []); - const shuffleSquares = () => { - setSquares(generateSquares()); - timeoutRef.current = setTimeout(shuffleSquares, 3000); - }; + useEffect(() => { + shuffleSquares(); + return () => { + if (timeoutRef.current) clearTimeout(timeoutRef.current); + }; + }, [shuffleSquares]); return (
- {squares.map((sq) => sq)} + {squares}
); }; -export default ShuffleHero; \ No newline at end of file +export default ShuffleHero;