You've already forked php-flasher
mirror of
https://github.com/php-flasher/php-flasher.git
synced 2026-04-05 12:32:55 +01:00
add neon theme
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* @file PHPFlasher Neon Theme Registration
|
||||||
|
* @description Registers the Neon theme with PHPFlasher
|
||||||
|
* @author yoeunes
|
||||||
|
*/
|
||||||
|
import flasher from '../../index'
|
||||||
|
import { neonTheme } from './neon'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the Neon theme.
|
||||||
|
*
|
||||||
|
* This theme provides elegant notifications with subtle glowing accents
|
||||||
|
* and a sophisticated visual style.
|
||||||
|
*
|
||||||
|
* The registration makes the theme available under the name 'neon'.
|
||||||
|
*
|
||||||
|
* The Neon theme can be used by calling:
|
||||||
|
* ```typescript
|
||||||
|
* flasher.use('theme.neon').success('Your changes have been saved');
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Key features:
|
||||||
|
* - Subtle glowing accents based on notification type
|
||||||
|
* - Floating illuminated circular indicator
|
||||||
|
* - Frosted glass background with blur effect
|
||||||
|
* - Refined typography with Inter font
|
||||||
|
* - Smooth entrance animation with blur transition
|
||||||
|
*/
|
||||||
|
flasher.addTheme('neon', neonTheme)
|
||||||
@@ -0,0 +1,286 @@
|
|||||||
|
/**
|
||||||
|
* @file PHPFlasher Neon Theme Styles
|
||||||
|
* @description CSS styling for elegant notifications with glowing accents
|
||||||
|
* @author yoeunes
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPFlasher - Neon Theme
|
||||||
|
*
|
||||||
|
* Notifications with subtle glowing accents and elegant typography.
|
||||||
|
* Features frosted glass backgrounds and gentle illumination effects.
|
||||||
|
*/
|
||||||
|
.fl-neon {
|
||||||
|
/* Theme variables - Define the visual appearance of Neon notifications */
|
||||||
|
|
||||||
|
/* Base colors and appearance */
|
||||||
|
--neon-bg-light: rgba(255, 255, 255, 0.9); /* Translucent white in light mode */
|
||||||
|
--neon-bg-dark: rgba(15, 23, 42, 0.9); /* Translucent slate in dark mode */
|
||||||
|
--neon-text-light: #334155; /* Slate gray text in light mode */
|
||||||
|
--neon-text-dark: #f1f5f9; /* Light gray text in dark mode */
|
||||||
|
--neon-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); /* Soft, spread shadow */
|
||||||
|
--neon-shadow-dark: 0 8px 30px rgba(0, 0, 0, 0.25); /* Deeper shadow for dark mode */
|
||||||
|
--neon-border-radius: 12px; /* Rounded corners */
|
||||||
|
|
||||||
|
/* Glow colors for different notification types */
|
||||||
|
--neon-success: #10b981; /* Emerald green for success */
|
||||||
|
--neon-info: #3b82f6; /* Blue for info */
|
||||||
|
--neon-warning: #f59e0b; /* Amber for warning */
|
||||||
|
--neon-error: #ef4444; /* Red for error */
|
||||||
|
|
||||||
|
/* Glow and animation properties */
|
||||||
|
--neon-glow-strength: 10px; /* How far the glow extends */
|
||||||
|
--neon-animation-duration: 0.35s; /* Duration for entrance animation */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entrance animation for Neon theme
|
||||||
|
* Combines movement, fade, and blur transitions
|
||||||
|
*/
|
||||||
|
@keyframes neonEntrance {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-15px); /* Start above final position */
|
||||||
|
filter: blur(3px); /* Start blurred */
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0); /* End at natural position */
|
||||||
|
filter: blur(0); /* End with clear focus */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pulsing glow animation for the indicator
|
||||||
|
* Creates a gentle breathing effect for the glow
|
||||||
|
*/
|
||||||
|
@keyframes neonGlow {
|
||||||
|
0%, 100% {
|
||||||
|
filter: drop-shadow(0 0 var(--neon-glow-strength) currentColor); /* Full glow */
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
filter: drop-shadow(0 0 calc(var(--neon-glow-strength) * 0.7) currentColor); /* Reduced glow */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base Neon theme styling
|
||||||
|
*/
|
||||||
|
.fl-neon {
|
||||||
|
background-color: var(--neon-bg-light);
|
||||||
|
color: var(--neon-text-light);
|
||||||
|
border-radius: var(--neon-border-radius);
|
||||||
|
box-shadow: var(--neon-shadow);
|
||||||
|
padding: 14px 18px; /* Comfortable padding */
|
||||||
|
margin: 12px 0; /* Vertical spacing */
|
||||||
|
position: relative;
|
||||||
|
animation: neonEntrance var(--neon-animation-duration) ease-out;
|
||||||
|
font-family: 'Inter', var(--fl-font), sans-serif; /* Prefer Inter font for elegant typography */
|
||||||
|
will-change: transform, opacity, filter; /* Optimize for animation performance */
|
||||||
|
|
||||||
|
/* Frosted glass effect */
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Floating illuminated indicator
|
||||||
|
* Creates a glowing circle that appears to float above the notification
|
||||||
|
*/
|
||||||
|
.fl-icon-box {
|
||||||
|
position: absolute;
|
||||||
|
top: -12px; /* Position above the notification */
|
||||||
|
left: 16px;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 50%; /* Perfectly circular */
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
animation: neonGlow 3s ease-in-out infinite; /* Continuous gentle pulsing */
|
||||||
|
|
||||||
|
/* Semi-transparent circular background */
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
opacity: 0.4; /* Subtle background */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Solid colored center dot */
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1; /* Ensure dot appears above the glow */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content container
|
||||||
|
* Holds message and close button
|
||||||
|
*/
|
||||||
|
.fl-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center; /* Vertically center content */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message styling
|
||||||
|
* Main notification text
|
||||||
|
*/
|
||||||
|
.fl-message {
|
||||||
|
flex: 1; /* Take available space */
|
||||||
|
font-size: 0.9375rem; /* 15px at default font size */
|
||||||
|
line-height: 1.5; /* Comfortable line height */
|
||||||
|
font-weight: 500; /* Medium weight for better readability */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close button styling
|
||||||
|
* Circular button with hover effect
|
||||||
|
*/
|
||||||
|
.fl-close {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
margin-left: 16px;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
border-radius: 50%; /* Circular button */
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: inherit; /* Inherit text color */
|
||||||
|
opacity: 0.6; /* Subtle appearance by default */
|
||||||
|
transition: all 0.2s ease; /* Smooth hover transition */
|
||||||
|
font-size: 1.2rem;
|
||||||
|
flex-shrink: 0; /* Prevent button from shrinking */
|
||||||
|
|
||||||
|
&:hover, &:focus {
|
||||||
|
opacity: 1; /* Full opacity on hover/focus */
|
||||||
|
background-color: rgba(0, 0, 0, 0.06); /* Subtle background on hover */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Progress bar container
|
||||||
|
* Holds the animated progress indicator
|
||||||
|
*/
|
||||||
|
.fl-progress-bar {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
height: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 0 0 var(--neon-border-radius) var(--neon-border-radius); /* Match parent corners */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Progress indicator
|
||||||
|
* Animated by JavaScript to show remaining time
|
||||||
|
*/
|
||||||
|
.fl-progress {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type-specific styling for each notification type
|
||||||
|
* Each type gets its own color for the indicator and progress bar
|
||||||
|
*/
|
||||||
|
&.fl-success {
|
||||||
|
.fl-icon-box {
|
||||||
|
color: var(--neon-success); /* Green glow */
|
||||||
|
&::before { background-color: var(--neon-success); } /* Transparent green circle */
|
||||||
|
&::after { background-color: var(--neon-success); } /* Solid green dot */
|
||||||
|
}
|
||||||
|
.fl-progress { background-color: var(--neon-success); } /* Green progress bar */
|
||||||
|
}
|
||||||
|
|
||||||
|
&.fl-info {
|
||||||
|
.fl-icon-box {
|
||||||
|
color: var(--neon-info); /* Blue glow */
|
||||||
|
&::before { background-color: var(--neon-info); } /* Transparent blue circle */
|
||||||
|
&::after { background-color: var(--neon-info); } /* Solid blue dot */
|
||||||
|
}
|
||||||
|
.fl-progress { background-color: var(--neon-info); } /* Blue progress bar */
|
||||||
|
}
|
||||||
|
|
||||||
|
&.fl-warning {
|
||||||
|
.fl-icon-box {
|
||||||
|
color: var(--neon-warning); /* Amber glow */
|
||||||
|
&::before { background-color: var(--neon-warning); } /* Transparent amber circle */
|
||||||
|
&::after { background-color: var(--neon-warning); } /* Solid amber dot */
|
||||||
|
}
|
||||||
|
.fl-progress { background-color: var(--neon-warning); } /* Amber progress bar */
|
||||||
|
}
|
||||||
|
|
||||||
|
&.fl-error {
|
||||||
|
.fl-icon-box {
|
||||||
|
color: var(--neon-error); /* Red glow */
|
||||||
|
&::before { background-color: var(--neon-error); } /* Transparent red circle */
|
||||||
|
&::after { background-color: var(--neon-error); } /* Solid red dot */
|
||||||
|
}
|
||||||
|
.fl-progress { background-color: var(--neon-error); } /* Red progress bar */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RTL Support
|
||||||
|
* Right-to-left language direction support
|
||||||
|
*/
|
||||||
|
&.fl-rtl {
|
||||||
|
direction: rtl;
|
||||||
|
|
||||||
|
.fl-icon-box {
|
||||||
|
left: auto;
|
||||||
|
right: 16px; /* Move icon to right side */
|
||||||
|
}
|
||||||
|
|
||||||
|
.fl-close {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 16px; /* Swap margins */
|
||||||
|
}
|
||||||
|
|
||||||
|
.fl-progress {
|
||||||
|
transform-origin: right center; /* Animation starts from right */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessibility
|
||||||
|
* Respects reduced motion preferences
|
||||||
|
*/
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
animation: none; /* Disable entrance animation */
|
||||||
|
|
||||||
|
.fl-icon-box {
|
||||||
|
animation: none; /* Disable glow animation */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dark mode support
|
||||||
|
* Different styling when in dark mode
|
||||||
|
*/
|
||||||
|
body.fl-dark .fl-neon,
|
||||||
|
html.fl-dark .fl-neon,
|
||||||
|
.fl-neon.fl-auto-dark {
|
||||||
|
background-color: var(--neon-bg-dark); /* Darker, semi-transparent background */
|
||||||
|
color: var(--neon-text-dark); /* Light text */
|
||||||
|
box-shadow: var(--neon-shadow-dark); /* Stronger shadow */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust hover effect for dark mode
|
||||||
|
* Use white instead of black with appropriate opacity
|
||||||
|
*/
|
||||||
|
.fl-close:hover, .fl-close:focus {
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* @file PHPFlasher Neon Theme Implementation
|
||||||
|
* @description Elegant notifications with subtle glowing accents
|
||||||
|
* @author yoeunes
|
||||||
|
*/
|
||||||
|
import './neon.scss'
|
||||||
|
import type { Envelope } from '../../types'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Neon notification theme for PHPFlasher.
|
||||||
|
*
|
||||||
|
* The Neon theme provides an elegant visual style with:
|
||||||
|
* - Subtle glowing accents based on notification type
|
||||||
|
* - Floating illuminated circular indicator
|
||||||
|
* - Frosted glass background with blur effect
|
||||||
|
* - Refined typography using Inter font
|
||||||
|
* - Smooth entrance animation with blur transition
|
||||||
|
* - Gentle pulsing glow effect on the indicator
|
||||||
|
*
|
||||||
|
* This theme creates a modern, sophisticated appearance with a touch
|
||||||
|
* of futuristic design through its subtle illumination effects.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* import flasher from '@flasher/flasher';
|
||||||
|
* import { neonTheme } from '@flasher/flasher/themes';
|
||||||
|
*
|
||||||
|
* // Register the theme (if not already registered)
|
||||||
|
* flasher.addTheme('neon', neonTheme);
|
||||||
|
*
|
||||||
|
* // Use the theme
|
||||||
|
* flasher.use('theme.neon').success('Your changes have been saved');
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export const neonTheme = {
|
||||||
|
/**
|
||||||
|
* Renders a notification envelope as HTML.
|
||||||
|
*
|
||||||
|
* Creates an elegant notification with a glowing indicator,
|
||||||
|
* message content, close button, and progress bar.
|
||||||
|
*
|
||||||
|
* @param envelope - The notification envelope to render
|
||||||
|
* @returns HTML string representation of the notification
|
||||||
|
*/
|
||||||
|
render: (envelope: Envelope): string => {
|
||||||
|
const { type, message } = envelope
|
||||||
|
|
||||||
|
// Set appropriate ARIA roles based on notification type
|
||||||
|
const isAlert = type === 'error' || type === 'warning'
|
||||||
|
const role = isAlert ? 'alert' : 'status'
|
||||||
|
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="fl-neon fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||||
|
<div class="fl-content">
|
||||||
|
<div class="fl-message">${message}</div>
|
||||||
|
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="fl-progress-bar">
|
||||||
|
<div class="fl-progress"></div>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
},
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user