Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/components/glass.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import { cn } from "@/lib/utils"

type GlassProps = React.HTMLAttributes<HTMLDivElement>

/**
* Render a div with a glass-like visual treatment that wraps provided children.
*
* Merges the caller-provided `className` with the component's default styling:
* rounded corners, border, translucent white background, padding, and backdrop blur.
*
* @param children - Content rendered inside the glass-styled container
* @returns A `div` element with merged classes and the provided `children`
*/
export function Glass({ children, ...props }: GlassProps) {
return (
<div
Expand Down
34 changes: 31 additions & 3 deletions src/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ import {
navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu"

// --- Custom Hook for Media Query ---
/**
* Subscribes to a CSS media query and exposes whether it currently matches.
*
* @param query - A valid CSS media query string (e.g. `"(max-width: 768px)"`)
* @returns `true` if the media query currently matches, `false` otherwise
*
* Observes changes and updates the returned value when the query match state changes; listener is cleaned up on unmount or when `query` changes.
*/
function useMediaQuery(query: string): boolean {
const [matches, setMatches] = React.useState(false)

Expand Down Expand Up @@ -66,15 +73,29 @@ const components: {
},
]

// --- Icon Button Handlers ---
/**
* Handle clicks on the user/profile icon.
*
* Logs "User icon clicked" to the console.
*/
function handleUserIconClick() {
console.log("User icon clicked")
}

/**
* Handle clicks on the globe (language) icon.
*
* Logs "Globe icon clicked" to the console.
*/
function handleGlobeIconClick() {
console.log("Globe icon clicked")
}

/**
* Log that the moon (theme) icon was clicked.
*
* Logs the string "Moon icon clicked" to the console.
*/
function handleMoonIconClick() {
console.log("Moon icon clicked")
}
Expand Down Expand Up @@ -247,7 +268,14 @@ const DesktopLayout = () => {
)
}

// --- Main Header Component ---
/**
* Render the responsive header that switches between mobile and desktop layouts.
*
* While the app hydrates, the component renders the mobile layout by default to avoid a layout flash;
* after mount it selects mobile or desktop based on the "(max-width: 768px)" media query.
*
* @returns A React element for the header: initially the mobile layout until hydration completes, then the mobile layout when the viewport is 768px wide or narrower, otherwise the desktop layout.
*/
export function Header() {
const [mounted, setMounted] = React.useState(false)
const isMobile = useMediaQuery("(max-width: 768px)") // TODO: Adjust breakpoint
Expand Down
45 changes: 45 additions & 0 deletions src/components/ui/navigation-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import type * as React from "react"

import { cn } from "@/lib/utils"

/**
* Root wrapper for Radix NavigationMenu that applies shared styling, data attributes, and optionally renders a viewport.
*
* @param viewport - When `true` (default), renders the associated `NavigationMenuViewport` element; when `false`, omits the viewport.
* @returns The rendered NavigationMenu root element with forwarded props.
*/
function NavigationMenu({
className,
children,
Expand All @@ -26,6 +32,12 @@ function NavigationMenu({
)
}

/**
* Wraps Radix's `NavigationMenuPrimitive.List`, adding layout classes and a `data-slot` attribute while forwarding all other props.
*
* @param className - Additional class names to merge with the component's base layout classes
* @returns The rendered `NavigationMenuPrimitive.List` element with merged classes and `data-slot="navigation-menu-list"`
*/
function NavigationMenuList({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {
return (
<NavigationMenuPrimitive.List
Expand All @@ -36,6 +48,11 @@ function NavigationMenuList({ className, ...props }: React.ComponentProps<typeof
)
}

/**
* Renders a NavigationMenu item wrapper that applies positioning and a `data-slot` attribute.
*
* @returns The wrapped `NavigationMenuPrimitive.Item` element with `data-slot="navigation-menu-item"` and merged `className` including `"relative"`.
*/
function NavigationMenuItem({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.Item>) {
return (
<NavigationMenuPrimitive.Item data-slot="navigation-menu-item" className={cn("relative", className)} {...props} />
Expand All @@ -46,6 +63,13 @@ const navigationMenuTriggerStyle = cva(
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium text-text-primary transition-[color,box-shadow] outline-none hover:bg-grey focus:bg-grey focus-visible:ring-[3px] focus-visible:ring-text-primary/50 focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=open]:bg-grey/50 data-[state=open]:hover:bg-grey data-[state=open]:focus:bg-grey"
)

/**
* Renders a styled navigation menu trigger with a chevron icon.
*
* Renders a NavigationMenuPrimitive.Trigger element with preset styling, a `data-slot="navigation-menu-trigger"` attribute, and a down-pointing chevron that rotates when the trigger is open.
*
* @returns The rendered trigger element for the navigation menu.
*/
function NavigationMenuTrigger({
className,
children,
Expand All @@ -67,6 +91,12 @@ function NavigationMenuTrigger({
)
}

/**
* Wraps Radix's `NavigationMenuPrimitive.Content`, applying layout, animation, and theme-related classes and forwarding all props.
*
* @param props - Props passed to the underlying `NavigationMenuPrimitive.Content`. The `className` prop, if provided, is merged with the component's internal classes.
* @returns A `NavigationMenuPrimitive.Content` element with a `data-slot="navigation-menu-content"` attribute, merged classes, and forwarded props.
*/
function NavigationMenuContent({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) {
return (
<NavigationMenuPrimitive.Content
Expand All @@ -81,6 +111,11 @@ function NavigationMenuContent({ className, ...props }: React.ComponentProps<typ
)
}

/**
* Renders a centered, absolutely positioned container that hosts the NavigationMenu viewport.
*
* @returns A React element containing the Radix NavigationMenu viewport wrapped in an absolutely positioned, centered container.
*/
function NavigationMenuViewport({
className,
...props
Expand All @@ -99,6 +134,11 @@ function NavigationMenuViewport({
)
}

/**
* Render a styled NavigationMenu link element with a consistent `data-slot` and utility classes.
*
* @returns A `NavigationMenuPrimitive.Link` element with base layout, typography, and state-aware styling; additional props are forwarded to the underlying element.
*/
function NavigationMenuLink({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) {
return (
<NavigationMenuPrimitive.Link
Expand All @@ -112,6 +152,11 @@ function NavigationMenuLink({ className, ...props }: React.ComponentProps<typeof
)
}

/**
* Renders the navigation menu indicator: an animated, diamond-shaped visual used to point to active menu content.
*
* @returns A NavigationMenuPrimitive.Indicator element containing the rotated square indicator.
*/
function NavigationMenuIndicator({
className,
...props
Expand Down
Loading