mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-15 02:11:05 +00:00
parent
422ac528a7
commit
94dceae1fb
11 changed files with 309 additions and 2 deletions
|
@ -28,9 +28,16 @@ Currently, the following components are supported:
|
||||||
- CopyButton
|
- CopyButton
|
||||||
- DataTableSkeleton
|
- DataTableSkeleton
|
||||||
- InlineLoading
|
- InlineLoading
|
||||||
- Loading
|
|
||||||
- Link
|
- Link
|
||||||
- ListItem
|
- ListItem
|
||||||
|
- Loading
|
||||||
|
- Notification
|
||||||
|
- ToastNotification
|
||||||
|
- InlineNotification
|
||||||
|
- NotificationActionButton
|
||||||
|
- NotificationButton
|
||||||
|
- NotificationIcon
|
||||||
|
- NotificationTextDetails
|
||||||
- OrderedList
|
- OrderedList
|
||||||
- RadioButton
|
- RadioButton
|
||||||
- RadioButtonSkeleton
|
- RadioButtonSkeleton
|
||||||
|
|
54
src/components/Notification/InlineNotification.svelte
Normal file
54
src/components/Notification/InlineNotification.svelte
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
<script>
|
||||||
|
let className = undefined;
|
||||||
|
export { className as class };
|
||||||
|
export let kind = 'error';
|
||||||
|
export let title = 'provide a title';
|
||||||
|
export let subtitle = ''; // TODO: support subtitle slot?
|
||||||
|
export let role = 'alert';
|
||||||
|
export let notificationType = 'inline';
|
||||||
|
export let iconDescription = 'closes notification';
|
||||||
|
export let hideCloseButton = false;
|
||||||
|
export let lowContrast = false;
|
||||||
|
export let style = undefined;
|
||||||
|
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
import NotificationIcon from './NotificationIcon.svelte';
|
||||||
|
import NotificationTextDetails from './NotificationTextDetails.svelte';
|
||||||
|
import NotificationButton from './NotificationButton.svelte';
|
||||||
|
import { cx } from '../../lib';
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
const _class = cx(
|
||||||
|
'--inline-notification',
|
||||||
|
lowContrast && '--inline-notification--low-contrast',
|
||||||
|
kind && `--inline-notification--${kind}`,
|
||||||
|
hideCloseButton && '--inline-notification--hide-close-button',
|
||||||
|
className
|
||||||
|
);
|
||||||
|
|
||||||
|
let open = true;
|
||||||
|
|
||||||
|
$: if (!open) {
|
||||||
|
dispatch('close');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if open}
|
||||||
|
<div on:click on:mouseover on:mouseenter on:mouseleave class={_class} {style} {role} {kind}>
|
||||||
|
<div class={cx('--inline-notification__details')}>
|
||||||
|
<NotificationIcon {notificationType} {kind} {iconDescription} />
|
||||||
|
<NotificationTextDetails {title} {subtitle} {notificationType}>
|
||||||
|
<slot />
|
||||||
|
</NotificationTextDetails>
|
||||||
|
</div>
|
||||||
|
<slot name="actions" />
|
||||||
|
{#if !hideCloseButton}
|
||||||
|
<NotificationButton
|
||||||
|
{iconDescription}
|
||||||
|
{notificationType}
|
||||||
|
on:click={() => {
|
||||||
|
open = false;
|
||||||
|
}} />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
20
src/components/Notification/Notification.Story.svelte
Normal file
20
src/components/Notification/Notification.Story.svelte
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<script>
|
||||||
|
export let story = undefined;
|
||||||
|
|
||||||
|
import Layout from '../../internal/ui/Layout.svelte';
|
||||||
|
import InlineNotification from './InlineNotification.svelte';
|
||||||
|
import ToastNotification from './ToastNotification.svelte';
|
||||||
|
import NotificationActionButton from './NotificationActionButton.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
{#if story === 'inline'}
|
||||||
|
<InlineNotification {...$$props}>
|
||||||
|
<div slot="actions">
|
||||||
|
<NotificationActionButton>{$$props.action}</NotificationActionButton>
|
||||||
|
</div>
|
||||||
|
</InlineNotification>
|
||||||
|
{:else if story === 'toast'}
|
||||||
|
<ToastNotification {...$$props} style="min-width: 30rem; margin-bottom: .5rem" />
|
||||||
|
{/if}
|
||||||
|
</Layout>
|
42
src/components/Notification/Notification.stories.js
Normal file
42
src/components/Notification/Notification.stories.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import { withKnobs, select, boolean, text } from '@storybook/addon-knobs';
|
||||||
|
import Component from './Notification.Story.svelte';
|
||||||
|
|
||||||
|
export default { title: 'Notification', decorators: [withKnobs] };
|
||||||
|
|
||||||
|
const kinds = {
|
||||||
|
'Error (error)': 'error',
|
||||||
|
'Info (info)': 'info',
|
||||||
|
'Success (success)': 'success',
|
||||||
|
'Warning (warning)': 'warning'
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Toast = () => ({
|
||||||
|
Component,
|
||||||
|
props: {
|
||||||
|
story: 'toast',
|
||||||
|
kind: select('The notification kind (kind)', kinds, 'info'),
|
||||||
|
lowContrast: boolean('Use low contrast variant (lowContrast)', false),
|
||||||
|
role: text('ARIA role (role)', 'alert'),
|
||||||
|
title: text('Title (title)', 'Notification title'),
|
||||||
|
subtitle: text('Subtitle (subtitle)', 'Subtitle text goes here.'),
|
||||||
|
caption: text('Caption (caption)', 'Time stamp [00:00:00]'),
|
||||||
|
iconDescription: text('Icon description (iconDescription)', 'describes the close button'),
|
||||||
|
hideCloseButton: boolean('Hide close button (hideCloseButton)', false)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const Inline = () => ({
|
||||||
|
Component,
|
||||||
|
props: {
|
||||||
|
story: 'inline',
|
||||||
|
kind: select('The notification kind (kind)', kinds, 'info'),
|
||||||
|
lowContrast: boolean('Use low contrast variant (lowContrast)', false),
|
||||||
|
role: text('ARIA role (role)', 'alert'),
|
||||||
|
title: text('Title (title)', 'Notification title'),
|
||||||
|
subtitle: text('Subtitle (subtitle)', 'Subtitle text goes here.'),
|
||||||
|
caption: text('Caption (caption)', 'Time stamp [00:00:00]'),
|
||||||
|
iconDescription: text('Icon description (iconDescription)', 'describes the close button'),
|
||||||
|
hideCloseButton: boolean('Hide close button (hideCloseButton)', false),
|
||||||
|
action: text('Action (NotificationActionButton > $$slot#action)', 'Action')
|
||||||
|
}
|
||||||
|
});
|
22
src/components/Notification/NotificationActionButton.svelte
Normal file
22
src/components/Notification/NotificationActionButton.svelte
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<script>
|
||||||
|
let className = undefined;
|
||||||
|
export { className as class };
|
||||||
|
export let style = undefined;
|
||||||
|
|
||||||
|
import Button from '../Button';
|
||||||
|
import { cx } from '../../lib';
|
||||||
|
|
||||||
|
const _class = cx('--inline-notification__action-button', className);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
kind="ghost"
|
||||||
|
size="small"
|
||||||
|
on:click
|
||||||
|
on:mouseover
|
||||||
|
on:mouseenter
|
||||||
|
on:mouseleave
|
||||||
|
class={_class}
|
||||||
|
{style}>
|
||||||
|
<slot />
|
||||||
|
</Button>
|
36
src/components/Notification/NotificationButton.svelte
Normal file
36
src/components/Notification/NotificationButton.svelte
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<script>
|
||||||
|
let className = undefined;
|
||||||
|
export { className as class };
|
||||||
|
export let notificationType = 'toast';
|
||||||
|
export let type = 'button';
|
||||||
|
export let iconDescription = 'close icon';
|
||||||
|
export let renderIcon = Close20;
|
||||||
|
export let title = undefined;
|
||||||
|
export let style = undefined;
|
||||||
|
|
||||||
|
import Close20 from 'carbon-icons-svelte/lib/Close20';
|
||||||
|
import { cx } from '../../lib';
|
||||||
|
|
||||||
|
const _class = cx(
|
||||||
|
notificationType === 'toast' && '--toast-notification__close-button',
|
||||||
|
notificationType === 'inline' && '--inline-notification__close-button',
|
||||||
|
className
|
||||||
|
);
|
||||||
|
const _iconClass = cx(
|
||||||
|
notificationType === 'toast' && '--toast-notification__close-icon',
|
||||||
|
notificationType === 'inline' && '--inline-notification__close-icon'
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button
|
||||||
|
on:click
|
||||||
|
on:mouseover
|
||||||
|
on:mouseenter
|
||||||
|
on:mouseleave
|
||||||
|
aria-label={iconDescription}
|
||||||
|
title={iconDescription}
|
||||||
|
class={_class}
|
||||||
|
{style}
|
||||||
|
{type}>
|
||||||
|
<svelte:component this={renderIcon} class={_iconClass} {title} />
|
||||||
|
</button>
|
21
src/components/Notification/NotificationIcon.svelte
Normal file
21
src/components/Notification/NotificationIcon.svelte
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<script>
|
||||||
|
export let kind = 'error';
|
||||||
|
export let notificationType = 'toast';
|
||||||
|
export let iconDescription = 'closes notification';
|
||||||
|
|
||||||
|
import ErrorFilled20 from 'carbon-icons-svelte/lib/ErrorFilled20';
|
||||||
|
import CheckmarkFilled20 from 'carbon-icons-svelte/lib/CheckmarkFilled20';
|
||||||
|
import WarningFilled20 from 'carbon-icons-svelte/lib/WarningFilled20';
|
||||||
|
import { cx } from '../../lib';
|
||||||
|
|
||||||
|
const icons = {
|
||||||
|
error: ErrorFilled20,
|
||||||
|
success: CheckmarkFilled20,
|
||||||
|
warning: WarningFilled20
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:component
|
||||||
|
this={icons[kind]}
|
||||||
|
class={cx(`--${notificationType}-notification__icon`)}
|
||||||
|
title={iconDescription} />
|
25
src/components/Notification/NotificationTextDetails.svelte
Normal file
25
src/components/Notification/NotificationTextDetails.svelte
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<script>
|
||||||
|
export let title = 'title';
|
||||||
|
export let subtitle = '';
|
||||||
|
export let caption = 'caption';
|
||||||
|
export let notificationType = 'toast';
|
||||||
|
|
||||||
|
import { cx } from '../../lib';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if notificationType === 'toast'}
|
||||||
|
<div class={cx('--toast-notification__details')}>
|
||||||
|
<h3 class={cx('--toast-notification__title')}>{title}</h3>
|
||||||
|
<div class={cx('--toast-notification__subtitle')}>{subtitle}</div>
|
||||||
|
<div class={cx('--toast-notification__caption')}>{caption}</div>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if notificationType === 'inline'}
|
||||||
|
<div class={cx('--inline-notification__text-wrapper')}>
|
||||||
|
<p class={cx('--inline-notification__title')}>{title}</p>
|
||||||
|
<div class={cx('--inline-notification__subtitle')}>{subtitle}</div>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
{/if}
|
60
src/components/Notification/ToastNotification.svelte
Normal file
60
src/components/Notification/ToastNotification.svelte
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<script>
|
||||||
|
let className = undefined;
|
||||||
|
export { className as class };
|
||||||
|
export let kind = 'error';
|
||||||
|
export let title = 'provide a title';
|
||||||
|
export let subtitle = ''; // TODO: support subtitle slot?
|
||||||
|
export let caption = 'provide a caption';
|
||||||
|
export let role = 'alert';
|
||||||
|
export let notificationType = 'toast';
|
||||||
|
export let iconDescription = 'closes notification';
|
||||||
|
export let hideCloseButton = false;
|
||||||
|
export let lowContrast = false;
|
||||||
|
export let timeout = 0;
|
||||||
|
export let style = undefined;
|
||||||
|
|
||||||
|
import { createEventDispatcher, onMount } from 'svelte';
|
||||||
|
import NotificationIcon from './NotificationIcon.svelte';
|
||||||
|
import NotificationTextDetails from './NotificationTextDetails.svelte';
|
||||||
|
import NotificationButton from './NotificationButton.svelte';
|
||||||
|
import { cx } from '../../lib';
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
const _class = cx(
|
||||||
|
'--toast-notification',
|
||||||
|
lowContrast && '--toast-notification--low-contrast',
|
||||||
|
kind && `--toast-notification--${kind}`,
|
||||||
|
className
|
||||||
|
);
|
||||||
|
|
||||||
|
let open = true;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (timeout) {
|
||||||
|
window.setTimeout(() => {
|
||||||
|
open = false;
|
||||||
|
}, timeout);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$: if (!open) {
|
||||||
|
dispatch('close');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if open}
|
||||||
|
<div on:click on:mouseover on:mouseenter on:mouseleave class={_class} {style} {role} {kind}>
|
||||||
|
<NotificationIcon {notificationType} {kind} {iconDescription} />
|
||||||
|
<NotificationTextDetails {title} {subtitle} {caption} {notificationType}>
|
||||||
|
<slot />
|
||||||
|
</NotificationTextDetails>
|
||||||
|
{#if !hideCloseButton}
|
||||||
|
<NotificationButton
|
||||||
|
{iconDescription}
|
||||||
|
{notificationType}
|
||||||
|
on:click={() => {
|
||||||
|
open = false;
|
||||||
|
}} />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
6
src/components/Notification/index.js
Normal file
6
src/components/Notification/index.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export { default as ToastNotification } from './ToastNotification.svelte';
|
||||||
|
export { default as InlineNotification } from './InlineNotification.svelte';
|
||||||
|
export { default as NotificationActionButton } from './NotificationActionButton.svelte';
|
||||||
|
export { default as NotificationButton } from './NotificationButton.svelte';
|
||||||
|
export { default as NotificationIcon } from './NotificationIcon.svelte';
|
||||||
|
export { default as NotificationTextDetails } from './NotificationTextDetails.svelte';
|
16
src/index.js
16
src/index.js
|
@ -8,9 +8,17 @@ import CopyButton from './components/CopyButton';
|
||||||
import CodeSnippet, { CodeSnippetSkeleton } from './components/CodeSnippet';
|
import CodeSnippet, { CodeSnippetSkeleton } from './components/CodeSnippet';
|
||||||
import DataTableSkeleton from './components/DataTableSkeleton';
|
import DataTableSkeleton from './components/DataTableSkeleton';
|
||||||
import InlineLoading from './components/InlineLoading';
|
import InlineLoading from './components/InlineLoading';
|
||||||
import Loading from './components/Loading';
|
|
||||||
import Link from './components/Link';
|
import Link from './components/Link';
|
||||||
import ListItem from './components/ListItem';
|
import ListItem from './components/ListItem';
|
||||||
|
import Loading from './components/Loading';
|
||||||
|
import {
|
||||||
|
ToastNotification,
|
||||||
|
InlineNotification,
|
||||||
|
NotificationActionButton,
|
||||||
|
NotificationButton,
|
||||||
|
NotificationIcon,
|
||||||
|
NotificationTextDetails
|
||||||
|
} from './components/Notification';
|
||||||
import OrderedList from './components/OrderedList';
|
import OrderedList from './components/OrderedList';
|
||||||
import RadioButton, { RadioButtonSkeleton } from './components/RadioButton';
|
import RadioButton, { RadioButtonSkeleton } from './components/RadioButton';
|
||||||
import Search, { SearchSkeleton } from './components/Search';
|
import Search, { SearchSkeleton } from './components/Search';
|
||||||
|
@ -53,9 +61,14 @@ export {
|
||||||
DataTableSkeleton,
|
DataTableSkeleton,
|
||||||
ExpandableTile,
|
ExpandableTile,
|
||||||
InlineLoading,
|
InlineLoading,
|
||||||
|
InlineNotification,
|
||||||
Link,
|
Link,
|
||||||
ListItem,
|
ListItem,
|
||||||
Loading,
|
Loading,
|
||||||
|
NotificationActionButton,
|
||||||
|
NotificationButton,
|
||||||
|
NotificationIcon,
|
||||||
|
NotificationTextDetails,
|
||||||
OrderedList,
|
OrderedList,
|
||||||
PasswordInput,
|
PasswordInput,
|
||||||
RadioButton,
|
RadioButton,
|
||||||
|
@ -76,6 +89,7 @@ export {
|
||||||
TileAboveTheFoldContent,
|
TileAboveTheFoldContent,
|
||||||
TileBelowTheFoldContent,
|
TileBelowTheFoldContent,
|
||||||
TileGroup,
|
TileGroup,
|
||||||
|
ToastNotification,
|
||||||
Toggle,
|
Toggle,
|
||||||
ToggleSkeleton,
|
ToggleSkeleton,
|
||||||
ToggleSmall,
|
ToggleSmall,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue