Vai al contenuto

Componente

Notification

Notifiche brevi con titolo, icona e barra laterale colorata. Nel flusso della pagina, oppure in un angolo dello schermo come popover nativo posizionato da daisyUI toast.

Riferimento
<it-notification>
Classi
ita-notificationita-notification-successita-notification-errorita-notification-infoita-notification-warningita-notification-bodyita-notification-titleita-notification-textita-notification-closeita-toast
Basato su (daisyUI)
alerttoasttoast-toptoast-bottomtoast-starttoast-centertoast-endbtn-ghostbtn-square
Solo CSS
Le notifiche posizionate sono popover="manual": le mostra un pulsante con popovertarget e le chiude un pulsante con popovertargetaction="hide", senza script. La chiusura automatica dopo qualche secondo richiede JavaScript. Errori e avvisi usano role=alert, gli altri role=status.
Storybook
Apri le storie di Notification

Varianti

Notifica di esempio

Testo della notifica.

Domanda inviata

Riceverai una conferma via email.

Manutenzione programmata

Il servizio non sarà disponibile domenica dalle 8 alle 12.

Mostra il codice HTML
<div class="flex flex-col gap-4">
<div role="status" aria-labelledby="notification-1-title" class="ita-notification">
  <div class="ita-notification-body">
    <p id="notification-1-title" class="ita-notification-title"><span>Notifica di esempio</span></p>
    <p class="ita-notification-text">Testo della notifica.</p>
  </div>
</div>
<div role="status" aria-labelledby="notification-2-title" class="ita-notification ita-notification-success">
  <div class="ita-notification-body">
    <p id="notification-2-title" class="ita-notification-title"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M17.1,7.9l0.7,0.7L10,16.2l-4.7-4.6L6,10.9l4,3.9L17.1,7.9z M22,12c0,5.5-4.5,10-10,10S2,17.5,2,12S6.5,2,12,2S22,6.5,22,12z M21,12c0-5-4-9-9-9s-9,4-9,9s4,9,9,9S21,17,21,12z" /></svg><span>Domanda inviata</span></p>
    <p class="ita-notification-text">Riceverai una conferma via email.</p>
  </div>
</div>
<div role="alert" aria-labelledby="notification-3-title" class="ita-notification ita-notification-error">
  <div class="ita-notification-body">
    <p id="notification-3-title" class="ita-notification-title"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M16.3,8.3L12.6,12l3.7,3.6l-0.7,0.7l-3.7-3.6l-3.6,3.6l-0.7-0.7l3.6-3.6L7.6,8.3l0.7-0.7l3.6,3.7l3.7-3.7L16.3,8.3z M22,12 c0,5.5-4.5,10-10,10S2,17.5,2,12S6.5,2,12,2S22,6.5,22,12z M21,12c0-5-4-9-9-9s-9,4-9,9s4,9,9,9S21,17,21,12z" /></svg><span>Pagamento non riuscito</span></p>
    <p class="ita-notification-text">Controlla i dati della carta e riprova.</p>
  </div>
</div>
<div role="status" aria-labelledby="notification-4-title" class="ita-notification ita-notification-info">
  <div class="ita-notification-body">
    <p id="notification-4-title" class="ita-notification-title"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,21c-5,0-9-4-9-9s4-9,9-9s9,4,9,9S17,21,12,21L12,21z M11.3,6h1.5v2h-1.5V6z M11.3,9h1.5v9h-1.5V9z" /></svg><span>Manutenzione programmata</span></p>
    <p class="ita-notification-text">Il servizio non sarà disponibile domenica dalle 8 alle 12.</p>
  </div>
</div>
<div role="alert" aria-labelledby="notification-5-title" class="ita-notification ita-notification-warning">
  <div class="ita-notification-body">
    <p id="notification-5-title" class="ita-notification-title"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,21c-5,0-9-4-9-9s4-9,9-9s9,4,9,9S17,21,12,21L12,21z M11.5,14.2V5.7h1.2v8.5H11.5z M11.4,16.5h1.2v1.8h-1.2V16.5z" /></svg><span>Sessione in scadenza</span></p>
    <p class="ita-notification-text">Salva il modulo entro 5 minuti.</p>
  </div>
</div>
</div>

Solo titolo

Modifiche salvate

Senza icona

Mostra il codice HTML
<div class="flex flex-col gap-4">
<div role="status" aria-labelledby="notification-6-title" class="ita-notification ita-notification-success">
  <div class="ita-notification-body">
    <p id="notification-6-title" class="ita-notification-title"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M17.1,7.9l0.7,0.7L10,16.2l-4.7-4.6L6,10.9l4,3.9L17.1,7.9z M22,12c0,5.5-4.5,10-10,10S2,17.5,2,12S6.5,2,12,2S22,6.5,22,12z M21,12c0-5-4-9-9-9s-9,4-9,9s4,9,9,9S21,17,21,12z" /></svg><span>Modifiche salvate</span></p>
  </div>
</div>
<div role="status" aria-labelledby="notification-7-title" class="ita-notification">
  <div class="ita-notification-body">
    <p id="notification-7-title" class="ita-notification-title"><span>Senza icona</span></p>
  </div>
</div>
</div>

Con chiusura

Premi la X: la notifica si nasconde solo con CSS.

Nuovo messaggio

Hai un nuovo messaggio dall'ufficio tributi.

Mostra il codice HTML
<div class="flex flex-col gap-4">
<div role="status" aria-labelledby="notification-8-title" class="ita-notification ita-notification-info">
  <div class="ita-notification-body">
    <p id="notification-8-title" class="ita-notification-title"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,21c-5,0-9-4-9-9s4-9,9-9s9,4,9,9S17,21,12,21L12,21z M11.3,6h1.5v2h-1.5V6z M11.3,9h1.5v9h-1.5V9z" /></svg><span>Nuovo messaggio</span></p>
    <p class="ita-notification-text">Hai un nuovo messaggio dall'ufficio tributi.</p>
  </div>
  <label class="ita-notification-close"><input type="checkbox" class="sr-only"><span class="sr-only">Chiudi notifica</span><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12.7,12l3.7,3.6l-0.8,0.8L12,12.7l-3.6,3.7l-0.8-0.8l3.7-3.6L7.6,8.4l0.8-0.8l3.6,3.7l3.6-3.7l0.8,0.8L12.7,12z" /></svg></label>
</div>
<div role="alert" aria-labelledby="notification-9-title" class="ita-notification ita-notification-warning">
  <div class="ita-notification-body">
    <p id="notification-9-title" class="ita-notification-title"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,21c-5,0-9-4-9-9s4-9,9-9s9,4,9,9S17,21,12,21L12,21z M11.5,14.2V5.7h1.2v8.5H11.5z M11.4,16.5h1.2v1.8h-1.2V16.5z" /></svg><span>Documento in scadenza</span></p>
  </div>
  <label class="ita-notification-close"><input type="checkbox" class="sr-only"><span class="sr-only">Chiudi notifica</span><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12.7,12l3.7,3.6l-0.8,0.8L12,12.7l-3.6,3.7l-0.8-0.8l3.7-3.6L7.6,8.4l0.8-0.8l3.6,3.7l3.6-3.7l0.8,0.8L12.7,12z" /></svg></label>
</div>
</div>

Posizioni sullo schermo

Ogni pulsante apre una notifica popover nell'angolo indicato; chiudila con la X.

Notifica top-start

Aperta con popovertarget, senza JavaScript.

Notifica top-center

Aperta con popovertarget, senza JavaScript.

Notifica top-end

Aperta con popovertarget, senza JavaScript.

Notifica bottom-end

Aperta con popovertarget, senza JavaScript.

Mostra il codice HTML
<div class="flex flex-wrap gap-3">
  <button type="button" class="ita-btn ita-btn-primary ita-btn-outline ita-btn-xs" popovertarget="notifica-top-start" popovertargetaction="show">top-start</button>
  <button type="button" class="ita-btn ita-btn-primary ita-btn-outline ita-btn-xs" popovertarget="notifica-top-center" popovertargetaction="show">top-center</button>
  <button type="button" class="ita-btn ita-btn-primary ita-btn-outline ita-btn-xs" popovertarget="notifica-top-end" popovertargetaction="show">top-end</button>
  <button type="button" class="ita-btn ita-btn-primary ita-btn-outline ita-btn-xs" popovertarget="notifica-bottom-start" popovertargetaction="show">bottom-start</button>
  <button type="button" class="ita-btn ita-btn-primary ita-btn-outline ita-btn-xs" popovertarget="notifica-bottom-center" popovertargetaction="show">bottom-center</button>
  <button type="button" class="ita-btn ita-btn-primary ita-btn-outline ita-btn-xs" popovertarget="notifica-bottom-end" popovertargetaction="show">bottom-end</button>
</div>
<div id="notifica-top-start" popover="manual" role="status" aria-labelledby="notifica-top-start-title" class="toast toast-top toast-start ita-toast">
  <div class="ita-notification">
  <div class="ita-notification-body">
    <p id="notifica-top-start-title" class="ita-notification-title"><span>Notifica top-start</span></p>
    <p class="ita-notification-text">Aperta con popovertarget, senza JavaScript.</p>
  </div>
  <button type="button" class="ita-notification-close" popovertarget="notifica-top-start" popovertargetaction="hide" aria-label="Chiudi notifica"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12.7,12l3.7,3.6l-0.8,0.8L12,12.7l-3.6,3.7l-0.8-0.8l3.7-3.6L7.6,8.4l0.8-0.8l3.6,3.7l3.6-3.7l0.8,0.8L12.7,12z" /></svg></button>
  </div>
</div>
<div id="notifica-top-center" popover="manual" role="status" aria-labelledby="notifica-top-center-title" class="toast toast-top toast-center ita-toast">
  <div class="ita-notification ita-notification-success">
  <div class="ita-notification-body">
    <p id="notifica-top-center-title" class="ita-notification-title"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M17.1,7.9l0.7,0.7L10,16.2l-4.7-4.6L6,10.9l4,3.9L17.1,7.9z M22,12c0,5.5-4.5,10-10,10S2,17.5,2,12S6.5,2,12,2S22,6.5,22,12z M21,12c0-5-4-9-9-9s-9,4-9,9s4,9,9,9S21,17,21,12z" /></svg><span>Notifica top-center</span></p>
    <p class="ita-notification-text">Aperta con popovertarget, senza JavaScript.</p>
  </div>
  <button type="button" class="ita-notification-close" popovertarget="notifica-top-center" popovertargetaction="hide" aria-label="Chiudi notifica"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12.7,12l3.7,3.6l-0.8,0.8L12,12.7l-3.6,3.7l-0.8-0.8l3.7-3.6L7.6,8.4l0.8-0.8l3.6,3.7l3.6-3.7l0.8,0.8L12.7,12z" /></svg></button>
  </div>
</div>
<div id="notifica-top-end" popover="manual" role="status" aria-labelledby="notifica-top-end-title" class="toast toast-top toast-end ita-toast">
  <div class="ita-notification ita-notification-info">
  <div class="ita-notification-body">
    <p id="notifica-top-end-title" class="ita-notification-title"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,21c-5,0-9-4-9-9s4-9,9-9s9,4,9,9S17,21,12,21L12,21z M11.3,6h1.5v2h-1.5V6z M11.3,9h1.5v9h-1.5V9z" /></svg><span>Notifica top-end</span></p>
    <p class="ita-notification-text">Aperta con popovertarget, senza JavaScript.</p>
  </div>
  <button type="button" class="ita-notification-close" popovertarget="notifica-top-end" popovertargetaction="hide" aria-label="Chiudi notifica"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12.7,12l3.7,3.6l-0.8,0.8L12,12.7l-3.6,3.7l-0.8-0.8l3.7-3.6L7.6,8.4l0.8-0.8l3.6,3.7l3.6-3.7l0.8,0.8L12.7,12z" /></svg></button>
  </div>
</div>
<div id="notifica-bottom-start" popover="manual" role="alert" aria-labelledby="notifica-bottom-start-title" class="toast toast-bottom toast-start ita-toast">
  <div class="ita-notification ita-notification-warning">
  <div class="ita-notification-body">
    <p id="notifica-bottom-start-title" class="ita-notification-title"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,21c-5,0-9-4-9-9s4-9,9-9s9,4,9,9S17,21,12,21L12,21z M11.5,14.2V5.7h1.2v8.5H11.5z M11.4,16.5h1.2v1.8h-1.2V16.5z" /></svg><span>Notifica bottom-start</span></p>
    <p class="ita-notification-text">Aperta con popovertarget, senza JavaScript.</p>
  </div>
  <button type="button" class="ita-notification-close" popovertarget="notifica-bottom-start" popovertargetaction="hide" aria-label="Chiudi notifica"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12.7,12l3.7,3.6l-0.8,0.8L12,12.7l-3.6,3.7l-0.8-0.8l3.7-3.6L7.6,8.4l0.8-0.8l3.6,3.7l3.6-3.7l0.8,0.8L12.7,12z" /></svg></button>
  </div>
</div>
<div id="notifica-bottom-center" popover="manual" role="alert" aria-labelledby="notifica-bottom-center-title" class="toast toast-bottom toast-center ita-toast">
  <div class="ita-notification ita-notification-error">
  <div class="ita-notification-body">
    <p id="notifica-bottom-center-title" class="ita-notification-title"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M16.3,8.3L12.6,12l3.7,3.6l-0.7,0.7l-3.7-3.6l-3.6,3.6l-0.7-0.7l3.6-3.6L7.6,8.3l0.7-0.7l3.6,3.7l3.7-3.7L16.3,8.3z M22,12 c0,5.5-4.5,10-10,10S2,17.5,2,12S6.5,2,12,2S22,6.5,22,12z M21,12c0-5-4-9-9-9s-9,4-9,9s4,9,9,9S21,17,21,12z" /></svg><span>Notifica bottom-center</span></p>
    <p class="ita-notification-text">Aperta con popovertarget, senza JavaScript.</p>
  </div>
  <button type="button" class="ita-notification-close" popovertarget="notifica-bottom-center" popovertargetaction="hide" aria-label="Chiudi notifica"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12.7,12l3.7,3.6l-0.8,0.8L12,12.7l-3.6,3.7l-0.8-0.8l3.7-3.6L7.6,8.4l0.8-0.8l3.6,3.7l3.6-3.7l0.8,0.8L12.7,12z" /></svg></button>
  </div>
</div>
<div id="notifica-bottom-end" popover="manual" role="status" aria-labelledby="notifica-bottom-end-title" class="toast toast-bottom toast-end ita-toast">
  <div class="ita-notification">
  <div class="ita-notification-body">
    <p id="notifica-bottom-end-title" class="ita-notification-title"><span>Notifica bottom-end</span></p>
    <p class="ita-notification-text">Aperta con popovertarget, senza JavaScript.</p>
  </div>
  <button type="button" class="ita-notification-close" popovertarget="notifica-bottom-end" popovertargetaction="hide" aria-label="Chiudi notifica"><svg class="shrink-0 fill-current" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12.7,12l3.7,3.6l-0.8,0.8L12,12.7l-3.6,3.7l-0.8-0.8l3.7-3.6L7.6,8.4l0.8-0.8l3.6,3.7l3.6-3.7l0.8,0.8L12.7,12z" /></svg></button>
  </div>
</div>

Con JavaScript (opzionale)

La ricetta è solo CSS e funziona così com'è. Questi frammenti non sono inclusi nel pacchetto: mostrano come aggiungere il comportamento che richiede uno script, in JavaScript semplice o in React.

Chiusura automaticajs

Mostra la notifica popover e la chiude dopo qualche secondo; il timer si ferma al passaggio del mouse e al focus.

function notify(id, ms = 6000) {
  const el = document.getElementById(id);
  el.showPopover();
  let timer = setTimeout(() => el.hidePopover(), ms);
  const pause = () => clearTimeout(timer);
  const resume = () => (timer = setTimeout(() => el.hidePopover(), ms));
  el.addEventListener("mouseenter", pause);
  el.addEventListener("mouseleave", resume);
  el.addEventListener("focusin", pause);
  el.addEventListener("focusout", resume);
}
// notify("notifica-bottom-end");

Notifiche in Reacttsx

Una coda di notifiche in una regione aria-live, con chiusura automatica.

import { createContext, useCallback, useContext, useState, type ReactNode } from "react";

type Toast = { id: number; title: string; variant?: "success" | "error" | "info" | "warning" };
const Ctx = createContext<(t: Omit<Toast, "id">) => void>(() => {});
export const useNotify = () => useContext(Ctx);
const tone = { success: "ita-notification-success", error: "ita-notification-error", info: "ita-notification-info", warning: "ita-notification-warning" };

export function Notifications({ children }: { children: ReactNode }) {
  const [items, setItems] = useState<Toast[]>([]);
  const notify = useCallback((t: Omit<Toast, "id">) => {
    const id = Date.now();
    setItems((xs) => [...xs, { ...t, id }]);
    setTimeout(() => setItems((xs) => xs.filter((x) => x.id !== id)), 6000);
  }, []);
  return (
    <Ctx.Provider value={notify}>
      {children}
      <div className="toast toast-end" role="status" aria-live="polite">
        {items.map((t) => (
          <div key={t.id} className={"ita-notification " + tone[t.variant ?? "info"]}>
            <p className="ita-notification-title">{t.title}</p>
          </div>
        ))}
      </div>
    </Ctx.Provider>
  );
}