Giter Club home page Giter Club logo

svelte-custom-element's Introduction

svelte-custom-element

A project template to build custom elements (web components) with Svelte.

Table of Contents

  1. Usage
  2. About this template
  3. Gotchas
  4. Demo (alert-box)

Usage

Note that you will need to have Node.js installed.

To create a new project based on this template using degit:

npx degit gojutin/svelte-custom-element my-custom-element
cd my-custom-element

Install the dependencies:

cd my-custom-element
npm install

Then start your development server with Rollup:

npm run dev

You can then view your site in your browser by visiting localhost:5000.

About this template

The Svelte compiler provides the option to compile to a custom element (web component). This allows you to use most of the niceties of Svelte to create your custom elements, which can be a nice alternative to the general class-based approach.

This template is pre-configured with everything you need to start building a custom element out of the box, including Jest and Svelte Testing Library for testing your custom element.

TODO: Add additional documentation about this test setup and how to test your custom elements.

Note: This template does not include any of the web component polyfills for broader support. It's typically best to leave that up to the consumer, so they were purposely left out.

The basic idea:

  1. You create your custom element in the App.svelte file and use the public/index.html file to interact with your element. During development (npm run dev), live reloading will be enabled. This means that any changes made to your custom-element or the HTML will be immediately reflected in the browser.

  2. Write tests for your custom element and ensure they are all passing.

  3. Once your element is ready to ship, you run npm run build in the terminal, which will compile a minified, production-ready version of your custom element in the public/bundle.js file. The compiler will take care of creating the Shadow DOM, applying attributes/properties, and defining your custom element.

You can then do whatever you want with the bundle.js file. Your custom element is completely self-contained and does not require any additional dependencies. This means that you can drop it in virtually any environment that supports HTML and JavaScript.

This template is very much a work in progress. As I learn or discover best practices or better solutions around creating custom elements with Svelte, I will be sure to update the template to incorporate my findings.

If you see any opportunities for improvement and would like to contribute, please feel free to create a PR.

Gotchas

imports

You cannot import regular Svelte components from other files unless you declare those component(s) as custom elements with the <svelte:option tag="some-element> tag. By declaring child components as custom elements, these elements are also publicly available to the consumer, which may not be your intention. They also share the same Shadow DOM as the parent component, which means there is no ability to set the Shadow DOM mode to "closed" for any child components.

props

Any props that your custom element accepts will automatically be transformed to element attributes at compile time. It is recommended to stick with lowercase attribute names as naming conventions like camelCase or PascalCase will not work in HTML.

Doesn't work in HTML

<script>
  export let someValue = "Default Text"
</script>

Does work in HTML

<script>
  export let somevalue = "Default Text"
</script>

events

Custom events can be created in your Svelte component using the CustomEvent api. After defining a custom event, you can dispatch that event by calling this.dispatchEvent(event) in response to changes in your component.

If you try to dispatch an event inside of an arrow function, you will get an error due to the lexical scoping of this in arrow functions. You can remedy this by simply converting your arrow function to a function expression or dispatching an event from a custom ref.

Custom events cannot be dispatched in response to lifecycle methods. For instance, if you try to dispatch a custom event in your onMount lifecycle method, your event will not be dispatched.

transitions

Svelte's built-in transitions do not work with custom elements. You are pretty much on your own to create any animations that you would like your custom element to use.

bundle.js

You will most likely encounter errors if you try to use a non-production build of your custom element (bundle.js file) in another framework like React or Vue. This is due to the the development build containing mapping meta data, which causes an error with some bundlers. This can be resolved by running npm run build before using the file.

Demo

This template includes a demo alert-box custom element.

alert-box is a closeable alert box similar to the alerts provided by Bootstrap. This element accepts various theme attributes (outlined below), as well as a fixed attribute, which prevents the alert-box from being closed. This custom element incorporates several concepts, including attribute definitions, custom events, and exposing styles via CSS variables.

You can see the alert-box custom element in action using a few different front end flavors with the following CodeSandbox demos:

React Demo

Vue Demo

HTML Demo

Here's a list of the attributes, events, and CSS variables that the alert-box custom element exposes:

Attributes

primary | success | warning | danger | dark

These attributes apply a background and text color style similar to the bootstrap alerts.

Note: You can also set your own colors. See CSS variables below.

svelte-custom-element

fixed

This attribute hides the close (X) button, which prevents users from being able to close the alert-box.

Example:

<alert-box primary fixed>Thanks for signing up!<alert-box>

Slots

This custom element includes two slots:

The default slot

The alert-box message content will be placed in this slot.

The close slot

You can optionally override the default close (X) icon with your own markup in this slot. The close event is automatically bound to this slot.

Example:

<alert-box>
 The alert-box content in the default slot.
 <small slot="close">Close</small>
</alert-box>

Events

close

This event is triggered on non-fixed alert-boxes when the close (X) icon is clicked. The event can be subscribed to with an event listener, which allows the end user to handle showing and hiding of the alert-box as the close (X) icon is clicked. By leaving the display logic to the consumer, they are given full control to implement animations and display logic that fits their needs.

Example:

const alertBox = document.querySelector('alert-box');

alertBox.addEventListener("close", () => {
  alertBox.setAttribute('hidden', true)
})

Note: If you are using your custom element in a framework like Vue or React, they take care of setting up the event listener for you.

React:

<alert-box onClose={doSomething}>Thanks for joining!</alert-box>

Vue:

<alert-box @close={doSomething}>Thanks for joining!</alert-box>

CSS Variables

You can use the following CSS variables to change the background color, text color, and width of the alert-box.

variable description
--alert-box-bg Changes the background color.
--alert-box-text Changes the text color.
--alert-box-width Changes the width.
alert-box {
  --alert-box-bg: #333;
}

alert-box#some-id {
  --alert-box-bg: steelblue;
}

Have fun making your own custom elements with Svelte! 😀

svelte-custom-element's People

Contributors

dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

svelte-custom-element's Issues

Cannot import Textfield from '@svelte-material-ui/textfield';

Hi, I am wondering if I am doing something incorrect. In your App.svelte example, if I put

<script>
import Textfield from '@svelte-material-ui/textfield';
</script> 

and try to save the bundle, I get the following error

rollup v1.20.2
bundles src/main.js → public\bundle.js...
[!] Error: Unexpected character '@' (Note that you need plugins to import files that are not JavaScript)
node_modules\@svelte-material-ui\textfield\_index.scss (1:0)
1: @import "smui-theme";
   ^
2: @import "./_style.scss";
Error: Unexpected character '@' (Note that you need plugins to import files that are not JavaScript)
    at error (J:\workspace\web-components\svelte\scc-address\node_modules\rollup\dist\rollup.js:9429:30)
    at Module.error (J:\workspace\web-components\svelte\scc-address\node_modules\rollup\dist\rollup.js:13412:9)
    at tryParse (J:\workspace\web-components\svelte\scc-address\node_modules\rollup\dist\rollup.js:13325:16)
    at Module.setSource (J:\workspace\web-components\svelte\scc-address\node_modules\rollup\dist\rollup.js:13639:33)
    at J:\workspace\web-components\svelte\scc-address\node_modules\rollup\dist\rollup.js:16425:20
    at async Promise.all (index 1)
    at async Promise.all (index 1)
    at async Promise.all (index 0)
    at async Promise.all (index 0)
    at async Promise.all (index 0)

1
�[2K�[1G�[31merror�[39m Command failed with exit code 1.
�[2K�[1G�[94minfo�[39m Visit �[1mhttps://yarnpkg.com/en/docs/cli/run�[22m for documentation about this command.
ERROR: "autobuild" exited with 1.
�[2K�[1G�[31merror�[39m Command failed with exit code 1.
�[2K�[1G�[94minfo�[39m Visit �[1mhttps://yarnpkg.com/en/docs/cli/run�[22m for documentation about this command.

How to Test Custom Element in Jest

Hey! Thank you for this very useful repo.
I see that you've mentioned in a TODO on the Readme that you'll add more documentation testing web components. I'm struggling with this myself. I am already using the Testing Library, but it doesn't see to work properly with custom elements.

How do I import a custom element in Jest and use it? I'm not exporting everything as custom elements, and am using this recipe to only expose things that I need as web components instead of having all child components also be custom elements.

Now how do I import this and set it up in Jest? Please give me an idea on how to get started.

Thank you again!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.