mirror of
https://github.com/php-flasher/php-flasher.git
synced 2026-03-31 15:07:47 +01:00
update symfony and laravel demos
This commit is contained in:
@@ -10,7 +10,7 @@ return [
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||
Nelmio\SecurityBundle\NelmioSecurityBundle::class => ['all' => true],
|
||||
// Nelmio\SecurityBundle\NelmioSecurityBundle::class => ['all' => true],
|
||||
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||
Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
flasher:
|
||||
# Default notification library (e.g., 'flasher', 'toastr', 'noty', etc.)
|
||||
# themes: flasher, crystal, emerald, sapphire
|
||||
default: theme.amazon
|
||||
default: theme.minimal
|
||||
|
||||
# Path to the main JavaScript file of PHPFlasher
|
||||
main_script: '/vendor/flasher/flasher.min.js'
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
nelmio_security:
|
||||
# prevents framing of the entire site
|
||||
clickjacking:
|
||||
paths:
|
||||
'^/.*': DENY
|
||||
|
||||
# disables content type sniffing for script resources
|
||||
content_type:
|
||||
nosniff: true
|
||||
|
||||
# forces Microsoft's XSS-Protection with
|
||||
# its block mode
|
||||
xss_protection:
|
||||
enabled: true
|
||||
mode_block: true
|
||||
|
||||
# Send a full URL in the `Referer` header when performing a same-origin request,
|
||||
# only send the origin of the document to secure destination (HTTPS->HTTPS),
|
||||
# and send no header to a less secure destination (HTTPS->HTTP).
|
||||
# If `strict-origin-when-cross-origin` is not supported, use `no-referrer` policy,
|
||||
# no referrer information is sent along with requests.
|
||||
referrer_policy:
|
||||
enabled: true
|
||||
policies:
|
||||
- 'no-referrer'
|
||||
- 'strict-origin-when-cross-origin'
|
||||
|
||||
csp:
|
||||
enabled: true
|
||||
|
||||
enforce:
|
||||
script-src:
|
||||
- 'self'
|
||||
# nelmio_security:
|
||||
# # prevents framing of the entire site
|
||||
# clickjacking:
|
||||
# paths:
|
||||
# '^/.*': DENY
|
||||
#
|
||||
# # disables content type sniffing for script resources
|
||||
# content_type:
|
||||
# nosniff: true
|
||||
#
|
||||
# # forces Microsoft's XSS-Protection with
|
||||
# # its block mode
|
||||
# xss_protection:
|
||||
# enabled: true
|
||||
# mode_block: true
|
||||
#
|
||||
# # Send a full URL in the `Referer` header when performing a same-origin request,
|
||||
# # only send the origin of the document to secure destination (HTTPS->HTTPS),
|
||||
# # and send no header to a less secure destination (HTTPS->HTTP).
|
||||
# # If `strict-origin-when-cross-origin` is not supported, use `no-referrer` policy,
|
||||
# # no referrer information is sent along with requests.
|
||||
# referrer_policy:
|
||||
# enabled: true
|
||||
# policies:
|
||||
# - 'no-referrer'
|
||||
# - 'strict-origin-when-cross-origin'
|
||||
#
|
||||
# csp:
|
||||
# enabled: true
|
||||
#
|
||||
# enforce:
|
||||
# script-src:
|
||||
# - 'self'
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const demoForm = document.getElementById('notification-demo-form');
|
||||
|
||||
if (demoForm) {
|
||||
demoForm.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const type = document.getElementById('notification-type').value;
|
||||
const title = document.getElementById('notification-title').value;
|
||||
const message = document.getElementById('notification-message').value;
|
||||
const position = document.getElementById('notification-position').value;
|
||||
const timeout = document.getElementById('notification-timeout').value;
|
||||
|
||||
// Use the PHPFlasher JavaScript API to show the notification
|
||||
window.flasher[type](message, {
|
||||
title: title,
|
||||
position: position,
|
||||
timeout: parseInt(timeout, 10)
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class ExamplesController extends AbstractController
|
||||
{
|
||||
#[Route('/examples', name: 'app_examples')]
|
||||
public function index(): Response
|
||||
{
|
||||
flash()->info('Browse through our examples to see PHPFlasher in action!');
|
||||
|
||||
return $this->render('examples/index.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/examples/form', name: 'app_form_example')]
|
||||
public function formExample(Request $request): Response
|
||||
{
|
||||
if ($request->isMethod('POST')) {
|
||||
$name = $request->request->get('name');
|
||||
$email = $request->request->get('email');
|
||||
|
||||
// Simulate validation
|
||||
$errors = [];
|
||||
|
||||
if (empty($name)) {
|
||||
$errors['name'] = 'Name is required';
|
||||
}
|
||||
|
||||
if (empty($email)) {
|
||||
$errors['email'] = 'Email is required';
|
||||
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$errors['email'] = 'Invalid email format';
|
||||
}
|
||||
|
||||
// Display appropriate notifications
|
||||
if (empty($errors)) {
|
||||
flash()->success('Form submitted successfully! Thank you, ' . $name);
|
||||
} else {
|
||||
foreach ($errors as $field => $message) {
|
||||
flash()->error($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('examples/form.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/examples/ajax', name: 'app_ajax_example')]
|
||||
public function ajaxExample(): Response
|
||||
{
|
||||
return $this->render('examples/ajax.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/examples/ajax/process', name: 'app_ajax_process', methods: ['POST'])]
|
||||
public function ajaxProcess(Request $request): JsonResponse
|
||||
{
|
||||
if (!$request->isXmlHttpRequest()) {
|
||||
return new JsonResponse(['error' => 'AJAX requests only'], 400);
|
||||
}
|
||||
|
||||
$action = $request->request->get('action');
|
||||
$success = mt_rand(0, 10) > 2; // 80% success rate for demo
|
||||
|
||||
if ($success) {
|
||||
switch ($action) {
|
||||
case 'save':
|
||||
flash()->success('Data saved successfully!');
|
||||
break;
|
||||
case 'update':
|
||||
flash()->success('Record updated successfully!');
|
||||
break;
|
||||
case 'delete':
|
||||
flash()->info('Item has been deleted.');
|
||||
break;
|
||||
default:
|
||||
flash()->success('Operation completed successfully!');
|
||||
}
|
||||
|
||||
return new JsonResponse(['success' => true]);
|
||||
} else {
|
||||
// Simulate errors
|
||||
flash()->error('An error occurred while processing your request. Please try again.');
|
||||
return new JsonResponse(['success' => false], 500);
|
||||
}
|
||||
}
|
||||
|
||||
#[Route('/examples/real-world', name: 'app_real_world')]
|
||||
public function realWorldExamples(): Response
|
||||
{
|
||||
return $this->render('examples/real-world.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/examples/real-world/user-registration', name: 'app_example_user_registration')]
|
||||
public function userRegistration(Request $request): Response
|
||||
{
|
||||
if ($request->isMethod('POST')) {
|
||||
// Simulate user registration
|
||||
$username = $request->request->get('username');
|
||||
|
||||
if (!empty($username)) {
|
||||
flash()->option('timeout', 5000)
|
||||
->option('showProgressbar', true)
|
||||
->success('Registration successful! Welcome, ' . $username . '!');
|
||||
|
||||
// Send additional notification about email verification
|
||||
flash()->option('timeout', 8000)
|
||||
->info('A verification email has been sent to your inbox.');
|
||||
} else {
|
||||
flash()->error('Username is required.');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('examples/user-registration.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/examples/real-world/shopping-cart', name: 'app_example_shopping_cart')]
|
||||
public function shoppingCart(): Response
|
||||
{
|
||||
return $this->render('examples/shopping-cart.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/examples/real-world/add-to-cart', name: 'app_add_to_cart', methods: ['POST'])]
|
||||
public function addToCart(Request $request): JsonResponse
|
||||
{
|
||||
if (!$request->isXmlHttpRequest()) {
|
||||
return new JsonResponse(['error' => 'AJAX requests only'], 400);
|
||||
}
|
||||
|
||||
$productId = $request->request->get('product_id');
|
||||
$productName = $request->request->get('product_name', 'Product');
|
||||
|
||||
// Simulate adding to cart
|
||||
flash()->option('position', 'bottom-right')
|
||||
->option('showCloseButton', true)
|
||||
->success($productName . ' added to your cart!');
|
||||
|
||||
return new JsonResponse(['success' => true]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class FeaturesController extends AbstractController
|
||||
{
|
||||
#[Route('/features', name: 'app_features')]
|
||||
public function index(): Response
|
||||
{
|
||||
// Demonstrate a few different notification types
|
||||
flash()->success('Explore the features of PHPFlasher!');
|
||||
flash()->option('timeout', 8000)
|
||||
->info('Click on the links to see each feature in action.');
|
||||
|
||||
return $this->render('features/index.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/features/types', name: 'app_types')]
|
||||
public function types(): Response
|
||||
{
|
||||
// Demonstrate different notification types
|
||||
flash()->success('This is a success notification!');
|
||||
flash()->info('This is an info notification!');
|
||||
flash()->warning('This is a warning notification!');
|
||||
flash()->error('This is an error notification!');
|
||||
|
||||
return $this->render('features/types.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/features/positions', name: 'app_positions')]
|
||||
public function positions(): Response
|
||||
{
|
||||
// Notifications with different positions
|
||||
flash()->option('position', 'top-right')->success('This notification appears in the top-right corner!');
|
||||
|
||||
return $this->render('features/positions.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/features/options', name: 'app_options')]
|
||||
public function options(): Response
|
||||
{
|
||||
// Notification with custom options
|
||||
flash()->option('timeout', 8000)
|
||||
->option('position', 'bottom-center')
|
||||
->option('showProgressbar', true)
|
||||
->success('This notification has custom options!');
|
||||
|
||||
return $this->render('features/options.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/features/plugins', name: 'app_plugins')]
|
||||
public function plugins(): Response
|
||||
{
|
||||
// Plugin examples
|
||||
flash()->addSuccess('This shows how PHPFlasher can be extended with plugins!');
|
||||
|
||||
return $this->render('features/plugins.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/features/presets', name: 'app_presets')]
|
||||
public function presets(): Response
|
||||
{
|
||||
// Example of using presets
|
||||
flash()->preset('profile.updated')
|
||||
->success('Your profile has been updated successfully!');
|
||||
|
||||
flash()->preset('item.deleted')
|
||||
->info('The item has been deleted.');
|
||||
|
||||
return $this->render('features/presets.html.twig');
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ declare(strict_types=1);
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
@@ -13,77 +15,68 @@ class HomeController extends AbstractController
|
||||
#[Route('/', name: 'app_home')]
|
||||
public function index(): Response
|
||||
{
|
||||
$themes = [
|
||||
// 'flasher',
|
||||
// 'amber',
|
||||
// 'sapphire',
|
||||
// 'crystal',
|
||||
|
||||
// 'emerald',
|
||||
// 'ruby',
|
||||
// 'onyx',
|
||||
|
||||
// 'jade',
|
||||
// 'aurora',
|
||||
// 'neon',
|
||||
// 'minimal',
|
||||
|
||||
// 'material',
|
||||
// 'google',
|
||||
|
||||
// 'ios',
|
||||
// 'slack',
|
||||
// 'facebook',
|
||||
// 'amazon',
|
||||
];
|
||||
|
||||
$positions = [
|
||||
// 'top-left',
|
||||
// 'top-right',
|
||||
// 'bottom-left',
|
||||
// 'bottom-right',
|
||||
// 'top-center',
|
||||
// 'bottom-center',
|
||||
// 'center-left',
|
||||
// 'center-right',
|
||||
// 'center-center',
|
||||
];
|
||||
|
||||
$messages = [
|
||||
'info' => 'Welcome back!',
|
||||
'warning' => 'Are you sure you want to proceed?',
|
||||
'error' => 'Oops! Something went wrong!',
|
||||
'success' => 'Data has been saved successfully!',
|
||||
];
|
||||
|
||||
// foreach ($themes as $index => $theme) {
|
||||
foreach ($messages as $type => $message) {
|
||||
// $position = $positions[$index % \count($positions)];
|
||||
|
||||
// $message = \sprintf('%s: %s', $theme, $message);
|
||||
|
||||
flash()
|
||||
// ->use("theme.$theme")
|
||||
// ->option('position', $position)
|
||||
->$type($message);
|
||||
}
|
||||
// }
|
||||
|
||||
$plugins = [
|
||||
// 'noty',
|
||||
// 'notyf',
|
||||
// 'sweetalert',
|
||||
// 'toastr',
|
||||
];
|
||||
|
||||
foreach ($plugins as $plugin) {
|
||||
foreach ($messages as $type => $message) {
|
||||
flash()
|
||||
->use($plugin)
|
||||
->$type($message);
|
||||
}
|
||||
}
|
||||
// Welcome notification
|
||||
flash()->option('timeout', 10000)
|
||||
->info('Welcome to the PHPFlasher Demo! 👋 Explore different features using the navigation.');
|
||||
|
||||
return $this->render('home/index.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/installation', name: 'app_installation')]
|
||||
public function installation(): Response
|
||||
{
|
||||
return $this->render('home/installation.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/basic-usage', name: 'app_basic_usage')]
|
||||
public function basicUsage(): Response
|
||||
{
|
||||
// Basic success notification
|
||||
flash()->success('This is a success notification!');
|
||||
|
||||
return $this->render('home/basic-usage.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/playground', name: 'app_playground')]
|
||||
public function playground(): Response
|
||||
{
|
||||
return $this->render('home/playground.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/theme-builder', name: 'app_theme_builder')]
|
||||
public function themeBuilder(): Response
|
||||
{
|
||||
return $this->render('home/theme-builder.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/show-notification', name: 'app_show_notification', methods: ['POST'])]
|
||||
public function showNotification(Request $request): JsonResponse
|
||||
{
|
||||
if (!$request->isXmlHttpRequest()) {
|
||||
return new JsonResponse(['error' => 'AJAX requests only'], 400);
|
||||
}
|
||||
|
||||
$data = json_decode($request->getContent(), true);
|
||||
$type = $data['type'] ?? 'info';
|
||||
$message = $data['message'] ?? 'This is a notification!';
|
||||
|
||||
// Create notification based on type
|
||||
switch ($type) {
|
||||
case 'success':
|
||||
flash()->success($message);
|
||||
break;
|
||||
case 'error':
|
||||
flash()->error($message);
|
||||
break;
|
||||
case 'warning':
|
||||
flash()->warning($message);
|
||||
break;
|
||||
case 'info':
|
||||
default:
|
||||
flash()->info($message);
|
||||
break;
|
||||
}
|
||||
|
||||
return new JsonResponse(['status' => 'success']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class IntegrationController extends AbstractController
|
||||
{
|
||||
#[Route('/integration/api', name: 'app_integration_api')]
|
||||
public function apiIntegration(): Response
|
||||
{
|
||||
// Example of how PHPFlasher can work with API responses
|
||||
flash()->option('position', 'bottom-center')
|
||||
->success('API request processed successfully!');
|
||||
|
||||
return $this->render('integration/api.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/integration/translation', name: 'app_integration_translation')]
|
||||
public function translationIntegration(): Response
|
||||
{
|
||||
// Example using translation integration
|
||||
flash()->option('translate', true)
|
||||
->success('messages.success.operation_completed');
|
||||
|
||||
return $this->render('integration/translation.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/integration/symfony-flashbag', name: 'app_integration_flashbag')]
|
||||
public function symfonyFlashbag(): Response
|
||||
{
|
||||
// Add message to Symfony flash bag to demonstrate integration
|
||||
$this->addFlash('success', 'This message was added using Symfony\'s addFlash method!');
|
||||
$this->addFlash('error', 'This error was added using Symfony\'s addFlash method!');
|
||||
$this->addFlash('warning', 'This warning was added using Symfony\'s addFlash method!');
|
||||
|
||||
return $this->render('integration/flashbag.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/integration/custom-templates', name: 'app_integration_templates')]
|
||||
public function customTemplates(): Response
|
||||
{
|
||||
// Example using custom templates
|
||||
flash()->option('template', 'custom_template')
|
||||
->success('This notification uses a custom template!');
|
||||
|
||||
return $this->render('integration/custom-templates.html.twig');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class ThemesController extends AbstractController
|
||||
{
|
||||
#[Route('/themes', name: 'app_themes')]
|
||||
public function index(): Response
|
||||
{
|
||||
// Show default theme notification
|
||||
flash()->success('This is a notification with the default theme!');
|
||||
|
||||
return $this->render('themes/index.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/themes/flasher', name: 'app_theme_flasher')]
|
||||
public function flasherTheme(): Response
|
||||
{
|
||||
// Using the Flasher theme
|
||||
flash()->option('theme', 'flasher')
|
||||
->success('This notification uses the Flasher theme!');
|
||||
|
||||
return $this->render('themes/flasher.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/themes/crystal', name: 'app_theme_crystal')]
|
||||
public function crystalTheme(): Response
|
||||
{
|
||||
// Using the Crystal theme
|
||||
flash()->option('theme', 'crystal')
|
||||
->success('This notification uses the Crystal theme!');
|
||||
|
||||
return $this->render('themes/crystal.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/themes/emerald', name: 'app_theme_emerald')]
|
||||
public function emeraldTheme(): Response
|
||||
{
|
||||
// Using the Emerald theme
|
||||
flash()->option('theme', 'emerald')
|
||||
->success('This notification uses the Emerald theme!');
|
||||
|
||||
return $this->render('themes/emerald.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/themes/sapphire', name: 'app_theme_sapphire')]
|
||||
public function sapphireTheme(): Response
|
||||
{
|
||||
// Using the Sapphire theme
|
||||
flash()->option('theme', 'sapphire')
|
||||
->success('This notification uses the Sapphire theme!');
|
||||
|
||||
return $this->render('themes/sapphire.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/themes/amazon', name: 'app_theme_amazon')]
|
||||
public function amazonTheme(): Response
|
||||
{
|
||||
// Using the Amazon theme
|
||||
flash()->option('theme', 'amazon')
|
||||
->success('This notification uses the Amazon theme!');
|
||||
|
||||
return $this->render('themes/amazon.html.twig');
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,231 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{% block title %}Welcome!{% endblock %}</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}PHPFlasher Demo{% endblock %}</title>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{# Tailwind CSS v4 CDN #}
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||
|
||||
{% block stylesheets %}{% endblock %}
|
||||
{% block javascripts %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}{% endblock %}
|
||||
</body>
|
||||
{# Prism.js for syntax highlighting #}
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/toolbar/prism-toolbar.min.css">
|
||||
|
||||
{# Custom styles using Tailwind #}
|
||||
<script type="text/tailwindcss">
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-4 py-2 rounded-md font-medium transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-opacity-50;
|
||||
}
|
||||
.btn-primary {
|
||||
@apply bg-indigo-600 text-white hover:bg-indigo-700 focus:ring-indigo-500;
|
||||
}
|
||||
.btn-success {
|
||||
@apply bg-emerald-600 text-white hover:bg-emerald-700 focus:ring-emerald-500;
|
||||
}
|
||||
.btn-danger {
|
||||
@apply bg-rose-600 text-white hover:bg-rose-700 focus:ring-rose-500;
|
||||
}
|
||||
.btn-warning {
|
||||
@apply bg-amber-500 text-white hover:bg-amber-600 focus:ring-amber-400;
|
||||
}
|
||||
.btn-info {
|
||||
@apply bg-sky-500 text-white hover:bg-sky-600 focus:ring-sky-400;
|
||||
}
|
||||
.btn-outline {
|
||||
@apply border border-gray-300 text-gray-700 bg-white hover:bg-gray-50 focus:ring-indigo-500;
|
||||
}
|
||||
.code-block {
|
||||
@apply rounded-lg overflow-hidden shadow-lg my-6;
|
||||
}
|
||||
.code-header {
|
||||
@apply bg-gray-800 text-gray-200 px-4 py-2 flex justify-between items-center;
|
||||
}
|
||||
.theme-card {
|
||||
@apply rounded-lg overflow-hidden bg-white shadow-md hover:shadow-lg transition duration-300;
|
||||
}
|
||||
.theme-preview {
|
||||
@apply h-32 flex items-center justify-center;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{% block stylesheets %}{% endblock %}
|
||||
</head>
|
||||
<body class="bg-gray-50 antialiased text-gray-900 min-h-screen flex flex-col">
|
||||
<header class="bg-indigo-600 text-white shadow-md">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between items-center py-4">
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="flex items-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||
</svg>
|
||||
<span class="ml-2 text-2xl font-bold">PHPFlasher</span>
|
||||
</div>
|
||||
<span class="hidden md:inline text-indigo-200">Beautiful Notifications for Your PHP Applications</span>
|
||||
</div>
|
||||
<div class="hidden md:flex space-x-4">
|
||||
<a href="https://github.com/php-flasher/flasher" class="text-indigo-100 hover:text-white transition flex items-center" target="_blank">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
||||
</svg>
|
||||
GitHub
|
||||
</a>
|
||||
<a href="https://php-flasher.io" class="text-indigo-100 hover:text-white transition flex items-center" target="_blank">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
|
||||
</svg>
|
||||
Documentation
|
||||
</a>
|
||||
</div>
|
||||
<button id="mobile-menu-button" class="md:hidden text-white">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div id="mobile-menu" class="hidden md:hidden bg-indigo-700 text-white">
|
||||
<div class="px-4 pt-2 pb-4 space-y-3">
|
||||
<a href="{{ path('app_home') }}" class="block py-2 hover:bg-indigo-600 rounded px-2">Home</a>
|
||||
<a href="{{ path('app_features') }}" class="block py-2 hover:bg-indigo-600 rounded px-2">Features</a>
|
||||
<a href="{{ path('app_themes') }}" class="block py-2 hover:bg-indigo-600 rounded px-2">Themes</a>
|
||||
<a href="{{ path('app_examples') }}" class="block py-2 hover:bg-indigo-600 rounded px-2">Examples</a>
|
||||
<a href="{{ path('app_playground') }}" class="block py-2 hover:bg-indigo-600 rounded px-2">Playground</a>
|
||||
<a href="https://github.com/php-flasher/flasher" class="block py-2 hover:bg-indigo-600 rounded px-2">GitHub</a>
|
||||
<a href="https://php-flasher.io" class="block py-2 hover:bg-indigo-600 rounded px-2">Documentation</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-1">
|
||||
<aside class="hidden md:block bg-white w-64 border-r border-gray-200 shadow-sm">
|
||||
<div class="p-6 border-b border-gray-200">
|
||||
<h2 class="text-lg font-semibold text-gray-800">Navigation</h2>
|
||||
<p class="text-sm text-gray-500 mt-1">Explore PHPFlasher</p>
|
||||
</div>
|
||||
<nav class="py-4">
|
||||
<div class="px-6 py-2 text-xs font-semibold text-gray-500 uppercase tracking-wider">
|
||||
Getting Started
|
||||
</div>
|
||||
<a href="{{ path('app_home') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_home' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Home
|
||||
</a>
|
||||
<a href="{{ path('app_installation') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_installation' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Installation
|
||||
</a>
|
||||
<a href="{{ path('app_basic_usage') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_basic_usage' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Basic Usage
|
||||
</a>
|
||||
|
||||
<div class="px-6 py-2 mt-4 text-xs font-semibold text-gray-500 uppercase tracking-wider">
|
||||
Features
|
||||
</div>
|
||||
<a href="{{ path('app_types') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_types' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Notification Types
|
||||
</a>
|
||||
<a href="{{ path('app_positions') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_positions' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Positions
|
||||
</a>
|
||||
<a href="{{ path('app_themes') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_themes' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Themes
|
||||
</a>
|
||||
<a href="{{ path('app_options') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_options' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Options & Configuration
|
||||
</a>
|
||||
<a href="{{ path('app_plugins') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_plugins' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Plugins
|
||||
</a>
|
||||
|
||||
<div class="px-6 py-2 mt-4 text-xs font-semibold text-gray-500 uppercase tracking-wider">
|
||||
Examples
|
||||
</div>
|
||||
<a href="{{ path('app_form_example') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_form_example' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Form Validation
|
||||
</a>
|
||||
<a href="{{ path('app_ajax_example') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_ajax_example' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
AJAX Requests
|
||||
</a>
|
||||
<a href="{{ path('app_presets') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_presets' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Presets
|
||||
</a>
|
||||
<a href="{{ path('app_real_world') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_real_world' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Real-World Examples
|
||||
</a>
|
||||
|
||||
<div class="px-6 py-2 mt-4 text-xs font-semibold text-gray-500 uppercase tracking-wider">
|
||||
Interactive
|
||||
</div>
|
||||
<a href="{{ path('app_playground') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_playground' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Interactive Playground
|
||||
</a>
|
||||
<a href="{{ path('app_theme_builder') }}" class="block px-6 py-2 text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 {% if app.request.get('_route') == 'app_theme_builder' %}bg-indigo-50 text-indigo-700 border-r-4 border-indigo-500{% endif %}">
|
||||
Theme Builder
|
||||
</a>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<main class="flex-1 overflow-x-hidden">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div class="mb-6">
|
||||
<h1 class="text-3xl font-bold text-gray-900">{% block page_title %}Welcome to PHPFlasher{% endblock %}</h1>
|
||||
<p class="mt-2 text-lg text-gray-600">{% block page_subtitle %}A powerful notification system for PHP applications{% endblock %}</p>
|
||||
</div>
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="bg-white border-t border-gray-200 mt-auto">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
|
||||
<div class="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0">
|
||||
<div class="text-center md:text-left">
|
||||
<p class="text-gray-500">
|
||||
© {{ "now"|date("Y") }} PHPFlasher. Made with ❤️ by <a href="https://github.com/yoeunes" class="text-indigo-600 hover:text-indigo-500">Younes ENNAJI</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex space-x-6">
|
||||
<a href="https://github.com/php-flasher/flasher" class="text-gray-500 hover:text-gray-700">
|
||||
<span class="sr-only">GitHub</span>
|
||||
<svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="https://php-flasher.io" class="text-gray-500 hover:text-gray-700">
|
||||
<span class="sr-only">Website</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{# Prism.js for syntax highlighting #}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/toolbar/prism-toolbar.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js"></script>
|
||||
|
||||
{# Mobile menu toggle script #}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const mobileMenuButton = document.getElementById('mobile-menu-button');
|
||||
const mobileMenu = document.getElementById('mobile-menu');
|
||||
|
||||
if (mobileMenuButton && mobileMenu) {
|
||||
mobileMenuButton.addEventListener('click', function() {
|
||||
mobileMenu.classList.toggle('hidden');
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{% block javascripts %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}PHPFlasher - Notification Positions{% endblock %}
|
||||
|
||||
{% block page_title %}Notification Positions{% endblock %}
|
||||
{% block page_subtitle %}Control where your notifications appear on the screen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden mb-8">
|
||||
<div class="p-6">
|
||||
<h2 class="text-xl font-bold mb-4">Available Positions</h2>
|
||||
<p class="text-gray-600 mb-6">
|
||||
PHPFlasher allows you to position your notifications in different areas of the screen.
|
||||
You can choose from 9 different positions to best fit your design and user experience needs.
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
|
||||
<div class="relative h-72 bg-gray-100 rounded-lg overflow-hidden border border-gray-200">
|
||||
<div class="absolute top-2 left-2 bg-indigo-100 text-indigo-800 px-3 py-1 rounded-lg text-sm">top-left</div>
|
||||
<div class="absolute top-2 right-2 bg-white shadow-md p-3 rounded w-3/4">
|
||||
<div class="h-2 w-12 bg-indigo-500 mb-2 rounded"></div>
|
||||
<div class="h-2 w-20 bg-gray-300 mb-2 rounded"></div>
|
||||
<div class="h-2 w-16 bg-gray-300 rounded"></div>
|
||||
</div>
|
||||
<button class="absolute bottom-4 left-1/2 transform -translate-x-1/2 btn btn-primary notification-position" data-position="top-left">
|
||||
Show Notification
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="relative h-72 bg-gray-100 rounded-lg overflow-hidden border border-gray-200">
|
||||
<div class="absolute top-2 left-1/2 transform -translate-x-1/2 bg-indigo-100 text-indigo-800 px-3 py-1 rounded-lg text-sm">top-center</div>
|
||||
<div class="absolute top-2 left-1/2 transform -translate-x-1/2 bg-white shadow-md p-3 rounded w-3/4">
|
||||
<div class="h-2 w-12 bg-indigo-500 mb-2 rounded"></div>
|
||||
<div class="h-2 w-20 bg-gray-300 mb-2 rounded"></div>
|
||||
<div class="h-2 w-16 bg-gray-300 rounded"></div>
|
||||
</div>
|
||||
<button class="absolute bottom-4 left-1/2 transform -translate-x-1/2 btn btn-primary notification-position" data-position="top-center">
|
||||
Show Notification
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="relative h-72 bg-gray-100 rounded-lg overflow-hidden border border-gray-200">
|
||||
<div class="absolute top-2 right-2 bg-indigo-100 text-indigo-800 px-3 py-1 rounded-lg text-sm">top-right</div>
|
||||
<div class="absolute top-2 right-2 bg-white shadow-md p-3 rounded w-3/4">
|
||||
<div class="h-2 w-12 bg-indigo-500 mb-2 rounded"></div>
|
||||
<div class="h-2 w-20 bg-gray-300 mb-2 rounded"></div>
|
||||
<div class="h-2 w-16 bg-gray-300 rounded"></div>
|
||||
</div>
|
||||
<button class="absolute bottom-4 left-1/2 transform -translate-x-1/2 btn btn-primary notification-position" data-position="top-right">
|
||||
Show Notification
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="relative h-72 bg-gray-100 rounded-lg overflow-hidden border border-gray-200">
|
||||
<div class="absolute top-1/2 left-2 transform -translate-y-1/2 bg-indigo-100 text-indigo-800 px-3 py-1 rounded-lg text-sm">center-left</div>
|
||||
<div class="absolute top-1/2 left-2 transform -translate-y-1/2 bg-white shadow-md p-3 rounded w-3/4">
|
||||
<div class="h-2 w-12 bg-indigo-500 mb-2 rounded"></div>
|
||||
<div class="h-2 w-20 bg-gray-300 mb-2 rounded"></div>
|
||||
<div class="h-2 w-16 bg-gray-300 rounded"></div>
|
||||
</div>
|
||||
<button class="absolute bottom-4 left-1/2 transform -translate-x-1/2 btn btn-primary notification-position" data-position="center-left">
|
||||
Show Notification
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="relative h-72 bg-gray-100 rounded-lg overflow-hidden border border-gray-200">
|
||||
<div class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-indigo-100 text-indigo-800 px-3 py-1 rounded-lg text-sm">center</div>
|
||||
<div class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white shadow-md p-3 rounded w-3/4">
|
||||
<div class="h-2 w-12 bg-indigo-500 mb-2 rounded"></div>
|
||||
<div class="h-2 w-20 bg-gray-300 mb-2 rounded"></div>
|
||||
<div class="h-2 w-16 bg-gray-300 rounded"></div>
|
||||
</div>
|
||||
<button class="absolute bottom-4 left-1/2 transform -translate-x-1/2 btn btn-primary notification-position" data-position="center">
|
||||
Show Notification
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="relative h-72 bg-gray-100 rounded-lg overflow-hidden border border-gray-200">
|
||||
<div class="absolute top-1/2 right-2 transform -translate-y-1/2 bg-indigo-100 text-indigo-800 px-3 py-1 rounded-lg text-sm">center-right</div>
|
||||
<div class="absolute top-1/2 right-2 transform -translate-y-1/2 bg-white shadow-md p-3 rounded w-3/4">
|
||||
<div class="h-2 w-12 bg-indigo-500 mb-2 rounded"></div>
|
||||
<div class="h-2 w-20 bg-gray-300 mb-2 rounded"></div>
|
||||
<div class="h-2 w-16 bg-gray-300 rounded"></div>
|
||||
</div>
|
||||
<button class="absolute bottom-4 left-1/2 transform -translate-x-1/2 btn btn-primary notification-position" data-position="center-right">
|
||||
Show Notification
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="relative h-72 bg-gray-100 rounded-lg overflow-hidden border border-gray-200">
|
||||
<div class="absolute bottom-2 left-2 bg-indigo-100 text-indigo-800 px-3 py-1 rounded-lg text-sm">bottom-left</div>
|
||||
<div class="absolute bottom-10 left-2 bg-white shadow-md p-3 rounded w-3/4">
|
||||
<div class="h-2 w-12 bg-indigo-500 mb-2 rounded"></div>
|
||||
<div class="h-2 w-20 bg-gray-300 mb-2 rounded"></div>
|
||||
<div class="h-2 w-16 bg-gray-300 rounded"></div>
|
||||
</div>
|
||||
<button class="absolute bottom-4 left-1/2 transform -translate-x-1/2 btn btn-primary notification-position" data-position="bottom-left">
|
||||
Show Notification
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="relative h-72 bg-gray-100 rounded-lg overflow-hidden border border-gray-200">
|
||||
<div class="absolute bottom-2 left-1/2 transform -translate-x-1/2 bg-indigo-100 text-indigo-800 px-3 py-1 rounded-lg text-sm">bottom-center</div>
|
||||
<div class="absolute bottom-10 left-1/2 transform -translate-x-1/2 bg-white shadow-md p-3 rounded w-3/4">
|
||||
<div class="h-2 w-12 bg-indigo-500 mb-2 rounded"></div>
|
||||
<div class="h-2 w-20 bg-gray-300 mb-2 rounded"></div>
|
||||
<div class="h-2 w-16 bg-gray-300 rounded"></div>
|
||||
</div>
|
||||
<button class="absolute bottom-4 left-1/2 transform -translate-x-1/2 btn btn-primary notification-position" data-position="bottom-center">
|
||||
Show Notification
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="relative h-72 bg-gray-100 rounded-lg overflow-hidden border border-gray-200">
|
||||
<div class="absolute bottom-2 right-2 bg-indigo-100 text-indigo-800 px-3 py-1 rounded-lg text-sm">bottom-right</div>
|
||||
<div class="absolute bottom-10 right-2 bg-white shadow-md p-3 rounded w-3/4">
|
||||
<div class="h-2 w-12 bg-indigo-500 mb-2 rounded"></div>
|
||||
<div class="h-2 w-20 bg-gray-300 mb-2 rounded"></div>
|
||||
<div class="h-2 w-16 bg-gray-300 rounded"></div>
|
||||
</div>
|
||||
<button class="absolute bottom-4 left-1/2 transform -translate-x-1/2 btn btn-primary notification-position" data-position="bottom-right">
|
||||
Show Notification
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden mb-8">
|
||||
<div class="p-6">
|
||||
<h2 class="text-xl font-bold mb-4">Setting Positions in Code</h2>
|
||||
<p class="text-gray-600 mb-4">
|
||||
You can set the position of notifications in your PHP code using the <code>option()</code> method:
|
||||
</p>
|
||||
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>PHP</span>
|
||||
</div>
|
||||
<pre><code class="language-php">// Top-right position (default)
|
||||
flash()->success('Your changes have been saved.');
|
||||
|
||||
// Bottom-left position
|
||||
flash()->option('position', 'bottom-left')
|
||||
->success('Your changes have been saved.');
|
||||
|
||||
// Top-center position
|
||||
flash()->option('position', 'top-center')
|
||||
->info('You have 3 unread messages.');
|
||||
|
||||
// Center position (middle of the screen)
|
||||
flash()->option('position', 'center')
|
||||
->warning('Your session will expire in 1 minute.');</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden">
|
||||
<div class="p-6">
|
||||
<h2 class="text-xl font-bold mb-4">Global Position Configuration</h2>
|
||||
<p class="text-gray-600 mb-4">
|
||||
You can set a default position for all notifications in your configuration file:
|
||||
</p>
|
||||
|
||||
<div class="code-block mb-6">
|
||||
<div class="code-header">
|
||||
<span>YAML</span>
|
||||
</div>
|
||||
<pre><code class="language-yaml"># config/packages/flasher.yaml
|
||||
flasher:
|
||||
options:
|
||||
position: 'top-right' # Default position for all notifications</code></pre>
|
||||
</div>
|
||||
|
||||
<p class="text-gray-600 mb-4">
|
||||
Or you can set specific positions for different themes:
|
||||
</p>
|
||||
|
||||
<div class="code-block mb-6">
|
||||
<div class="code-header">
|
||||
<span>YAML</span>
|
||||
</div>
|
||||
<pre><code class="language-yaml"># config/packages/flasher.yaml
|
||||
flasher:
|
||||
themes:
|
||||
amazon:
|
||||
options:
|
||||
position: 'bottom-right'
|
||||
|
||||
sapphire:
|
||||
options:
|
||||
position: 'top-center'</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center">
|
||||
<a href="{{ path('app_themes') }}" class="btn btn-primary">
|
||||
Explore Themes
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const positionButtons = document.querySelectorAll('.notification-position');
|
||||
|
||||
positionButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const position = this.getAttribute('data-position');
|
||||
|
||||
// Send AJAX request to show notification
|
||||
fetch('{{ path('app_show_notification') }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
type: 'success',
|
||||
message: 'This notification is at the ' + position + ' position!',
|
||||
options: {
|
||||
position: position
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,220 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}PHPFlasher - Notification Types{% endblock %}
|
||||
|
||||
{% block page_title %}Notification Types{% endblock %}
|
||||
{% block page_subtitle %}Display different notification types to communicate various messages{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden mb-8">
|
||||
<div class="p-6">
|
||||
<h2 class="text-xl font-bold mb-4">Available Notification Types</h2>
|
||||
<p class="text-gray-600 mb-6">
|
||||
PHPFlasher provides four primary notification types to communicate different types of messages to your users.
|
||||
Each type has a distinct visual style to clearly convey the nature of the message.
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
|
||||
<div class="border border-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow">
|
||||
<div class="flex items-center mb-3">
|
||||
<div class="bg-emerald-100 p-2 rounded-md mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-emerald-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-lg font-semibold">Success</h3>
|
||||
</div>
|
||||
<p class="text-gray-600 mb-3">
|
||||
Used for positive feedback when an action has been completed successfully.
|
||||
</p>
|
||||
<div class="code-block mb-3">
|
||||
<div class="code-header">
|
||||
<span>PHP</span>
|
||||
</div>
|
||||
<pre><code class="language-php">flash()->success('Your profile has been updated successfully!');</code></pre>
|
||||
</div>
|
||||
<button class="btn btn-success w-full notification-demo" data-type="success" data-message="This is a success notification!">
|
||||
Show Success Notification
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="border border-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow">
|
||||
<div class="flex items-center mb-3">
|
||||
<div class="bg-rose-100 p-2 rounded-md mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-rose-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-lg font-semibold">Error</h3>
|
||||
</div>
|
||||
<p class="text-gray-600 mb-3">
|
||||
Used to alert users about errors or problems that need attention.
|
||||
</p>
|
||||
<div class="code-block mb-3">
|
||||
<div class="code-header">
|
||||
<span>PHP</span>
|
||||
</div>
|
||||
<pre><code class="language-php">flash()->error('An error occurred while processing your request.');</code></pre>
|
||||
</div>
|
||||
<button class="btn btn-danger w-full notification-demo" data-type="error" data-message="This is an error notification!">
|
||||
Show Error Notification
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="border border-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow">
|
||||
<div class="flex items-center mb-3">
|
||||
<div class="bg-amber-100 p-2 rounded-md mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-amber-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-lg font-semibold">Warning</h3>
|
||||
</div>
|
||||
<p class="text-gray-600 mb-3">
|
||||
Used to inform users about potential issues or actions they should be aware of.
|
||||
</p>
|
||||
<div class="code-block mb-3">
|
||||
<div class="code-header">
|
||||
<span>PHP</span>
|
||||
</div>
|
||||
<pre><code class="language-php">flash()->warning('Your subscription will expire in 3 days.');</code></pre>
|
||||
</div>
|
||||
<button class="btn btn-warning w-full notification-demo" data-type="warning" data-message="This is a warning notification!">
|
||||
Show Warning Notification
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="border border-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow">
|
||||
<div class="flex items-center mb-3">
|
||||
<div class="bg-sky-100 p-2 rounded-md mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-sky-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-lg font-semibold">Info</h3>
|
||||
</div>
|
||||
<p class="text-gray-600 mb-3">
|
||||
Used to provide neutral information or updates to users.
|
||||
</p>
|
||||
<div class="code-block mb-3">
|
||||
<div class="code-header">
|
||||
<span>PHP</span>
|
||||
</div>
|
||||
<pre><code class="language-php">flash()->info('You have 5 unread messages.');</code></pre>
|
||||
</div>
|
||||
<button class="btn btn-info w-full notification-demo" data-type="info" data-message="This is an info notification!">
|
||||
Show Info Notification
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden mb-8">
|
||||
<div class="p-6">
|
||||
<h2 class="text-xl font-bold mb-4">Usage in Controllers</h2>
|
||||
<p class="text-gray-600 mb-4">
|
||||
Here's how you can use notification types in your Symfony controllers:
|
||||
</p>
|
||||
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>PHP</span>
|
||||
</div>
|
||||
<pre><code class="language-php"><?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class ExampleController extends AbstractController
|
||||
{
|
||||
#[Route('/process-form', name: 'app_process_form')]
|
||||
public function processForm(): Response
|
||||
{
|
||||
// Simulate form processing
|
||||
$success = true;
|
||||
|
||||
if ($success) {
|
||||
// Show success notification
|
||||
flash()->success('Form submitted successfully!');
|
||||
} else {
|
||||
// Show error notification
|
||||
flash()->error('An error occurred while processing the form.');
|
||||
}
|
||||
|
||||
// Show info notification
|
||||
flash()->info('You will receive a confirmation email shortly.');
|
||||
|
||||
// Show warning notification
|
||||
flash()->warning('Please verify your email within 24 hours.');
|
||||
|
||||
return $this->redirectToRoute('app_home');
|
||||
}
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden">
|
||||
<div class="p-6">
|
||||
<h2 class="text-xl font-bold mb-4">Advanced Usage</h2>
|
||||
<p class="text-gray-600 mb-4">
|
||||
You can combine notification types with other options to create more customized notifications:
|
||||
</p>
|
||||
|
||||
<div class="code-block mb-6">
|
||||
<div class="code-header">
|
||||
<span>PHP</span>
|
||||
</div>
|
||||
<pre><code class="language-php">// Success notification with custom timeout
|
||||
flash()->option('timeout', 8000)
|
||||
->success('Changes saved successfully!');
|
||||
|
||||
// Warning notification with custom position
|
||||
flash()->option('position', 'bottom-center')
|
||||
->warning('Your session will expire soon.');
|
||||
|
||||
// Error notification with progress bar
|
||||
flash()->option('showProgressbar', true)
|
||||
->error('Unable to connect to the server.');</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center">
|
||||
<a href="{{ path('app_options') }}" class="btn btn-primary">
|
||||
Learn More About Options
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const demoButtons = document.querySelectorAll('.notification-demo');
|
||||
|
||||
demoButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const type = this.getAttribute('data-type');
|
||||
const message = this.getAttribute('data-message') || 'This is a notification!';
|
||||
|
||||
// Send AJAX request to show notification
|
||||
fetch('{{ path('app_show_notification') }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
type: type,
|
||||
message: message
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -1,7 +1,97 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}PHPFlasher{% endblock %}
|
||||
{% block title %}PHPFlasher Features{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% block page_title %}PHPFlasher Features{% endblock %}
|
||||
{% block page_subtitle %}Explore the powerful features of PHPFlasher{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-12">
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition duration-300">
|
||||
<div class="bg-indigo-600 h-2"></div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center space-x-3 mb-3">
|
||||
<div class="bg-indigo-100 p-2 rounded-md">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-indigo-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-800">Notification Types</h3>
|
||||
</div>
|
||||
<p class="text-gray-600">Display success, error, warning, and info notifications to communicate different messages to your users.</p>
|
||||
<div class="mt-4">
|
||||
<a href="{{ path('app_types') }}" class="text-indigo-600 hover:text-indigo-800 font-medium">See Notification Types →</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition duration-300">
|
||||
<div class="bg-emerald-600 h-2"></div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center space-x-3 mb-3">
|
||||
<div class="bg-emerald-100 p-2 rounded-md">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-emerald-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-800">Notification Positions</h3>
|
||||
</div>
|
||||
<p class="text-gray-600">Place notifications in different positions around the screen to best suit your UI design.</p>
|
||||
<div class="mt-4">
|
||||
<a href="{{ path('app_positions') }}" class="text-emerald-600 hover:text-emerald-800 font-medium">Explore Positions →</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition duration-300">
|
||||
<div class="bg-amber-500 h-2"></div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center space-x-3 mb-3">
|
||||
<div class="bg-amber-100 p-2 rounded-md">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-amber-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-800">Configuration Options</h3>
|
||||
</div>
|
||||
<p class="text-gray-600">Customize timeouts, animations, progressbars, and more with PHPFlasher's flexible configuration.</p>
|
||||
<div class="mt-4">
|
||||
<a href="{{ path('app_options') }}" class="text-amber-600 hover:text-amber-800 font-medium">View Options →</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 mb-12">
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden">
|
||||
<div class="p-6">
|
||||
<h3 class="text-xl font-bold mb-4 text-gray-800">Plugins & Extensions</h3>
|
||||
<p class="text-gray-600 mb-4">PHPFlasher can be extended with plugins to add more functionality.</p>
|
||||
<div class="flex justify-end">
|
||||
<a href="{{ path('app_plugins') }}" class="btn btn-primary">Explore Plugins</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden">
|
||||
<div class="p-6">
|
||||
<h3 class="text-xl font-bold mb-4 text-gray-800">Notification Presets</h3>
|
||||
<p class="text-gray-600 mb-4">Create reusable notification configurations for consistent messaging.</p>
|
||||
<div class="flex justify-end">
|
||||
<a href="{{ path('app_presets') }}" class="btn btn-primary">View Presets</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-indigo-50 rounded-lg p-8 mb-12">
|
||||
<div class="text-center">
|
||||
<h2 class="text-2xl font-bold text-indigo-800 mb-4">Try Out the Interactive Playground</h2>
|
||||
<p class="text-indigo-600 mb-6 max-w-2xl mx-auto">Want to experiment with different notification settings? Use our interactive playground to test PHPFlasher's features in real-time.</p>
|
||||
<div class="flex justify-center">
|
||||
<a href="{{ path('app_playground') }}" class="btn btn-primary">Go to Playground</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}PHPFlasher - Themes{% endblock %}
|
||||
|
||||
{% block page_title %}PHPFlasher Themes{% endblock %}
|
||||
{% block page_subtitle %}Beautiful notification themes to match your application's design{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden mb-8">
|
||||
<div class="p-6">
|
||||
<h2 class="text-xl font-bold mb-4">Available Themes</h2>
|
||||
<p class="text-gray-600 mb-6">
|
||||
PHPFlasher comes with various themes to help you match the notification style to your application's design.
|
||||
Each theme provides a distinct visual appearance while maintaining the same functionality.
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
|
||||
<div class="theme-card">
|
||||
<div class="bg-indigo-600 h-2"></div>
|
||||
<div class="theme-preview bg-indigo-50 flex items-center justify-center p-4">
|
||||
<div class="w-full bg-white rounded-lg shadow-md p-4">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-indigo-500" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p class="text-sm font-medium text-gray-900">Flasher Default Theme</p>
|
||||
<p class="text-xs text-gray-500">Clean and minimal design</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<h3 class="text-lg font-semibold mb-2">Flasher (Default)</h3>
|
||||
<p class="text-gray-600 text-sm mb-4">The default theme with a clean, minimal design that works well in most applications.</p>
|
||||
<button class="w-full btn btn-primary theme-demo" data-theme="flasher">
|
||||
Preview Theme
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="theme-card">
|
||||
<div class="bg-emerald-600 h-2"></div>
|
||||
<div class="theme-preview bg-emerald-50 flex items-center justify-center p-4">
|
||||
<div class="w-full bg-white rounded-lg shadow-md p-4 border-l-4 border-emerald-500">
|
||||
<div class="flex">
|
||||
<div class="ml-3">
|
||||
<p class="text-sm font-medium text-gray-900">Emerald Theme</p>
|
||||
<p class="text-xs text-gray-500">Elegant left-border style</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<h3 class="text-lg font-semibold mb-2">Emerald</h3>
|
||||
<p class="text-gray-600 text-sm mb-4">A sleek theme with colored left borders and subtle design elements.</p>
|
||||
<button class="w-full btn btn-primary theme-demo" data-theme="emerald">
|
||||
Preview Theme
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="theme-card">
|
||||
<div class="bg-blue-600 h-2"></div>
|
||||
<div class="theme-preview bg-blue-50 flex items-center justify-center p-4">
|
||||
<div class="w-full bg-white rounded-lg shadow-md p-4">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0 bg-blue-100 rounded-full p-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-blue-500" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2h-1V9a1 1 0 00-1-1z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p class="text-sm font-medium text-gray-900">Sapphire Theme</p>
|
||||
<p class="text-xs text-gray-500">Modern with rounded icons</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<h3 class="text-lg font-semibold mb-2">Sapphire</h3>
|
||||
<p class="text-gray-600 text-sm mb-4">A modern theme with rounded icons and smooth animations.</p>
|
||||
<button class="w-full btn btn-primary theme-demo" data-theme="sapphire">
|
||||
Preview Theme
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="theme-card">
|
||||
<div class="bg-purple-600 h-2"></div>
|
||||
<div class="theme-preview bg-purple-50 flex items-center justify-center p-4">
|
||||
<div class="w-full bg-white rounded-lg shadow-md p-4 bg-opacity-80 backdrop-filter backdrop-blur-sm">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-purple-500" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path d="M2 10.5a1.5 1.5 0 113 0v6a1.5 1.5 0 01-3 0v-6zM6 10.333v5.43a2 2 0 001.106 1.79l.05.025A4 4 0 008.943 18h5.416a2 2 0 001.962-1.608l1.2-6A2 2 0 0015.56 8H12V4a2 2 0 00-2-2 1 1 0 00-1 1v.667a4 4 0 01-.8 2.4L6.8 7.933a4 4 0 00-.8 2.4z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p class="text-sm font-medium text-gray-900">Crystal Theme</p>
|
||||
<p class="text-xs text-gray-500">Transparent with blur effects</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<h3 class="text-lg font-semibold mb-2">Crystal</h3>
|
||||
<p class="text-gray-600 text-sm mb-4">A modern glass-like theme with transparency and blur effects.</p>
|
||||
<button class="w-full btn btn-primary theme-demo" data-theme="crystal">
|
||||
Preview Theme
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="theme-card">
|
||||
<div class="bg-amber-500 h-2"></div>
|
||||
<div class="theme-preview bg-amber-50 flex items-center justify-center p-4">
|
||||
<div class="w-full bg-white rounded-lg shadow-md p-4">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0 bg-amber-100 p-1 rounded">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-amber-500" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M18 3a1 1 0 00-1.447-.894L8.763 6H5a3 3 0 000 6h.28l1.771 5.316A1 1 0 008 18h1a1 1 0 001-1v-4.382l6.553 3.276A1 1 0 0018 15V3z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p class="text-sm font-medium text-gray-900">Amazon Theme</p>
|
||||
<p class="text-xs text-gray-500">Inspired by Amazon's notification style</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<h3 class="text-lg font-semibold mb-2">Amazon</h3>
|
||||
<p class="text-gray-600 text-sm mb-4">Inspired by Amazon's notification style with distinctive icons.</p>
|
||||
<button class="w-full btn btn-primary theme-demo" data-theme="amazon">
|
||||
Preview Theme
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden mb-8">
|
||||
<div class="p-6">
|
||||
<h2 class="text-xl font-bold mb-4">Using Themes in Your Code</h2>
|
||||
<p class="text-gray-600 mb-4">
|
||||
You can specify which theme to use for each notification using the <code>option()</code> method:
|
||||
</p>
|
||||
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>PHP</span>
|
||||
</div>
|
||||
<pre><code class="language-php">// Using the default theme
|
||||
flash()->success('Your profile has been updated successfully!');
|
||||
|
||||
// Using the Emerald theme
|
||||
flash()->option('theme', 'emerald')
|
||||
->success('Your profile has been updated successfully!');
|
||||
|
||||
// Using the Sapphire theme with additional options
|
||||
flash()->option('theme', 'sapphire')
|
||||
->option('position', 'bottom-right')
|
||||
->option('timeout', 5000)
|
||||
->info('You have 3 unread messages.');
|
||||
|
||||
// Using the Amazon theme
|
||||
flash()->option('theme', 'amazon')
|
||||
->warning('Your subscription will expire in 3 days.');</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden mb-8">
|
||||
<div class="p-6">
|
||||
<h2 class="text-xl font-bold mb-4">Theme Configuration</h2>
|
||||
<p class="text-gray-600 mb-4">
|
||||
You can configure themes globally in your configuration file:
|
||||
</p>
|
||||
|
||||
<div class="code-block mb-6">
|
||||
<div class="code-header">
|
||||
<span>YAML</span>
|
||||
</div>
|
||||
<pre><code class="language-yaml"># config/packages/flasher.yaml
|
||||
flasher:
|
||||
# Set the default theme for all notifications
|
||||
default: theme.amazon
|
||||
|
||||
themes:
|
||||
amazon:
|
||||
scripts:
|
||||
- '/vendor/flasher/themes/amazon/amazon.min.js'
|
||||
styles:
|
||||
- '/vendor/flasher/flasher.min.css'
|
||||
- '/vendor/flasher/themes/amazon/amazon.min.css'
|
||||
options:
|
||||
position: 'bottom-right'
|
||||
timeout: 6000
|
||||
|
||||
emerald:
|
||||
scripts:
|
||||
- '/vendor/flasher/themes/emerald/emerald.min.js'
|
||||
styles:
|
||||
- '/vendor/flasher/flasher.min.css'
|
||||
- '/vendor/flasher/themes/emerald/emerald.min.css'
|
||||
options:
|
||||
position: 'top-right'
|
||||
timeout: 5000</code></pre>
|
||||
</div>
|
||||
|
||||
<p class="text-gray-600 mb-4">
|
||||
Each theme can have its own default options, scripts, and styles. This allows you to create a consistent notification experience throughout your application.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden">
|
||||
<div class="p-6">
|
||||
<h2 class="text-xl font-bold mb-4">Custom Theme Templates</h2>
|
||||
<p class="text-gray-600 mb-4">
|
||||
Need something more customized? PHPFlasher allows you to create your own themes:
|
||||
</p>
|
||||
|
||||
<div class="code-block mb-6">
|
||||
<div class="code-header">
|
||||
<span>YAML</span>
|
||||
</div>
|
||||
<pre><code class="language-yaml"># config/packages/flasher.yaml
|
||||
flasher:
|
||||
themes:
|
||||
custom_theme:
|
||||
scripts:
|
||||
- '/assets/js/custom-theme.js'
|
||||
styles:
|
||||
- '/assets/css/custom-theme.css'
|
||||
options:
|
||||
position: 'top-center'
|
||||
timeout: 7000
|
||||
# Add any custom options your theme supports</code></pre>
|
||||
</div>
|
||||
|
||||
<p class="text-gray-600 mb-4">
|
||||
Then you can use your custom theme in your code:
|
||||
</p>
|
||||
|
||||
<div class="code-block mb-6">
|
||||
<div class="code-header">
|
||||
<span>PHP</span>
|
||||
</div>
|
||||
<pre><code class="language-php">flash()->option('theme', 'custom_theme')
|
||||
->success('This uses your custom theme!');</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center">
|
||||
<a href="{{ path('app_theme_builder') }}" class="btn btn-primary">
|
||||
Try the Theme Builder
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const themeButtons = document.querySelectorAll('.theme-demo');
|
||||
|
||||
themeButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const theme = this.getAttribute('data-theme');
|
||||
const messages = {
|
||||
'flasher': 'This notification uses the Flasher theme!',
|
||||
'emerald': 'This notification uses the Emerald theme!',
|
||||
'sapphire': 'This notification uses the Sapphire theme!',
|
||||
'crystal': 'This notification uses the Crystal theme!',
|
||||
'amazon': 'This notification uses the Amazon theme!'
|
||||
};
|
||||
|
||||
// Send AJAX request to show notification
|
||||
fetch('{{ path('app_show_notification') }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
type: 'success',
|
||||
message: messages[theme] || 'Theme preview',
|
||||
options: {
|
||||
theme: theme
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user