carbon-components-svelte icon indicating copy to clipboard operation
carbon-components-svelte copied to clipboard

Inline Notification - Ability to Reuse

Open natasha-f opened this issue 4 years ago • 1 comments

Would it be possible to open the ability to reuse the Inline Notification control, please? Right now, it appears there is no way to show a notification, hide it, and then show it again with either new or the same message. It is fairly common to display error messages or success messages in the same place of the page, depending on user actions.

natasha-f avatar May 10 '21 17:05 natasha-f

I wrote this as a separate component, can be opened/closed by changing open prop;

<script>
  /**
   * @event {{ timeout: boolean }} close
   */

  /**
   * Specify the kind of notification
   * @type {"error" | "info" | "info-square" | "success" | "warning" | "warning-alt"}
   */
  export let kind = "error";

  /** Set to `true` to use the low contrast variant */
  export let lowContrast = false;

  /** Set the timeout duration (ms) to hide the notification after opening it */
  export let timeout = 0;

  /** Set the `role` attribute */
  export let role = "alert";

  /** Specify the title text */
  export let title = "";

  /** Specify the subtitle text */
  export let subtitle = "";

  /** Set to `true` to hide the close button */
  export let hideCloseButton = false;

  /** Specify the ARIA label for the icon */
  export let iconDescription = "Closes notification";

  let timeoutId = undefined;
  export let open = false;
  $: if (open) { 
    clearTimeout(timeoutId)
    timeoutId = setTimeout(() => close(true), timeout)
  } else {
    clearTimeout(timeoutId)
  }

  import { createEventDispatcher, onMount } from "svelte";
  import { NotificationIcon } from "carbon-components-svelte";
  import { NotificationButton } from "carbon-components-svelte";

  const dispatch = createEventDispatcher();

  function close(closeFromTimeout) {
    const shouldContinue = dispatch(
      "close",
      { timeout: closeFromTimeout === true },
      { cancelable: true }
    );
    if (shouldContinue) {
      open = false;
    }
    if (timeoutId) clearTimeout(timeoutId)
  }

  onMount(() => {
    if (timeout) {
      timeoutId = setTimeout(() => close(true), timeout);
    }

    return () => {
      clearTimeout(timeoutId);
    };
  });
</script>

<!-- svelte-ignore a11y-mouse-events-have-key-events -->
{#if open}
  <div
    role="{role}"
    kind="{kind}"
    class:bx--inline-notification="{true}"
    class:bx--inline-notification--low-contrast="{lowContrast}"
    class:bx--inline-notification--hide-close-button="{hideCloseButton}"
    class:bx--inline-notification--error="{kind === 'error'}"
    class:bx--inline-notification--info="{kind === 'info'}"
    class:bx--inline-notification--info-square="{kind === 'info-square'}"
    class:bx--inline-notification--success="{kind === 'success'}"
    class:bx--inline-notification--warning="{kind === 'warning'}"
    class:bx--inline-notification--warning-alt="{kind === 'warning-alt'}"
    {...$$restProps}
    on:click
    on:mouseover
    on:mouseenter
    on:mouseleave
  >
    <div class:bx--inline-notification__details="{true}">
      <NotificationIcon notificationType="inline" kind="{kind}" />
      <div class:bx--inline-notification__text-wrapper="{true}">
        <p class:bx--inline-notification__title="{true}">
          <slot name="title">{title}</slot>
        </p>
        <div class:bx--inline-notification__subtitle="{true}">
          <slot name="subtitle">{subtitle}</slot>
        </div>
        <slot />
      </div>
    </div>
    <slot name="actions" />
    {#if !hideCloseButton}
      <NotificationButton
        iconDescription="{iconDescription}"
        notificationType="inline"
        on:click="{close}"
      />
    {/if}
  </div>
{/if}

i-void avatar Nov 12 '22 08:11 i-void