Footer Widget
Relevant source files
The following files were used as context for generating this wiki page:The Footer widget is a comprehensive and responsive component that serves as the concluding element for all pages within the application. It provides essential navigation through a collapsible "Quick Links" section, offers social media connectivity, displays copyright information, and integrates a theme-switching control. Its design adapts from a mobile-first accordion layout to a multi-column desktop view, ensuring a consistent user experience across devices.
The widget is integrated into the main application layout in App.tsx, placing it at the bottom of the div that wraps the entire application, ensuring its presence on every page. The index.ts file in the widget's directory serves as a public API, exporting the Footer component for use in other parts of the application.
Sources: src/widgets/Footer/Footer.tsx, src/app/App.tsx:93-95, src/widgets/Footer/index.ts:1-1
Component Architecture
The Footer component is structured into two main parts: a collapsible "Quick Links" area and a static bottom bar containing copyright and social links. The component's structure is built using standard HTML and React components, styled with Tailwind CSS and animated with Framer Motion.
The following diagram illustrates the high-level structure of the Footer component.
Sources: src/widgets/Footer/Footer.tsx:23-380
Collapsible "Quick Links" Section
This section is designed to be initially hidden and can be expanded by the user.
State and Animation
A local React state, isOpen, manages the visibility of the quick links section. The toggle mechanism is a <button> element that flips the boolean value of isOpen.
The expansion and collapse animations are handled by framer-motion. The <AnimatePresence> component manages the mounting and unmounting of the content, while <motion.div> animates the height and opacity properties for a smooth transition.
// State management for the collapsible section
const [isOpen, setIsOpen] = useState(false);
// ...
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: "auto", opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: "easeInOut" }}
className="overflow-hidden"
>
{/* ... content ... */}
</motion.div>
)}
</AnimatePresence>
Sources: src/widgets/Footer/Footer.tsx:21, src/widgets/Footer/Footer.tsx:44-53
The user interaction flow for this feature is as follows:
Responsive Layout
The quick links section employs a responsive strategy to present content optimally on different screen sizes.
- Mobile View (
< lgbreakpoint): It renders a series ofAccordioncomponents. Each category of links ("Explore", "Work", etc.) is an individual accordion item, allowing users to expand one category at a time. This is achieved by hiding the desktop layout withlg:hidden. - Desktop View (
>= lgbreakpoint): It uses a four-column grid layout (grid-cols-1 sm:grid-cols-2 lg:grid-cols-4). The accordion is hidden on large screens usinghidden lg:flex.
The content for the links and their section titles is sourced from the homeContent object.
| Section Title | Source Configuration |
|---|---|
| Explore | homeContent.footer.sections.explore |
| Work | homeContent.footer.sections.work |
| Socials | homeContent.footer.sections.socials |
| Legal & Extras | homeContent.footer.sections.legal |
Sources: src/widgets/Footer/Footer.tsx:58-299, src/shared/config/content.ts:81-86
Bottom Bar
The bottom bar is always visible and contains essential information and controls. It is a flex container that adjusts its layout from a column on small screens to a row on medium screens and above (md:flex-row).
Sources: src/widgets/Footer/Footer.tsx:304-305
Left Side
This area displays the copyright notice and a link to the Privacy Policy page. The copyright text is dynamically pulled from homeContent.footer.copyright. The "Privacy Policy" is a Link component from react-router-dom wrapped in a shared Button component with a underline variant.
Sources: src/widgets/Footer/Footer.tsx:307-319, src/shared/config/content.ts:79
Right Side
This area groups social media links and the theme toggle control.
- Social Icons: Links to GitHub, LinkedIn, and X (Twitter) are rendered using icons from
react-icons/si. Each link is an<a>tag styled as a circular button with a surface background color (bg-bg-surface) and a subtle shadow. - Theme Toggle: The
ThemeTogglefeature component is rendered here, allowing users to switch between light and dark modes.
Sources: src/widgets/Footer/Footer.tsx:324-358
Styling and Theming
The Footer widget relies on a theming system defined in src/app/index.css. It uses Tailwind CSS utility classes that map to CSS variables, allowing its appearance to adapt automatically when the theme changes.
Key CSS variables used include:
--bg-surface: Background for social icon buttons.--fg-primary,--fg-secondary: Text colors for links and copyright.--border-default: Color for separators and borders.
/* Example variables from index.css */
html[data-theme="light"] {
--bg-surface: #ffffff;
--fg-primary: #18181b; /* Zinc-950 */
--fg-secondary: #52525b; /* Zinc-600 */
--border-default: #e4e4e7; /* Zinc-200 */
}
html[data-theme="dark"] {
--bg-surface: #27272a;
--fg-primary: #f4f4f5; /* Zinc-50 */
--fg-secondary: #a1a1aa; /* Zinc-400 */
--border-default: #27272a; /* Zinc-800 */
}
Sources: src/app/index.css:18-49, src/widgets/Footer/Footer.tsx
Loading State
A corresponding FooterSkeleton component provides a loading placeholder. This skeleton mimics the layout of the final footer's bottom bar, showing placeholders for the copyright text and social icons with a pulse animation (animate-pulse). This ensures a good user experience during initial page loads or when the main Footer component is being lazy-loaded.
const FooterSkeleton = () => {
return (
<div className="border-t border-border-default pt-8 pb-8 mt-32 animate-pulse">
<Container className="flex flex-col gap-6 items-center justify-between md:flex-row">
{/* Left */}
<div className="h-4 w-64 rounded bg-bg-subtle"></div>
{/* Right */}
<div className="flex items-center gap-6">
{/* ... icon placeholders ... */}
</div>
</Container>
</div>
);
};