Navigation / React + CSS
Floating dock
A compact action dock with lifting icons and a sliding selection indicator.
Home
"use client";
import styles from "./FloatingDock.module.css";
import { useState } from "react";
const defaults = [
{ id: "home", label: "Home", glyph: "⌂" },
{ id: "projects", label: "Projects", glyph: "▦" },
{ id: "activity", label: "Activity", glyph: "◷" },
{ id: "saved", label: "Saved", glyph: "♡" },
];
export default function FloatingDock({ items = defaults, onSelect }) {
const [active, setActive] = useState(items[0]?.id);
return (
<div className={styles.root}>
<div className={styles.dock} role="group" aria-label="Workspace view">
{items.map((item) => (
<button
key={item.id}
type="button"
aria-label={item.label}
aria-pressed={active === item.id}
onClick={() => {
setActive(item.id);
onSelect?.(item.id);
}}
>
<span className={styles.tip}>{item.label}</span>
<span className={styles.glyph} aria-hidden="true">
{item.glyph}
</span>
<i aria-hidden="true" />
</button>
))}
</div>
<p role="status">{items.find((item) => item.id === active)?.label}</p>
</div>
);
}
Make it yours
Use for a small set of frequent workspace actions. This example changes selection and calls onSelect; connect that callback to real content. Use links instead if each destination is a separate URL.
- Use a React project with CSS Modules support, such as Next.js or Vite.
- Save the JSX as
FloatingDock.jsxand the CSS asFloatingDock.module.cssin the same folder. - Import
FloatingDockand connect its props to your application. Controlled components need parent state and change handlers.
No third-party component or animation package is required. Use the theme controls to adjust accent, corners, spacing, and type. Copy the Theme CSS into your stylesheet and wrap your components in <div className="tdp-components">. The theme applies to every component inside that wrapper. TDP defaults work without a theme file.
Props
| Prop | Type | Use |
|---|---|---|
items | array | Unique id, label, and decorative glyph per action. |
onSelect | function | Receives the chosen id. Connect to your view logic. |
Accessibility & behavior
Buttons expose selected state through aria-pressed and names through aria-label. Every action has a touch-sized target. Tooltips also appear on keyboard focus.
Visible focus styles and reduced-motion support are included. Check labels, contrast, keyboard behavior, and screen-reader output again after adapting the component to your product.