standard-ui/components/index.html
2023-07-17 02:13:02 +05:30

2437 lines
103 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SM Components</title>
<meta name="description" content="SM-Components. collection of web components">
<link rel="stylesheet" href="css/main.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;700&family=Roboto+Mono&family=Roboto:wght@400;500;700&display=swap"
rel="stylesheet">
</head>
<body class="hide-completely">
<sm-notifications id="notification_drawer"></sm-notifications>
<audio id="notification_sound">
<source src="https://rmservices.duckdns.org/files/notification-sound.mp3" type="audio/mpeg">
<source src="https://rmservices.duckdns.org/files/notification-sound.ogg" type="audio/ogg">
</audio>
<main>
<header id="main_header" class="flex align-center space-between">
<button id="side_nav_button" class="interact" onclick="getRef('side_nav').open()"
aria-label="Hamburger menu toggle button">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path fill="none" d="M0 0h24v24H0z" />
<path d="M16 18v2H5v-2h11zm5-7v2H3v-2h18zm-2-7v2H8V4h11z" />
</svg>
</button>
<h4>SM Components</h4>
<theme-toggle></theme-toggle>
</header>
<hamburger-menu id="side_nav">
<h4>Getting Started</h4>
<ul class="list">
<li>
<a href="#overview_page" class="list__item list__item--active interact">
Overview
</a>
</li>
<li>
<a href="#quick_start_page" class="list__item interact">
Quick start
</a>
</li>
<li>
<a href="#global_styling_page" class="list__item interact">
Global styling
</a>
</li>
</ul>
<h4>Components</h4>
<ul id="components_list" class="list"></ul>
</hamburger-menu>
<article class="right language-html">
<section id="overview_page" class="page">
<div>
<h5 class="color-0-8 weight-500">Total components</h5>
<h1 id="total_components_count" class="h1"></h1>
</div>
<div>
<h1 class="page__title">Overview</h1>
<div class="grid gap-2">
<div class="div">
<p>
Component-based design is the cornerstone of the modern UI development process. With
rise of
more UI frameworks every day, the web platform has a serious issue of fragmentation and
portability.
</p>
<p>
Web components to the rescue! This is the collection of web components (WC here forward)
that we
use at RanchiMall, especially since we are a framework-less development environment so
this was
a logical choice.
</p>
</div>
<div class="grid gap-1">
<h3>Features</h3>
<ul class="grid gap-0-5">
<li>Native and Cross framework support</li>
<li>Encapsulated style and functionality</li>
<li>Easy styling</li>
<li>Adaptive scaling </li>
</ul>
</div>
</div>
</div>
</section>
<section id="quick_start_page" class="page hide-completely">
<h1 class="page__title">Quick Start</h1>
<ol>
<li>
To start using these components, Select the ones you want to add to your project. You can
un-check 'get minified' to get the readable code.
</li>
<li>
Now you can download or copy the source code for selected components.
<strong class="important">
You might get a warning while downloading like this file is not safe,
please allow the download as this is caused when downloading files with '.js' extension.
These components are 100% safe to use.
</strong>
</li>
<li>
Link the downloaded js before <span class="highlight">&lt;/body&gt;</span>
<pre>
<code>
&lt;script src=".../components.js"&gt;&lt;/script&gt;
</code>
</pre>
</li>
</ol>
<div class="grid grid-3 gap-0-5 align-center">
<sm-checkbox id="get_minified" checked>
<span class="comp-checkbox__title">
Get minified
</span>
</sm-checkbox>
<sm-button onclick="selectAll()">Select all</sm-button>
<sm-button onclick="clearAll()">Clear all</sm-button>
</div>
<div id="components_selection_list"></div>
<div class="flex align-center space-between">
<sm-button onclick="copySourceCode()">Copy source code</sm-button>
<sm-button variant="primary" onclick="downloadComponents()">Download JS file</sm-button>
</div>
</section>
<section id="global_styling_page" class="page hide-completely">
<h1 class="page__title">Global styling</h1>
<p>These components use <strong>CSS variables</strong> to customize styling. they share some CSS
variables that make global styling easier. <br>
Of course you can set these variables at individual component CSS rule set level.
</p>
<h4>Some common CSS variables and their use</h4>
<section class="table">
<div class="tr">
<h4 class="table__heading">Variable</h4>
<h4 class="table__heading">Use</h4>
</div>
<div class="tr">
<div><span class="highlight">--accent-color</span></div>
<p>Color which will be used for denoting active state</p>
</div>
<div class="tr">
<div><span class="highlight">--text-color</span></div>
<p>
default text color for all components. <br>
( Use comma separated rgb values. e.g 17, 17, 17 )
</p>
</div>
<div class="tr">
<div><span class="highlight">--background-color</span></div>
<p>
default background color for all components. <br>
( Use comma separated rgb values. e.g 255, 255, 255 )
</p>
</div>
<div class="tr">
<div><span class="highlight">--danger-color</span></div>
<p>Used for error/invalid state</p>
</div>
</section>
</section>
<section id="button_page" class="page hide-completely">
<h1 class="page__title">Buttons</h1>
<sm-button>Default button</sm-button>
<h2>Variants</h2>
<p>These are styled variations of base component</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Variant type</h4>
<h4 class="table__heading">Example</h4>
</div>
<div class="tr">
<div><span class="highlight">primary</span></div>
<p>
<sm-button variant="primary">Primary</sm-button>
</p>
</div>
<div class="tr">
<div><span class="highlight">outlined</span></div>
<p>
<sm-button variant="outlined">Outlined</sm-button>
</p>
</div>
<div class="tr">
<div><span class="highlight">no--outline</span></div>
<p>
<sm-button variant="no-outline">No outline</sm-button>
</p>
</div>
</section>
<h4>How to define variant</h4>
<pre>
<code>
&lt;sm-button variant="primary"&gt;primary&lt;/sm-button&gt;
&lt;sm-button variant="outlined"&gt;outlined&lt;/sm-button&gt;
&lt;sm-button variant="no-outline"&gt;no-outline&lt;/sm-button&gt;
</code>
</pre>
<h2>States</h2>
<h4>Disabled</h4>
<p>To disable the button add <span class="highlight">disabled</span> attribute.</p>
<sm-button disabled>Disabled</sm-button>
<pre>
<code>
&lt;sm-button disabled&gt;Disabled&lt;/sm-button&gt;
</code>
</pre>
<h2>Attributes</h2>
<p>All the native HTML checkbox attributes are valid</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">disabled</span> (boolean)</div>
<p>
Button is disabled by default. all the interactions are disabled
</p>
</div>
<div class="tr">
<div><span class="highlight">type</span> (string)</div>
<p>
Has values <span class="highlight">submit</span> <span class="highlight">reset</span> <br>
Can only used withing <spna class="highlight">sm-form</spna> to submit or reset the form.
</p>
</div>
</section>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Variable</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">--background</span></div>
<p>
Define background of button. accepts all values of CSS background property
</p>
</div>
<div class="tr">
<div><span class="highlight">--border-radius</span></div>
<p>
Set curvature at button corners
</p>
</div>
<div class="tr">
<div><span class="highlight">--padding</span></div>
<p>
Specify padding of button
</p>
</div>
</section>
</section>
<section id="carousel_page" class="page hide-completely">
<h1 class="page__title">Carousel</h1>
<p>
Carousel is a very common UI component primarily used to display images or slides.
This carousel switches user interactions based on type of input devices present. For hover capable
devices slides can be scrolled with buttons and on
touch enabled devices swipe can be used.
</p>
<h2>Interactive demo</h2>
<sm-carousel indicator>
<div class="card">
<h3>Title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, optio.</p>
</div>
<div class="card">
<h3>Title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, optio.</p>
</div>
<div class="card">
<h3>Title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, optio.</p>
</div>
<div class="card">
<h3>Title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, optio.</p>
</div>
</sm-carousel>
<pre>
<code>
&lt;sm-carousel align-items="start" indicator&gt;
&lt;!-- carousel items --&gt;
&lt;/sm-carousel&gt;
</code>
</pre>
<h2>Custom attributes</h2>
<p>These attributes cane used to customize carousel behaviour and features</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">align-items</span></div>
<p>
Has values <span class="highlight">start</span>
<span class="highlight">center</span> <span class="highlight">end</span>
Specifies how carousel items should align. default is <span class="highlight">center</span>.
</p>
</div>
<div class="tr">
<div><span class="highlight">indicator</span> (boolean)</div>
<p>
if added carousel shows dot indicators of carousel items.
</p>
</div>
</section>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Variable</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">--active-indicator-color</span></div>
<p>
Defines background color of active slide indicator
</p>
</div>
<div class="tr">
<div><span class="highlight">--nav-background-color</div>
<p>
Defines background color of carousel navigation buttons
</p>
</div>
<div class="tr">
<div><span class="highlight">--nav-box-shadow</div>
<p>
Defines box shadow of carousel navigation buttons
</p>
</div>
<div class="tr">
<div><span class="highlight">--nav-icon-fill</div>
<p>
Defines fill of arrow icon on carousel navigation buttons
</p>
</div>
</section>
</section>
<section id="checkbox_page" class="page hide-completely">
<h1 class="page__title">Checkbox</h1>
<p><span class="highlight">sm-checkbox</span> supports all the attributes of native HTML5 checkbox</p>
<strong>
linking some HTML element with <span class="highlght">sm-checbox</span> using <span
class="highlight">label</span> tag won't work. <br>
Add the element inside the opening and closing checkbox tag.
</strong>
<h2>Interactive demo</h2>
<sm-checkbox id="checkbox">
<div style="margin-left: 0.5rem;">
Check this box
</div>
</sm-checkbox>
<h2>States</h2>
<h4>Checked</h4>
<p>To make checkbox checked by default add <span class="highlight">checked</span> attribute.</p>
<sm-checkbox checked>
<div style="margin-left: 0.5rem;">
Checked checkbox
</div>
</sm-checkbox>
<pre>
<code>
&lt;sm-checkbox checked&gt;
&lt;div style="margin-left: 0.5rem;"&gt;Checked checkbox&lt;/div&gt;
&lt;/sm-checkbox&gt;
</code>
</pre>
<h4>Disabled</h4>
<p>To disable the checkbox add <span class="highlight">disabled</span> attribute.</p>
<sm-checkbox disabled>
<div style="margin-left: 0.5rem;">
Disabled checkbox
</div>
</sm-checkbox>
<pre>
<code>
&lt;sm-checkbox disabled&gt;
&lt;div style="margin-left: 0.5rem;"&gt;Disabled checkbox&lt;/div&gt;
&lt;/sm-checkbox&gt;
</code>
</pre>
<h2>Attributes</h2>
<p>All the native HTML checkbox attributes are valid</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">checked</span> (boolean)</div>
<p>
If present, checkbox is set to checked state as default.
</p>
</div>
<div class="tr">
<div><span class="highlight">disabled</span> (boolean)</div>
<p>
If present checkbox is set to disabled state. all the interactions are disabled
</p>
</div>
<div class="tr">
<div><span class="highlight">value</span> (string)</div>
<p>
Sets value of checkbox which can be accessed by value property with JS
</p>
</div>
</section>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Variable</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">--border-color</span></div>
<p>
Defines color of un-checked checkbox border
</p>
</div>
<div class="tr">
<div><span class="highlight">--border-radius</span></div>
<p>
Defines border-radius of checkbox square
</p>
</div>
<div class="tr">
<div><span class="highlight">--height</div>
<p>
Defines height of checkbox
</p>
</div>
<div class="tr">
<div><span class="highlight">--width</div>
<p>
Defines width of checkbox
</p>
</div>
</section>
</section>
<section id="copy_page" class="page hide-completely">
<h1 class="page__title">Copy</h1>
<h2>Interactive demo</h2>
<sm-copy value="copy this message">
<div>ssafd</div>
</sm-copy>
<pre>
<code>
&lt;sm-copy value="copy this message"&gt;&lt;/sm-copy&gt;
</code>
</pre>
<h2>Usage</h2>
<pre>
<code>
&lt;sm-copy id="text_to_copy" value="sample text"&gt;&lt;/sm-copy&gt;
&lt;script&gt;
const textToCopy = document.getElementById('text_to_copy')
textToCopy.value = 'Different value'; /* Setting value to be copied */
&lt;/script&gt;
</code>
</pre>
<h2>Attributes</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">value</span> ( string )</div>
<p>
Defines content that will be copied when copy button is clicked
</p>
</div>
</section>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Variable</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">--button-background-color</span></div>
<p>
Defines background color of copy button
</p>
</div>
<div class="tr">
<div><span class="highlight">--button-border-radius</span></div>
<p>
Defines border-radius of copy button
</p>
</div>
</section>
<h2>Supported events</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Event</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">copy</span></div>
<p>
Fired when text is copied by user.
</p>
</div>
</section>
</section>
<section id="file_input_page" class="page hide-completely">
<h1 class="page__title">File input</h1>
<p>
<span class="highlight">&lt;file-input&gt;</span> is essentially native <span
class="highlight">&lt;input type="file"/&gt;
</span> with added style. <br>
So every attribute supported by native file input is supported as can be used in exactly same way.
</p>
<h2>Interactive demo</h2>
<file-input multiple>Select multiple files</file-input>
<pre>
<code>
&lt;file-input multiple&gt;Select multiple files&lt;/file-input&gt;
</code>
</pre>
<h2>Attributes</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">accept</span></div>
<p>
One or more unique file type specifiers describing file types to allow
</p>
</div>
<div class="tr">
<div><span class="highlight">capture</span></div>
<p>
What source to use for capturing image or video data
</p>
</div>
<div class="tr">
<div><span class="highlight">files</span></div>
<p>
A FileList listing the chosen files
</p>
</div>
<div class="tr">
<div><span class="highlight">multiple</span></div>
<p>
A Boolean which, if present, indicates that the user may choose more than one file
</p>
</div>
</section>
</section>
<section id="form_page" class="page hide-completely">
<h1 class="page__title">Form</h1>
<p>
Browser support for web components form validation or form submition is not perfect.
so to circumvent this problem <span class="highlight">&lt;sm-form&gt;</span> can be used.
</p>
<h2>Interactive demo</h2>
<sm-form>
<sm-input placeholder="Email" type="email" error-text="please enter correct email" required animate>
</sm-input>
<sm-input placeholder="Password" type="password" required animate></sm-input>
<sm-button variant="primary" disabled>Login</sm-button>
</sm-form>
<h2>Supported functions</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Function</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">reset()</span></div>
<p>
When this function is called upon form element. all the form elements (sm- form components
only) will be reset to default state.
</p>
</div>
</section>
<h2>Nested element behaviour</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Element</h4>
<h4 class="table__heading">behaviour</h4>
</div>
<div class="tr">
<div>
sm-button
<span class="highlight">variant="primary"</span>
or
<span class="highlight">type="submit"</span>
</div>
<p>
Whenever enter is pressed inside an active <span class="highlight">sm-input</span>, this
will fire click event. <br>
This will also change state depending opon validation conditions.
</p>
</div>
<div class="tr">
<div>
sm-button
<span class="highlight">type="reset"</span>
</div>
<p>
When clicked, the whole form will reset.
</p>
</div>
</section>
</section>
<section id="hamburger_menu_page" class="page hide-completely">
<h1 class="page__title">Hamburger menu</h1>
<section class="grid auto-grid-2 gap-3">
<div class="grid gap-1">
<img class="screenshot" loading="lazy" src="assets/ham-menu-closed.png"
alt="Hamburger menu closed">
<h4>Hamburger menu closed</h4>
</div>
<div class="grid gap-1">
<img class="screenshot" loading="lazy" src="assets/ham-menu-open.png"
alt="Hamburger menu opened">
<h4>Hamburger menu open</h4>
</div>
</section>
<h2>Usage</h2>
<pre>
<code>
&lt;hamburger-menu id="navigation_drawer"&gt;
<!-- Navigation links -->
&lt;/hamburger-menu&gt;
&lt;script&gt;
const navigationDrawer = document.getElementById('navigation_drawer')
const navigationDrawerButton = document.getElementById('navigation_drawer_button')
navigationDrawerButton.addEventListner('click', e => {
navigationDrawer.open(); // Will open hamburger menu on mobile devices when hidden
})
&lt;/script&gt;
</code>
</pre>
</section>
<section id="input_page" class="page hide-completely">
<h1 class="page__title">Input</h1>
<h2>Interactive demo</h2>
<sm-input id="my_input" placeholder="Email" type="email" value="john@doe" animate>
</sm-input>
<pre>
<code>
&lt;sm-input id="my_input" placeholder="Email" type="email" value="john@doe" animate&gt;&lt;/sm-input&gt;
</code>
</pre>
<h2>Variants</h2>
<p><span class="highlight">outlined</span> is only one styled variation. Default is filled which doesn't
require variant specified.</p>
<sm-input placeholder="Name" variant="outlined" animate></sm-input>
<pre>
<code>
&lt;sm-input placeholder="Name" variant="outlined" animate&gt;&lt;/sm-input&gt;
</code>
</pre>
<h2>Custom Attributes</h2>
<p>All the native HTML input attributes are valid. These are additional attributes which can be used to
add more functionality</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">animate</span> (boolean)</div>
<p>
If present, placeholder of input will be animated to occupy space above enterned text
instead of vanishing.
</p>
</div>
<div class="tr">
<div><span class="highlight">error-text</span> (string)</div>
<p>
Message specified as value of this attribute will be shown if validation fails.
</p>
</div>
</section>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Variable</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">--background</span></div>
<p>
Defines background property of input. Any valid CSS background values are supported.
</p>
</div>
<div class="tr">
<div><span class="highlight">--border-radius</div>
<p>
Sets border-radius of input.
</p>
</div>
<div class="tr">
<div><span class="highlight">--icon-gap</div>
<p>
Sets space between input icon and input box. Default is "0.5rem"
</p>
</div>
<div class="tr">
<div><span class="highlight">--font-size</div>
<p>
Sets font size of input text. Default is "1rem".
</p>
</div>
<div class="tr">
<div><span class="highlight">--padding</div>
<p>
Sets padding around whole input box including icon.
</p>
</div>
<div class="tr">
<div><span class="highlight">--width</div>
<p>
Sets width of input box.
</p>
</div>
</section>
<h2>Supported functions</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Function</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">focusIn()</span></div>
<p>
To give focus to this component use this function instead of <span
class="highlight">focus()</span>
</p>
</div>
<div class="tr">
<div><span class="highlight">reset()</span></div>
<p>
When this function is called value will be set to empty string.
</p>
</div>
</section>
<h2>Custom Setters</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Function</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">customValidation</span></div>
<p>
If you want to perform custom validation on input value, set the desired validation
function.
</p>
</div>
<div class="tr">
<div><span class="highlight">disabled</span></div>
<p>
Set disabled state to <span class="highlight">true</span> or <span
class="highlight">false</span>
</p>
</div>
<div class="tr">
<div><span class="highlight">value</span></div>
<p>
Sets the value of input with JS
</p>
</div>
</section>
<pre>
<code>
&lt;script&gt;
/* Setting custom validation function */
document.getElelementById('my_input').customValidation = myValidation
function myValidation(inputValue) {
/* Custom validation logic */
return Boolean; /* Must return Boolean ( true/ false ) */
}
&lt;/script&gt;
</code>
</pre>
</section>
<section id="menu_page" class="page hide-completely">
<h1 class="page__title">Menu</h1>
<h2>Interactive demo</h2>
<sm-menu>
<menu-option>first option</menu-option>
<menu-option>second option</menu-option>
<menu-option>third option</menu-option>
</sm-menu>
<pre>
<code>
&lt;sm-menu&gt;
&lt;menu-option&gt;first option&lt;/menu-option&gt;
&lt;menu-option&gt;second option&lt;/menu-option&gt;
&lt;menu-option&gt;third option&lt;/menu-option&gt;
&lt;/sm-menu&gt;
</code>
</pre>
<h2>Custom Attributes</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">align-options</span> (string)</div>
<p>
Specifies alignment of options relative to left or right edge of menu button. <br>
Valid values are <span class="highlight">left</span> <span class="highlight">right</span>.
</p>
</div>
</section>
<h2>Supported events</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Event</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">click</span></div>
<p>
To setup functions on click event. use standard method to add event listeners on options
themselves or
delegate event on menu component level.
</p>
</div>
</section>
</section>
<section id="notifications_page" class="page hide-completely">
<h1 class="page__title">Notifications</h1>
<p>
To start using notifications add the <span class="highlight">&lt;sm-notifications&gt;</span>
at top level of markup like just below starting <span class="highlight">&lt;body&gt;</span> tag.
</p>
<h2>Supported functions</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Function</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">push()</span></div>
<p>
Used to display notifications with two parameters. <br>
Notification text and notification options.
</p>
</div>
<div class="tr">
<div><span class="highlight">clearAll()</span></div>
<p>
Removes all the notifications present in notification drawer.
</p>
</div>
</section>
<h2>Push() options</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Property</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">icon</span> (svg)</div>
<p>
To display custom icon with notification icon option can be used.
</p>
</div>
<div class="tr">
<div><span class="highlight">pinned</span> (Boolean)</div>
<p>
If set <span class="highlight">true</span> notifications won't disappear after some time.
they need to be dismissed by user
manually.
</p>
</div>
</section>
<h2>Interactive demo</h2>
<sm-button onclick="getRef('notification_drawer').push('This is a notification', {pinned: true})">
push pinned notification</sm-button>
<pre>
<code>
&lt;sm-notifications id="notification_drawer"&gt;&lt;/sm-notifications&gt;
&lt;script&gt;
const notificationDrawer = document.getElementById('notification_drawer')
notificationDrawer.push('This is a notification', { pinned: true })
&lt;/script&gt;
</code>
</pre>
</section>
<section id="popup_page" class="page hide-completely">
<h1 class="page__title">Popup / dialog</h1>
<p>
Popups are used to show addition UI elements that you may want to hide at first and reveal them when
needed.
</p>
<h2>Interactive demo</h2>
<sm-popup id="my_popup">
<h2>Title</h2>
<p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Dolore tenetur natus, pariatur beatae
veritatis debitis repellat laudantium corporis velit adipisci!</p>
</sm-popup>
<sm-button onclick="getRef('my_popup').show()">show popup</sm-button>
<pre>
<code>
&lt;sm-popup id="my_popup"&gt;
&lt;!--Popup content --&gt;
&lt;/sm-popup&gt;
</code>
</pre>
<h2>Usage</h2>
<pre>
<code>
&lt;sm-popup id="my_popup"&gt;
&lt;!--Popup content --&gt;
&lt;/sm-popup&gt;
&lt;sm-button id="show_popup_button"&gt;Show popup&lt;/sm-button&gt;
&lt;script&gt;
const myPopup = document.getElementById('my_popup')
document.getElementById('show_popup_button').addEventListener('click', e =&gt; {
myPopup.show({options});
})
&lt;/script&gt;
</code>
</pre>
<h2>Custom Attributes</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">open</span> (boolean)</div>
<p>
If present, popup will be in opened state by default. useful for development purpose.
</p>
</div>
</section>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Variable</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">--backdrop-background</span></div>
<p>
Defines background property of popup backdrop. Any valid CSS background value is supported.
</p>
</div>
<div class="tr">
<div><span class="highlight">--border-radius</span></div>
<p>
Defines border-radius of popup dialog box.
</p>
</div>
<div class="tr">
<div><span class="highlight">--body-padding</span></div>
<p>
Defines padding of popup dialog box.
</p>
</div>
<div class="tr">
<div><span class="highlight">--height</span></div>
<p>
Defines height of popup dialog box.
</p>
</div>
<div class="tr">
<div><span class="highlight">--min-height</span></div>
<p>
Defines min-height of popup dialog box.
</p>
</div>
<div class="tr">
<div><span class="highlight">--width</span></div>
<p>
Defines width of popup dialog box.
</p>
</div>
<div class="tr">
<div><span class="highlight">--min-width</span></div>
<p>
Defines min-width of popup dialog box.
</p>
</div>
</section>
<h2>Supported functions</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Function</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">show()</span></div>
<p>
Displays the hidden popup, when called upon specified popup.
</p>
</div>
<div class="tr">
<div><span class="highlight">hide()</span></div>
<p>
Hides the visible popup, when called upon specified popup
</p>
</div>
</section>
<h4>Show() options</h4>
<section class="table">
<div class="tr">
<h4 class="table__heading">Property</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">pinned</span> ( Boolean )</div>
<p>
If set <span class="highlight">true</span>, opened popup won't be closed when clicked
outside the popup area.
</p>
</div>
</section>
<h2>Custom events</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Event</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">popupopned</span></div>
<p>
Fired when a popup is opened, to access which popup fired the event you can use
<span class="highlight">event.detail.popup</span> within event listener
</p>
</div>
<div class="tr">
<div><span class="highlight">popupclosed</span></div>
<p>
Fired when a popup is closed, to access which popup fired the event you can use
<span class="highlight">event.detail.popup</span> within event listener
</p>
</div>
</section>
</section>
<section id="radio_page" class="page hide-completely">
<h1 class="page__title">Radio button</h1>
<p>
Radio buttons are useful whenever only one option needs to be selected from mutiple options. this
functionality can be
achieved by assigning same name to the group of radio buttons. <br>
<span class="highlight">sm-radio</span> supports all the attributes of native HTML5 radio.
</p>
<strong>
linking some HTML element with <span class="highlght">sm-radio</span> using <span
class="highlight">label</span> tag won't work. <br>
Add the element inside the opening and closing sm-radio tag.
</strong>
<h2>Interactive demo</h2>
<div class="grid gap-0-5">
<sm-radio name="abc" value="on" checked>
<div>&nbsp;&nbsp;On</div>
</sm-radio>
<sm-radio name="abc" value="off">
<div>&nbsp;&nbsp;Off</div>
</sm-radio>
<sm-radio name="abc" value="🤷">
<div>&nbsp;&nbsp;🤷</div>
</sm-radio>
</div>
<pre>
<code>
&lt;sm-radio name="abc" value="on" checked&gt;
&lt;div&gt;&nbsp;&nbsp;On&lt;/div&gt;
&lt;/sm-radio&gt;
&lt;sm-radio name="abc" value="off"&gt;
&lt;div&gt;&nbsp;&nbsp;Off&lt;/div&gt;
&lt;/sm-radio&gt;
&lt;sm-radio name="abc" value="🤷"&gt;
&lt;div&gt;&nbsp;&nbsp;🤷&lt;/div&gt;
&lt;/sm-radio&gt;
</code>
</pre>
<h2>States</h2>
<h4>Checked</h4>
<p>To make switch turned on by default add <span class="highlight">checked</span> attribute.</p>
<sm-radio checked>
<div style="margin-left: 0.5rem;">
Checked radio button
</div>
</sm-radio>
<pre>
<code>
&lt;sm-radio checked&gt;
&lt;div&gt;On switch&lt;/div&gt;
&lt;/sm-radio&gt;
</code>
</pre>
<h4>Disabled</h4>
<p>To disable the radio button add <span class="highlight">disabled</span> attribute.</p>
<sm-radio disabled>
<div style="margin-left: 0.5rem;">
Disabled radio button
</div>
</sm-radio>
<pre>
<code>
&lt;sm-radio disabled&gt;
&lt;div&gt;Disabled switch&lt;/div&gt;
&lt;/sm-radio&gt;
</code>
</pre>
<h2>Attributes</h2>
<p>All the native HTML radio attributes are valid</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">checked</span> (boolean)</div>
<p>
If present, radio button is set to checked state as default.
</p>
</div>
<div class="tr">
<div><span class="highlight">disabled</span> (boolean)</div>
<p>
If present radio button is set to disabled state. all the interactions are disabled
</p>
</div>
<div class="tr">
<div><span class="highlight">name</span> (string)</div>
<p>
Can be used to group radio buttons with same name. only one radio button will be active in a
group.
</p>
</div>
<div class="tr">
<div><span class="highlight">value</span> (string)</div>
<p>
Sets value of radio button which can be accessed by value property with JS
</p>
</div>
</section>
</section>
<section id="select_page" class="page hide-completely">
<h1 class="page__title">Select</h1>
<p>
<span class="highlight">&lt;sm-select&gt;</span> is very similar to starndatd HTML5 select and it's
markup stucture is
also identical.
</p>
<h2>Interactive demo</h2>
<sm-select>
<sm-option value="1">option1</sm-option>
<sm-option value="2">option2</sm-option>
<sm-option value="3">option3</sm-option>
</sm-select>
<pre>
<code>
&lt;sm-select&gt;
&lt;sm-option value="1"&gt;option1&lt;/sm-option&gt;
&lt;sm-option value="2"&gt;option2&lt;/sm-option&gt;
&lt;sm-option value="3"&gt;option3&lt;/sm-option&gt;
&lt;/sm-select&gt;
</code>
</pre>
<h2>Usage</h2>
<pre>
<code>
&lt;sm-select id="my_select"&gt;
&lt;sm-option value="1"&gt;option1&lt;/sm-option&gt;
&lt;sm-option value="2"&gt;option2&lt;/sm-option&gt;
&lt;sm-option value="3"&gt;option3&lt;/sm-option&gt;
&lt;/sm-select&gt;
&lt;script&gt;
const mySelect = document.getElementById('my_select')
mySelect.addEventListener('change', event =&gt; {
console.log(event.target.value) // logs out value of selected option
})
&lt;/script&gt;
</code>
</pre>
<h2>States</h2>
<h4>Disabled</h4>
<p>To disable the select add <span class="highlight">disabled</span> attribute.</p>
<sm-select disabled>
<sm-option value="1">option1</sm-option>
<sm-option value="2">option2</sm-option>
<sm-option value="3">option3</sm-option>
</sm-select>
<pre>
<code>
&lt;sm-select disabled&gt;
&lt;!-- Options --&gt;
&lt;/sm-select&gt;
</code>
</pre>
<h2>Supported events</h2>
<p>These are the events that will be fired when component state changes</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Event</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">change</span></div>
<p>
Whenever a different options is selected by user the this event is
fired. <br>
You can listen to this event and access the current value with event object <span
class="highlight">event.target.value</span>
</p>
</div>
</section>
</section>
<section id="spinner_page" class="page hide-completely">
<h1 class="page__title">Spinner</h1>
<p>
Just drop the <span class="highlight">sm-spinner</span> in markup where you want to show the spinner
</p>
<sm-spinner></sm-spinner>
<pre>
<code>
&lt;sm-spinner&gt;&lt;/sm-spinner&gt;
</code>
</pre>
</section>
<section id="switch_page" class="page hide-completely">
<h1 class="page__title">Switch</h1>
<p><span class="highlight">sm-switch</span> supports all the attributes of native HTML5 checkbox</p>
<strong>
linking some HTML element with <span class="highlght">sm-switch</span> using <span
class="highlight">label</span> tag won't work. <br>
Add the element inside the opening and closing sm-switch tag.
</strong>
<h2>Interactive demo</h2>
<sm-switch id="my_switch">
<div slot="left">
Turn the switch
</div>
</sm-switch>
<h2>States</h2>
<h4>Checked</h4>
<p>To make switch turned on by default add <span class="highlight">checked</span> attribute.</p>
<sm-switch checked>
<div slot="left">
On switch
</div>
</sm-switch>
<pre>
<code>
&lt;sm-switch checked&gt;
&lt;div slot="left"&gt;
On switch
&lt;/div&gt;
&lt;/sm-switch&gt;
</code>
</pre>
<h4>Disabled</h4>
<p>To disable the switch add <span class="highlight">disabled</span> attribute.</p>
<sm-switch disabled>
<div slot="left">
Disabled checkbox
</div>
</sm-switch>
<pre>
<code>
&lt;sm-switch disabled&gt;
&lt;div slot="left"&gt;
Disabled switch
&lt;/div&gt;
&lt;/sm-switch&gt;
</code>
</pre>
<h2>Attributes</h2>
<p>All the native HTML checkbox attributes are valid</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">checked</span> (boolean)</div>
<p>
If present, switch is set to checked state as default.
</p>
</div>
<div class="tr">
<div><span class="highlight">disabled</span> (boolean)</div>
<p>
If present switch is set to disabled state. all the interactions are disabled
</p>
</div>
<div class="tr">
<div><span class="highlight">value</span> (string)</div>
<p>
Sets value of switch which can be accessed by value property with JS
</p>
</div>
</section>
</section>
<section id="chips_page" class="page hide-completely">
<h1 class="page__title">Chips</h1>
<p>
This is a modern interpretation of classical HTML <span class="highlight">select</span> tag. More
suitable for touch devices,
</p>
<h2>Interactive demo</h2>
<span>Sort by </span>
<sm-chips id="sort_by">
<sm-chip value="relevance" selected>Relevance</sm-chip>
<sm-chip value="popularity">Popularity</sm-chip>
<sm-chip value="price">Price</sm-chip>
<sm-chip value="rating">Rating</sm-chip>
</sm-chips>
<pre>
<code>
&lt;sm-chips id="sort_by"&gt;
&lt;sm-chip value="relevance" selected&gt;Relevance&lt;/sm-chip&gt;
&lt;sm-chip value="popularity"&gt;Popularity&lt;/sm-chip&gt;
&lt;sm-chip value="price"&gt;Price&lt;/sm-chip&gt;
&lt;sm-chip value="rating"&gt;Rating&lt;/sm-chip&gt;
&lt;/sm-chips&gt;
</code>
</pre>
<h2>Custom attributes</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">multiline</span> ( Boolean )</div>
<p>
If present, options will wrap around instead of overflowing horizontally.
</p>
</div>
</section>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Variable</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">--gap</span></div>
<p>
Defines space between options. Default is "0.5rem".
</p>
</div>
</section>
<h2>Supported events</h2>
<p>These are the events that will be fired when component state changes</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Event</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">change</span></div>
<p>
Whenever a different options is selected by user the this event is
fired. <br>
You can listen to this event and access the current value with event object <span
class="highlight">event.target.value</span>
</p>
</div>
</section>
<h2>Usage</h2>
<pre>
<code>
&lt;sm-chips id="sort_by"&gt;
&lt;sm-chip value="relevance" selected&gt;Relevance&lt;/sm-chip&gt;
&lt;sm-chip value="popularity"&gt;Popularity&lt;/sm-chip&gt;
&lt;sm-chip value="price"&gt;Price&lt;/sm-chip&gt;
&lt;sm-chip value="rating"&gt;Rating&lt;/sm-chip&gt;
&lt;/sm-chips&gt;
&lt;script&gt;
const sortBy = document.getElementById('sort_by')
sortBy.addEventListener('change', event =&gt; {
console.log(event.target.value) // logs out value of selected option
})
&lt;/script&gt;
</code>
</pre>
</section>
<section id="tabs_page" class="page hide-completely">
<h1 class="page__title">Tabs</h1>
<p>
This component can be used sub-page navigation.
</p>
<h2>Interactive demo</h2>
<sm-tab-header target="tab1">
<sm-tab>Audio</sm-tab>
<sm-tab>Video</sm-tab>
</sm-tab-header>
<sm-tab-panels id="tab1">
<section>
<h3>Audio</h3>
<p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Exercitationem esse quod quae
repellat qui. Expedita fugiat voluptates beatae itaque corporis!</p>
</section>
<section>
<h3>Video</h3>
<p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Exercitationem esse quod quae
repellat qui. Expedita fugiat voluptates beatae itaque corporis!</p>
</section>
</sm-tab-panels>
<h2>Usage</h2>
<pre>
<code>
&lt;sm-tab-header target="tab1"&gt;
&lt;sm-tab&gt;
tab name
&lt;/sm-tab&gt;
&lt;sm-tab&gt;
tab name
&lt;/sm-tab&gt;
&lt;/sm-tab-header&gt;
&lt;sm-tab-panels id="tab1"&gt;
&lt;section&gt;
&lt;!-- Panel content --&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;!-- Panel content --&gt;
&lt;/section&gt;
&lt;/sm-tab-panels&gt;
</code>
</pre>
<p>
There are three components that together make the tabs components.
<ol>
<li>sm-tab-header</li>
<li>sm-tab</li>
<li>sm-tab-panels</li>
</ol>
</p>
<h3>sm-tab-header</h3>
<p>This is the first half of tabs that include the tabs header and actual tab buttons.</p>
<pre>
<code>
&lt;sm-tab-header variant="tab" target="tab2"&gt;
&lt;sm-tab&gt;Audio&lt;/sm-tab&gt;
&lt;sm-tab&gt;Video&lt;/sm-tab&gt;
&lt;/sm-tab-header&gt;
</code>
</pre>
<h2>Supported attributes</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">variant</span> ( string )</div>
<p>
Specifies variant of sm-tab-header. Only value can be <span class="highlight">tab</span>
</p>
</div>
<div class="tr">
<div><span class="highlight">target</span> ( string )</div>
<p>
Pass in the ID of respective sm-tab-panels to link them. This is how sm-tab-header
communicates with sm-tab-panel on which tab or panel should be displayed.
</p>
</div>
</section>
<h2>Variants</h2>
<p><span class="highlight">tab</span> is the only other variant than default style.</p>
<sm-tab-header variant="tab" target="tab2">
<sm-tab>Audio</sm-tab>
<sm-tab>Video</sm-tab>
</sm-tab-header>
<sm-tab-panels id="tab2">
<section>
<h3>Audio</h3>
<p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Exercitationem esse quod quae
repellat qui. Expedita fugiat voluptates beatae itaque corporis!</p>
</section>
<section>
<h3>Video</h3>
<p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Exercitationem esse quod quae
repellat qui. Expedita fugiat voluptates beatae itaque corporis!</p>
</section>
</sm-tab-panels>
<pre>
<code>
&lt;sm-tab-header variant="tab" target="tab2"&gt;
&lt;sm-tab&gt;Audio&lt;/sm-tab&gt;
&lt;sm-tab&gt;Video&lt;/sm-tab&gt;
&lt;/sm-tab-header&gt;
</code>
</pre>
</section>
<section id="tags_input_page" class="page hide-completely">
<h1 class="page__title">Tags input</h1>
<p>
This component has a very specific use case and that is for accepting tags.
Each time user presses enter or space, a new tag is created. Only unique values are allowed.
</p>
<h2>Interactive demo</h2>
<tags-input placeholder="Add tags..."></tags-input>
<pre>
<code>
&lt;tags-input placeholder="Add tags..."&gt;&lt;/tags-input&gt;
</code>
</pre>
<h2>Attributes</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">placeholder</span> ( string )</div>
<p>
Define some string to let user know which kind of input is required.
</p>
</div>
<div class="tr">
<div><span class="highlight">limit</span> ( number )</div>
<p>
Set a limit of tags that will be accepted atmost
</p>
</div>
</section>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Variable</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">--background</span></div>
<p>
Defines background of tags-input. Any valid CSS background property values are supported.
</p>
</div>
<div class="tr">
<div><span class="highlight">--border-radius</span></div>
<p>
Defines border-radius of tags-input
</p>
</div>
</section>
<h2>Supported functions</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Function</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">focusIn()</span></div>
<p>
To give focus to this component use this function instead of <span
class="highlight">focus()</span>
</p>
</div>
<div class="tr">
<div><span class="highlight">reset()</span></div>
<p>
When this function is called value will be set to empty string.
</p>
</div>
</section>
<h2>Usage</h2>
<pre>
<code>
&lt;tags-input id="get_tags" placeholder="Add tags..."&gt;&lt;/tags-input&gt;
&lt;script&gt;
const getTags = document.getElementById('get_tags')
console.log(getTags.value); /* returns an array of string that are user input */
&lt;/script&gt;
</code>
</pre>
</section>
<section id="textarea_page" class="page hide-completely">
<h1 class="page__title">Textarea</h1>
<p>Textarea is suitable component where multiline input is required. you can either specify
the number of lines textarea should expand or let the textarea expand according to user input until
a max-height is reached.</p>
<h2>Interactive demo</h2>
<sm-textarea id="my_textarea" placeholder="Add some text here..." rows="4"></sm-textarea>
<pre>
<code>
&lt;sm-textarea id="my_textarea" placeholder="Add some text here..." rows="4"&gt;&lt;/sm-textarea&gt;
</code>
</pre>
<h2>Variants</h2>
<p><span class="highlight">outlined</span> is only one styled variation. Default is filled which doesn't
require variant specified.</p>
<sm-textarea placeholder="This is a textarea" variant="outlined"></sm-textarea>
<pre>
<code>
&lt;sm-textarea placeholder="This is a textarea" variant="outlined"&gt;&lt;/sm-textarea&gt;
</code>
</pre>
<h2>Supported Attributes</h2>
<p>All the native HTML textarea attributes are valid.</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">disabled</span> (boolean)</div>
<p>
If present, all the interactions will be blocked.
</p>
</div>
<div class="tr">
<div><span class="highlight">rows</span> (number)</div>
<p>
Sets the number of rows textarea will be expanded by default.
Default is "1".
</p>
</div>
<div class="tr">
<div><span class="highlight">value</span> (string)</div>
<p>
Sets the default value of textarea.
</p>
</div>
</section>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Variable</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">--background</span></div>
<p>
Defines background textarea. Any valid CSS background property values are supported.
</p>
</div>
<div class="tr">
<div><span class="highlight">--border-radius</span></div>
<p>
Defines border-radius of textarea
</p>
</div>
<div class="tr">
<div><span class="highlight">--max-height</div>
<p>
Defines max-height to which textarea is allowed to expand. Default is "8rem"
</p>
</div>
</section>
<h2>Supported functions</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Function</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">focusIn()</span></div>
<p>
To give focus to this component use this function instead of <span
class="highlight">focus()</span>
</p>
</div>
<div class="tr">
<div><span class="highlight">reset()</span></div>
<p>
When this function is called value will be set to empty string.
</p>
</div>
</section>
<h2>Setters</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Function</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">disabled</span></div>
<p>
Set disabled state to <span class="highlight">true</span> or <span
class="highlight">false</span>
</p>
</div>
<div class="tr">
<div><span class="highlight">value</span></div>
<p>
Sets the value of textarea with JS
</p>
</div>
</section>
<h2>Usage</h2>
<pre>
<code>
&lt;sm-textarea placeholder="This is a textarea" id="my_textarea"&gt;&lt;/sm-textarea&gt;
&lt;script&gt;
const myTextarea = document.getElelementById('my_textarea')
myTextarea.value = 'some string'; /* setting value of textarea */
myTextarea.addEventListener('input', event => {
const value = event.target.value; /* accessing value of textarea */
})
&lt;/script&gt;
</code>
</pre>
</section>
<section id="text_field_page" class="page hide-completely">
<h1 class="page__title">Text field</h1>
<p>
This component can be used in scenarios where you need to display a name or something that user
should be able to edit directly
in-place instead of going to other UI element.
</p>
<h2>Interactive demo</h2>
<text-field value="John doe"></text-field>
<h2>Usage</h2>
<pre>
<code>
&lt;text-field id="name_field" value="John doe"&gt;&lt;/text-field&gt;
&lt;script&gt;
const nameField = document.getElementById('name_field')
nameField.addEventListener('change', event =&gt; {
console.log(event.target.value) // logs out new value set by user
console.log(nameField.value) // Accessing value directly with getter
})
&lt;/script&gt;
</code>
</pre>
<h2>Custom attributes</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Attribute</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">disabled</span> ( Boolean )</div>
<p>
If present, text can't be edited.
</p>
</div>
<div class="tr">
<div><span class="highlight">value</span> ( string )</div>
<p>
Set initial text that can be edited by user.
</p>
</div>
</section>
<h2>Supported events</h2>
<section class="table">
<div class="tr">
<h4 class="table__heading">Event</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">change</span></div>
<p>
Fired when text changes are saved by user.
</p>
</div>
</section>
</section>
<section id="theme_toggle_page" class="page hide-completely">
<h1 class="page__title">Theme toggle</h1>
<p>
Use <span class="highlight">theme-toggle</span> to create light/dark theme easily with CSS
variables.
</p>
<p>When this is toggled by user the component changes the custom data attribute <span
class="highlight">data-theme=""</span> on HTML body tag
to either <span class="highlight">light</span> or <span class="highlight">dark</span>
</p>
<p>
By default theme is set to OS level preferred-color-scheme ( supported by Android, iOS, Windows and
MacOS ).
</p>
<h2>Interactive demo</h2>
<theme-toggle></theme-toggle>
<h2>HTML</h2>
<pre>
<code>
&lt;theme-toggle&gt;&lt;/theme-toggle&gt;
</code>
</pre>
<h2>CSS</h2>
<pre>
<code>
&lt;style&gt;
body ,
body *{
/* Set CSS variables according to light theme or default theme*/
--accent-color: #0D7377;
--text-color: 17, 17, 17;
--background-color: 255, 255, 255;
--danger-color: red;
}
body[data-theme='dark'],
body[data-theme='dark'] *{
/* Set CSS variables according to dark theme */
--accent-color: #32E0C4;
--text-color: 240, 240, 240;
--text-color-light: 170, 170, 170;
--background-color: 10, 10, 10;
--danger-color: rgb(255, 106, 106);
}
body{
color: rgba(var(--text-color), 1);
background: rgba(var(--background-color), 1);
}
&lt;/style&gt;
</code>
</pre>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Variable</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">--height</div>
<p>
Defines height of toggle button
</p>
</div>
<div class="tr">
<div><span class="highlight">--width</div>
<p>
Defines width of toggle button
</p>
</div>
</section>
<h2>Custom events</h2>
<p>These are the events that will be fired when component state changes</p>
<section class="table">
<div class="tr">
<h4 class="table__heading">Event</h4>
<h4 class="table__heading">Description</h4>
</div>
<div class="tr">
<div><span class="highlight">themechange</span></div>
<p>
Whenever theme is toggled by user the <span class="highlight">themechange</span> event is
fired. <br>
You can listen to this event and access the current value of toggle with event object <span
class="highlight">event.detail.theme</span>
</p>
</div>
</section>
<pre>
<code>
&lt;theme-toggle id="my_theme_toggle"&gt;&lt;/theme-toggle&gt;
&lt;script&gt;
const myThemeToggle = document.getElementById('my_theme_toggle')
myThemeToggle.addEventListener('themechange', event =&gt; {
console.log(event.detail.theme) // logs out current theme ( light / dark )
})
&lt;/script&gt;
</code>
</pre>
</section>
</article>
</main>
<template id="nav_item_template">
<li>
<a class="list__item interact"></a>
</li>
</template>
<template id="comp_checkbox_template">
<sm-checkbox>
<span class="comp-checkbox__title"></span>
</sm-checkbox>
</template>
<script src="assets/prism.js" defer></script>
<script src="dist/button.min.js" defer></script>
<script src="dist/carousel.min.js" defer></script>
<script src="dist/checkbox.min.js" defer></script>
<script src="dist/chips.min.js" defer></script>
<script src="dist/copy.min.js" defer></script>
<script src="dist/file-input.min.js" defer></script>
<script src="dist/form.min.js" defer></script>
<script src="dist/hamburger-menu.min.js" defer></script>
<script src="dist/input.min.js" defer></script>
<script src="dist/menu.min.js" defer></script>
<script src="dist/notifications.min.js" defer></script>
<script src="dist/popup.min.js" defer></script>
<script src="dist/radio.min.js" defer></script>
<script src="dist/select.min.js" defer></script>
<script src="dist/spinner.min.js" defer></script>
<script src="dist/switch.min.js" defer></script>
<script src="dist/tabs.min.js" defer></script>
<script src="dist/tags-input.min.js" defer></script>
<script src="dist/text-field.min.js" defer></script>
<script src="dist/textarea.min.js" defer></script>
<script src="dist/theme-toggle.min.js" defer></script>
<script id="default_ui_library">
const domRefs = {};
function getRef(elementId) {
if (!domRefs.hasOwnProperty(elementId)) {
domRefs[elementId] = {
count: 1,
ref: null,
};
return document.getElementById(elementId);
} else {
if (domRefs[elementId].count < 3) {
domRefs[elementId].count = domRefs[elementId].count + 1;
return document.getElementById(elementId);
} else {
if (!domRefs[elementId].ref)
domRefs[elementId].ref = document.getElementById(elementId);
return domRefs[elementId].ref;
}
}
}
function createElement(tagName, obj) {
const { className, textContent, innerHTML, attributes = {} } = obj
const elem = document.createElement(tagName)
for (let attribute in attributes) {
elem.setAttribute(attribute, attributes[attribute])
}
if (className)
elem.className = className
if (textContent)
elem.textContent = textContent
if (innerHTML)
elem.innerHTML = innerHTML
return elem
}
const debounce = (callback, wait) => {
let timeoutId = null;
return (...args) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
callback.apply(null, args);
}, wait);
};
}
let timerId;
function throttle(func, delay) {
// If setTimeout is already scheduled, no need to do anything
if (timerId) {
return;
}
// Schedule a setTimeout after delay seconds
timerId = setTimeout(function () {
func();
// Once setTimeout function execution is finished, timerId = undefined so that in
// the next scroll event function execution can be scheduled by the setTimeout
timerId = undefined;
}, delay);
}
//Checks for internet connection status
if (!navigator.onLine)
notify(
"There seems to be a problem connecting to the internet, Please check you internet connection.",
"error",
{ sound: true }
);
window.addEventListener("offline", () => {
notify(
"There seems to be a problem connecting to the internet, Please check you internet connection.",
"error",
{ pinned: true, sound: true }
);
});
window.addEventListener("online", () => {
getRef("notification_drawer").clearAll();
notify("We are back online.", "success");
});
let zIndex = 10
// function required for popups or modals to appear
function showPopup(popupId, pinned) {
zIndex++
getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
getRef(popupId).show({ pinned })
return getRef(popupId);
}
// hides the popup or modal
function hidePopup() {
if (popupStack.peek() === undefined)
return;
popupStack.peek().popup.hide()
}
// displays a popup for asking permission. Use this instead of JS confirm
let confirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
return new Promise(resolve => {
showPopup('confirmation_popup', true)
getRef('confirm_title').textContent = title;
getRef('confirm_message').textContent = message;
let cancelButton = getRef('confirmation_popup').children[2].children[0],
submitButton = getRef('confirmation_popup').children[2].children[1]
submitButton.textContent = confirmText
cancelButton.textContent = cancelText
submitButton.onclick = () => {
hidePopup()
resolve(true);
}
cancelButton.onclick = () => {
hidePopup()
resolve(false);
}
})
}
// displays a popup for asking user input. Use this instead of JS prompt
async function getPromptInput(title, message = '', showText = true, trueBtn = "Ok", falseBtn = "Cancel") {
showPopup('prompt_popup', true)
getRef('prompt_title').textContent = title;
let input = getRef('prompt_input');
input.setAttribute("placeholder", message)
let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
if (showText)
input.setAttribute("type", "text")
else
input.setAttribute("type", "password")
input.focusIn()
buttons[0].textContent = falseBtn;
buttons[1].textContent = trueBtn;
return new Promise((resolve, reject) => {
buttons[0].onclick = () => {
hidePopup()
return;
}
buttons[1].onclick = () => {
let value = input.value;
hidePopup()
resolve(value)
}
})
}
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
function notify(message, mode, options = {}) {
const { pinned = false, sound } = options
if (mode === "error") console.error(message);
let icon
switch (mode) {
case 'success':
icon = `<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z"/></svg>`
break;
case 'error':
icon = `<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-7v2h2v-2h-2zm0-8v6h2V7h-2z"/></svg>`
break;
}
getRef("notification_drawer").push(message, { pinned, icon });
if (navigator.onLine && sound) {
getRef("notification_sound").currentTime = 0;
getRef("notification_sound").play();
}
}
const currentYear = new Date().getFullYear();
function getFormatedTime(time, relative) {
try {
if (String(time).indexOf("_")) time = String(time).split("_")[0];
const intTime = parseInt(time);
if (String(intTime).length < 13) time *= 1000;
let timeFrag = new Date(intTime).toString().split(" "),
day = timeFrag[0],
month = timeFrag[1],
date = timeFrag[2],
year = timeFrag[3],
minutes = new Date(intTime).getMinutes(),
hours = new Date(intTime).getHours(),
currentTime = new Date().toString().split(" ");
minutes = minutes < 10 ? `0${minutes}` : minutes;
let finalHours = ``;
if (hours > 12) finalHours = `${hours - 12}:${minutes}`;
else if (hours === 0) finalHours = `12:${minutes}`;
else finalHours = `${hours}:${minutes}`;
finalHours = hours >= 12 ? `${finalHours} PM` : `${finalHours} AM`;
if (relative) {
return `${date} ${month} ${year}`;
} else return `${finalHours} ${month} ${date} ${year}`;
} catch (e) {
console.error(e);
return time;
}
}
window.addEventListener("load", () => {
// document.querySelectorAll('sm-input[data-flo-id]').forEach(input => input.customValidation = validateAddr)
document.addEventListener('keyup', (e) => {
if (e.code === 'Escape') {
hidePopup()
}
})
document.addEventListener("pointerdown", (e) => {
if (e.target.closest("button, sm-button:not([disabled]), .interact")) {
createRipple(e, e.target.closest("button, sm-button, .interact"));
}
});
document.addEventListener('copy', () => {
notify('copied', 'success')
})
});
function createRipple(event, target) {
const circle = document.createElement("span");
const diameter = Math.max(target.clientWidth, target.clientHeight);
const radius = diameter / 2;
const targetDimensions = target.getBoundingClientRect();
circle.style.width = circle.style.height = `${diameter}px`;
circle.style.left = `${event.clientX - (targetDimensions.left + radius)}px`;
circle.style.top = `${event.clientY - (targetDimensions.top + radius)}px`;
circle.classList.add("ripple");
const rippleAnimation = circle.animate(
[
{
transform: "scale(4)",
opacity: 0,
},
],
{
duration: 600,
fill: "forwards",
easing: "ease-out",
}
);
target.append(circle);
rippleAnimation.onfinish = () => {
circle.remove();
};
}
</script>
<script>
const render = {
navListItem(obj) {
const { name, pageId } = obj
const item = getRef('nav_item_template').content.cloneNode(true).firstElementChild
const itemLink = item.firstElementChild
itemLink.textContent = name
itemLink.href = `#${pageId}`
return item
},
compCheckbox(obj) {
const { name } = obj
const checkbox = getRef('comp_checkbox_template').content.cloneNode(true).firstElementChild
checkbox.setAttribute('value', name.toLowerCase().replaceAll(' ', '-'))
checkbox.firstElementChild.textContent = name
return checkbox
}
}
window.addEventListener('hashchange', e => showPage(window.location.hash, { hashChange: true }))
window.addEventListener('load', e => {
document.body.classList.remove('hide-completely')
renderComponentList()
showPage(window.location.hash, { firstLoad: true })
getRef('total_components_count').textContent = componentsList.length
getComponents()
})
function showPage(targetPage, options = {}) {
const { firstLoad, hashChange } = options
let pageId
if (targetPage === '') {
pageId = 'overview_page'
}
else {
pageId = targetPage.includes('#') ? targetPage.split('#')[1] : targetPage
}
if (!getRef(pageId).classList.contains('page')) return
document.querySelector('.page:not(.hide-completely)').classList.add('hide-completely')
document.querySelector('.list__item--active').classList.remove('list__item--active')
getRef(pageId).classList.remove('hide-completely')
getRef(pageId).animate([
{
opacity: 0,
transform: 'translateX(-1rem)'
},
{
opacity: 1,
transform: 'none'
},
],
{
duration: 300,
easing: 'ease'
})
getRef(pageId).parentNode.scroll(0, 0)
const targetListItem = document.querySelector(`.list__item[href="#${pageId}"]`)
targetListItem.classList.add('list__item--active')
if (firstLoad && window.innerWidth > 640 && targetListItem.getBoundingClientRect().top > getRef('side_nav').getBoundingClientRect().height) {
getRef('side_nav').scrollTo({
top: (targetListItem.getBoundingClientRect().top - getRef('side_nav').getBoundingClientRect().top + getRef('side_nav').scrollTop),
behavior: 'smooth'
})
}
if (hashChange && window.innerWidth < 640) {
getRef('side_nav').close()
}
}
const componentsList = [
{
name: 'button',
pageId: 'button_page'
},
{
name: 'Carousel',
pageId: 'carousel_page'
},
{
name: 'Checkbox',
pageId: 'checkbox_page'
},
{
name: 'Chips',
pageId: 'chips_page'
},
{
name: 'Copy',
pageId: 'copy_page'
},
{
name: 'File input',
pageId: 'file_input_page'
},
{
name: 'Form',
pageId: 'form_page'
},
{
name: 'Hamburger menu',
pageId: 'hamburger_menu_page'
},
{
name: 'Input',
pageId: 'input_page'
},
{
name: 'Menu',
pageId: 'menu_page'
},
{
name: 'Notifications',
pageId: 'notifications_page'
},
{
name: 'Popup',
pageId: 'popup_page'
},
{
name: 'Radio',
pageId: 'radio_page'
},
{
name: 'Switch',
pageId: 'switch_page'
},
{
name: 'Select',
pageId: 'select_page'
},
{
name: 'Spinner',
pageId: 'spinner_page'
},
{
name: 'Tabs',
pageId: 'tabs_page'
},
{
name: 'Tags input',
pageId: 'tags_input_page'
},
{
name: 'textarea',
pageId: 'textarea_page'
},
{
name: 'Text field',
pageId: 'text_field_page'
},
{
name: 'theme toggle',
pageId: 'theme_toggle_page'
},
]
function renderComponentList() {
const itemsFrag = document.createDocumentFragment()
const checkboxFrag = document.createDocumentFragment()
componentsList.forEach((component, index) => {
itemsFrag.append(render.navListItem(component))
checkboxFrag.append(render.compCheckbox({ ...component, index }))
})
getRef('components_list').innerHTML = ''
getRef('components_selection_list').innerHTML = ''
getRef('components_list').append(itemsFrag)
getRef('components_selection_list').append(checkboxFrag)
}
function selectAll() {
getRef('components_selection_list').querySelectorAll('sm-checkbox').forEach(elem => elem.checked = true)
}
function clearAll() {
getRef('components_selection_list').querySelectorAll('sm-checkbox').forEach(elem => elem.checked = false)
}
async function getSelectedComponents() {
const selectedComponents = [...getRef('components_selection_list').querySelectorAll('sm-checkbox[checked]')].map(v => v.value)
const extension = getRef('get_minified').checked ? '.min.js' : '.js'
const filesList = []
selectedComponents.forEach(async component => {
for (const compObj in allComponentsObj) {
const { name, download_url } = allComponentsObj[compObj]
if (name === `${component}${extension}`) {
filesList.push(fetch(download_url).then(async res => await res.text()))
break;
}
}
});
return await Promise.all(filesList)
}
async function downloadComponents() {
const sourceCode = await getFormattedSourceCode()
if (sourceCode) {
downloadJs(sourceCode)
} else {
notify('Please select at least one component', 'error')
}
}
async function copySourceCode() {
const sourceCode = await getFormattedSourceCode()
if (sourceCode) {
window.navigator.clipboard.writeText(sourceCode).then(success => {
notify('Copied components source code')
}).catch(err => console.error(error))
}
else {
notify('Please select at least one component', 'error')
}
}
async function getFormattedSourceCode(components) {
const selectedComponents = await getSelectedComponents()
if (selectedComponents.length) {
const selectedComponentsList = [...getRef('components_selection_list').querySelectorAll('sm-checkbox[checked]')].map(v => v.value)
const minified = getRef('get_minified').checked
let componentsSourceCode = selectedComponents
if (minified) {
// replace all whitespace with single space and remove new line characters
componentsSourceCode = selectedComponents.map(v => v.replace(/\s+/g, ' ').replace(/\\n/g, ''))
}
return `// Components downloaded: ${selectedComponentsList.join(',')}\n${componentsSourceCode.join("\n")}`
} else {
return false
}
}
let allComponentsObj = []
async function getComponents() {
const files = await fetch('https://api.github.com/repos/ranchimall/standard-ui/contents/components/dist')
allComponentsObj = await files.json()
}
function downloadJs(sourceCode) {
const minified = getRef('get_minified').checked
const extension = minified ? '.min.js' : '.js'
const element = createElement('a', {
attributes: {
'href': 'data:application/javascript;charset=utf-8,' + encodeURIComponent(sourceCode),
'download': `components${extension}`,
'style': 'display:none'
}
});
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
</script>
</body>
</html>