|
| 1 | +// |
| 2 | + |
| 3 | +import { Htmx_Events } from "@~/app.core/htmx"; |
| 4 | +import type { Child, PropsWithChildren } from "hono/jsx"; |
| 5 | +import type { VariantProps } from "tailwind-variants"; |
| 6 | +import { toast } from "../index"; |
| 7 | + |
| 8 | +// |
| 9 | + |
| 10 | +export const DefaultToast = CommonToastFactory( |
| 11 | + <svg |
| 12 | + class="h-4 w-4" |
| 13 | + aria-hidden="true" |
| 14 | + xmlns="http://www.w3.org/2000/svg" |
| 15 | + fill="none" |
| 16 | + viewBox="0 0 18 20" |
| 17 | + > |
| 18 | + <path |
| 19 | + stroke="currentColor" |
| 20 | + stroke-linecap="round" |
| 21 | + stroke-linejoin="round" |
| 22 | + stroke-width="2" |
| 23 | + d="M15.147 15.085a7.159 7.159 0 0 1-6.189 3.307A6.713 6.713 0 0 1 3.1 15.444c-2.679-4.513.287-8.737.888-9.548A4.373 4.373 0 0 0 5 1.608c1.287.953 6.445 3.218 5.537 10.5 1.5-1.122 2.706-3.01 2.853-6.14 1.433 1.049 3.993 5.395 1.757 9.117Z" |
| 24 | + /> |
| 25 | + </svg>, |
| 26 | + "Fire icon", |
| 27 | +); |
| 28 | + |
| 29 | +export const SuccessToast = CommonToastFactory( |
| 30 | + <svg |
| 31 | + class="h-5 w-5" |
| 32 | + aria-hidden="true" |
| 33 | + xmlns="http://www.w3.org/2000/svg" |
| 34 | + fill="currentColor" |
| 35 | + viewBox="0 0 20 20" |
| 36 | + > |
| 37 | + <path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z" /> |
| 38 | + </svg>, |
| 39 | + "Check icon", |
| 40 | +); |
| 41 | + |
| 42 | +export const ErrorToast = CommonToastFactory( |
| 43 | + <svg |
| 44 | + class="h-5 w-5" |
| 45 | + aria-hidden="true" |
| 46 | + xmlns="http://www.w3.org/2000/svg" |
| 47 | + fill="currentColor" |
| 48 | + viewBox="0 0 20 20" |
| 49 | + > |
| 50 | + <path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 11.793a1 1 0 1 1-1.414 1.414L10 11.414l-2.293 2.293a1 1 0 0 1-1.414-1.414L8.586 10 6.293 7.707a1 1 0 0 1 1.414-1.414L10 8.586l2.293-2.293a1 1 0 0 1 1.414 1.414L11.414 10l2.293 2.293Z" /> |
| 51 | + </svg>, |
| 52 | + "Error icon", |
| 53 | +); |
| 54 | + |
| 55 | +export const WarningToast = CommonToastFactory( |
| 56 | + <svg |
| 57 | + class="h-5 w-5" |
| 58 | + aria-hidden="true" |
| 59 | + xmlns="http://www.w3.org/2000/svg" |
| 60 | + fill="currentColor" |
| 61 | + viewBox="0 0 20 20" |
| 62 | + > |
| 63 | + <path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM10 15a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-4a1 1 0 0 1-2 0V6a1 1 0 0 1 2 0v5Z" /> |
| 64 | + </svg>, |
| 65 | + "Warning icon", |
| 66 | +); |
| 67 | + |
| 68 | +export function ToasterContainer() { |
| 69 | + return ( |
| 70 | + <div class="fixed bottom-4 left-4 z-50 flex flex-col gap-2"> |
| 71 | + <template> |
| 72 | + <DefaultToast>DefaultToast</DefaultToast> |
| 73 | + </template> |
| 74 | + <template> |
| 75 | + <SuccessToast variant={{ color: "success" }}>SuccessToast</SuccessToast> |
| 76 | + </template> |
| 77 | + <template |
| 78 | + _={` |
| 79 | + on every ${Htmx_Events.enum.responseError} from body |
| 80 | + render me then put it after me |
| 81 | + `} |
| 82 | + > |
| 83 | + <ErrorToast variant={{ color: "danger" }}> |
| 84 | + Une erreur est survenue ! |
| 85 | + </ErrorToast> |
| 86 | + </template> |
| 87 | + <template> |
| 88 | + <WarningToast variant={{ color: "warning" }}>WarningToast</WarningToast> |
| 89 | + </template> |
| 90 | + </div> |
| 91 | + ); |
| 92 | +} |
| 93 | + |
| 94 | +export function CommonToastFactory(iconNode: Child, title: string) { |
| 95 | + return function Toast(props: ToastProps) { |
| 96 | + const { children, variant } = props; |
| 97 | + const { base, body, icon, close_button } = toast(variant); |
| 98 | + |
| 99 | + return ( |
| 100 | + <div class={base()} role="alert"> |
| 101 | + <div class={icon()}> |
| 102 | + {iconNode} |
| 103 | + <span class="sr-only">{title}</span> |
| 104 | + </div> |
| 105 | + <div class={body()}>{children}</div> |
| 106 | + <button |
| 107 | + _="on click remove closest <div[role='alert']/> " |
| 108 | + type="button" |
| 109 | + class={close_button()} |
| 110 | + aria-label="Close" |
| 111 | + > |
| 112 | + <span class="sr-only">Close</span> |
| 113 | + <svg |
| 114 | + class="h-3 w-3" |
| 115 | + aria-hidden="true" |
| 116 | + xmlns="http://www.w3.org/2000/svg" |
| 117 | + fill="none" |
| 118 | + viewBox="0 0 14 14" |
| 119 | + > |
| 120 | + <path |
| 121 | + stroke="currentColor" |
| 122 | + stroke-linecap="round" |
| 123 | + stroke-linejoin="round" |
| 124 | + stroke-width="2" |
| 125 | + d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" |
| 126 | + /> |
| 127 | + </svg> |
| 128 | + </button> |
| 129 | + </div> |
| 130 | + ); |
| 131 | + }; |
| 132 | +} |
| 133 | + |
| 134 | +type ToastProps = PropsWithChildren<{ |
| 135 | + variant?: VariantProps<typeof toast>; |
| 136 | +}>; |
0 commit comments