Skip to content
Merged
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
131 changes: 131 additions & 0 deletions blendmate-app/src/components/IslandPanelDemo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import IslandPanel from './ui/IslandPanel';

/**
* Demo component showcasing the IslandPanel in various configurations
*/
export default function IslandPanelDemo() {
return (
<div className="space-y-6">
{/* Basic panel with just content */}
<IslandPanel>
<p style={{ color: 'var(--island-text)' }}>
This is a basic Island panel with just content. It automatically adapts to light/dark mode.
</p>
</IslandPanel>

{/* Panel with title */}
<IslandPanel title="Panel with Title">
<p style={{ color: 'var(--island-text-secondary)' }}>
This panel has a title in the header. The header has a subtle background to separate it from the content.
</p>
</IslandPanel>

{/* Panel with title and subtitle */}
<IslandPanel
title="Complete Panel"
subtitle="With title and subtitle"
>
<div className="space-y-3">
<p style={{ color: 'var(--island-text)' }}>
This panel demonstrates all features: title, subtitle, and content.
</p>
<p style={{ color: 'var(--island-text-secondary)' }}>
The colors automatically adjust based on your system's light/dark mode preference.
</p>
</div>
</IslandPanel>

{/* Panel with actions */}
<IslandPanel
title="Panel with Actions"
subtitle="Featuring header buttons"
actions={
<>
<button
className="px-3 py-1.5 rounded-lg text-sm font-medium transition-colors"
style={{
backgroundColor: 'var(--island-hover)',
color: 'var(--island-text)',
border: '1px solid var(--island-border)',
}}
>
Action
</button>
<button
className="px-3 py-1.5 rounded-lg text-sm font-medium transition-colors"
style={{
backgroundColor: 'var(--island-text)',
color: 'var(--island-bg)',
}}
>
Primary
</button>
</>
}
>
<p style={{ color: 'var(--island-text)' }}>
Actions in the header provide quick access to common operations.
</p>
</IslandPanel>

{/* Nested content example */}
<IslandPanel title="Rich Content Example">
<div className="space-y-4">
<div
className="p-4 rounded-lg"
style={{
backgroundColor: 'var(--island-bg-secondary)',
border: '1px solid var(--island-border)',
}}
>
<h4 className="font-semibold mb-2" style={{ color: 'var(--island-text)' }}>
Nested Section
</h4>
<p style={{ color: 'var(--island-text-secondary)' }}>
You can nest other elements with system colors inside the panel.
</p>
</div>

<div className="grid grid-cols-2 gap-3">
<div
className="p-3 rounded-lg text-center"
style={{ backgroundColor: 'var(--island-hover)' }}
>
<p className="text-sm font-medium" style={{ color: 'var(--island-text)' }}>
Grid Item 1
</p>
</div>
<div
className="p-3 rounded-lg text-center"
style={{ backgroundColor: 'var(--island-hover)' }}
>
<p className="text-sm font-medium" style={{ color: 'var(--island-text)' }}>
Grid Item 2
</p>
</div>
</div>
</div>
</IslandPanel>

{/* Info box about the component */}
<div
className="rounded-lg p-4"
style={{
backgroundColor: 'var(--island-bg-secondary)',
border: '1px solid var(--island-border)',
}}
>
<h4 className="font-semibold mb-2" style={{ color: 'var(--island-text)' }}>
About Island Panels
</h4>
<ul className="space-y-1 text-sm" style={{ color: 'var(--island-text-secondary)' }}>
<li>• Rounded corners (16px) for modern aesthetic</li>
<li>• Subtle shadow for depth and elevation</li>
<li>• Automatic light/dark mode via prefers-color-scheme</li>
<li>• Uses CSS variables for system colors</li>
<li>• No hard-coded brand palette</li>
</ul>
</div>
</div>
);
}
91 changes: 91 additions & 0 deletions blendmate-app/src/components/ui/IslandPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { ReactNode } from 'react';

interface IslandPanelProps {
/** Title displayed in the panel header */
title?: string;
/** Optional subtitle or description */
subtitle?: string;
/** Actions to display in the header (buttons, icons, etc.) */
actions?: ReactNode;
/** Main content of the panel */
children: ReactNode;
/** Additional CSS classes for customization */
className?: string;
}

/**
* Island Panel Component
*
* A modern, elevated panel with soft rounded corners and subtle shadow.
* Automatically adapts to light/dark mode using system color preferences.
*
* Features:
* - Rounded corners (16px)
* - Subtle shadow for depth
* - Header with title and optional actions
* - Content area with proper spacing
* - Light/dark mode support via prefers-color-scheme
* - Uses CSS variables for system colors (no hard-coded brand palette)
*/
export default function IslandPanel({
title,
subtitle,
actions,
children,
className = ''
}: IslandPanelProps) {
return (
<div
className={`rounded-2xl overflow-hidden ${className}`}
style={{
backgroundColor: 'var(--island-bg)',
border: '1px solid var(--island-border)',
boxShadow: '0 2px 8px var(--island-shadow), 0 1px 2px var(--island-shadow)',
}}
>
{/* Header - only render if title or actions exist */}
{(title || actions) && (
<div
className="flex items-center justify-between px-5 py-4 border-b"
style={{
borderColor: 'var(--island-border)',
backgroundColor: 'var(--island-bg-secondary)',
}}
>
<div className="flex-1 min-w-0">
{title && (
<h3
className="text-base font-semibold truncate"
style={{ color: 'var(--island-text)' }}
>
{title}
</h3>
)}
{subtitle && (
<p
className="text-sm mt-0.5 truncate"
style={{ color: 'var(--island-text-secondary)' }}
>
{subtitle}
</p>
)}
</div>

{actions && (
<div className="flex items-center gap-2 ml-4 flex-shrink-0">
{actions}
</div>
)}
</div>
)}

{/* Content Area */}
<div
className="p-5"
style={{ color: 'var(--island-text)' }}
>
{children}
</div>
</div>
);
}
82 changes: 82 additions & 0 deletions blendmate-app/src/components/ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# UI Components

## IslandPanel

A modern, elevated panel component with automatic light/dark mode support.

### Features

- **Rounded corners** (16px) for a soft, modern aesthetic
- **Subtle shadow** for depth and elevation
- **Automatic theme switching** via `prefers-color-scheme`
- **System colors** using CSS variables (no hard-coded brand palette)
- **Flexible header** with optional title, subtitle, and actions
- **Clean content area** with proper spacing

### Usage

```tsx
import IslandPanel from './components/ui/IslandPanel';

// Basic panel
<IslandPanel>
<p>Your content here</p>
</IslandPanel>

// Panel with title
<IslandPanel title="My Panel">
<p>Content with a title</p>
</IslandPanel>

// Complete panel with title, subtitle, and actions
<IslandPanel
title="Settings"
subtitle="Configure your preferences"
actions={
<>
<button>Cancel</button>
<button>Save</button>
</>
}
>
<p>Panel content</p>
</IslandPanel>
```

### Props

- `title` (optional): String - Title displayed in the panel header
- `subtitle` (optional): String - Subtitle or description below the title
- `actions` (optional): ReactNode - Actions to display in the header (buttons, icons, etc.)
- `children`: ReactNode - Main content of the panel
- `className` (optional): String - Additional CSS classes for customization

### CSS Variables

The component uses the following CSS variables defined in `index.css`:

**Light mode:**
- `--island-bg`: rgb(255 255 255)
- `--island-bg-secondary`: rgb(249 249 249)
- `--island-border`: rgb(229 229 229)
- `--island-text`: rgb(23 23 23)
- `--island-text-secondary`: rgb(115 115 115)
- `--island-shadow`: rgba(0 0 0 / 0.08)
- `--island-hover`: rgb(245 245 245)

**Dark mode:**
- `--island-bg`: rgb(30 30 30)
- `--island-bg-secondary`: rgb(23 23 23)
- `--island-border`: rgb(64 64 64)
- `--island-text`: rgb(250 250 250)
- `--island-text-secondary`: rgb(163 163 163)
- `--island-shadow`: rgba(0 0 0 / 0.3)
- `--island-hover`: rgb(40 40 40)

### Design Philosophy

The Island panel follows modern OS UI conventions:
- Uses system-defined colors that adapt to user preferences
- No hard-coded brand colors in the component itself
- Maintains consistency with native OS aesthetics
- Provides visual hierarchy through subtle shadows and backgrounds
42 changes: 41 additions & 1 deletion blendmate-app/src/index.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,54 @@
@import "tailwindcss";
@plugin "@tailwindcss/typography";

@theme {
--color-blendmate-dark: #0a0a0a;
--color-blendmate-gray: #1a1a1a;
--color-blendmate-orange: #ff9d5c;
--color-blendmate-blue: #3d94ff;
}

/* System color variables for Island panels - light/dark mode support */
:root {
/* Light mode (default system colors) */
--island-bg: rgb(255 255 255);
--island-bg-secondary: rgb(249 249 249);
--island-border: rgb(229 229 229);
--island-text: rgb(23 23 23);
--island-text-secondary: rgb(115 115 115);
--island-shadow: rgba(0 0 0 / 0.08);
--island-hover: rgb(245 245 245);

background-color: rgb(250 250 250);
color: var(--island-text);
}

/* Dark mode system colors */
@media (prefers-color-scheme: dark) {
:root {
--island-bg: rgb(30 30 30);
--island-bg-secondary: rgb(23 23 23);
--island-border: rgb(64 64 64);
--island-text: rgb(250 250 250);
--island-text-secondary: rgb(163 163 163);
--island-shadow: rgba(0 0 0 / 0.3);
--island-hover: rgb(40 40 40);

background-color: rgb(17 17 17);
color: var(--island-text);
}
}

* {
box-sizing: border-box;
}

body {
margin: 0;
background-color: inherit;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}