chore: organize documentation - move markdown files to docs/ folder
This commit is contained in:
181
docs/DOCKER.md
Normal file
181
docs/DOCKER.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# Docker Deployment
|
||||
|
||||
This application can be easily deployed using Docker with configurable environment variables.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Using Docker Run
|
||||
|
||||
```bash
|
||||
# Run using pre-built image (app will prompt for Navidrome config)
|
||||
docker run -p 3000:3000 sillyangel/mice:latest
|
||||
|
||||
# Or build locally
|
||||
docker build -t mice .
|
||||
docker run -p 3000:3000 mice
|
||||
|
||||
# Run with pre-configured Navidrome settings
|
||||
docker run -p 3000:3000 \
|
||||
-e NEXT_PUBLIC_NAVIDROME_URL=http://your-navidrome-server:4533 \
|
||||
-e NEXT_PUBLIC_NAVIDROME_USERNAME=your_username \
|
||||
-e NEXT_PUBLIC_NAVIDROME_PASSWORD=your_password \
|
||||
-e PORT=3000 \
|
||||
sillyangel/mice:latest
|
||||
```
|
||||
|
||||
### Using Docker Compose
|
||||
|
||||
1. Copy the environment template:
|
||||
|
||||
```bash
|
||||
cp .env.docker .env
|
||||
```
|
||||
|
||||
2. Edit `.env` with your configuration:
|
||||
|
||||
```bash
|
||||
nano .env
|
||||
```
|
||||
|
||||
3. Start the application:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
**Note**: The default docker-compose.yml uses the pre-built image `sillyangel/mice:latest`.
|
||||
|
||||
For local development, you can use the override example:
|
||||
|
||||
```bash
|
||||
cp docker-compose.override.yml.example docker-compose.override.yml
|
||||
# This will build locally instead of using the pre-built image
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
All configuration is done through environment variables. If Navidrome server configuration is not provided via environment variables, the application will automatically prompt you to configure it within the client interface.
|
||||
|
||||
### Runtime Environment Variables (Docker)
|
||||
|
||||
When running with Docker, use these variable names (without the `NEXT_PUBLIC_` prefix):
|
||||
|
||||
- `NAVIDROME_URL`: URL of your Navidrome server (optional - app will prompt if not set)
|
||||
- `NAVIDROME_USERNAME`: Navidrome username (optional - app will prompt if not set)
|
||||
- `NAVIDROME_PASSWORD`: Navidrome password (optional - app will prompt if not set)
|
||||
- `PORT`: Port for the application to listen on (default: `3000`)
|
||||
- `HOST_PORT`: Host port to map to container port (docker-compose only, default: `3000`)
|
||||
|
||||
### Development Environment Variables
|
||||
|
||||
For local development (non-Docker), use these variable names:
|
||||
|
||||
- `NEXT_PUBLIC_NAVIDROME_URL`: URL of your Navidrome server
|
||||
- `NEXT_PUBLIC_NAVIDROME_USERNAME`: Navidrome username
|
||||
- `NEXT_PUBLIC_NAVIDROME_PASSWORD`: Navidrome password
|
||||
|
||||
**Note**: Docker deployment uses a runtime replacement mechanism to inject environment variables, while development uses Next.js's built-in `NEXT_PUBLIC_` variables.
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Setup (App will prompt for configuration)
|
||||
|
||||
```bash
|
||||
# Using pre-built image - app will ask for Navidrome server details on first launch
|
||||
docker run -p 3000:3000 sillyangel/mice:latest
|
||||
|
||||
# Or build locally
|
||||
docker build -t mice .
|
||||
docker run -p 3000:3000 mice
|
||||
```
|
||||
|
||||
### Pre-configured Development Setup
|
||||
|
||||
```bash
|
||||
docker run -p 3000:3000 \
|
||||
-e NEXT_PUBLIC_NAVIDROME_URL=http://localhost:4533 \
|
||||
-e NEXT_PUBLIC_NAVIDROME_USERNAME=admin \
|
||||
-e NEXT_PUBLIC_NAVIDROME_PASSWORD=admin \
|
||||
sillyangel/mice:latest
|
||||
```
|
||||
|
||||
### Pre-configured Production Setup
|
||||
|
||||
```bash
|
||||
docker run -p 80:3000 \
|
||||
-e NEXT_PUBLIC_NAVIDROME_URL=https://music.yourdomain.com \
|
||||
-e NEXT_PUBLIC_NAVIDROME_USERNAME=your_user \
|
||||
-e NEXT_PUBLIC_NAVIDROME_PASSWORD=your_secure_password \
|
||||
-e PORT=3000 \
|
||||
--restart unless-stopped \
|
||||
sillyangel/mice:latest
|
||||
```
|
||||
|
||||
### Using Environment File
|
||||
|
||||
#### Option 1: Let the app prompt for configuration
|
||||
|
||||
Create a minimal `.env` file:
|
||||
|
||||
```env
|
||||
PORT=3000
|
||||
HOST_PORT=80
|
||||
```
|
||||
|
||||
#### Option 2: Pre-configure Navidrome settings
|
||||
|
||||
Create a `.env` file with Navidrome configuration:
|
||||
|
||||
```env
|
||||
NAVIDROME_URL=https://music.yourdomain.com
|
||||
NAVIDROME_USERNAME=your_user
|
||||
NAVIDROME_PASSWORD=your_secure_password
|
||||
PORT=3000
|
||||
HOST_PORT=80
|
||||
```
|
||||
|
||||
Then run either way:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## Health Check
|
||||
|
||||
The Docker Compose setup includes a health check that verifies the application is responding correctly. You can check the health status with:
|
||||
|
||||
```bash
|
||||
docker-compose ps
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Connection refused**: Ensure your Navidrome server is accessible from the Docker container
|
||||
2. **Authentication failed**: Verify your username and password are correct
|
||||
3. **Port conflicts**: Change the `HOST_PORT` if port 3000 is already in use
|
||||
|
||||
### Logs
|
||||
|
||||
View application logs:
|
||||
|
||||
```bash
|
||||
# Docker run
|
||||
docker logs <container_name>
|
||||
|
||||
# Docker compose
|
||||
docker-compose logs -f mice
|
||||
```
|
||||
|
||||
### Container Shell Access
|
||||
|
||||
Access the container for debugging:
|
||||
|
||||
```bash
|
||||
# Docker run
|
||||
docker exec -it <container_name> sh
|
||||
|
||||
# Docker compose
|
||||
docker-compose exec mice sh
|
||||
```
|
||||
121
docs/KEYBOARD_SHORTCUTS.md
Normal file
121
docs/KEYBOARD_SHORTCUTS.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Keyboard Shortcuts & Queue Management Features
|
||||
|
||||
This document outlines the new keyboard shortcuts, queue management, and context menu features added to the music player.
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
The following keyboard shortcuts work globally throughout the application:
|
||||
|
||||
### Playback Controls
|
||||
- **Space** - Play/Pause current track
|
||||
- **→ (Right Arrow)** - Skip to next track
|
||||
- **← (Left Arrow)** - Skip to previous track
|
||||
|
||||
### Volume Controls
|
||||
- **↑ (Up Arrow)** - Increase volume by 10%
|
||||
- **↓ (Down Arrow)** - Decrease volume by 10%
|
||||
- **M** - Toggle mute/unmute
|
||||
|
||||
### Navigation
|
||||
- **/** - Quick search (navigates to search page and focuses input)
|
||||
|
||||
### Notes
|
||||
- Keyboard shortcuts are disabled when typing in input fields
|
||||
- When in fullscreen player mode, shortcuts are handled by the fullscreen player
|
||||
- Volume changes are saved to localStorage
|
||||
|
||||
## Queue Management
|
||||
|
||||
### Drag and Drop Queue Reordering
|
||||
- **Drag Handle**: Hover over queue items to reveal the grip handle (⋮⋮)
|
||||
- **Reorder**: Click and drag the handle to reorder tracks in the queue
|
||||
- **Visual Feedback**: Dragged items become semi-transparent during drag
|
||||
- **Keyboard Support**: Use Tab to focus items, then Space + Arrow keys to reorder
|
||||
|
||||
### Queue Features
|
||||
- Real-time visual feedback during drag operations
|
||||
- Maintains playback order after reordering
|
||||
- Works with both mouse and keyboard navigation
|
||||
- Accessible drag and drop implementation
|
||||
|
||||
## Context Menus (Right-Click)
|
||||
|
||||
Right-click on tracks, albums, and artists to access quick actions:
|
||||
|
||||
### Track Context Menu
|
||||
- **Play Now** - Immediately play the selected track
|
||||
- **Play Next** - Add track to the beginning of the queue
|
||||
- **Add to Queue** - Add track to the end of the queue
|
||||
- **Add/Remove from Favorites** - Toggle favorite status
|
||||
- **Go to Album** - Navigate to the track's album
|
||||
- **Go to Artist** - Navigate to the track's artist
|
||||
- **Track Info** - View detailed track information
|
||||
- **Share** - Share the track
|
||||
|
||||
### Album Context Menu
|
||||
- **Play Album** - Play the entire album from the beginning
|
||||
- **Add Album to Queue** - Add all album tracks to queue
|
||||
- **Play Album Next** - Add album tracks to beginning of queue
|
||||
- **Add to Favorites** - Add album to favorites
|
||||
- **Go to Artist** - Navigate to the album's artist
|
||||
- **Album Info** - View detailed album information
|
||||
- **Share Album** - Share the album
|
||||
|
||||
### Artist Context Menu
|
||||
- **Play All Songs** - Play all songs by the artist
|
||||
- **Add All to Queue** - Add all artist songs to queue
|
||||
- **Play All Next** - Add all artist songs to beginning of queue
|
||||
- **Add to Favorites** - Add artist to favorites
|
||||
- **Artist Info** - View detailed artist information
|
||||
- **Share Artist** - Share the artist
|
||||
|
||||
## Where to Find These Features
|
||||
|
||||
### Keyboard Shortcuts
|
||||
- Available globally throughout the application
|
||||
- Work in main player, fullscreen player, and all pages
|
||||
- Search shortcut (/) works from any page
|
||||
|
||||
### Queue Management
|
||||
- **Queue Page**: `/queue` - Full drag and drop interface
|
||||
- **Mini Player**: Shows current track and basic controls
|
||||
- **Fullscreen Player**: Queue management button available
|
||||
|
||||
### Context Menus
|
||||
- **Search Results**: Right-click on any track, album, or artist
|
||||
- **Album Pages**: Right-click on individual tracks
|
||||
- **Artist Pages**: Right-click on tracks and albums
|
||||
- **Queue Page**: Right-click on queued tracks
|
||||
- **Library Browse**: Right-click on any item
|
||||
|
||||
## Technical Implementation
|
||||
|
||||
### Components Used
|
||||
- `useKeyboardShortcuts` hook for global keyboard shortcuts
|
||||
- `@dnd-kit` for drag and drop functionality
|
||||
- `@radix-ui/react-context-menu` for context menus
|
||||
- Custom context menu components for different content types
|
||||
|
||||
### Accessibility
|
||||
- Full keyboard navigation support
|
||||
- Screen reader compatible
|
||||
- Focus management
|
||||
- ARIA labels and descriptions
|
||||
- High contrast support
|
||||
|
||||
## Tips for Users
|
||||
|
||||
1. **Keyboard Shortcuts**: Most shortcuts work anywhere in the app, just start typing
|
||||
2. **Queue Reordering**: Hover over queue items to see the drag handle
|
||||
3. **Context Menus**: Right-click almost anything to see available actions
|
||||
4. **Quick Search**: Press `/` from anywhere to jump to search
|
||||
5. **Volume Control**: Use arrow keys for precise volume adjustment
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Potential future additions:
|
||||
- Custom keyboard shortcut configuration
|
||||
- More queue management options (clear queue, save as playlist)
|
||||
- Additional context menu actions (edit metadata, download)
|
||||
- Gesture support for mobile devices
|
||||
- Queue templates and smart playlists
|
||||
168
docs/OFFLINE_DOWNLOADS.md
Normal file
168
docs/OFFLINE_DOWNLOADS.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# Offline Downloads Feature
|
||||
|
||||
This document describes the offline downloads functionality implemented in the Mice Navidrome client.
|
||||
|
||||
## Overview
|
||||
|
||||
The offline downloads feature allows users to download music for offline listening using modern web technologies including Service Workers and Cache API, with localStorage fallback for browsers without Service Worker support.
|
||||
|
||||
## Components
|
||||
|
||||
### 1. Service Worker (`/public/sw.js`)
|
||||
- Handles audio, image, and API caching
|
||||
- Manages download operations in the background
|
||||
- Provides offline audio playback capabilities
|
||||
- Implements cache-first strategy for downloaded content
|
||||
|
||||
### 2. Download Manager Hook (`/hooks/use-offline-downloads.ts`)
|
||||
- Provides React interface for download operations
|
||||
- Manages download progress and status
|
||||
- Handles Service Worker communication
|
||||
- Provides localStorage fallback for metadata
|
||||
|
||||
### 3. Cache Management Component (`/app/components/CacheManagement.tsx`)
|
||||
- Enhanced to show offline download statistics
|
||||
- Displays download progress during operations
|
||||
- Lists downloaded content with removal options
|
||||
- Shows Service Worker support status
|
||||
|
||||
### 4. Offline Indicator Component (`/app/components/OfflineIndicator.tsx`)
|
||||
- Shows download status for albums and songs
|
||||
- Provides download/remove buttons
|
||||
- Displays visual indicators on album artwork
|
||||
|
||||
## Features
|
||||
|
||||
### Download Capabilities
|
||||
- **Album Downloads**: Download entire albums with all tracks and artwork
|
||||
- **Individual Song Downloads**: Download single tracks
|
||||
- **Progress Tracking**: Real-time download progress with track-by-track updates
|
||||
- **Error Handling**: Graceful handling of failed downloads with retry options
|
||||
|
||||
### Visual Indicators
|
||||
- **Album Artwork**: Small download icon in top-right corner of downloaded albums
|
||||
- **Album Pages**: Download buttons and status indicators
|
||||
- **Song Lists**: Individual download indicators for tracks
|
||||
- **Library View**: Visual badges showing offline availability
|
||||
|
||||
### Offline Storage
|
||||
- **Service Worker Cache**: True offline storage for audio files and images
|
||||
- **localStorage Fallback**: Metadata-only storage for limited browser support
|
||||
- **Progressive Enhancement**: Works in all browsers with varying capabilities
|
||||
|
||||
### Cache Management
|
||||
- **Storage Statistics**: Shows total offline storage usage
|
||||
- **Content Management**: List and remove downloaded content
|
||||
- **Cache Cleanup**: Clear expired and unnecessary cache data
|
||||
- **Progress Monitoring**: Real-time download progress display
|
||||
|
||||
## Usage
|
||||
|
||||
### Downloading Content
|
||||
|
||||
#### From Album Page
|
||||
1. Navigate to any album page
|
||||
2. Click the "Download" button (desktop) or small download button (mobile)
|
||||
3. Monitor progress in the cache management section
|
||||
4. Downloaded albums show indicators on artwork and in lists
|
||||
|
||||
#### From Settings Page
|
||||
1. Go to Settings → Cache & Offline Downloads
|
||||
2. View current download statistics
|
||||
3. Monitor active downloads
|
||||
4. Manage downloaded content
|
||||
|
||||
### Managing Downloads
|
||||
|
||||
#### Viewing Downloaded Content
|
||||
- Settings page shows list of all downloaded albums and songs
|
||||
- Album artwork displays download indicators
|
||||
- Individual songs show download status
|
||||
|
||||
#### Removing Downloads
|
||||
- Use the "X" button next to items in the cache management list
|
||||
- Use "Remove Download" button on album pages
|
||||
- Clear all cache to remove everything
|
||||
|
||||
## Technical Implementation
|
||||
|
||||
### Service Worker Features
|
||||
- **Audio Caching**: Streams are cached using the Subsonic API
|
||||
- **Image Caching**: Album artwork and avatars cached separately
|
||||
- **API Caching**: Metadata cached with network-first strategy
|
||||
- **Background Downloads**: Downloads continue even when page is closed
|
||||
|
||||
### Browser Compatibility
|
||||
- **Full Support**: Modern browsers with Service Worker support
|
||||
- **Limited Support**: Older browsers get metadata-only caching
|
||||
- **Progressive Enhancement**: Features gracefully degrade
|
||||
|
||||
### Storage Strategy
|
||||
- **Audio Cache**: Large files stored in Service Worker cache
|
||||
- **Image Cache**: Artwork cached separately for optimization
|
||||
- **Metadata Cache**: Song/album information in localStorage
|
||||
- **Size Management**: Automatic cleanup of old cached content
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
The offline downloads use existing Navidrome configuration:
|
||||
- `NEXT_PUBLIC_NAVIDROME_URL`
|
||||
- `NEXT_PUBLIC_NAVIDROME_USERNAME`
|
||||
- `NEXT_PUBLIC_NAVIDROME_PASSWORD`
|
||||
|
||||
### Cache Limits
|
||||
- Default audio cache: No explicit limit (browser manages)
|
||||
- Image cache: Optimized sizes based on display requirements
|
||||
- Metadata: Stored in localStorage with cleanup
|
||||
|
||||
## Development Notes
|
||||
|
||||
### File Structure
|
||||
```
|
||||
hooks/
|
||||
use-offline-downloads.ts # Main download hook
|
||||
app/components/
|
||||
CacheManagement.tsx # Enhanced cache UI
|
||||
OfflineIndicator.tsx # Download status components
|
||||
album-artwork.tsx # Updated with indicators
|
||||
album/[id]/
|
||||
page.tsx # Enhanced with download buttons
|
||||
public/
|
||||
sw.js # Service Worker implementation
|
||||
```
|
||||
|
||||
### API Integration
|
||||
- Uses existing Navidrome API endpoints
|
||||
- Leverages Subsonic streaming URLs
|
||||
- Integrates with current authentication system
|
||||
- Compatible with existing cache infrastructure
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Planned Features
|
||||
- **Playlist Downloads**: Download entire playlists
|
||||
- **Smart Sync**: Automatic download of favorites
|
||||
- **Storage Limits**: User-configurable storage limits
|
||||
- **Download Scheduling**: Queue downloads for later
|
||||
- **Offline Mode Detection**: Automatic offline behavior
|
||||
|
||||
### Performance Optimizations
|
||||
- **Compression**: Audio compression options
|
||||
- **Quality Selection**: Choose download quality
|
||||
- **Selective Sync**: Download only specific tracks
|
||||
- **Background Sync**: Download during idle time
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
- **Service Worker not registering**: Check browser console
|
||||
- **Downloads failing**: Verify Navidrome server connection
|
||||
- **Storage full**: Clear cache or check browser storage limits
|
||||
- **Slow downloads**: Check network connection and server performance
|
||||
|
||||
### Debug Information
|
||||
- Browser Developer Tools → Application → Service Workers
|
||||
- Cache storage inspection in DevTools
|
||||
- Console logs for download progress and errors
|
||||
- Network tab for failed requests
|
||||
135
docs/SPOTLIGHT_SEARCH.md
Normal file
135
docs/SPOTLIGHT_SEARCH.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# Spotlight Search Feature
|
||||
|
||||
## Overview
|
||||
|
||||
The Spotlight Search feature provides a macOS Spotlight-style search interface for your music library, enhanced with Last.fm metadata for rich music information.
|
||||
|
||||
## Features
|
||||
|
||||
### 🔍 **Instant Search**
|
||||
|
||||
- **Global Search**: Press `Cmd+K` (macOS) / `Ctrl+K` (Windows/Linux) from anywhere in the app
|
||||
- **Real-time Results**: Search as you type with 300ms debouncing
|
||||
- **Multiple Types**: Search across tracks, albums, and artists simultaneously
|
||||
|
||||
### ⌨️ **Keyboard Navigation**
|
||||
- `↑`/`↓` arrows to navigate results
|
||||
- `Enter` to select and play/view
|
||||
- `Tab` to show detailed information
|
||||
- `Esc` to close (or close details panel)
|
||||
|
||||
### 🎵 **Quick Actions**
|
||||
- **Play Now**: Click on any result to play immediately
|
||||
- **Play Next**: Add track to the beginning of queue
|
||||
- **Add to Queue**: Add track to the end of queue
|
||||
- **Show Details**: Get rich information from Last.fm
|
||||
|
||||
### 🌍 **Last.fm Integration**
|
||||
When viewing details, you'll see:
|
||||
- **Artist Biography**: Rich biographical information
|
||||
- **Statistics**: Play counts and listener numbers
|
||||
- **Tags**: Genre and style tags
|
||||
- **Similar Artists**: Discover new music based on your selections
|
||||
- **Album Art**: High-quality images
|
||||
|
||||
## Usage
|
||||
|
||||
### Opening Search
|
||||
|
||||
- **Keyboard**: Press `Cmd+K` (macOS) / `Ctrl+K` (Windows/Linux)
|
||||
- **Mouse**: Click the search button in the top menu bar (desktop)
|
||||
- **Mobile**: Tap the search icon in the bottom navigation
|
||||
|
||||
### Search Tips
|
||||
- Type partial song names, artist names, or album titles
|
||||
- Results appear in real-time as you type
|
||||
- Use keyboard navigation for fastest access
|
||||
- Press Tab to see detailed Last.fm information
|
||||
|
||||
### Quick Actions
|
||||
- **Tracks**: Play, Play Next, Add to Queue
|
||||
- **Albums**: View album page, Add entire album to queue
|
||||
- **Artists**: View artist page, Play all songs
|
||||
|
||||
## Last.fm Data
|
||||
|
||||
The search integrates with Last.fm to provide:
|
||||
|
||||
### Artist Information
|
||||
- **Bio**: Artist biography and background
|
||||
- **Stats**: Total plays and listeners globally
|
||||
- **Similar**: Artists with similar style
|
||||
- **Tags**: Genre classification and style tags
|
||||
|
||||
### Enhanced Discovery
|
||||
- Click on similar artists to search for them
|
||||
- Explore tags to discover new genres
|
||||
- View play statistics to understand popularity
|
||||
|
||||
## Keyboard Shortcuts Summary
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Cmd+K` / `Ctrl+K` | Open Spotlight Search |
|
||||
| `↑` / `↓` | Navigate results |
|
||||
| `Enter` | Select result |
|
||||
| `Tab` | Show details |
|
||||
| `Esc` | Close search/details |
|
||||
| `Space` | Play/Pause (when not in search) |
|
||||
| `←` / `→` | Previous/Next track |
|
||||
| `↑` / `↓` | Volume up/down (when not in search) |
|
||||
| `M` | Toggle mute |
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Architecture
|
||||
- **Global Context**: `GlobalSearchProvider` manages search state
|
||||
- **Component**: `SpotlightSearch` handles UI and interactions
|
||||
- **Hooks**: `useKeyboardShortcuts` for global hotkeys
|
||||
- **Integration**: Uses existing Navidrome search API + Last.fm API
|
||||
|
||||
### Performance
|
||||
- **Debounced Search**: 300ms delay prevents excessive API calls
|
||||
- **Keyboard Optimized**: All interactions available via keyboard
|
||||
- **Lazy Loading**: Last.fm data loaded only when details are viewed
|
||||
- **Caching**: Search results cached during session
|
||||
|
||||
### Accessibility
|
||||
- **Keyboard Navigation**: Full keyboard support
|
||||
- **Screen Reader**: Proper ARIA labels and descriptions
|
||||
- **Focus Management**: Automatic focus on search input
|
||||
- **Visual Feedback**: Clear hover and selection states
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Planned Features
|
||||
- **Search History**: Remember recent searches
|
||||
- **Smart Suggestions**: AI-powered search suggestions
|
||||
- **Scoped Search**: Filter by type (tracks only, albums only, etc.)
|
||||
- **Advanced Filters**: Date ranges, genres, etc.
|
||||
- **Playlist Integration**: Search within specific playlists
|
||||
|
||||
### Last.fm Enhancements
|
||||
- **Track Information**: Individual track details from Last.fm
|
||||
- **Album Reviews**: User reviews and ratings
|
||||
- **Concert Information**: Upcoming shows and tour dates
|
||||
- **Scrobbling Integration**: Enhanced scrobbling with search data
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Search Not Working
|
||||
1. Check Navidrome connection in settings
|
||||
2. Verify network connectivity
|
||||
3. Try refreshing the page
|
||||
|
||||
### Last.fm Data Missing
|
||||
1. Last.fm API may be unavailable
|
||||
2. Artist/album may not exist in Last.fm database
|
||||
3. Network connectivity issues
|
||||
|
||||
### Keyboard Shortcuts Not Working
|
||||
1. Ensure you're not in an input field
|
||||
2. Check if fullscreen mode is interfering
|
||||
3. Try clicking outside any input fields first
|
||||
|
||||
The Spotlight Search feature transforms how you discover and interact with your music library, making it faster and more intuitive than ever before!
|
||||
593
docs/themes.md
Normal file
593
docs/themes.md
Normal file
@@ -0,0 +1,593 @@
|
||||
# Shadcn UI Themes Upgrade
|
||||
|
||||
## Default (White)
|
||||
|
||||
```css
|
||||
:root {
|
||||
--radius: 0.5rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: oklch(0.205 0 0);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
--muted: oklch(0.97 0 0);
|
||||
--muted-foreground: oklch(0.556 0 0);
|
||||
--accent: oklch(0.97 0 0);
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.708 0 0);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--radius: 0.5rem;
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||
--sidebar-border: oklch(0.922 0 0);
|
||||
--sidebar-ring: oklch(0.708 0 0);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.205 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.205 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.922 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.556 0 0);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.205 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.556 0 0);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Red
|
||||
|
||||
```css
|
||||
:root {
|
||||
--radius: 0.5rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.141 0.005 285.823);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.141 0.005 285.823);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.141 0.005 285.823);
|
||||
--primary: oklch(0.637 0.237 25.331);
|
||||
--primary-foreground: oklch(0.971 0.013 17.38);
|
||||
--secondary: oklch(0.967 0.001 286.375);
|
||||
--secondary-foreground: oklch(0.21 0.006 285.885);
|
||||
--muted: oklch(0.967 0.001 286.375);
|
||||
--muted-foreground: oklch(0.552 0.016 285.938);
|
||||
--accent: oklch(0.967 0.001 286.375);
|
||||
--accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.92 0.004 286.32);
|
||||
--input: oklch(0.92 0.004 286.32);
|
||||
--ring: oklch(0.637 0.237 25.331);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
||||
--sidebar-primary: oklch(0.637 0.237 25.331);
|
||||
--sidebar-primary-foreground: oklch(0.971 0.013 17.38);
|
||||
--sidebar-accent: oklch(0.967 0.001 286.375);
|
||||
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--sidebar-border: oklch(0.92 0.004 286.32);
|
||||
--sidebar-ring: oklch(0.637 0.237 25.331);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.141 0.005 285.823);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.21 0.006 285.885);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.21 0.006 285.885);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.637 0.237 25.331);
|
||||
--primary-foreground: oklch(0.971 0.013 17.38);
|
||||
--secondary: oklch(0.274 0.006 286.033);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.274 0.006 286.033);
|
||||
--muted-foreground: oklch(0.705 0.015 286.067);
|
||||
--accent: oklch(0.274 0.006 286.033);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.637 0.237 25.331);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.21 0.006 285.885);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.637 0.237 25.331);
|
||||
--sidebar-primary-foreground: oklch(0.971 0.013 17.38);
|
||||
--sidebar-accent: oklch(0.274 0.006 286.033);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.637 0.237 25.331);
|
||||
}
|
||||
```
|
||||
|
||||
## Rose
|
||||
|
||||
```css
|
||||
:root {
|
||||
--radius: 0.5rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.141 0.005 285.823);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.141 0.005 285.823);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.141 0.005 285.823);
|
||||
--primary: oklch(0.645 0.246 16.439);
|
||||
--primary-foreground: oklch(0.969 0.015 12.422);
|
||||
--secondary: oklch(0.967 0.001 286.375);
|
||||
--secondary-foreground: oklch(0.21 0.006 285.885);
|
||||
--muted: oklch(0.967 0.001 286.375);
|
||||
--muted-foreground: oklch(0.552 0.016 285.938);
|
||||
--accent: oklch(0.967 0.001 286.375);
|
||||
--accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.92 0.004 286.32);
|
||||
--input: oklch(0.92 0.004 286.32);
|
||||
--ring: oklch(0.645 0.246 16.439);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
||||
--sidebar-primary: oklch(0.645 0.246 16.439);
|
||||
--sidebar-primary-foreground: oklch(0.969 0.015 12.422);
|
||||
--sidebar-accent: oklch(0.967 0.001 286.375);
|
||||
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--sidebar-border: oklch(0.92 0.004 286.32);
|
||||
--sidebar-ring: oklch(0.645 0.246 16.439);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.141 0.005 285.823);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.21 0.006 285.885);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.21 0.006 285.885);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.645 0.246 16.439);
|
||||
--primary-foreground: oklch(0.969 0.015 12.422);
|
||||
--secondary: oklch(0.274 0.006 286.033);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.274 0.006 286.033);
|
||||
--muted-foreground: oklch(0.705 0.015 286.067);
|
||||
--accent: oklch(0.274 0.006 286.033);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.645 0.246 16.439);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.21 0.006 285.885);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.645 0.246 16.439);
|
||||
--sidebar-primary-foreground: oklch(0.969 0.015 12.422);
|
||||
--sidebar-accent: oklch(0.274 0.006 286.033);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.645 0.246 16.439);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Orange
|
||||
|
||||
```css
|
||||
:root {
|
||||
--radius: 0.5rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.141 0.005 285.823);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.141 0.005 285.823);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.141 0.005 285.823);
|
||||
--primary: oklch(0.705 0.213 47.604);
|
||||
--primary-foreground: oklch(0.98 0.016 73.684);
|
||||
--secondary: oklch(0.967 0.001 286.375);
|
||||
--secondary-foreground: oklch(0.21 0.006 285.885);
|
||||
--muted: oklch(0.967 0.001 286.375);
|
||||
--muted-foreground: oklch(0.552 0.016 285.938);
|
||||
--accent: oklch(0.967 0.001 286.375);
|
||||
--accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.92 0.004 286.32);
|
||||
--input: oklch(0.92 0.004 286.32);
|
||||
--ring: oklch(0.705 0.213 47.604);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
||||
--sidebar-primary: oklch(0.705 0.213 47.604);
|
||||
--sidebar-primary-foreground: oklch(0.98 0.016 73.684);
|
||||
--sidebar-accent: oklch(0.967 0.001 286.375);
|
||||
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--sidebar-border: oklch(0.92 0.004 286.32);
|
||||
--sidebar-ring: oklch(0.705 0.213 47.604);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.141 0.005 285.823);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.21 0.006 285.885);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.21 0.006 285.885);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.646 0.222 41.116);
|
||||
--primary-foreground: oklch(0.98 0.016 73.684);
|
||||
--secondary: oklch(0.274 0.006 286.033);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.274 0.006 286.033);
|
||||
--muted-foreground: oklch(0.705 0.015 286.067);
|
||||
--accent: oklch(0.274 0.006 286.033);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.646 0.222 41.116);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.21 0.006 285.885);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.646 0.222 41.116);
|
||||
--sidebar-primary-foreground: oklch(0.98 0.016 73.684);
|
||||
--sidebar-accent: oklch(0.274 0.006 286.033);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.646 0.222 41.116);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Green
|
||||
|
||||
```css
|
||||
:root {
|
||||
--radius: 0.5rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.141 0.005 285.823);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.141 0.005 285.823);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.141 0.005 285.823);
|
||||
--primary: oklch(0.723 0.219 149.579);
|
||||
--primary-foreground: oklch(0.982 0.018 155.826);
|
||||
--secondary: oklch(0.967 0.001 286.375);
|
||||
--secondary-foreground: oklch(0.21 0.006 285.885);
|
||||
--muted: oklch(0.967 0.001 286.375);
|
||||
--muted-foreground: oklch(0.552 0.016 285.938);
|
||||
--accent: oklch(0.967 0.001 286.375);
|
||||
--accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.92 0.004 286.32);
|
||||
--input: oklch(0.92 0.004 286.32);
|
||||
--ring: oklch(0.723 0.219 149.579);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
||||
--sidebar-primary: oklch(0.723 0.219 149.579);
|
||||
--sidebar-primary-foreground: oklch(0.982 0.018 155.826);
|
||||
--sidebar-accent: oklch(0.967 0.001 286.375);
|
||||
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--sidebar-border: oklch(0.92 0.004 286.32);
|
||||
--sidebar-ring: oklch(0.723 0.219 149.579);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.141 0.005 285.823);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.21 0.006 285.885);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.21 0.006 285.885);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.696 0.17 162.48);
|
||||
--primary-foreground: oklch(0.393 0.095 152.535);
|
||||
--secondary: oklch(0.274 0.006 286.033);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.274 0.006 286.033);
|
||||
--muted-foreground: oklch(0.705 0.015 286.067);
|
||||
--accent: oklch(0.274 0.006 286.033);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.527 0.154 150.069);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.21 0.006 285.885);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.696 0.17 162.48);
|
||||
--sidebar-primary-foreground: oklch(0.393 0.095 152.535);
|
||||
--sidebar-accent: oklch(0.274 0.006 286.033);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.527 0.154 150.069);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Blue
|
||||
|
||||
```css
|
||||
:root {
|
||||
--radius: 0.5rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.141 0.005 285.823);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.141 0.005 285.823);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.141 0.005 285.823);
|
||||
--primary: oklch(0.623 0.214 259.815);
|
||||
--primary-foreground: oklch(0.97 0.014 254.604);
|
||||
--secondary: oklch(0.967 0.001 286.375);
|
||||
--secondary-foreground: oklch(0.21 0.006 285.885);
|
||||
--muted: oklch(0.967 0.001 286.375);
|
||||
--muted-foreground: oklch(0.552 0.016 285.938);
|
||||
--accent: oklch(0.967 0.001 286.375);
|
||||
--accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.92 0.004 286.32);
|
||||
--input: oklch(0.92 0.004 286.32);
|
||||
--ring: oklch(0.623 0.214 259.815);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
||||
--sidebar-primary: oklch(0.623 0.214 259.815);
|
||||
--sidebar-primary-foreground: oklch(0.97 0.014 254.604);
|
||||
--sidebar-accent: oklch(0.967 0.001 286.375);
|
||||
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--sidebar-border: oklch(0.92 0.004 286.32);
|
||||
--sidebar-ring: oklch(0.623 0.214 259.815);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.141 0.005 285.823);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.21 0.006 285.885);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.21 0.006 285.885);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.546 0.245 262.881);
|
||||
--primary-foreground: oklch(0.379 0.146 265.522);
|
||||
--secondary: oklch(0.274 0.006 286.033);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.274 0.006 286.033);
|
||||
--muted-foreground: oklch(0.705 0.015 286.067);
|
||||
--accent: oklch(0.274 0.006 286.033);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.488 0.243 264.376);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.21 0.006 285.885);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.546 0.245 262.881);
|
||||
--sidebar-primary-foreground: oklch(0.379 0.146 265.522);
|
||||
--sidebar-accent: oklch(0.274 0.006 286.033);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.488 0.243 264.376);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Yellow
|
||||
|
||||
```css
|
||||
:root {
|
||||
--radius: 0.5rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.141 0.005 285.823);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.141 0.005 285.823);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.141 0.005 285.823);
|
||||
--primary: oklch(0.795 0.184 86.047);
|
||||
--primary-foreground: oklch(0.421 0.095 57.708);
|
||||
--secondary: oklch(0.967 0.001 286.375);
|
||||
--secondary-foreground: oklch(0.21 0.006 285.885);
|
||||
--muted: oklch(0.967 0.001 286.375);
|
||||
--muted-foreground: oklch(0.552 0.016 285.938);
|
||||
--accent: oklch(0.967 0.001 286.375);
|
||||
--accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.92 0.004 286.32);
|
||||
--input: oklch(0.92 0.004 286.32);
|
||||
--ring: oklch(0.795 0.184 86.047);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
||||
--sidebar-primary: oklch(0.795 0.184 86.047);
|
||||
--sidebar-primary-foreground: oklch(0.421 0.095 57.708);
|
||||
--sidebar-accent: oklch(0.967 0.001 286.375);
|
||||
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--sidebar-border: oklch(0.92 0.004 286.32);
|
||||
--sidebar-ring: oklch(0.795 0.184 86.047);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.141 0.005 285.823);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.21 0.006 285.885);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.21 0.006 285.885);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.795 0.184 86.047);
|
||||
--primary-foreground: oklch(0.421 0.095 57.708);
|
||||
--secondary: oklch(0.274 0.006 286.033);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.274 0.006 286.033);
|
||||
--muted-foreground: oklch(0.705 0.015 286.067);
|
||||
--accent: oklch(0.274 0.006 286.033);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.554 0.135 66.442);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.21 0.006 285.885);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.795 0.184 86.047);
|
||||
--sidebar-primary-foreground: oklch(0.421 0.095 57.708);
|
||||
--sidebar-accent: oklch(0.274 0.006 286.033);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.554 0.135 66.442);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Violet
|
||||
|
||||
```css
|
||||
:root {
|
||||
--radius: 0.5rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.141 0.005 285.823);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.141 0.005 285.823);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.141 0.005 285.823);
|
||||
--primary: oklch(0.606 0.25 292.717);
|
||||
--primary-foreground: oklch(0.969 0.016 293.756);
|
||||
--secondary: oklch(0.967 0.001 286.375);
|
||||
--secondary-foreground: oklch(0.21 0.006 285.885);
|
||||
--muted: oklch(0.967 0.001 286.375);
|
||||
--muted-foreground: oklch(0.552 0.016 285.938);
|
||||
--accent: oklch(0.967 0.001 286.375);
|
||||
--accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.92 0.004 286.32);
|
||||
--input: oklch(0.92 0.004 286.32);
|
||||
--ring: oklch(0.606 0.25 292.717);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
||||
--sidebar-primary: oklch(0.606 0.25 292.717);
|
||||
--sidebar-primary-foreground: oklch(0.969 0.016 293.756);
|
||||
--sidebar-accent: oklch(0.967 0.001 286.375);
|
||||
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--sidebar-border: oklch(0.92 0.004 286.32);
|
||||
--sidebar-ring: oklch(0.606 0.25 292.717);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.141 0.005 285.823);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.21 0.006 285.885);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.21 0.006 285.885);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.541 0.281 293.009);
|
||||
--primary-foreground: oklch(0.969 0.016 293.756);
|
||||
--secondary: oklch(0.274 0.006 286.033);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.274 0.006 286.033);
|
||||
--muted-foreground: oklch(0.705 0.015 286.067);
|
||||
--accent: oklch(0.274 0.006 286.033);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.541 0.281 293.009);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.21 0.006 285.885);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.541 0.281 293.009);
|
||||
--sidebar-primary-foreground: oklch(0.969 0.016 293.756);
|
||||
--sidebar-accent: oklch(0.274 0.006 286.033);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.541 0.281 293.009);
|
||||
}
|
||||
|
||||
```
|
||||
Reference in New Issue
Block a user