/smoo

Simple Modal or Outlet

Primary LanguageSvelte

Hold your horses!

Build status NPM version Known Vulnerabilities

<script>
  import { Fence, Search } from 'smoo';

  let users = [
    { id: 1, name: 'Juanito Hace', value: 'j@do.e' },
    { id: 2, name: 'Carlangas Marca', value: 'cmrx@so.co' },
  ];

  let members = [];
  let visible = false;

  function open() {
    visible = true;
  }
  function close() {
    visible = false;
  }
</script>

<Fence modal bind:visible on:cancel={close}>
  <h1>It works.</h1>
  <Search multiple data={users} bind:value={members} />
  <pre>Got: {JSON.stringify(members)}</pre>
</Fence>

<button on:click={open}>Open modal</button>

How it works?

smoo lets you place any kind of markup or components inside a <div role="dialog">...</div>, it also brings to you many other useful components, you'll see below.

Components

We have a Fence component, i.e. a thing you need to guard your cows...

<Fence {id} {class} {loading} {modal} {visible} {autofocus} on:submit on:cancel />

This is a <form /> wrapper that handle various effects:

  • Allows you to subscribe to any connection status and block its content while loading...
  • All focusable inputs found during onMount(...) will be traped an cycled back and forth
  • When rendered as a modal-overlay, it can be canceled with the ESC key or clicking outside
  • It can setup autofocus on the first input-element found inside the inner <form /> wrapper (js only)

Before submitting HTML5 validation will run, if it's valid a submit event will be triggered. The cancel event is fired when you click outside the modal, or press the ESC key to close the modal.

Available props:

  • {id} — Used id for the inner <form /> element
  • {class} — Used class for the inner <form /> element
  • {loading} — Its presence will protect the UI with pointer-events:none
  • {modal} — Its presence will render the inner <form /> in a modal-overlay
  • {noform} — It disables the <form /> render, use the main slot instead
  • {visible} — Its value is used to toggle the render of the entire custom-element
  • {autofocus} — Its presence enables focus() on the first input-element found

Available slots:

  • before — Renders before the <form /> tag
  • after — Renders after the <form /> tag

Add the nofocus or data-nofocus attribute to any element to skip autofocus on it (useful for close-icons, etc.).

<Search {id} {pk} {keys} {data} {value} {class} {label} {disabled} {multiple} {autoclose} {placeholder} on:change />

This is an <input type="search" /> wrapper that handle various effects:

  • It is fully accessible through the keyboard, e.g.
    • you can press ESC to clear search
    • on items, press ESC to focus back to the input
  • It allows you to customize the data-source used and the render options
  • The search input fires their input, focus and blur events, while the dropdown fires open and close events.

It uses checkboxes or radios to enable selection through the keyboard, once values are choosen a change event is fired with the current selection. You can use CSS to hide those inputs and render the items by using :focus and :checked selectors.

Available props:

  • {id} — Used id for the inner <input /> element
  • {pk} — Property to identify each item from data list, default is id
  • {keys} — Properties to filter-out when searching for values, default are ['name', 'value']
  • {data} — Used data-source to retrieve items when searching, it must be an Array
  • {value} — This is an Array of selected ids from the data-source, can be bound
  • {class} — Used class for the inner <input /> element
  • {label} — Property used to print a human-readable value from each rendered item
  • {nofilter} — its presence will disable the filtering over the passed data-source
  • {disabled} — It just disables the <input /> field, while disabled options are hidden
  • {multiple} — Enable multiple selection of values (checkbox vs radio), disabled by default
  • {autoclose} — Close the dropdown on click-selection, it should not work with multiple options, disabled by default
  • {fallback} — This message is shown when no results are found while searching
  • {placeholder} — Custom placeholder for the <input /> field

Available slots:

  • before — Renders before the <input /> tag
  • after — Renders before the <input /> tag
  • item — Renders each value, use let:item to access its props
  • empty — Renders when no values where found in the data-source

If you like, place an icon like <svg slot="before">...</svg> and it will be positioned inside the <input /> on its left. Later you can use CSS to customize this through the [role=search] selector.