diff options
| -rw-r--r-- | apps/kit/src/lib/components/alert.svelte | 220 | ||||
| -rw-r--r-- | apps/kit/src/routes/book/+page.svelte | 1 | ||||
| -rw-r--r-- | apps/kit/src/routes/book/alerts/+page.svelte | 13 |
3 files changed, 166 insertions, 68 deletions
diff --git a/apps/kit/src/lib/components/alert.svelte b/apps/kit/src/lib/components/alert.svelte index 53aa783..6cc0e63 100644 --- a/apps/kit/src/lib/components/alert.svelte +++ b/apps/kit/src/lib/components/alert.svelte @@ -11,30 +11,74 @@ XMark, } from "./icons"; + const dispatch = createEventDispatcher(); const noCooldownSetting = "no-cooldown"; + + let iconComponent: any; + let colorClassPart = ""; + // if no unique id is supplied, cooldown will not work between page loads. // Therefore we are disabling it with noCooldownSetting in the fallback id. + /** + * An optional id for this alert, a default is set if not specified. + * This value is necessary for closeable cooldown to work. + */ export let id = "alert--" + noCooldownSetting + "--" + random_string(4); + /** + * The title to communicate, value is optional + */ export let title = ""; + /** + * The message to communicate, value is optional + */ export let message = ""; + /** + * Changes the alerts color and icon. + */ export let type: "info" | "success" | "warning" | "error" = "info"; + /** + * If true the alert can be removed from the DOM by clicking on a X icon on the upper right hand courner + */ export let closeable = false; + /** + * The amount of seconds that should go by before this alert is shown again, only works when a unique id is set. + * Set to ~ if it should be only shown once per client (State stored in localestorage). + **/ export let closeableCooldown = "-1"; + /** + * The text that is displayed on the right link + */ export let rightLinkText = ""; + /** + * An array of list items displayed under the message or title + */ export let listItems: Array<string> = []; + /** + * An array of {id:string;text:string;color?:string}, where id is dispatched back as an svelte event with this syntax act$id (ex: on:actcancel). + * Text is the button text + * Color is the optional tailwind color to used, the value is used in classes like bg-$color-50. + */ export let actions: Array<{ id: string; text: string; color?: string }> = []; - // This value is set on a plain anchor tag without any svelte routing, - // listen to the rightLinkClick if you want to intercept the click without navigating + /** + * This value is set on a plain anchor tag without any svelte routing, + * listen to the on:rightLinkClick if you want to intercept the click without navigating + */ export let rightLinkHref = "javascript:void(0)"; - export let visible = true; + $: cooldownEnabled = + id.indexOf(noCooldownSetting) === -1 && + closeable && + (closeableCooldown === "~" || parseInt(closeableCooldown) > 0); + /** + * Sets this alerts visibility state, when this is false it is removed from the dom using svelte a {#if} block. + */ + export let visible = + closeableCooldown === "~" || parseInt(closeableCooldown) > 0 + ? false + : true; - const dispatch = createEventDispatcher(); const cooldownStorageKey = "lastseen--" + id; - let iconComponent: any; - let colorClassPart = ""; - $: switch (type) { case "info": { colorClassPart = "blue"; @@ -58,11 +102,6 @@ } } - $: cooldownEnabled = - id.indexOf(noCooldownSetting) === -1 && - closeable && - (closeableCooldown === "~" || parseInt(closeableCooldown) > 0); - function close() { visible = false; if (cooldownEnabled) { @@ -83,7 +122,7 @@ } function actionClicked(name: string) { - dispatch("act-" + name); + dispatch("act" + name); } // Manages the state of the alert if cooldown is enabled @@ -97,12 +136,12 @@ visible = true; return; } - if (!visible) { - console.log( - "Alert " + id + " is not visible, stopping cooldown change" - ); - return; - } + // if (!visible) { + // console.log( + // "Alert " + id + " is not visible, stopping cooldown change" + // ); + // return; + // } if (closeableCooldown === "~") { console.log("Alert " + id + " has an infinite cooldown, hiding"); visible = false; @@ -137,6 +176,19 @@ if (cooldownEnabled) { run_cooldown(); } + + if ( + closeable && + closeableCooldown && + id.indexOf(noCooldownSetting) !== -1 + ) { + // TODO: This prints twice before shutting up as it should, in this example look at the only alert with closeableCooldown in alertsbook. + // Looks like svelte mounts three times and that my id is only set on the third. Not sure it does at all after logging the id onMount. + console.error( + "Alert cooldown does not work without specifying a unique id, related id: " + + id + ); + } }); </script> @@ -149,52 +201,85 @@ class="text-{colorClassPart}-400" /> </div> - <div class="ml-3"> - {#if title} - <h3 class="text-sm font-medium text-{colorClassPart}-800"> - {title} - </h3> - {/if} - {#if message} - <div - class="{title - ? 'mt-2 text-sm' - : ''} text-{colorClassPart}-700" - > - <p> - {@html message} - {#if rightLinkText} - <p class="mt-3 text-sm md:mt-0 md:ml-6"> - <a - href={rightLinkHref} - on:click={() => rightLinkClicked()} - class="whitespace-nowrap font-medium text-{colorClassPart}-700 hover:text-{colorClassPart}-600" - > - {rightLinkText} - <span aria-hidden="true"> →</span> - </a> - </p> + <div class="ml-3 text-sm w-full"> + {#if !rightLinkText} + {#if title} + <h3 class="font-medium text-{colorClassPart}-800"> + {title} + </h3> + {/if} + {#if message} + <div + class="{title + ? 'mt-2' + : ''} text-{colorClassPart}-700 justify-start" + > + <p> + {@html message} + </p> + </div> + {/if} + {#if listItems?.length ?? 0} + <ul + class="list-disc space-y-1 pl-5 text-{colorClassPart}-700" + > + {#each listItems as listItem} + <li>{listItem}</li> + {/each} + </ul> + {/if} + {:else} + <div class="flex-1 md:flex md:justify-between"> + <div> + {#if title} + <h3 + class="font-medium text-{colorClassPart}-800" + > + {title} + </h3> {/if} + {#if message} + <div + class="{title + ? 'mt-2' + : ''} text-{colorClassPart}-700 justify-start" + > + <p> + {@html message} + </p> + </div> + {/if} + {#if listItems?.length ?? 0} + <ul + class="list-disc space-y-1 pl-5 text-{colorClassPart}-700" + > + {#each listItems as listItem} + <li>{listItem}</li> + {/each} + </ul> + {/if} + </div> + <p class="mt-3 text-sm md:mt-0 md:ml-6 flex items-end"> + <a + href={rightLinkHref} + on:click={() => rightLinkClicked()} + class="whitespace-nowrap font-medium text-{colorClassPart}-700 hover:text-{colorClassPart}-600" + > + {rightLinkText} + <span aria-hidden="true"> →</span> + </a> </p> - {#if listItems?.length ?? 0} - <ul class="list-disc space-y-1 pl-5"> - {#each listItems as listItem} - <li>{listItem}</li> - {/each} - </ul> - {/if} </div> {/if} - </div> - {#if actions?.length ?? 0} - <div class="mt-4"> - <div class="-mx-2 -my-1.5 flex"> - {#each actions as action} - {@const color = action?.color ?? colorClassPart} - <button - type="button" - on:click={() => actionClicked(action.id)} - class="rounded-md + {#if actions?.length ?? 0} + <div class="ml-2 mt-4"> + <div class="-mx-2 -my-1.5 flex gap-1"> + {#each actions as action} + {@const color = action?.color ?? colorClassPart} + <button + type="button" + on:click={() => actionClicked(action.id)} + class="rounded-md bg-{color}-50 px-2 py-1.5 text-sm font-medium text-{color}-800 @@ -203,13 +288,14 @@ focus:ring-{color}-600 focus:ring-offset-2 focus:ring-offset-{color}-50" - > - {action.text} - </button> - {/each} + > + {action.text} + </button> + {/each} + </div> </div> - </div> - {/if} + {/if} + </div> {#if closeable} <div class="ml-auto pl-3"> <div class="-mx-1.5 -my-1.5"> diff --git a/apps/kit/src/routes/book/+page.svelte b/apps/kit/src/routes/book/+page.svelte index e69de29..635b3c2 100644 --- a/apps/kit/src/routes/book/+page.svelte +++ b/apps/kit/src/routes/book/+page.svelte @@ -0,0 +1 @@ +<p>A showcase of greatoffices components</p> diff --git a/apps/kit/src/routes/book/alerts/+page.svelte b/apps/kit/src/routes/book/alerts/+page.svelte index 93b4850..566ccca 100644 --- a/apps/kit/src/routes/book/alerts/+page.svelte +++ b/apps/kit/src/routes/book/alerts/+page.svelte @@ -26,6 +26,7 @@ type="info" message="This is message" title="This is title" + closeable actions={[ { id: "confirm", @@ -45,6 +46,8 @@ <Alert on:rightLinkCliked={() => alert("Right link clicked")} rightLinkText="Link or action" + title="Go here" + message="Hehe" type="info" /> </section> @@ -53,7 +56,15 @@ <Alert title="This is title" listItems={["Message 1", "Message 2"]} - type="info" + type="error" + message="This is bad dude" + closeable + closeableCooldown="60" + id="alert-1" + on:actrepeat={() => { + alert("Repeat requested"); + }} + actions={[{ id: "repeat", text: "Try again" }]} /> </section> <section> |
