@phloxcz/capify
v1.2.0
Published
Modern, themeable replacement for native alert, confirm & prompt dialogs. Zero dependencies.
Maintainers
Readme
Capify
Modern, themeable replacement for native alert(), confirm() and prompt() dialogs.
Zero dependencies · ~5 KB · UMD · TypeScript ready
Features
- Three built-in themes: Default (custom), Bootstrap 5, Tailwind CSS
- Dark / Light mode: auto-detect via
prefers-color-scheme, or force light/dark - Modal & non-modal: modal variant includes backdrop blur effect
- Promise-based API:
await Capify.confirm('Sure?') - Popover variant: kompaktní dialog ukotvený k elementu s auto-flip
- Notifications: toast notifikace se štosováním, auto-dismiss, progress bar
- Class overrides: customize any CSS class slot globally or per-call
- Accessible:
role="dialog",aria-modal, keyboard support (Escape, Enter) - Extensible: register custom themes via
Capify.registerTheme()
Installation
npm (recommended for Vite / bundler projects)
npm install @phloxcz/capifyimport Capify from '@phloxcz/capify';
import '@phloxcz/capify/capify.css';Composer
composer require phloxcz/capifySoubory se nainstalují do vendor/phloxcz/capify/. Jak je dostat do
veřejné složky závisí na tvém setupu — viz sekce Nette + Vite
a Composer bez bundleru níže.
CDN / manuálně
<link href="capify.css" rel="stylesheet">
<script src="capify.js"></script>Nette + Vite
Doporučený moderní setup — Capify se nainstaluje přes npm, Vite ho
zabundlí spolu se zbytkem frontendu a nette/assets se postará o
vložení do šablon.
1. Předpoklady
composer require nette/assets
npm install vite @nette/vite-plugin2. Instalace Capify
npm install @phloxcz/capify3. Entry point
V hlavním JS souboru (typicky assets/app.js nebo assets/main.js)
importuj Capify:
// assets/app.js
import '@phloxcz/capify/capify.css'; // CSS se zabundlí automaticky
import Capify from '@phloxcz/capify';
// Zpřístupni globálně (pro použití v inline scriptech a Latte šablonách)
window.Capify = Capify;
// Volitelně — globální konfigurace
Capify.config({
theme: 'bootstrap',
darkMode: 'auto',
okText: 'OK',
cancelText: 'Zrušit',
});4. Vite config
// vite.config.ts
import { defineConfig } from 'vite';
import nette from '@nette/vite-plugin';
export default defineConfig({
plugins: [
nette({ entry: 'app.js' }),
],
});5. Nette config
# config/common.neon
assets:
mapping:
default:
type: vite6. Latte šablona
{* @layout.latte *}
<!DOCTYPE html>
<html>
<head>
{asset 'app.js'} {* Vite vloží JS + CSS automaticky *}
</head>
<body>
{include content}
</body>
</html>7. Použití v šablonách
{* kdekoliv v šabloně — Capify je na window *}
<button onclick="Capify.confirm('Opravdu smazat?').then(ok => { if (ok) location.href = '{link delete! $id}' })">
Smazat
</button>Nebo v samostatném JS modulu:
// assets/modules/admin.js
import Capify from '@phloxcz/capify';
document.querySelectorAll('[data-confirm]').forEach(el => {
el.addEventListener('click', async (e) => {
e.preventDefault();
const ok = await Capify.confirm(el.dataset.confirm, { title: 'Potvrdit akci' });
if (ok) location.href = el.href;
});
});Vývoj vs. produkce
V dev módu (npx vite) se Capify načítá přes Vite dev server s HMR —
změny v CSS se projeví okamžitě bez reloadu. Pro produkci spustíš
npx vite build, Vite vygeneruje optimalizované soubory do www/assets/
a nette/assets je automaticky servíruje se správným verzováním.
Composer bez bundleru
Pokud nepoužíváš Vite ani jiný bundler, můžeš soubory z vendor/
nakopírovat do veřejné složky ručně nebo symlinkem:
# Symlink (Linux/macOS)
ln -s ../../vendor/phloxcz/capify/capify.js www/js/capify.js
ln -s ../../vendor/phloxcz/capify/capify.css www/css/capify.cssV Latte pak:
<link rel="stylesheet" href="{$basePath}/css/capify.css">
<script src="{$basePath}/js/capify.js"></script>Quick Start
<link href="capify.css" rel="stylesheet">
<script src="capify.js"></script>
<script>
Capify.config({
theme: 'default', // 'default' | 'bootstrap' | 'tailwind'
modal: true, // true = blur overlay
darkMode: 'auto', // 'auto' | 'light' | 'dark'
});
await Capify.alert('Hotovo!');
const ok = await Capify.confirm('Smazat?');
const name = await Capify.prompt('Vaše jméno?');
</script>TypeScript
Typové definice jsou součástí balíčku (capify.d.ts):
import Capify from '@phloxcz/capify';
import type { DialogOptions, CapifyConfig, ThemeRenderer } from '@phloxcz/capify';
const opts: DialogOptions = {
title: 'Potvrdit',
theme: 'bootstrap',
classes: {
header: 'modal-header border-0',
btnOk: 'btn btn-danger',
},
};
const confirmed: boolean = await Capify.confirm('Smazat?', opts);API
| Metoda | Vrací | Popis |
|--------|-------|-------|
| Capify.alert(msg, opts?) | Promise<true> | Notifikace s tlačítkem OK |
| Capify.confirm(msg, opts?) | Promise<boolean> | OK → true, Cancel → false |
| Capify.prompt(msg, opts?) | Promise<string\|null> | OK → zadaný text, Cancel → null |
| Capify.notify(msg, opts?) | { close() } | Toast notifikace, vrací handle |
| Capify.loading(html, opts?) | { close(), update(html) } | Okénko bez tlačítek s libovolným HTML, zavírá se programově |
| Capify.config(opts) | void | Nastaví globální výchozí hodnoty |
| Capify.registerTheme(name, renderer) | void | Registrace vlastního tématu |
| Capify.getThemeClasses(name) | object\|null | Vrátí výchozí třídy tématu |
| Capify.reset() | void | Reset konfigurace na výchozí hodnoty |
Popover varianta
Kompaktní dialog ukotvený k libovolnému elementu — ideální pro kontextové vstupy, inline potvrzení nebo notifikace přímo u tlačítka.
// Prompt popover pod tlačítkem, zarovnaný vlevo
const name = await Capify.prompt('Název:', {
variant: 'popover',
anchor: document.getElementById('myBtn'),
placement: 'bottom-left',
modal: true, // volitelný blur overlay
okText: 'Uložit',
cancelText: 'Zrušit',
});
// Confirm popover bez overlay
const ok = await Capify.confirm('Smazat?', {
variant: 'popover',
anchor: deleteBtn,
placement: 'bottom-right',
modal: false,
});
// Alert popover
await Capify.alert('Uloženo.', {
variant: 'popover',
anchor: saveBtn,
placement: 'top-left',
});Placement
Kombinace vertikální a horizontální osy:
| Hodnota | Dialog se objeví… |
|---------|-------------------|
| bottom-left | Pod elementem, zarovnaný k levému okraji |
| bottom-right | Pod elementem, zarovnaný k pravému okraji |
| top-left | Nad elementem, zarovnaný k levému okraji |
| top-right | Nad elementem, zarovnaný k pravému okraji |
Automatický flip — pokud se dialog nevejde na zadanou stranu, otočí se na opačnou. Na mobilech (< 480px) se popover zobrazí vycentrovaný.
Overlay
Vzhled modálního overlay (pozadí za dialogem) je plně konfigurovatelný.
// Silnější blur
Capify.config({ overlayBlur: 12 });
// Bez bluru
Capify.config({ overlayBlur: 0 });
// Tmavší overlay
Capify.config({ overlayBg: 'rgba(0, 0, 0, .7)' });
// Světlý frost efekt
Capify.config({
overlayBlur: 8,
overlayBg: 'rgba(255, 255, 255, .3)',
});
// Plně vlastní backdrop-filter (přebije overlayBlur)
Capify.alert('OK', {
overlayFilter: 'blur(4px) brightness(.7) saturate(.5)',
});| Volba | Typ | Default | Popis |
|-------|-----|---------|-------|
| overlayBlur | number | 6 | Blur v px, 0 = bez bluru |
| overlayBg | string | rgba(0,0,0,.45) | Barva pozadí overlay |
| overlayFilter | string | — | Vlastní backdrop-filter (přebije overlayBlur) |
Všechny tři lze nastavit globálně i per-call.
Notifikace
Toast notifikace, které se štosují na zvolené pozici. Auto-dismiss s progress barem, pause na hover, programatické zavření.
// Základní použití
Capify.notify('Soubor uložen.', {
type: 'success', // 'info' | 'success' | 'warning' | 'error'
title: 'Hotovo', // volitelný titulek
position: 'top-right', // kam na obrazovku
duration: 4000, // ms, 0 = bez auto-dismiss
});
// Všechny pozice
// 'top-left' | 'top-center' | 'top-right'
// 'bottom-left' | 'bottom-center' | 'bottom-right'
// Persistent notifikace s programatickým zavřením
const n = Capify.notify('Zpracovávám...', {
type: 'info',
duration: 0, // nezavře se samo
});
// ... později:
n.close();Notify options
| Volba | Typ | Default | Popis |
|-------|-----|---------|-------|
| position | string | 'top-right' | Pozice na obrazovce (6 možností) |
| duration | number | 4000 | Auto-dismiss v ms, 0 = manuální |
| type | string | 'info' | Typ — ovlivňuje barvu akcentu |
| title | string | '' | Tučný titulek nad zprávou |
| closable | boolean | true | Zobrazit tlačítko × |
| maxWidth | number | 380 | Maximální šířka v px |
| showProgress | boolean | true | Progress bar odpočtu |
| theme | string | z config | 'default' / 'bootstrap' / 'tailwind' |
| darkMode | string | z config | 'auto' / 'light' / 'dark' |
| html | boolean | false | true = titulek/zpráva se vloží jako raw HTML (needescapuje se) |
Chování
Notifikace se štosují automaticky — top pozice rostou dolů, bottom pozice rostou nahoru. Při najetí myší se odpočet pozastaví a progress bar se zastaví. Po odjetí myši odpočet pokračuje.
Notifikace respektují globální téma (default, bootstrap, tailwind)
a dark mode. Bootstrap používá alert komponenty, Tailwind utility třídy
s barevnými variantami per type. Přetížení tříd funguje přes classes
stejně jako u dialogů — notify sloty: notifyCard, notifyTitle,
notifyMsg, notifyClose, notifyProgress.
Loading
Okénko ve stejném stylu jako alert/confirm/prompt, ale bez tlačítek — pro libovolné HTML zobrazené po dobu dlouho trvající akce. Zavírá se výhradně programově přes vrácený handle, nereaguje na klik na overlay ani Escape (pokud to explicitně nepovolíte).
const loader = Capify.loading('<div class="cap-spinner"></div><span>Ukládám…</span>');
await saveData();
loader.close();Obsah je ve výchozím stavu vkládán jako raw HTML (html: true), protože
smyslem je zobrazit vlastní markup (spinner, progress bar apod.) — pokud
potřebujete escapovat, nastavte html: false. Capify.loading() respektuje
theme, darkMode, modal, overlay volby i variant: 'popover' +
anchor/placement stejně jako ostatní metody. Vrácený handle má i
update(html) pro změnu obsahu za běhu (např. update procenta průběhu),
aniž by se okno muselo zavírat a znovu otevírat.
// Popover verze u tlačítka, bez overlay
const loader = Capify.loading('Nahrávám soubor…', {
variant: 'popover',
anchor: uploadBtn,
placement: 'bottom-left',
modal: false,
});
loader.update('Nahrávám… 80 %');
loader.close();CSS třída .cap-spinner je volitelný předpřipravený spinner v barvách
aktuálního tématu (--cap-accent/--cap-border), který lze použít v
obsahu, ale není povinný — klidně vložte vlastní HTML/GIF/progress bar.
Per-call Options
Capify.confirm('Uložit?', {
title: 'Neuložené změny',
okText: 'Uložit',
cancelText: 'Zahodit',
theme: 'bootstrap',
modal: true,
darkMode: 'dark',
closeOnOverlay: true,
closeOnEscape: true,
zIndex: 10000,
animationDuration: 200,
html: false, // true = titulek/zpráva se vloží jako raw HTML (needescapuje se)
classes: { ... },
// overlay appearance
overlayBlur: 6, // blur in px (0 = off)
overlayBg: 'rgba(0,0,0,.45)', // overlay background color
overlayFilter: null, // custom backdrop-filter (overrides overlayBlur)
// popover options
variant: 'popover', // 'dialog' (default) | 'popover'
anchor: HTMLElement, // element pro ukotvení
placement: 'bottom-left', // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
});Class Overrides
Každé téma definuje pojmenované sloty s výchozími CSS třídami. Jakýkoli
slot lze přetížit globálně přes config() nebo jednorázově přes options.classes.
// Zjisti dostupné sloty:
console.log(Capify.getThemeClasses('bootstrap'));
// → { content: 'modal-content shadow-lg border-0 text-body bg-body',
// header: 'modal-header border-bottom',
// footer: 'modal-footer border-top',
// btnOk: 'btn btn-primary', ... }
// Přetížení globálně:
Capify.config({
theme: 'bootstrap',
classes: {
header: 'modal-header border-0',
footer: 'modal-footer border-0',
}
});
// Přetížení per-call:
Capify.confirm('Smazat vše?', {
classes: {
btnOk: 'btn btn-danger',
header: 'modal-header border-0 bg-danger bg-opacity-10',
}
});Dostupné sloty podle tématu
Default (dialog): overlay, dialog, title, body, input, actions, btnOk, btnCancel
Default (notify): notifyCard, notifyTitle, notifyMsg, notifyClose, notifyProgress
Bootstrap (dialog): overlay, dialog, content, header, title, body, bodyText, input, footer, btnOk, btnCancel
Bootstrap (notify): notifyCard, notifyCardInfo, notifyCardSuccess, notifyCardWarning, notifyCardError, notifyTitle, notifyMsg, notifyClose, notifyProgress
Tailwind (dialog): overlay, dialog, card, cardLight, cardDark, title, body, input, inputLight, inputDark, actions, btnOk, btnCancel, btnCancelLight, btnCancelDark
Tailwind (notify): notifyCard, notifyCardLightInfo, notifyCardLightSuccess, notifyCardLightWarning, notifyCardLightError, notifyCardDarkInfo, notifyCardDarkSuccess, notifyCardDarkWarning, notifyCardDarkError, notifyTitle, notifyMsg, notifyClose, notifyProgress
Témata
- Default — plně samostatné, potřebuje jen
capify.css - Bootstrap — využívá třídy Bootstrap 5, vyžaduje Bootstrap CSS
- Tailwind — využívá Tailwind utility třídy, vyžaduje Tailwind CSS
Soubory
| Soubor | Účel |
|--------|------|
| capify.js | Knihovna (UMD) |
| capify.css | Styly — bundluj se styly projektu |
| capify.d.ts | TypeScript definice |
| package.json | npm manifest |
| composer.json | Composer manifest |
| demo.html | Interaktivní demo |
Licence
MIT
