0.7.0 • Published 4 years ago

@ignatiusmb/elements v0.7.0

Weekly downloads
2
License
-
Repository
github
Last release
4 years ago

Elements Total npm downloads · Published npm version Monthly npm downloads License Made with Svelte

A collection of hassle-free and ready-to-use functional components made with Svelte. Feather icons included.

Elements is a Svelte component library consisting of various essential, mostly functional, and some pre-styled components. Create your own or use pre-existing, uniquely styled components and still get all the benefits from Elements. By utilizing Svelte <slot>, we're able to integrate our components while still getting the benefits of scoped styles and not having to worry about global styling modifiers or how to integrate components.

Elements is not a(nother) UI library / components library adhering to specific design language or certain guidelines. Though Elements has some generic components, the focus is mostly on its functionality. There's already a ton of UI libraries with various buttons, cards, menus, and other components in one complete package if you're looking for that kind of stuff.

Originally made with ease of use in mind for personal projects only, turned into something potentially bigger and useful to other projects as well. As it grew bigger and more components being added, I realize this might also be beneficial to others as well, in hopes that this would help fellow Svelte developers in quickstarting new projects as well.

Notes:

  • All classes in Namespaces are also written in PascalCase and can be accessed as such.
  • Prop attributes with * means it's required to pass a non-null and non-empty value to the prop

Usage

# Optimized for use with Sapper
npm install -D @ignatiusmb/elements

# Not tested with pure Svelte yet, but
npm install @ignatiusmb/elements

Import only the components you need, play around in the REPL to try the code block below.

Side note: REPL will take some time to load because it will bundle all generated Feather icons components as well. The statement Optimized for use with Sapper is because Sapper supports code splitting and you'll only be compiling the components and icons you import and use in your app.

<script>
  import { Feather, Loader, SearchBar } from '@ignatiusmb/elements';
  let query;
</script>

<SearchBar bind:query />

<p>
  {#if query}
    <Feather.Search />
    <span>{query}</span>
  {:else}
    <span>Waiting for queries</span>
    <Loader.ThreeWavyBalls />
  {/if}
</p>

Disclaimer

Please keep in mind that this is basically still a hobby project I'm doing to help myself in other projects. Elements will try to be as design agnostic as possible except for styled components, which would be whatever I thought was good at the time of making it. Elements does not adhere to any existing design language, any resemblance to certain design language is either inspired by or just purely coincidental. In other words, please do not expect a lot design-wise.

I personally never used a CSS framework or library and will not try to make one either, especially with Svelte where there's only a workaround, or escape hatch as they call it, using the :global() modifier. Either way, isn't it more fun to style your own website rather than using a pre-made UI component library? It would also make your website unique and better.

Working with Sapper and already having a ton of devDependencies, installing svelte-* packages e.g. svelte-search-bar, svelte-pagination, svelte-theme-switcher, and so on feels like it would make it harder to manage and quite the chore to keep up with each updates. I also like to create my own components as pure as possible, and I find myself reusing the same components across multiple projects. Hence, why I try to (re)create most components myself and bundle it as one collection here in Elements, Svelte-flavoured.

If some components you think are essential is missing and you feel it should be here, please understand that it was specifically excluded to spite you personally. All jokes aside, contributions are welcome as always!



Namespaces

Feather

PropsDefault
size24
weight1.5
color'currentColor'
class''

All icons from Feather Icons are available as classes to use in this namespace. Declaration .d.ts file is included, but if you don't get the autocompletion, you can just refer to Feather's website and convert the kebab-name to PascalName.

<script>
  import { Feather } from '@ignatiusmb/elements';
</script>

<Feather.IconName />

Loader

PropsDefault
--

There's currently only one loader available to use, which is ThreeWavyBalls. More is coming soon...

<script>
  import { Loader } from '@ignatiusmb/elements';
</script>

<Loader.ThreeWavyBalls />

Components

EssentialsFunctionalStyled
DialogLazyLoadImageButtonLink
ImagePaginationGradientBorder
LinkSearchBarProgressBar
ModalThemeSwitcherScrollTop
ObserverWeavedImage
Overlay

Dialog

PropsDefault
showfalse

Dialog element backdrop can be clicked by the user to close the interface, its almost exactly the same as Modal with some minor difference in functionality, see this question on Quora for more details on why.

<script>
  import { Dialog } from '@ignatiusmb/elements';
</script>

<Dialog show>
  <!-- Immediately shows the Dialog -->
</Dialog>
<script>
  import { Dialog } from '@ignatiusmb/elements';
  let show = false;
</script>

<button on:click={() => (show = true)}>Show</button>

<!-- Use "bind:" so "show" variable here will be updated too -->
<Dialog bind:show>
  <!-- Optional: Explicitly have button to close "Dialog" inside -->
  <button on:click={() => (show = false)}>Close</button>
</Dialog>

Image

PropsDefault
src *''
alt *''
containfalse
overlayfalse
absolutefalse
ratio9 / 16

Image element is created to have a fixed ratio, not size. It will be responsive by default and will follow its parent container size. To set a fixed size, just explicitly set the parent container size.

  • contain - images will have property object-fit with the value of cover by default, pass this prop to set the value to contain
<script>
  import { Image } from '@ignatiusmb/elements';
  const src = '//example.com/image.png';
  const alt = 'An example text for this element';
</script>

<Image {src} {alt} contain />
  • overlay - Overlay element is provided and available to use if you need it, you can pass in other components when this prop is used
<script>
  import { Image } from '@ignatiusmb/elements';
  const src = '//example.com/image.png';
  const alt = 'An example text for this element';
</script>

<Image {src} {alt} overlay>
  <p>I will appear when this Image is hovered</p>
</Image>
  • absolute - set the Image container position as absolute
<script>
  import { Image } from '@ignatiusmb/elements';
  const src = '//example.com/image.png';
  const alt = 'An example text for this element';
</script>

<div style="position: relative">
  <!-- Image is now absolute positioned in this div -->
  <Image {src} {alt} absolute />
</div>
  • ratio - this receives a float to determine the ratio of your image, set to 16:9 by default
<script>
  import { Image } from '@ignatiusmb/elements';
  const src = '//example.com/image.png';
  const alt = 'An example text for this element';
</script>

<!-- Square Image -->
<Image {src} {alt} ratio={1} />

<!-- Vertical format -->
<Image {src} {alt} ratio={4 / 3} />

<!-- Horizontal format -->
<Image {src} {alt} ratio={3 / 4} />

Pagination

PropsDefault
store *writable(0)
total *0
bound1
incrementbound
tweenfalse

Pagination element handles all the complicated and unnecessary stuff for us, including all the edge cases. We just need to pass in the necessary props and handle the actual items slicing ourself.

  • store - a Svelte store to manage the state of the current paginated index
  • total - usually just the .length of your data array
  • bound - maximum number of items per page
  • increment - number of items to skip every next/prev page
  • tween - boolean value to use tween increments rather than jump
<script>
  export let items = []; // Your data array
  import { Pagination } from '@ignatiusmb/elements';
  import { posts as store } from './stores.js';
  const bound = 3;
  const increment = 1;

  $: count = $store * increment;
  $: filtered = items.slice(count, count + bound);
  $: total = filtered.length;
</script>

<Pagination {store} {total} {bound} {increment} tween />

{#each filtered as post}
  <div>
    <h2>{post.title}</h2>
    <p>{post.description}</p>
  </div>
{:else}
  <h2>No posts available</h2>
{/each}

SearchBar

PropsDefault
query *''
filtersnull
uniquenull

SearchBar element provides a searchbox and query to bind the value.

  • query - prop that holds the query value from the searchbox
  • filters - object with arrays that holds filters checked by user
  • unique - object with arrays consisting of unique values complementing filters
<script>
  // Filtered object of arrays with unique values
  export let unique = { categories: [], tags: [] };
  import { SearchBar } from '@ignatiusmb/elements';
  let filters = { categories: [], tags: [], sort: 'updated' };
  let query;
</script>

<!-- Only searchbox -->
<SearchBar bind:query />

<!-- With filters -->
<SearchBar bind:query bind:filters {unique}>
  <section>
    <h3>Sort by</h3>
    <label>
      <input type="radio" bind:group={filters.sort} value="updated" />
      <span>Last updated</span>
    </label>
    <label>
      <input type="radio" bind:group={filters.sort} value="published" />
      <span>Date published</span>
    </label>
  </section>
</SearchBar>


0.7.0

4 years ago

0.6.2

4 years ago

0.6.1

4 years ago

0.6.0

4 years ago

0.5.0

4 years ago

0.4.1

4 years ago

0.4.0

4 years ago

0.4.2

4 years ago

0.3.1

4 years ago

0.3.0

4 years ago

0.2.1

4 years ago

0.2.0

4 years ago

0.2.2

4 years ago

0.1.1

4 years ago

0.1.0

4 years ago

0.0.5

4 years ago

0.0.4

4 years ago

0.0.3

4 years ago

0.0.2

4 years ago

0.0.1

4 years ago