A modern, component-based React/Next.js application for managing protection settings and protected domains, built with shadcn/ui components.
This project uses shadcn/ui - a collection of beautifully designed, accessible components built on top of Radix UI and Tailwind CSS.
tray-overlay/
├── app/ # Next.js app directory
│ ├── layout.tsx # Root layout component
│ ├── page.tsx # Home page
│ └── globals.css # Global styles and Tailwind imports
├── components/ # Reusable React components
│ ├── StatusDot.tsx # Status indicator dot
│ ├── ThemeToggle.tsx # Light/dark mode toggle
│ ├── ExtensionIndicator.tsx # Extension connection status
│ ├── ProtectionToggle.tsx # Main protection toggle
│ ├── PauseControls.tsx # Pause/resume with time selection
│ ├── DomainManager.tsx # Add/edit/remove domains
│ ├── TrayOverlay.tsx # Main container component
│ └── index.ts # Component exports
├── hooks/ # Custom React hooks
│ ├── useDesktopApi.ts # Desktop API access
│ ├── useTrayState.ts # Tray state management
│ ├── useDomains.ts # Domain management logic
│ ├── useExtensionStatus.ts # Extension status polling
│ ├── useTheme.ts # Theme management
│ └── index.ts # Hook exports
├── lib/ # Utility functions and constants
│ ├── constants.ts # Application constants
│ ├── utils.ts # Helper functions
├── types/ # TypeScript type definitions
│ └── index.ts
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
├── tailwind.config.js # Tailwind CSS configuration
├── postcss.config.js # PostCSS configuration
├── next.config.js # Next.js configuration
└── README.md # This file
- Components: UI presentation only
- Hooks: State management and business logic
- Utils: Pure functions for transformations
- Types: Type safety with TypeScript
| Component | Purpose |
|---|---|
TrayOverlay |
Main container managing all features |
ProtectionToggle |
Toggle protection on/off |
PauseControls |
Set pause duration and manage pause/resume |
DomainManager |
Add, edit, remove protected domains |
ExtensionIndicator |
Show extension connection status |
ThemeToggle |
Switch between light/dark themes |
StatusDot |
Visual indicator of current state |
The following shadcn/ui components are used throughout the application:
| Component | Usage |
|---|---|
Button |
All interactive buttons (pause, resume, add, save, remove, etc.) |
Input |
Domain input field in DomainManager |
Checkbox |
Protection toggle checkbox |
Label |
Associated labels for form inputs |
Alert & AlertDescription |
Error and feedback messages |
Badge |
Domain count indicator |
Card & CardContent |
Main container layout |
All shadcn/ui components are located in components/ui/ and are built on:
- Radix UI for unstyled, accessible primitives
- Tailwind CSS for styling
- class-variance-authority for component variants
| Hook | Responsibility |
|---|---|
useTrayState |
Manage protection state and API calls |
useDomains |
Handle domain CRUD operations |
useExtensionStatus |
Poll and track extension status |
useTheme |
Manage theme preference and persistence |
useDesktopApi |
Provide desktop API singleton |
- Component Composition: Small, focused components with single responsibilities
- Custom Hooks: Encapsulated logic in reusable hooks
- Type Safety: Full TypeScript coverage with interfaces
- State Management: React hooks with useCallback for optimization
- Responsive Design: Tailwind CSS for styling
- Accessibility: ARIA labels, semantic HTML, keyboard support
- Error Handling: Comprehensive error messages and feedback
- Performance: Memoization and effect dependencies
npm installnpm run devOpen http://localhost:3000 in your browser.
npm run build
npm run startnpm run type-checkThe application expects a window.desktopApi object with the following interface:
const desktopApi = {
tray: {
getState: () => Promise<TrayState>,
setProtectionEnabled: (enabled: boolean) => Promise<TrayState>,
setPause: (minutes: number) => Promise<TrayState>,
clearPause: () => Promise<TrayState>,
openMainApp: () => Promise<void>,
onStateChanged: (callback: (state: TrayState) => void) => () => void,
},
getProtectedDomains: () => Promise<{ domains: string[] }>,
saveProtectedDomains: (domains: string[]) => Promise<{ domains: string[] }>,
getExtensionConnectionStatus: () => Promise<ExtensionStatus>,
};The project uses Tailwind CSS for styling with:
- Custom color extensions for accent colors
- Dark mode support via
data-themeattribute - Responsive design utilities
- Create a Hook (
hooks/useNewFeature.ts) if it involves state or API logic - Create Component(s) (
components/NewFeature.tsx) for UI - Update Types (
types/index.ts) as needed - Add Constants (
lib/constants.ts) if applicable - Add Utilities (
lib/utils.ts) for helper functions
import React from "react";
interface NewComponentProps {
// props
}
export const NewComponent: React.FC<NewComponentProps> = (props) => {
return <div>{/* content */}</div>;
};import { useState, useCallback } from "react";
export const useNewFeature = () => {
const [state, setState] = useState(null);
const update = useCallback(() => {
// logic
}, []);
return { state, update };
};To add or use shadcn/ui components:
-
Import from
@/components/ui:import { Button, Input, Alert, AlertDescription } from "@/components/ui";
-
Use with variants:
<Button variant="outline" size="sm">Click me</Button> <Alert variant="destructive"> <AlertDescription>Error message</AlertDescription> </Alert>
-
Customize with Tailwind CSS:
<Button className="rounded-full">Custom Button</Button>
-
Component Variants:
- Button:
default,destructive,outline,secondary,ghost,link - Alert:
default,destructive,success,warning - Badge:
default,secondary,destructive,outline,success,warning
- Button:
To add a new shadcn component:
- The component files are already set up in
components/ui/ - Import and use them in your custom components
- Components can be customized by modifying the corresponding file in
components/ui/ - All components use the CSS custom properties defined in
app/globals.css
Proprietary - Redactosaurus