Neon Sakura
A gem that provides styling and theming components for Rails applications with a dark-themed UI, multi-theme support, and comprehensive UI components.
Installation
Add this line to your application's Gemfile:
gem 'neon_sakura'
And then execute:
$ bundle install
Requirements
This gem requires Propshaft for asset loading and management. Make sure you have Propshaft installed and configured in your Rails application.
Usage
Assets
The gem provides a set of CSS stylesheets and JavaScript components that can be used in any Rails application.
Stylesheets
The gem includes the following stylesheets:
base.css- Core utility classes (spacing, colors, typography, responsive utilities)components.css- UI components (navigation, cards, badges, buttons, tables, etc.)forms.css- Form element stylingpagy-tailwind.css- Pagination styling with Tailwind CSS
Layouts and Components
The gem also provides layout templates and view components:
- Layout templates for application and error pages
- SVG icon components for common UI elements
- Shared partials for common UI patterns
- Header and footer components for consistent page structure
Integration
To integrate with your Rails application:
- Add the gem to your Gemfile
- Run
bundle install - Include the gem's assets in your application layout
- Use gem-provided layouts and components in your views
CSS Assets
The gem provides styling that needs to be included in your application's layout. Add the following to your application's layout file (e.g., app/views/layouts/application.html.erb):
<%# Load neon_sakura stylesheets (Propshaft-compatible) %>
<%= neon_sakura_stylesheets %>
<%# Load your app-specific styles %>
<%= stylesheet_link_tag 'application', 'data-turbo-track': 'reload' %>
The neon_sakura_stylesheets helper loads all CSS files in the correct order for proper cascade. This is necessary because Propshaft (Rails 8) does not process @import statements in CSS files like Sprockets did.
IMPORTANT: Do NOT use @import "neon_sakura.css" in your application.css - this does not work with Propshaft. Always use the neon_sakura_stylesheets helper in your layout.
JavaScript Assets
The gem includes JavaScript functionality for interactive components. To include the gem's JavaScript in your application, add the following to your application's layout file:
<%= javascript_importmap_tags "neon_sakura", "data-turbo-track": "reload" %>
Or if using the asset pipeline directly, you can include:
<%= javascript_include_tag "neon_sakura", "data-turbo-track": "reload" %>
The dropdown functionality and other interactive components will be available after including this JavaScript.
Pagination with Pagy
The gem includes styling for Pagy pagination with the pagy-tailwind.css stylesheet. For best results, use the pagy_input_nav_js helper which combines navigation and info in minimum space.
Setup
Add pagy to your Gemfile:
gem 'pagy'Enable the input_nav_js extra in
config/initializers/pagy.rb:require 'pagy/extras/input_nav_js'Add pagy to your importmap in
config/importmap.rb:pin "pagy", to: "https://cdn.jsdelivr.net/npm/pagy@9.3.3/javascripts/pagy.min.js"Import pagy in
app/javascript/application.js:import "pagy"
Usage
In your controller:
@pagy, @records = pagy(YourModel.all)
In your view:
<%== pagy_input_nav_js(@pagy) %>
The pagy_input_nav_js helper provides:
- Direct page number input for quick navigation
- Responsive navigation buttons
- Compact display combining navigation and info
- Fastest Pagy navigation option
Custom Search Pagination
For search results with custom parameters, you can still use pagy_input_nav_js by passing the pagy object. The gem's styling will automatically apply.
Style Guide (Development Only)
The gem includes a comprehensive style guide that showcases all UI components, themes, icons, and provides code examples. This feature is only available in development and test environments.
Accessing the Style Guide
In your Rails application (development environment), navigate to:
http://localhost:3000/style-guide
The style guide is automatically available and includes a navbar link (visible only in dev/test).
What's Included
- Live Theme Previews: Switch between all 6 themes (Green/Purple/Red × Light/Dark) in real-time
- Icon Library: All 94 SVG icons (including ouroboros) with clickable zoom modal and helper usage examples
- Image Assets: All gem images with clickable zoom modal and usage examples
- Component Examples: Each component shown with rendered preview AND code examples:
- Typography (headings, text colors, gradients)
- Colors (CSS custom properties reference)
- Gradients (primary, navbar, secondary blue, and secondary purple gradients with visual comparisons)
- Buttons (submit, primary, icon, link)
- Forms (inputs, textareas, selects, checkboxes, radios)
- Cards (basic, with headers, grids)
- Badges (status, outline, counter, tags)
- Alerts (success, error, warning, info)
- Loading Indicators (spinners, progress bars, skeleton loaders)
- Pagination (Pagy integration with working examples)
Configuration
The style guide is enabled by default in development and test environments. To disable it:
# config/initializers/neon_sakura.rb
NeonSakura.configure do |config|
config.enable_style_guide = false
end
To control the navbar link position:
NeonSakura.configure do |config|
# Options: :start, :end, :before_logout, or integer position
config. = :start # Shows at beginning of navbar
end
To control Pagy pagination examples:
NeonSakura.configure do |config|
# Default: true (auto-detect and show Pagy examples if available)
# Set to false to hide pagination section entirely
config.style_guide_pagy_examples = false
end
Pagy Integration Behavior:
- When
true(default): Automatically detects if Pagy is installed and shows working pagination examples - If Pagy is not installed or fails to initialize: Shows helpful error message with configuration instructions
- When
false: Hides the entire pagination section from the style guide - Note: Pagy is not a required dependency - the style guide will work without it
Environment Restriction
The style guide is automatically restricted to development and test environments through multiple layers:
- Route: Only defined in development/test (returns Rails 404 in production)
- Controller: Returns 404 if somehow accessed in production
- Navbar: Link only visible in development/test via condition check
This ensures the style guide never appears in production, even if accidentally enabled.
Icon System
The gem includes 94+ SVG icon components based on Heroicons (MIT License), plus custom icons like ouroboros. All icons are commercially safe and require no attribution.
Usage
Icons are available as ERB partials in app/views/shared/icons/:
<%= render "shared/icons/check", css_class: "w-4 h-4" %>
<%= render "shared/icons/heart", css_class: "w-6 h-6 text-red-500" %>
Icon Helpers
Neon Sakura provides two helper modules for working with icons:
NeonSakura::IconHelper - General-purpose icon rendering:
<%= render_icon("check", css_class: "w-4 h-4") %>
<%= render_icon("heart", css_class: "w-6 h-6", aria_label: "Favorite") %>
<%= render_icon("star", css_class: "w-5 h-5", aria_hidden: true) %>
NeonSakura::ThemeHelper - Theme-aware icon rendering (includes IconHelper functionality):
<%= render_theme_icon("palette", css_class: "w-4 h-4") %>
<%= render_theme_icon("moon", css_class: "w-4 h-4") %>
<%= render_theme_icon("chevron_down", css_class: "w-4 h-4") %>
Helper Methods:
render_icon(name, options = {})- Renders an icon partial with optionscss_class- CSS classes (default: "w-4 h-4")aria_hidden- Whether icon is aria-hiddenaria_label- Accessibility label
render_theme_icon(name, options = {})- Same as render_icon, used in ThemeHelperavailable_icons- Returns array of all available icon namesicon_exists?(name)- Check if an icon existsrender_icon_list(icon_names, options = {})- Renders multiple icons in a containercss_class- Container CSS class (default: "flex items-center gap-2")icon_css_class- Individual icon CSS class
render_login_logo(options = {})- Renders the configured login logo from NeonSakura configuration (v0.1.6+)icon- Override configured icon namecss_class- Override configured CSS classesgradient_id- Override configured gradient ID- Falls back to
app_iconif no login logo is configured - Returns nil if no icon is configured
Examples:
<%# Single icon with custom styling %>
<%= render_icon("check", css_class: "w-6 h-6 text-green-500") %>
<%# Icon with accessibility label %>
<%= render_icon("heart", css_class: "w-5 h-5", aria_label: "Add to favorites") %>
<%# Multiple icons in a list %>
<%= render_icon_list(["check", "heart", "star"], icon_css_class: "w-4 h-4") %>
<%# Check if icon exists before rendering %>
<% if icon_exists?("custom_icon") %>
<%= render_icon("custom_icon") %>
<% end %>
<%# Get all available icons %>
<% available_icons.each do |icon_name| %>
<%= render_icon(icon_name, css_class: "w-4 h-4") %>
<% end %>
<%# Render configured login logo (from initializer config) %>
<%= render_login_logo %>
<%# Render login logo with custom size %>
<%= render_login_logo(css_class: "w-16 h-16") %>
<%# Render login logo with gradient %>
<%= render_login_logo(gradient_id: "loginGradient") %>
<%# Override configured icon %>
<%= render_login_logo(icon: "auth_banner", css_class: "w-full max-w-md") %>
Available Icons
The icon library includes 94+ icons across categories:
- Navigation & UI: arrow_left, arrow_up, arrow_down, chevron_down, close, check, plus, etc.
- Content & Actions: edit, save, trash, bookmark, download, upload, sync, etc.
- Tools & Features: magic, qrcode, receipt, camera, search, filter, etc.
- User & Auth: user, lock, unlock, key, shield_check, sign_in, logout, etc.
- Communication: envelope, bell, share, chat, etc.
- Data & Analytics: chart_bar, calendar, clock, table, etc.
- Files & Folders: folder, folder_open, folder_plus, archive, etc.
- Status & Alerts: spinner, alert_circle, alert_triangle, check_circle, etc.
- Custom: ouroboros (serpent eating its own tail), cherry blossom variants, etc.
Icon Styling
Icons use currentColor by default and inherit the parent's text color:
<div class="text-cyan-400">
<%= render "shared/icons/heart" %> <!-- Will be cyan-400 -->
</div>
Size Classes
Use Tailwind-style sizing classes:
w-3 h-3- 12px (extra small)w-4 h-4- 16px (small, default)w-5 h-5- 20px (medium)w-6 h-6- 24px (large)w-8 h-8- 32px (extra large)
License
All icons are based on Heroicons and distributed under the MIT License. Free for commercial use with no attribution required.
Loading Indicators
The gem provides a comprehensive set of loading indicators for async operations, all theme-aware using CSS custom properties.
Spinners
CSS classes for spinning loaders:
<!-- Basic spinner (border color) -->
<div class="spinner-basic"></div>
<!-- Accent color spinner -->
<div class="spinner-accent"></div>
<!-- Small spinner (16px) -->
<div class="spinner-small"></div>
<!-- Large spinner (48px) -->
<div class="spinner-large"></div>
All spinners use smooth rotation animations and adapt to the current theme.
Progress Bars
Determinate and indeterminate progress indicators:
<!-- Indeterminate progress (animated sliding bar) -->
<div class="progress-bar-container">
<div class="progress-bar-indeterminate"></div>
</div>
<!-- Determinate progress (set width via inline style) -->
<div class="progress-bar-container">
<div class="progress-bar-fill" style="width: 50%"></div>
</div>
Progress bars use theme gradients and smooth animations.
Skeleton Loaders
Placeholder content with shimmer animation:
<!-- Text placeholder -->
<div class="skeleton-text"></div>
<div class="skeleton-text" style="width: 80%"></div>
<!-- Avatar/image placeholder -->
<div class="skeleton-avatar"></div>
Loading States
Common loading state patterns:
<!-- Button loading state -->
<button class="px-4 py-2 bg-accent text-white rounded" disabled>
<div class="spinner-small"></div>
<span>Loading...</span>
</button>
<!-- Card loading state -->
<div class="border rounded-lg p-6">
<div class="flex items-center justify-center">
<div class="spinner-accent"></div>
</div>
<p class="text-center mt-4">Loading content...</p>
</div>
<!-- Full-screen loading overlay -->
<div class="loading-overlay">
<div class="spinner-accent"></div>
</div>
Available CSS Classes
.spinner-basic- Border color spinner (32px).spinner-accent- Accent color spinner (32px).spinner-small- Small spinner (16px).spinner-large- Large spinner (48px).progress-bar-container- Progress bar wrapper.progress-bar-fill- Progress bar fill (set width via style).progress-bar-indeterminate- Animated sliding progress.skeleton-text- Text placeholder with shimmer.skeleton-avatar- Circular avatar placeholder (48px).loading-overlay- Full-screen loading overlay
All loading indicators are included in loading.css and automatically loaded via neon_sakura_stylesheets.
Navigation Bar Component
The gem provides a flexible, configurable navigation bar component that supports multiple positioning modes, dropdown menus, and custom content injection.
Basic Usage
<!-- In your view (under page heading) -->
<%= render "shared/navbar" %>
<!-- In your layout (at top of page) -->
<%= render "shared/navbar" %>
<!-- With custom content (e.g., search form, quick import) -->
<%= render "shared/navbar" do %>
<form class="inline-flex items-center">
<input type="text" placeholder="Search..." class="px-2 py-1">
<button type="submit" class="btn-primary">Go</button>
</form>
<% end %>
Configuration
Configure the navbar in config/initializers/neon_sakura.rb:
NeonSakura.configure do |config|
# Positioning: :none (hidden), :top (in layout), :under_heading (in views)
config.nav_position = :under_heading
# Optional: Add application icon
config.app_icon = "search" # Icon partial name
# Optional: Show search input (future feature)
config.show_search = false
# Navigation links
config.nav_links = [
# Simple link
{
type: "link",
name: "Home",
path: "/",
icon: "home", # Optional
active_paths: ["/", "/dashboard"], # Optional
condition: "user_signed_in?" # Optional
},
# Dropdown menu
{
type: "dropdown",
name: "Tools",
icon: "tools",
items: [
{ name: "Jobs", path: "/jobs", icon: "briefcase" },
{ name: "Health", path: "/health", icon: "heart_pulse" },
{
name: "Metrics",
path: "/metrics",
icon: "chart_bar",
condition: "current_user&.admin?"
}
]
},
# Form button (for logout, etc.)
{
type: "button",
name: "Logout",
path: "/users/sign_out",
icon: "logout",
method: :delete,
condition: "user_signed_in?"
}
]
end
Navigation Positioning Modes
:under_heading (Default)
- Renders navbar in views below page headings
- Used by: Artemis (below page titles)
- Add
<%= render "shared/navbar" %>in individual views
:top
- Renders navbar at top of layout (sticky navigation)
- Used by: prys-m, Mission Control
- Add to layout file (e.g.,
app/views/layouts/application.html.erb)
:none
- Navigation hidden (must be manually rendered)
- Use when you want complete control over navbar placement
Link Configuration Schema
Simple Link
{
type: "link",
name: "Link Name",
path: "/path",
icon: "icon_name", # Optional: icon partial name
active_paths: ["/alt"], # Optional: additional active paths
condition: "ruby_code", # Optional: eval for conditional rendering
target: "_blank", # Optional: link target
aria_label: "Custom label" # Optional: accessibility label
}
Dropdown Menu
{
type: "dropdown",
name: "Menu Name",
icon: "icon_name", # Optional
aria_label: "Menu label", # Optional
items: [
{ name: "Item 1", path: "/path1", icon: "icon1" },
{ name: "Item 2", path: "/path2", icon: "icon2", target: "_blank" },
{ name: "Item 3", path: "/path3", condition: "user_signed_in?" }
]
}
Form Button
{
type: "button",
name: "Button Name",
path: "/path",
icon: "icon_name", # Optional
method: :delete, # :get, :post, :patch, :delete
condition: "ruby_code", # Optional
aria_label: "Button label" # Optional
}
Active State Detection
The navbar automatically highlights the current page link:
- Matches
request.pathagainst linkpath - Checks
active_pathsarray for additional matches - Uses
current_page?(path)helper when available - Applies
nav-activeCSS class (cyan bottom border)
Conditional Links
Use the condition parameter to conditionally render links based on runtime evaluation:
{
type: "link",
name: "Admin Panel",
path: "/admin",
condition: "current_user&.admin?" # Only shown to admins
}
{
type: "link",
name: "Profile",
path: "/profile",
condition: "defined?(user_signed_in?) && user_signed_in?" # Only when authenticated
}
{
type: "link",
name: "Settings",
path: "/settings",
condition: "defined?(settings_path)" # Only if route exists
}
The condition is evaluated as Ruby code in the view context, allowing access to helpers and instance variables.
Custom Content Block
Pass a block to render "shared/navbar" to inject custom HTML between navigation links:
<%= render "shared/navbar" do %>
<!-- Quick Import Form (prys-m example) -->
<form class="inline-flex items-center gap-2" onsubmit="handleQuickImport(event)">
<input type="url"
class="px-3 py-1 bg-gray-800 border border-gray-700 rounded text-white text-sm"
placeholder="Quick Import URL"
required>
<button type="submit" class="btn-primary btn-sm">
<%= render "shared/icons/plus", css_class: "w-4 h-4" %> Import
</button>
</form>
<% end %>
The custom content appears as part of the navbar with proper styling and responsive behavior.
Accessibility
All navigation elements include proper ARIA attributes:
role="navigation"on<nav>elementaria-labelon all links and buttons (auto-generated or custom)aria-haspopupandaria-expandedon dropdown togglesaria-current="page"on active links- Keyboard support (Escape key closes dropdowns)
Styling
Navigation uses the dark theme styles from components.css:
- Cyan links (
text-cyan-300) with hover states (hover:text-cyan-200) - Gray dropdown backgrounds (
bg-gray-800) with borders (border-gray-700) - Active state: white text, bold font, cyan bottom border (
.nav-active) - Smooth transitions on hover and focus
- Focus rings for keyboard navigation (
focus:ring-cyan-500) - Responsive design with flexbox wrapping
- Mobile-friendly touch targets
JavaScript
The navbar includes vanilla JavaScript for dropdown functionality (no dependencies):
- Auto-closes other dropdowns when opening one
- Click-outside detection to close menus
- Escape key support
- Turbo-compatible (works with Turbo page loads)
- No Stimulus required
Include the navbar JavaScript in your application:
<%= javascript_include_tag "neon_sakura/navbar", "data-turbo-track": "reload" %>
Or with importmap:
# config/importmap.rb
pin "neon_sakura/navbar", to: "neon_sakura/navbar.js"
Architecture
This gem is structured as a Rails engine that provides:
- Theming Components: Dark-themed styling for consistent UI across Rails applications
- Reusable UI Elements: Components like navigation, cards, badges, buttons, and tables
- Form Styling: Consistent form element styling
- Layout Templates: Application and error page layouts for consistent page structure
- Icon System: 87+ Heroicons-based SVG icon components (MIT licensed) for common UI elements that can be reused across projects
- Responsive Design: Tailwind-inspired utility classes for responsive layouts
The gem is designed for code reusability, making it possible to maintain consistent UI themes and components across multiple Rails projects.
CSS Architecture
Neon Sakura uses a modular CSS architecture with separate files for themes and utilities.
File Organization
- Themes (
themes/*.css): Color definitions for each theme (purple, green, red) - Utilities (
utilities/*.css): Reusable utility classes (layout, spacing, typography, etc.) - Components (
components.css): UI component styles (cards, navigation, badges, etc.) - Forms (
forms.css): Form element styling - Pagination (
pagy-tailwind.css): Pagination styling
Customizing Themes
Each theme file contains both light and dark variants. To customize:
- Edit the appropriate theme file in
app/assets/stylesheets/themes/ - Update CSS custom properties (e.g.,
--color-accent,--gradient-from) - Test in both light and dark modes
See CLAUDE.md for detailed contribution guidelines.
Configuration
The gem provides several configuration options that can be customized in your Rails application's initializer (config/initializers/neon_sakura.rb):
NeonSakura.configure do |config|
# Application name (used in header, footer, and error pages)
config.app_name = "My Application"
# Show version in header
config.show_version = true
# Show header component
config.show_header = true
# Enable automatic error page routes
config.enable_error_pages = true
# Navigation links for header
config.nav_links = [
{ name: "Home", path: "/" },
{ name: "About", path: "/about" }
]
end
Configuration Options
app_name(String, default:"My Application") - Application name displayed in header, footer, and error pagesshow_version(Boolean, default:true) - Show version information in the headershow_header(Boolean, default:true) - Enable the header componentenable_error_pages(Boolean, default:true) - Automatically mount error page routesnav_links(Array, default:[{ name: "Home", path: "/" }, { name: "About", path: "/about" }]) - Navigation links (see Navigation Bar Component section for full schema)nav_position(Symbol, default::under_heading) - Navigation positioning (:none, :top, :under_heading)app_icon(String, default:nil) - Icon partial name for app brandingshow_search(Boolean, default:false) - Show search input in navbar (future feature)login_logo(Hash, default:{ icon: nil, css_class: "w-12 h-12 sm:w-16 sm:h-16", gradient_id: nil }) - Login page logo configuration (v0.1.6+)icon(String) - Icon name to display on login page (e.g., "artemis_logo", "auth_banner")css_class(String) - CSS classes for sizing the icon (default: responsive 48px-64px)gradient_id(String) - Optional gradient ID for icons that support gradients
default_theme(Hash, default:{ name: "purple", mode: "dark" }) - Default theme to useavailable_themes(Array, default:[{ name: "purple", mode: "dark", label: "Purple Dark" }]) - Available themes for switchingenable_theme_persistence(Boolean, default:true) - Enable localStorage theme persistencetheme_api_endpoint(String, default:nil) - Optional API endpoint for backend theme persistence
Theme System
Neon Sakura includes a comprehensive multi-theme system with 6 built-in themes that support both light and dark modes.
Built-in Themes
The gem provides six professionally designed themes:
| Theme | Name | Mode | Primary Color | Gradient | Best For |
|---|---|---|---|---|---|
| Purple Dark | purple |
dark |
#a855f7 (Purple) | Blue → Purple | Default theme, developer tools, admin panels |
| Purple Light | purple |
light |
#a855f7 (Purple) | Purple → Purple | Light mode alternative, business applications |
| Green Dark | green |
dark |
#10b981 (Emerald) | Green → Cyan | Content-focused apps, reading interfaces |
| Green Light | green |
light |
#009990 (Teal) | Green → Cyan | Clean, professional applications |
| Red Dark | red |
dark |
#ef4444 (Red) | Red → Orange | Bold, energetic applications |
| Red Light | red |
light |
#dc2626 (Red) | Red → Orange | Dynamic, attention-grabbing interfaces |
Theme Configuration
Configure themes in config/initializers/neon_sakura.rb:
NeonSakura.configure do |config|
# Set default theme
config.default_theme = { name: "purple", mode: "dark" }
# Configure available themes for switching
config.available_themes = [
{ name: "green", mode: "light", label: "Green Light" },
{ name: "green", mode: "dark", label: "Green Dark" },
{ name: "purple", mode: "light", label: "Purple Light" },
{ name: "purple", mode: "dark", label: "Purple Dark" },
{ name: "red", mode: "light", label: "Red Light" },
{ name: "red", mode: "dark", label: "Red Dark" }
]
# Enable localStorage persistence (default: true)
config.enable_theme_persistence = true
# Optional: API endpoint for backend persistence
# config.theme_api_endpoint = "/settings/theme"
end
Theme Color Palettes
Each theme defines a complete color system using CSS custom properties:
Purple Dark (Default):
--color-text-primary: #ffffff
--color-background: #111827
--color-surface: #1f2937
--color-accent: #a855f7
--color-border: #374151
Purple Light:
--color-text-primary: #374151
--color-background: #FFFFFF
--color-surface: #f9fafb
--color-accent: #a855f7
--color-border: #e5e7eb
Green Dark:
--color-text-primary: #e2e8f0
--color-background: #0f172a
--color-surface: #1e293b
--color-accent: #10b981
--color-border: #334155
Green Light:
--color-text-primary: #545E75
--color-background: #FFFFFF
--color-surface: #f8f9fa
--color-accent: #009990
--color-border: #dee2e6
Red Dark:
--color-text-primary: #ffffff
--color-background: #111827
--color-surface: #1f2937
--color-accent: #ef4444
--color-border: #374151
Red Light:
--color-text-primary: #374151
--color-background: #FFFFFF
--color-surface: #f9fafb
--color-accent: #dc2626
--color-border: #e5e7eb
Using Themes
Themes are applied via data-theme-name and data-theme-mode attributes on the <html> element:
<!-- Purple Dark (default) -->
<html data-theme-name="purple" data-theme-mode="dark">
<!-- Green Light -->
<html data-theme-name="green" data-theme-mode="light">
The theme switcher JavaScript automatically manages these attributes based on user selection and localStorage persistence.
Theme Switcher Component
Add the theme switcher to your navbar dropdown:
config.nav_links = [
{
type: "dropdown",
name: "Settings",
icon: "cog",
items: [
{ name: "Profile", path: "/profile", icon: "user" },
{ type: "divider" },
{ type: "theme_selector" } # Renders theme list with checkmarks
]
}
]
The theme selector automatically:
- Displays all available themes with icons (sun/moon)
- Shows checkmark next to current theme
- Persists selection to localStorage
- Updates all UI components dynamically
Theme Persistence
localStorage (Default): Theme selection is automatically saved to localStorage and restored on page load.
Backend Persistence (Optional): Configure an API endpoint to save theme preferences to your database:
config.theme_api_endpoint = "/settings/theme"
The theme switcher will send POST requests with:
{
"theme_name": "green",
"theme_mode": "dark"
}
CSS Custom Properties
All colors use CSS custom properties (CSS variables) for dynamic theming:
/* Using theme colors in your CSS */
.my-component {
color: var(--color-text-primary);
background: var(--color-surface);
border: 1px solid var(--color-border);
}
.my-button {
background: linear-gradient(to right, var(--gradient-from), var(--gradient-to));
}
.my-button:hover {
background: linear-gradient(to right, var(--gradient-from-hover), var(--gradient-to-hover));
}
Available CSS variables:
Colors:
--color-text-primary- Primary text color--color-text-secondary- Secondary text color--color-text-muted- Muted/disabled text--color-background- Page background--color-surface- Card/panel background--color-accent- Primary accent color--color-notification- Success/notification color--color-alert- Error/alert color--color-warning- Warning color--color-border- Border color--color-white- Pure white
Gradients:
--gradient-from/--gradient-to- Primary button gradients--gradient-from-hover/--gradient-to-hover- Primary button hover gradients--text-gradient-from/--text-gradient-to- Text gradients for headings--gradient-navbar-from/--gradient-navbar-to- Navbar gradient (accent to notification)--gradient-secondary-blue-from/--gradient-secondary-blue-to- Secondary blue gradient (cyan to blue, all themes)--gradient-secondary-start/--gradient-secondary-mid/--gradient-secondary-end- Alternative purple gradient (purple themes only)
Creating Custom Themes
You can define custom themes by extending the CSS:
/* custom_theme.css */
:root[data-theme-name="custom"][data-theme-mode="dark"] {
--color-text-primary: #your-color;
--color-background: #your-color;
--color-surface: #your-color;
--color-accent: #your-color;
--color-notification: #your-color;
--color-alert: #your-color;
--color-warning: #your-color;
--color-border: #your-color;
--gradient-from: #your-color;
--gradient-to: #your-color;
--gradient-from-hover: #your-color;
--gradient-to-hover: #your-color;
--text-gradient-from: #your-color;
--text-gradient-to: #your-color;
}
Then configure it:
config.available_themes = [
{ name: "custom", mode: "dark", label: "My Custom Theme" },
# ... other themes
]
Header Component Usage
The gem includes a header component that can be used in your layouts by rendering:
<%= render 'shared/header' %>
The header component accepts configuration parameters through Rails initializer settings:
Configuration
To customize the header component, add the following to your Rails application's initializer (config/initializers/neon_sakura.rb):
NeonSakura.configure do |config|
config.app_name = "My Application"
config.show_version = true
config.show_header = true
config.nav_links = [
{ name: "Home", path: "/" },
{ name: "About", path: "/about" }
]
end
To disable the header component completely, set config.show_header = false.
Footer Component Usage
The gem includes a footer component that can be used in your layouts by rendering:
<%= render 'shared/footer' %>
The footer component is dynamic and automatically detects the application name from the Rails configuration or defaults to "Shared Application".
Configuration
To customize the footer component, add the following to your Rails application's initializer (config/initializers/neon_sakura.rb):
NeonSakura.configure do |config|
config.app_name = "My Application"
end
Error Handling
The gem includes an ErrorsController that provides consistent error pages for common HTTP error codes. The controller handles both HTML and JSON responses, making it suitable for both web and API applications.
Supported Error Codes
400- Bad Request401- Unauthorized403- Forbidden404- Not Found406- Not Acceptable (browser compatibility issues)422- Unprocessable Entity500- Internal Server Error503- Service Unavailable
Configuration
Error pages are enabled by default. To configure error page behavior, add the following to your Rails application's initializer (config/initializers/neon_sakura.rb):
NeonSakura.configure do |config|
config.enable_error_pages = true # Set to false to disable error routes
end
Mounting the Engine (Required)
IMPORTANT: You must mount the NeonSakura engine in your application's routes to enable error pages and other features.
Add this to your config/routes.rb file (typically near the top):
# config/routes.rb
Rails.application.routes.draw do
# Mount NeonSakura engine for error pages and other routes
mount NeonSakura::Engine => "/", as: "neon_sakura"
# ... rest of your routes
end
Available Error Routes
After mounting the engine, the following error routes are available when enable_error_pages is true (default):
/400- Bad Request/401- Unauthorized/403- Forbidden/404- Not Found/406- Not Acceptable/422- Unprocessable Entity/500- Internal Server Error/503- Service Unavailable
You can use them in your application by calling the route helpers:
redirect_to neon_sakura.not_found_path
redirect_to neon_sakura.internal_server_error_path
redirect_to neon_sakura.not_acceptable_path
Note: If you prefer to define your own error routes, set config.enable_error_pages = false in your initializer and define custom routes:
# In config/routes.rb
get "/404", to: "errors#not_found", as: :not_found
get "/500", to: "errors#internal_server_error", as: :internal_server_error
# ... other error routes
Configuring Rails Error Pages
To use these error pages in production, configure your config/environments/production.rb:
config.exceptions_app = routes
This will route Rails exceptions to your error controller actions.
Custom Error Messages
You can provide custom error messages and details by passing parameters:
# In your controller
redirect_to not_found_path(message: "The resource you're looking for doesn't exist")
# With additional details
redirect_to unprocessable_entity_path(
message: "Validation failed",
details: { field1: "is required", field2: "is invalid" }
)
API Support
The error controller automatically responds with JSON for API requests:
{
"success": false,
"error": "The page you're looking for doesn't exist.",
"details": {
"field1": "is required",
"field2": "is invalid"
}
}
Customization
To customize the error pages, you can override the views in your application by creating files in app/views/errors/:
app/views/errors/show.html.erb- Main error page templateapp/views/layouts/error.html.erb- Error page layout
The error views use the gem's icon system and styling components for a consistent dark-themed appearance.
Testing
To run the tests:
rake test
To run tests with coverage:
rake test:coverage
Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests.
To install this gem onto your local machine, run bundle exec rake install.
CSS Linting
The gem uses Stylelint with the industry-standard configuration for CSS code quality.
Setup (first time only):
yarn install
Run linting:
yarn lint:css # Check for CSS issues
yarn lint:css:fix # Auto-fix CSS issues
Git hooks: Stylelint runs automatically on git commit to ensure code quality. The pre-commit hook includes:
- RuboCop (Ruby linting)
- Stylelint (CSS linting)
- Brakeman (security scanning)
- Bundle Audit (dependency security)
- Secrets detection
To install git hooks:
./bin/install-hooks
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/trex22/neon_sakura.
License
The gem is available as open source under the terms of the MIT License.
Icon Attribution
Icons are based on Heroicons by Tailwind Labs, also licensed under the MIT License. No attribution required for commercial use.
AI PR Reviewer
This gem includes an AI PR reviewer that helps ensure code quality and adherence to project guidelines. The reviewer uses a comprehensive system prompt to provide feedback that's specific to the neon_sakura gem project.
Review Configuration
The AI reviewer is configured using:
CLAUDE.md- Project documentation and guidelinesbuild-system-prompt.sh- System prompt for AI reviewextract-claude-sections.sh- Script to extract relevant sections from documentation
The AI reviewer ensures code quality and security adherence by running checks before each PR merge.