דילוג לתוכן
uiify

Toast

תור של הודעות קצרות מועד.

דפדפנים
Chrome 114+Firefox 125+Safari 17+
שכבה
1
גודל חבילה דחוסה
2.87 kB
מגבלת פריסה כפויה
0 ms
מגבלת Axe
0
תואם SSR
כן
חוזה מפורסם
סביבת בדיקות

מגרש ניסויים

Toast

אזור תצוגה

"use client";

import { Toast, useToast } from "@gunkin/uiify";

function ShowToast() {
  const { toast } = useToast();
  return (
    <button className="" type="button" onClick={() => toast({ title: "Saved" })}>
      Save
    </button>
  );
}

export default function Example() {
  return (
    <Toast.Provider>
      <ShowToast />
      <Toast.Viewport className="" />
    </Toast.Provider>
  );
}
/* Toast — a fixed viewport stacking cards in the corner, promoted to the top
   layer via [popover]. inset: auto overrides the UA popover default of
   inset: 0 so the corner offsets below can apply; the top-layer stack is
   ordered by show order, not z-index, so no manual z-index is needed. Cards
   use `data-part="item"`. Cards enter, leave, and restack through React view
   transitions (view-transition-class `uiify-toast`) with the shared presence
   motion; the snapshots hang off the root, so they read root tokens only. */

@layer components {
  [data-uiify-toast] [data-part="viewport"]:where(:not([popover]), :popover-open),
  [data-uiify-toast][data-part="viewport"]:where(:not([popover]), :popover-open) {
    display: flex;
  }

  [data-uiify-toast] [data-part="viewport"],
  [data-uiify-toast][data-part="viewport"] {
    position: fixed;
    inset: auto;
    inset-block-end: var(--space-lg);
    inset-inline-end: var(--space-lg);
    flex-direction: column;
    gap: var(--space-sm);
    inline-size: min(24rem, calc(100vw - 2 * var(--space-lg)));
    margin: 0;
    padding: 0;

    /* Cancels the UA popover default (`border: solid` + Canvas background) —
       the viewport is a transparent stacking container; cards carry their
       own border and background. */
    border: none;
    background: none;
    list-style: none;
  }

  [data-uiify-toast] [data-part="item"],
  [data-uiify-toast][data-part="viewport"] [data-part="item"] {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    padding: var(--space-md) var(--space-lg);
    border: var(--border-width) solid var(--border);
    border-radius: var(--radius-lg);
    background-color: var(--popover);
    color: var(--popover-foreground);
    box-shadow: var(--shadow-popover);
    margin: 0;
    min-inline-size: 0;
  }

  [data-uiify-toast] [data-part="close"] {
    align-self: flex-end;
    min-block-size: 30px;
    padding-block: 0;
    padding-inline: var(--space-sm);
    border: 0;
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--popover-foreground);
    font: inherit;
    cursor: pointer;
  }

  [data-uiify-toast] [data-part="close"]:focus-visible {
    outline: 2px solid var(--ring);
    outline-offset: 2px;
  }

  @media (hover: hover) and (pointer: fine) {
    [data-uiify-toast] [data-part="close"]:hover {
      background-color: var(--accent);
      color: var(--accent-foreground);
    }
  }

  @media (prefers-reduced-motion: no-preference) {
    ::view-transition-group(.uiify-toast) {
      animation-duration: var(--duration-fast);
      animation-timing-function: var(--ease-out);
    }

    ::view-transition-new(.uiify-toast):only-child {
      animation: uiify-presence-in var(--duration-fast) var(--ease-out) both;
    }

    ::view-transition-old(.uiify-toast):only-child {
      animation: uiify-presence-out var(--duration-fast) var(--ease-out) both;
    }
  }

  @keyframes uiify-presence-in {
    from {
      opacity: 0;
      scale: var(--presence-scale);
    }
  }

  @keyframes uiify-presence-out {
    to {
      opacity: 0;
      scale: var(--presence-scale);
    }
  }
}
"use client";

import { Toast, useToast } from "@gunkin/uiify";

function ShowToast() {
  const { toast } = useToast();
  return (
    <button
      className={
        "relative isolate inline-flex items-center justify-center gap-1.5 min-h-10 min-w-10 px-5 py-px border-[lengt" +
        "h:var(--border-width)] border-solid border-transparent rounded-full bg-clip-padding text-base font-medium l" +
        "eading-6 no-underline cursor-pointer [transition:var(--transition-colors)] focus-visible:[outline:none] foc" +
        "us-visible:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_20%,_transparent)] disabled:" +
        "opacity-50 disabled:cursor-not-allowed data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed [&:is(" +
        "[data-selected],[aria-pressed=true],[aria-current=page])]:[--uiify-button-rim:rgb(255_255_255_/_20%)] [&:is" +
        "([data-selected],[aria-pressed=true],[aria-current=page])]:[--uiify-button-wash:rgb(255_255_255_/_15%)] [&:" +
        "is([data-selected],[aria-pressed=true],[aria-current=page])]:border-transparent [&:is([data-selected],[aria" +
        "-pressed=true],[aria-current=page])]:bg-primary [&:is([data-selected],[aria-pressed=true],[aria-current=pag" +
        "e])]:text-primary-foreground [:checked+&]:[--uiify-button-rim:rgb(255_255_255_/_20%)] [:checked+&]:[--uiify" +
        "-button-wash:rgb(255_255_255_/_15%)] [:checked+&]:border-transparent [:checked+&]:bg-primary [:checked+&]:t" +
        "ext-primary-foreground [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:[&:is([data-selected],[aria-pres" +
        "sed=true],[aria-current=page]):hover:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_" +
        "var(--primary)_88%,_var(--primary-foreground))] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:[:check" +
        "ed:not(:disabled)+&:hover]:[background-color:color-mix(in_oklch,_var(--primary)_88%,_var(--primary-foregrou" +
        "nd))] bg-foreground text-background [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:hover:[&:not(:disab" +
        "led,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_90%,_var(--background))] acti" +
        "ve:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_80%,_var(--ba" +
        "ckground))]"
      }
      type="button"
      onClick={() => toast({ title: "Saved" })}
    >
      Save
    </button>
  );
}

export default function Example() {
  return (
    <Toast.Provider>
      <ShowToast />
      <Toast.Viewport
        className="
          fixed [inset:auto] [inset-block-end:var(--space-lg)] [inset-inline-end:var(--space-lg)] flex-col gap-sm
          [inline-size:min(24rem,calc(100vw_-_2_*_var(--space-lg)))] m-0 p-0 border-0 border-none bg-transparent
          list-none [&:where(:not([popover]),:popover-open)]:flex [&_[data-part=item]]:flex
          [&_[data-part=item]]:flex-col [&_[data-part=item]]:gap-xs
          [&_[data-part=item]]:[padding:var(--space-md)_var(--space-lg)]
          [&_[data-part=item]]:border-[length:var(--border-width)] [&_[data-part=item]]:border-solid
          [&_[data-part=item]]:border-border [&_[data-part=item]]:rounded-lg [&_[data-part=item]]:bg-popover
          [&_[data-part=item]]:text-popover-foreground [&_[data-part=item]]:shadow-popover [&_[data-part=item]]:m-0
          [&_[data-part=item]]:[min-inline-size:0] [&_[data-part=close]]:self-end
          [&_[data-part=close]]:[min-block-size:30px] [&_[data-part=close]]:py-0 [&_[data-part=close]]:px-sm
          [&_[data-part=close]]:border-0 [&_[data-part=close]]:border-none [&_[data-part=close]]:rounded-md
          [&_[data-part=close]]:bg-transparent [&_[data-part=close]]:text-popover-foreground
          [&_[data-part=close]]:cursor-pointer [&_[data-part=close]:focus-visible]:outline-2
          [&_[data-part=close]:focus-visible]:outline-ring [&_[data-part=close]:focus-visible]:outline-offset-2
          [@media_(hover:_hover)_and_(pointer:_fine)]:[&_[data-part=close]:hover]:bg-accent
          [@media_(hover:_hover)_and_(pointer:_fine)]:[&_[data-part=close]:hover]:text-accent-foreground
        "
      />
    </Toast.Provider>
  );
}

API

Toast.Provider

מאפייןטיפוסברירת מחדלתיאור
limitnumber3המספר המרבי של הודעות זמניות הנשמרות בתור; הישנות יותר מוסרות.
slotPropsToastProviderSlotProps—מאפיינים לאלמנטים של האזורים החיים המנומסים והנחרצים.
childrenReactNode—העץ שיכול לקרוא ל-useToast ולהציג אזור תצוגה.

Toast.Viewport

מאפייןטיפוסברירת מחדלתיאור
aria-labelstring—שם נגיש לאזור המכיל את ההודעות הזמניות שבתור.
classNamestring—המחלקה המוחלת על אלמנט אזור התצוגה.
popover"manual"—מוגדר על ידי אזור התצוגה החי בצד הלקוח כדי שהתור המוצג יהיה בשכבה העליונה; מעטפת השרת משאירה אותו ללא ערך.
refRef<HTMLElement>—ref לאלמנט אזור התצוגה.
slotPropsToastViewportSlotProps—מאפיינים לכרטיסי הודעות זמניות ולתוכן שהם יוצרים; ניתן למקד משבצות חוזרות לפי מזהה הודעה.
childrenReactNode—תוכן נוסף המוצג בתוך אזור התצוגה לצד ההודעות הזמניות שבתור.

Toast.Root

מאפייןטיפוסברירת מחדלתיאור
classNamestring—המחלקה המוחלת על כרטיס ההודעה הזמנית.
styleCSSProperties—סגנונות מוטבעים המוחלים על כרטיס ההודעה הזמנית.
refRef<HTMLDivElement>—ref לאלמנט כרטיס ההודעה הזמנית.
slotPropsToastRootSlotProps—מאפיינים לכרטיסי הודעות זמניות ולתוכן שהם יוצרים; ניתן למקד משבצות חוזרות לפי מזהה הודעה.
toast*ToastRecord—הרשומה מהתור להצגה, עם id, כותרת, תיאור, פעולה, משך ועדיפות לאחר קביעת ערכיהם.

Toast.Title

מאפייןטיפוסברירת מחדלתיאור
classNamestring—המחלקה המוחלת על אלמנט הכותרת.
childrenReactNode—תוכן הכותרת.

Toast.Description

מאפייןטיפוסברירת מחדלתיאור
classNamestring—המחלקה המוחלת על אלמנט התיאור.
childrenReactNode—תוכן התיאור.

Toast.Action

מאפייןטיפוסברירת מחדלתיאור
classNamestring—המחלקה המוחלת על כפתור הפעולה.
onClick(event: MouseEvent<HTMLButtonElement>) => void—נקראת בלחיצה על כפתור הפעולה.
childrenReactNode—תוכן כפתור הפעולה.

Toast.Close

מאפייןטיפוסברירת מחדלתיאור
classNamestring—המחלקה המוחלת על כפתור הסגירה.
onClick(event: MouseEvent<HTMLButtonElement>) => void—נקראת בלחיצה על כפתור הסגירה.
childrenReactNode—תוכן כפתור הסגירה.

useToast().toast(input)

מאפייןטיפוסברירת מחדלתיאור
titleReactNode—שורת הכותרת של ההודעה הזמנית.
descriptionReactNode—שורה משלימה מתחת לכותרת.
action{ label: ReactNode; onClick: () => void }—תווית ומטפל אירוע לכפתור פעולה יחיד בהודעה הזמנית.
durationnumber4000מספר אלפיות השנייה לפני שההודעה הזמנית נסגרת מעצמה; אפס או פחות משאירים אותה עד לסגירה מפורשת.
priority"polite" | "assertive""polite"האזור החי שיכריז על ההודעה הזמנית.
idstring—מזהה ההודעה הזמנית; נוצר אוטומטית כשהוא מושמט.

מקלדת

מקשפעולה
Tabמיקוד כפתורי פעולה בתוך ההודעה
Escapeסגירה כאשר ניתן לסגור

נגישות

הכרזות polite/assertive באזור חי; הוספה לתור אינה מזיזה את המיקוד, וריחוף או מיקוד משהים סגירה אוטומטית.

נקודות חיבור לעיצוב

data-statedata-part="item"data-part="title"data-part="description"data-part="action"data-part="close"
דף זה תורגם אוטומטית וטרם נבדק.