Guidelines

Here are the guidelines and best practices for Grail UI functions.

# Destructuring

Most of the in Grail UI factory methods return an object of stores and actions. You can use ES6's object destructuring syntax to easily extract the specific stores and actions you need. This way you can leverage Svelte's auto-subscription syntax. For example:

<script>
import { createModal } from '@grail-ui/svelte';
const { useModal, modalAttrs, titleAttrs, triggerAttrs, open } = createModal();
</script>

# Reactive DOM props

The factory methods return readonly store objects that contain all the required attributes. These stores, which are suffixed with Attrs, must be spread onto the corresponding DOM elements.

For example, in the following snippet, modalAttrs, titleAttrs, and triggerAttrs contain DOM attributes that adhere to the WAI-ARIA guidelines.

<script>
import { createModal } from '@grail-ui/svelte';
const { useModal, modalAttrs, titleAttrs, triggerAttrs, open } = createModal();
</script>
<button type="button" {...$triggerAttrs} on:click={() => ($open = true)}>Open</button>
{#if $open}
<div use:useModal {...$modalAttrs}>
<h3 {...$titleAttrs}>Modal title</h3>
<div>Modal content</div>
</div>
{/if}

# State

Most of the Grail UI factory methods return readonly and/or writable stores that reflect the current state of the component. If the store is writable, you can use it to update the component's state.

For example:

<script>
import { createModal } from '@grail-ui/svelte';
const { useModal, modalAttrs, titleAttrs, triggerAttrs, open } = createModal();
</script>
<button type="button" {...$triggerAttrs} on:click={() => ($open = true)}>Open</button>
{#if $open}
<div use:useModal {...$modalAttrs}>
<h3 {...$titleAttrs}>Modal title</h3>
<div>Modal content</div>
</div>
{/if}

# Actions

All the actions returned by the factory methods, are prefixed with use. By leveraging the event delegation technique, usually you need to apply such actions only to a root element. For example, in the below component, useAccordion will "listen" to all the keyboard and pointer events for all the triggers and the sections.

<script>
import { createAccordion } from '@grail-ui/svelte';
const { useAccordion, itemAttrs, triggerAttrs, contentAttrs } = createAccordion();
</script>
<ul use:useAccordion>
<li {...$itemAttrs('item-1')}>
<button {...$triggerAttrs('item-1')}>Button 1</button
>
<div {...$contentAttrs('item-1')}>
Content for one.
</div>
</li>
<li {...$itemAttrs('item-2')}>
<button {...$triggerAttrs('item-2')}>Button 2</button
>
<div {...$contentAttrs('item-2')}>
Content for two.
</div>
</li>
</ul>