Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic Toast component #487

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/shaggy-roses-attack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte-ux': minor
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you do not select any packages when prompted for major and minor, it will produce a patch changeset (I think the flow is a little odd to be honest, but that's driven by the changesets project).

The flow is different when using changesets in a multi-package monorepo (like Svelte UX)...

image

vs a single-package repo (like LayerChart at the moment)...

image

The single package is much more straight forward.
At some point LayerChart might become multi-package.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With that said you can manually edit this .md file and just change minor to patch (all the CLI does is help you write this file, including generating a filename)

---

Add toast components
14 changes: 14 additions & 0 deletions packages/svelte-ux/src/lib/components/Toast.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script lang="ts">
import toastStore from '$lib/stores/toastStore.js';
import Notification from './Notification.svelte';
</script>

<div class="fixed bottom-0 left-1/2 translate-x-[-50%] z-50 gap-y-4">
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could see us adding a placement prop to control which of the 8 corners/edges to place the notifications (at least top-left, top, top-right, bottom-left, bottom, bottom-right).

you can see some examples of this in Drawer and Badge

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would also be good if Toast supported class overrides, either directly (<Toast classes={...}>) or via settings.

To support this, you would need to add a classes prop and also getting the classes defined in settings(...) using...

<script>
  ...

  export let classes: {
    root?: string;
    actions?: string;
    // ...any other internal element/component you might want to pass a class to
  } = {};
  const settingsClasses = getComponentClasses('Toast');
</script>

and change...

<div class="fixed bottom-0 left-1/2 translate-x-[-50%] z-50 gap-y-4">

to

<div
    class={cls(
      'Toast',
      'fixed bottom-0 left-1/2 translate-x-[-50%] z-50 gap-y-4',
      settingsClasses.root,
      classes.root,
      $$props.class
    )}
>

{#each $toastStore as toast}
<div class="mt-4">
<Notification open={true} closeIcon>
<span slot="title">{toast.text}</span>
</Notification>
</div>
{/each}
</div>
1 change: 1 addition & 0 deletions packages/svelte-ux/src/lib/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export { default as ThemeInit } from './ThemeInit.svelte';
export { default as Tilt } from './Tilt.svelte';
export { default as Timeline } from './Timeline.svelte';
export { default as TimelineEvent } from './TimelineEvent.svelte';
export { default as Toast } from './Toast.svelte';
export { default as Toggle } from './Toggle.svelte';
export { default as ToggleButton } from './ToggleButton.svelte';
export { default as ToggleGroup } from './ToggleGroup.svelte';
Expand Down
31 changes: 31 additions & 0 deletions packages/svelte-ux/src/lib/stores/toastStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { get, writable } from 'svelte/store';

const DEFAULT_TOAST_TIME_IN_MS = 3000;

export type Toast = {
text: string;
timeAdded: Date;
};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not to feature creep this too much, but also consider a little bit more future state, I'm thinking the the type could be:

export type Toast = {
  title: string;
  description?: string;
  actions?: Record<string, Function>; // this will need more thought to support primary styling, etc
  icon?: IconInput;
  variant?: string;
  timeAdded: Date;
};

variant would need to wait til #86 is tackled, but it's not a big lift (mostly just taking the styles from the doc examples. See ToggleGroup for a semi-related example (there are other components with variant as well).

image


/**
* Create a global store to save information on toast components
*/
const toastStore = writable<Toast[]>([]);

export function addToast(text: string, durationInMS = DEFAULT_TOAST_TIME_IN_MS) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would want to change text: string into an object to support the various additional inputs (description, icon, actions, etc)

const timeAdded = new Date();
const toast: Toast = {
text,
timeAdded,
};
toastStore.set([...get(toastStore), toast]);

setTimeout(() => {
const remainingToasts = [...get(toastStore)].filter((toast) => {
return toast.timeAdded != timeAdded;
});
toastStore.set(remainingToasts);
}, durationInMS);
}

export default toastStore;
1 change: 1 addition & 0 deletions packages/svelte-ux/src/routes/_NavMenu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
'ResponsiveMenu',
'Notification',
'Popover',
'Toast',
'Tooltip',
],
Feedback: ['Badge', 'Progress', 'ProgressCircle'],
Expand Down
22 changes: 22 additions & 0 deletions packages/svelte-ux/src/routes/docs/components/Toast/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="ts">
import { Button } from 'svelte-ux';
import { Toast } from 'svelte-ux';
import { addToast } from '$lib/stores/toastStore.js';

function addSimpleToast() {
addToast('This is a simple toast!');
}

function addLongerToast() {
addToast('This is a longer toast!', 10000);
}
</script>

<h1>Examples</h1>

<Toast />
<h2>Add Simple Toast</h2>
<Button variant="fill-outline" color="primary" on:click={addSimpleToast}>Click Me</Button>

<h2>Add Longer Toast</h2>
<Button variant="fill-outline" color="primary" on:click={addLongerToast}>Click Me</Button>
16 changes: 16 additions & 0 deletions packages/svelte-ux/src/routes/docs/components/Toast/+page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import api from '$lib/components/Toast.svelte?raw&sveld';
import source from '$lib/components/Toast.svelte?raw';
import pageSource from './+page.svelte?raw';

export async function load() {
return {
meta: {
api,
source,
pageSource,
description:
'Adds the ability to include Toast popup notifications that go away after a couple of seconds.',
related: ['components/Notification', '/customization'],
},
};
}