Created
May 15, 2020 15:50
-
-
Save toomanyredirects/91f27f28603a4b64ec685881e0385c0c to your computer and use it in GitHub Desktop.
Replace Native UI Alert, Prompt & Confirm Dialogs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<body id="app" role="application" data-scheme="auto"> | |
<!-- Drawer --> | |
<aside id="sidebar" class="drawer shadow"> | |
<div class="drawer-header"> | |
<h4>Profile</h4> | |
<a class="close" href="#!" data-dismiss="drawer">Close</a> | |
</div> | |
<div class="drawer-body"> | |
Body | |
</div> | |
<div class="drawer-footer"> | |
Footer | |
</div> | |
</aside> | |
<!-- Header --> | |
<header id="header"> | |
<div class="container-fluid container-sm"> | |
<!-- Logo --> | |
<a href="#!" class="float-left"> | |
<figure id="logo"> | |
<svg viewBox="0 0 9 9" role="presentation"> | |
<use xlink:href="#ui-icon"/> | |
</svg> | |
<figcaption>UX</figcaption> | |
</figure> | |
</a> | |
<!-- Navigation trigger--> | |
<a href="#navigation" class="float-left d-none hamburger" data-toggle="collapse" aria-expanded="false" data-expanded="Close navigation">Open navigation</a> | |
<!-- Navigation --> | |
<nav id="navigation" class="d-none d-m-block" aria-labelledby="titleNavigation"> | |
<h4 id="titleNavigation">Navigation</h4> | |
<ul class="nav"> | |
<li> | |
<a href="#!">Home <span class="sr-only">(current)</span></a> | |
</li> | |
<li> | |
<a href="#!">Something</a> | |
</li> | |
<li> | |
<a href="#!">Somthing else</a> | |
</li> | |
</ul> | |
</nav> | |
<div class="dropdown float-right"> | |
<a href="#menu" class="ripple" type="button" id="dots" data-toggle="dropdown" data-offset="-35" data-align="right" aria-haspopup="true" aria-expanded="false" title="more..." data-tooltip="left"> | |
<svg viewBox="0 0 9 9" role="img"> | |
<use xlink:href="#dots-icon"/> | |
</svg> | |
</a> | |
<div class="dropdown-menu" id="menu" aria-labelledby="dots"> | |
<h6>Settings</h6> | |
<a role="menuitem" href="#sidebar" data-toggle="collapse" aria-controls="sidebar" aria-expanded="false" data-expanded="Close profile">Open profile</a> | |
<a role="menuitem" href="#!">Something else here</a> | |
</div> | |
</div> | |
</div> | |
</header> | |
<!--Tab List / Navigation --> | |
<nav id="nav" class="nav tab-list" role="tablist" aria-label="Tab Navigation"> | |
<a href="#grid-tab" id="grid" role="tab" data-toggle="tab" aria-selected="false" aria-controls="grid-tab" tabindex="-1">Grid</a> | |
<a href="#cards-tab" id="cards" role="tab" data-toggle="tab" aria-selected="false" aria-controls="cards-tab" tabindex="-1">Cards</a> | |
<a href="#forms-tab" id="forms" role="tab" data-toggle="tab" aria-selected="false" aria-controls="forms-tab" tabindex="-1">Forms</a> | |
<a href="#buttons-tab" id="forms" role="tab" data-toggle="tab" aria-selected="false" aria-controls="buttons-tab" tabindex="-1">Buttons</a> | |
<a href="#icons-tab" id="icons" role="tab" data-toggle="tab" aria-selected="false" aria-controls="icons-tab" tabindex="-1">Icons</a> | |
<a href="#nativeui-tab" id="nativeui" role="tab" data-toggle="tab" aria-selected="false" aria-controls="nativeui-tab" tabindex="-1">Native UI</a> | |
<a href="#dropdowns-tab" id="dropdowns" role="tab" data-toggle="tab" aria-selected="false" aria-controls="dropdowns-tab" tabindex="-1">Dropdowns</a> | |
<a href="#tooltips-tab" class="active" id="tooltips" role="tab" data-toggle="tab" aria-selected="true" aria-controls="tooltips-tab">Tooltips</a> | |
<a href="#notifications-tab" id="notifications" role="tab" data-toggle="tab" aria-selected="false" aria-controls="notifications-tab" tabindex="-1">Notifications</a> | |
<a href="#toasts-tab" id="toasts" role="tab" data-toggle="tab" aria-selected="false" aria-controls="toasts-tab" tabindex="-1">Toasts</a> | |
<i class="indicator">current item</i> | |
</nav> | |
<!-- Tabs --> | |
<main id="main" class="tabs"> | |
<!--Tab Grid --> | |
<section class="tab-panel slide" tabindex="0" role="tabpanel" id="grid-tab" aria-labelledby="grid"> | |
<div class="container-fluid container-sm"> | |
<legend>Grid</legend> | |
<p>A responsive grid system based on bootstrap logic.</p> | |
<style> | |
#grid-tab .col {background-color: rgba(127,127,127,0.1); padding: 1em 0; border: 1px dotted #ccc; text-align: center; margin-bottom:0.5em} | |
</style> | |
<div class="row"> | |
<div class="col">1 of 2</div> | |
<div class="col">2 of 2</div> | |
</div> | |
<div class="row"> | |
<div class="col">1 of 3</div> | |
<div class="col">2 of 3</div> | |
<div class="col">3 of 3</div> | |
</div> | |
<div class="row"> | |
<div class="col">1 of 4</div> | |
<div class="col">2 of 4</div> | |
<div class="col">3 of 4</div> | |
<div class="col">4 of 4</div> | |
</div> | |
</div> | |
</section> | |
<!--Tab Cards --> | |
<section class="tab-panel slide" tabindex="0" role="tabpanel" id="cards-tab" aria-labelledby="cards"> | |
<div class="container-fluid container-sm"> | |
<h2>Cards</h2> | |
<div class="card-columns"> | |
<div class="card"> | |
<svg class="card-img-top" width="100%" height="10rem" role="img" aria-label="Placeholder: Image cap"> | |
<rect width="100%" height="100%" fill="#868e96"/> | |
</svg> | |
<div class="card-body"> | |
<h5 class="card-title">Card title</h5> | |
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p> | |
<a href="#" class="btn btn-primary">Go somewhere</a> | |
</div> | |
</div> | |
<div class="card"> | |
<svg class="card-img-top" width="100%" height="10rem" role="img" aria-label="Placeholder: Image cap"> | |
<rect width="100%" height="100%" fill="#868e96"/> | |
</svg> | |
<div class="card-body"> | |
<h5 class="card-title">Card title</h5> | |
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p> | |
<a href="#" class="btn btn-primary">Go somewhere</a> | |
</div> | |
</div> | |
<div class="card"> | |
<svg class="card-img-top" width="100%" height="10rem" role="img" aria-label="Placeholder: Image cap"> | |
<rect width="100%" height="100%" fill="#868e96"/> | |
</svg> | |
<div class="card-body"> | |
<h5 class="card-title">Card title</h5> | |
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p> | |
<a href="#" class="btn btn-primary">Go somewhere</a> | |
</div> | |
</div> | |
<div class="card"> | |
<svg class="card-img-top" width="100%" height="10rem" role="img" aria-label="Placeholder: Image cap"> | |
<rect width="100%" height="100%" fill="#868e96"/> | |
</svg> | |
<div class="card-body"> | |
<h5 class="card-title">Card title</h5> | |
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p> | |
<a href="#" class="btn btn-primary">Go somewhere</a> | |
</div> | |
</div> | |
</div> | |
</div> | |
</section> | |
<!--Tab Forms --> | |
<section class="tab-panel slide" tabindex="0" role="tabpanel" id="forms-tab" aria-labelledby="forms"> | |
<div class="container-fluid container-sm"> | |
<h2>Forms</h2> | |
<p>Native UI & Form Submission</p> | |
<form lang="en" data-validate="true" id="form"> | |
<legend>Example</legend> | |
<div class="row form-row"> | |
<fieldset class="form-group col-md-6"> | |
<label for="input-name" class="form-label">Name</label> | |
<input class="form-control" id="input-name" name="name" type="text" placeholder="Change name here" autocomplete="name" required/> | |
</fieldset> | |
<fieldset class="form-group col-md-6"> | |
<label for="input-password" class="form-label">Password</label> | |
<input class="form-control" id="input-password" type="password" placeholder="Type password here" inputmode="password" autocomplete="new-password" required/> | |
</fieldset> | |
</div> | |
<div class="row form-row"> | |
<fieldset class="form-group col-10"> | |
<label for="input-street" class="form-label">Street</label> | |
<input class="form-control" id="input-street" name="street" type="text" placeholder="Change street here" autocomplete="street-address" required/> | |
</fieldset> | |
<fieldset class="form-group col-2"> | |
<label for="input-number" class="form-label">No.</label> | |
<input class="form-control" id="input-number" type="number" min="1" max="99" step="1" value="" inputmode="numeric" autocomplete="street-number"/> | |
</fieldset> | |
</div> | |
<div class="row form-row"> | |
<fieldset class="form-group col-md-6"> | |
<label for="input-email" class="form-label">Email</label> | |
<input class="form-control" id="input-email" name="email" type="email" placeholder="Change email here" autocomplete="email" required/> | |
</fieldset> | |
<fieldset class="form-group col-md-6"> | |
<label for="input-phone" class="form-label">Phone</label> | |
<input class="form-control" id="input-phone" type="tel" placeholder="Change number here" inputmode="tel" required/> | |
</fieldset> | |
</div> | |
<div class="row form-row"> | |
<fieldset class="form-group col-md-4 col-8"> | |
<label for="input-date" class="form-label">Date</label> | |
<input class="form-control" id="input-date" type="date" placeholder="Change date here" inputmode="date" required/> | |
</fieldset> | |
<fieldset class="form-group col-md-2 col-4"> | |
<label for="input-time" class="form-label">Time</label> | |
<input class="form-control" id="input-time" type="time" placeholder="Change time here" inputmode="time" required/> | |
</fieldset> | |
<fieldset class="form-group col-md-6"> | |
<label for="input-select" class="form-label">Select</label> | |
<select id="input-select" class="form-control" type="text" placeholder="Please select" required> | |
<optgroup label="Group"> | |
<option>Please select</option> | |
<option value="option1">Option 1</option> | |
<option value="option2">Option 2</option> | |
</optgroup> | |
</select> | |
</fieldset> | |
</div> | |
<div class="row form-row"> | |
<fieldset class="form-group col-md-6"> | |
<label for="input-range" class="form-label">Range slider</label> | |
<input id="input-range" class="form-range" type="range" value="33" min="0" max="100" step="1" data-unit="%" required/> | |
</fieldset> | |
<fieldset class="form-group col-md-6"> | |
<label for="input-disabled" class="form-label">Text disabled</label> | |
<input id="input-disabled" class="form-control" type="text" placeholder="Disabled input" disabled/> | |
</fieldset> | |
</div> | |
<fieldset class="form-group"> | |
<label for="input-textarea" class="form-label">Textarea</label> | |
<textarea class="form-control" id="input-textarea" type="text" placeholder="Change text here" required></textarea> | |
</fieldset> | |
<fieldset class="form-group"> | |
<label for="color" class="form-label">Color</label> | |
<input id="color" class="form-control form-control-color" type="color" inputmode="color" value="" list="swatches" required/> | |
<datalist id="swatches"> | |
<option>#cc0000</option> | |
<option>#00cc00</option> | |
<option>#0000cc</option> | |
<option>#cc00cc</option> | |
</datalist> | |
</fieldset> | |
<fieldset> | |
<button type="reset" class="btn float-left">Reset</button> | |
<button type="submit" class="btn btn-primary float-right">Submit</button> | |
</fieldset> | |
</form> | |
</div> | |
</section> | |
<!--Tab buttons --> | |
<section class="tab-panel slide" tabindex="0" role="tabpanel" id="buttons-tab" aria-labelledby="forms"> | |
<div class="container-fluid container-sm"> | |
<h2>Buttons</h2> | |
<p>Theme colored:</p> | |
<form> | |
<fieldset> | |
<button type="button" class="btn">default</button> | |
<button type="button" class="btn btn-primary">primary</button> | |
<button type="button" class="btn btn-secondary">secondary</button> | |
<button type="button" class="btn btn-success">success</button> | |
</fieldset> | |
<fieldset> | |
<button type="button" class="btn btn-danger">danger</button> | |
<button type="button" class="btn btn-warning">warning</button> | |
<button type="button" class="btn btn-info">info</button> | |
<button type="button" class="btn btn-dark">dark</button> | |
<button type="button" class="btn btn-light">light</button> | |
</fieldset> | |
</form> | |
<p>With SVG icons:</p> | |
<form> | |
<fieldset> | |
<button type="button" class="btn"> | |
<svg viewBox="0 0 9 9" role="img"><use xlink:href="#home-icon"/></svg> Default | |
</button> | |
<button type="button" class="btn btn-primary"> | |
<svg viewBox="0 0 9 9" role="img"><use xlink:href="#ui-icon"/></svg> Primary | |
</button> | |
<button type="button" class="btn btn-secondary"> | |
<svg viewBox="0 0 9 9" role="img"><use xlink:href="#dots-icon"/></svg> Secondary | |
</button> | |
<button type="button" class="btn btn-success"> | |
<svg viewBox="0 0 9 9" role="img"><use xlink:href="#check-icon"/></svg> Success | |
</button> | |
</fieldset> | |
<fieldset> | |
<button type="button" class="btn btn-danger"> | |
<svg viewBox="0 0 9 9" role="img"><use xlink:href="#delete-icon"/></svg> Danger | |
</button> | |
<button type="button" class="btn btn-warning"> | |
<svg viewBox="0 0 9 9" role="img"><use xlink:href="#warning-icon"/></svg> Warning | |
</button> | |
<button type="button" class="btn btn-info"> | |
<svg viewBox="0 0 9 9" role="img"><use xlink:href="#star-icon"/></svg> Info | |
</button> | |
<button type="button" class="btn btn-dark"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#refresh-icon"/></svg> Dark</button> | |
<button type="button" class="btn btn-light"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#dots-icon"/></svg></button> | |
</fieldset> | |
</form> | |
<p>Outlined:</p> | |
<form> | |
<fieldset> | |
<button type="button" class="btn"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#home-icon"/></svg> Default</button> | |
<button type="button" class="btn btn-outline-primary"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#star-outline-icon"/></svg> Primary</button> | |
<button type="button" class="btn btn-outline-secondary"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#refresh-outline-icon"/></svg> Secondary</button> | |
<button type="button" class="btn btn-outline-success"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#fader-icon"/></svg> Success</button> | |
</fieldset> | |
<fieldset> | |
<button type="button" class="btn btn-outline-danger"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#pdf-icon"/></svg> Danger</button> | |
<button type="button" class="btn btn-outline-warning"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#settings-icon"/></svg> Warning</button> | |
<button type="button" class="btn btn-outline-info"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#copy-outline-icon"/></svg> Info</button> | |
<button type="button" class="btn btn-outline-dark"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#copy-icon"/></svg> Dark</button> | |
<button type="button" class="btn btn-outline-light">light</button> | |
</fieldset> | |
</form> | |
<p>Variations:</p> | |
<form> | |
<fieldset> | |
<button type="button" class="btn rounded-pill"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#home-icon"/></svg> Default</button> | |
<button type="button" class="btn btn-outline-primary rounded-pill"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#star-outline-icon"/></svg> Primary</button> | |
<button type="button" class="btn btn-secondary rounded-circle"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#refresh-outline-icon"/></svg> </button> | |
<button type="button" class="btn btn-success shadow-elevated rounded-circle"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#plus-outline-icon"/></svg> </button> | |
<button type="button" class="btn btn-outline-danger rounded-circle"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#pdf-outline-icon"/></svg></button> | |
<button type="button" class="btn btn-outline-warning"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#settings-icon"/></svg></button> | |
<button type="button" class="btn btn-info"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#copy-icon"/></svg></button> | |
<button type="button" class="btn btn-outline-dark"><svg viewBox="0 0 9 9" role="img"><use xlink:href="#copy-outline-icon"/></svg></button> | |
<button type="button" class="btn btn-outline-light">light</button> | |
</fieldset> | |
</form> | |
</div> | |
</section> | |
<!--Tab Icons --> | |
<section class="tab-panel slide" tabindex="0" role="tabpanel" id="icons-tab" aria-labelledby="icons"> | |
<div class="container-fluid container-sm"> | |
<h2>Icons</h2> | |
<p>Available SVG icons:</p> | |
<div id='icons-wrapper'> | |
<form class="form-group"> | |
<div class="input-group"> | |
<div class="input-group-prepend"> | |
<label for="search-icons" class="input-group-text">Search</label> | |
</div> | |
<input type="search" class="form-control" id="search-icons" placeholder="Search icon" autocomplete="search" required/> | |
<div class="input-group-append"> | |
<button type="button" class="btn btn-primary">Search</button> | |
</div> | |
</div> | |
</form> | |
</div> | |
</div> | |
</section> | |
<!--Tab Native UI --> | |
<section class="tab-panel slide" tabindex="0" role="tabpanel" id="nativeui-tab" aria-labelledby="nativeui"> | |
<div class="container-fluid container-sm"> | |
<form onsubmit="alert('submitted form!')" id="native-ui" class="clearfix"> | |
<legend>Native UI & Form Submission</legend> | |
<p>Native UI & Form Submission</p> | |
<fieldset> | |
<input class="form-control" type="text" placeholder="Change input here" inputmode="tel"/> | |
<input class="form-control" type="text" placeholder="Disabled input" disabled/> | |
<select class="form-control form-select" type="text" placeholder="Disabled input"> | |
<optgroup label="Group"> | |
<option>Option 1</option> | |
<option>Option 2</option> | |
</optgroup> | |
</select> | |
</fieldset> | |
<button type="button" onclick="alert('Something just happened!')" title="alert('text' [ , options, callback ]);" class="btn">Alert</button> | |
<button type="submit" onclick="confirm('Do you really want to do this?')" title="confirm('text' [ , options, callback ]);" class="btn">Confirm</button> | |
<button type="button" onclick="prompt('Type something. Just do it.', 'something')" title="prompt('text', value [ , options, callback ]);" class="btn">Prompt</button> | |
<button type="button" onclick="prompt('Type something. Just do it.', 'something')" title="dialog('text', value [ , options, callback ]);" class="btn">Dialog</button> | |
<button type="submit" data-tooltip="bottom" onclick="confirm('Would you like to submit the form?')" title="Confirm form submission" class="btn">Submit</button> | |
</form> | |
<form id="dialog"> | |
<h2>Dialog</h2> | |
<p>Open a <a href="#customModal" data-toggle="modal" data-target="customModal" title="Custom modal dialog">Custom modal dialog</a> for testing purpose.</p> | |
</form> | |
</div> | |
</section> | |
<!--Tab Dropdowns --> | |
<section class="tab-panel slide" role="tabpanel" id="dropdowns-tab" aria-labelledby="dropdowns"> | |
<div class="container-fluid container-sm"> | |
<form id="dropdowns"> | |
<legend>Dropdowns</legend> | |
<p>Dropdowns are absolute positioned to their parent element.</p> | |
<fieldset class="dropdown"> | |
<button class="btn ripple" type="button" id="dropdownLink" data-toggle="dropdown" data-offset="7" aria-haspopup="true" aria-expanded="false">Drop down <i class="caret" aria-hidden="true"></i></button> | |
<div class="dropdown-menu" aria-labelledby="dropdownLink"> | |
<h6>Dropdown header</h6> | |
<a class="disabled" role="menuitem" href="#!" tabindex="-1" aria-disabled="true">Action</a> | |
<a role="menuitem" href="#!">Another action</a> | |
<a role="menuitem" href="#!">Something else here</a> | |
<div class="divider"></div> | |
<a role="menuitem" href="#!">Separated link</a> | |
</div> | |
</fieldset> | |
<fieldset class="dropdown dropup"> | |
<button class="btn ripple" type="button" id="dropupLink" data-toggle="dropdown" data-offset="7" data-align="right top" aria-haspopup="true" aria-expanded="false">Drop up <i class="caret" aria-hidden="true"></i></button> | |
<div class="dropdown-menu" aria-labelledby="dropupLink"> | |
<h6>Dropup header</h6> | |
<a role="menuitem" href="#!" class="disabled" tabindex="-1" aria-disabled="true">Action</a> | |
<a role="menuitem" href="#!">Another action</a> | |
<a role="menuitem" href="#!">Something else here</a> | |
<div class="divider"></div> | |
<a role="menuitem" href="#!">Separated link</a> | |
<i class="indicator"></i> | |
</div> | |
</fieldset> | |
</form> | |
</div> | |
</section> | |
<!--Tab Tooltips --> | |
<section class="tab-panel slide show active" tabindex="0" role="tabpanel" id="tooltips-tab" aria-labelledby="tooltips"> | |
<form id="tooltips" class="container-fluid container-sm"> | |
<legend>Tooltips</legend> | |
<p>Tooltips for the HTML title property are single elements for descriptive user interface feedbacks or descriptions.</p> | |
<fieldset> | |
<button type="button" class="btn ripple" title="Tooltip top" data-tooltip="top">Top</button><br> | |
<button type="button" class="btn" title="Tooltip left" data-tooltip="left">Left</button> | |
<button type="button" class="btn" title="Tooltip right" data-tooltip="right">Right</button><br> | |
<button type="button" class="btn" title="Tooltip right" data-tooltip="right">Right</button> | |
<button type="button" class="btn" title="Tooltip left" data-tooltip="left">Left</button><br> | |
<button type="button" class="btn" title="Tooltip bottom" data-tooltip="bottom">Bottom</button> | |
</fieldset> | |
</form> | |
</section> | |
<!--Tab Notifications --> | |
<section class="tab-panel slide" tabindex="0" role="tabpanel" id="notifications-tab" aria-labelledby="notifications"> | |
<form id="notifications" class="container-fluid container-sm"> | |
<legend>Notifications</legend> | |
<p>Notifications and browser notifications with or without the Notification API The browser Notification API is only triggered when the window / tab is not active or in the actual view of the user..</p> | |
<button class="btn" type="button" onclick="notify('Something just happened!')" title="notify('text', type [ , options, callback ]);">Notify</button> | |
<button class="btn" type="button" onclick="notify('Something just happened with an image!', 'image')" title="notify('text', type [ , options, callback ]);">with Image</button> | |
<button class="btn" type="button" onclick="notify('Error just happened!', 'error')" title="notify('text', type [ , options, callback ]);">an Error</button> | |
<button class="btn" type="button" onclick="notify('Warning just happened!', 'warning')" title="notify('text', type [ , options, callback ]);">a Warning</button> | |
<button class="btn" type="button" onclick="notify('Success just happened!', 'Success')" title="notify('text', type [ , options, callback ]);">a Success</button> | |
</form> | |
</section> | |
<!--Tab Toasts --> | |
<section class="tab-panel slide" tabindex="0" role="tabpanel" id="toasts-tab" ria-labelledby="toasts"> | |
<form id="Toaster" class="container-fluid container-sm"> | |
<legend>Toaster</legend> | |
<p>Toast messages are single elements for user interface feedbacks for the user and can not be stacked.</p> | |
<button class="btn" type="button" onclick="toast('Something just happened!')" title="notify('text' [ , type, options ]);">Toast</button> | |
<button class="btn" type="button" onclick="toast('Error just happened!', 'error')" title="toast('text' [ , type, options ]);">an Error</button> | |
<button class="btn" type="button" onclick="toast('Success just happened!', 'success')" title="toast('text' [ , type, options ]);">a Success</button> | |
<button class="btn" type="button" onclick="toast('Warning just happened!', 'warning')" title="toast('text' [ , type, options ]);">a | |
Warning</button> | |
</form> | |
</section> | |
</main> | |
<footer> | |
<div class="container-fluid container-md"></div> | |
</footer> | |
<!-- Inline Modals --> | |
<div class="modal ui-modal" id="customModal" tabindex="-1" role="dialog" aria-hidden="true" aria-describedby="title-customModal"> | |
<div class="modal-dialog" role="document"> | |
<div class="modal-content"> | |
<div class="modal-header"> | |
<h3 id="title-customModal">Custom</h3> | |
<button href="#!" class="close" data-dismiss="modal">Close</button> | |
</div> | |
<div class="modal-body"> | |
<p>Custom modal content</p> | |
</div> | |
<div class="modal-footer"> | |
<button class="btn btn-secondary" data-dismiss="modal">Cancel</button> | |
<button class="btn btn-primary">Yes</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- SVG Icon system --> | |
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;" id="ui-icons"> | |
<symbol id="ui-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M8 7h.5v.4c0 .3-.3.6-.6.6H1.1c-.3 0-.6-.3-.6-.6V7H1V3.1c0-.3.3-.6.6-.6H3v.8H1.8V7h2c0 .1.1.2.2.2h1c.1 0 .2-.1.2-.2h2V5H8v2zM6.1 3.7v-.5H4.5v.5h1.6zM4.6 2.4v.5h2.9v-.5M4.1 4.6c-.4-.1-.6-.4-.6-.7V1.7c0-.4.3-.7.7-.7h3.6c.4 0 .7.3.7.7v2.2c0 .4-.3.7-.7.7H5.3L4.1 5.8V4.6zm1.1-3.1c0 .1.1.2.2.2s.2-.1.2-.2-.1-.2-.2-.2-.2.1-.2.2zm-.6 0c0 .1.1.2.2.2s.2-.1.2-.2-.1-.2-.2-.2-.2.1-.2.2zm-.5 0c0 .1.1.2.2.2s.2-.1.2-.2-.1-.2-.2-.2c-.2 0-.2.1-.2.2zm.1 2.6h.4v.6l.6-.6h2.6c.1 0 .2-.1.2-.2V2H4v1.9c0 .1.1.2.2.2z"/> | |
</symbol> | |
<symbol id="dots-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<circle cx="4.5" cy="1.5" r="1"/><circle cx="4.5" cy="4.5" r="1"/><circle cx="4.5" cy="7.5" r="1"/> | |
</symbol> | |
<symbol id="check-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path fill="none" stroke="currentColor" stroke-width="1.5" d="M8 2L3 7 1 5"/> | |
</symbol> | |
<symbol id="reveal-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4.5 4.1c-.7 0-1.4.6-1.4 1.4s.6 1.4 1.4 1.4 1.4-.6 1.4-1.4-.7-1.4-1.4-1.4zm0-2.2C2 1.9 0 3.5 0 5.5h1C1 4 2.5 2.9 4.5 2.9 6.4 2.9 8 4 8 5.5h1c0-2-2-3.6-4.5-3.6z"/> | |
</symbol> | |
<symbol id="warning-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4.5,0.5L0,8.5h9L4.5,0.5z M5,7.5H4V6.7h1V7.5z M4,6V3h1v3H4z"/> | |
</symbol> | |
<symbol id="time-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4.5.5c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm1.8 5.2l-.4.1-.2-.1-1.4-1-.1-.1v-.1-.1-.1-.1L5 1.3c0-.2.2-.3.4-.2.2.1.3.3.3.5L5 4.3l1.2.8c.1.2.2.4.1.6z"/> | |
</symbol> | |
<symbol id="calendar-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M1.8.5v.8h-.7c-.2 0-.4.2-.4.4v6.5c0 .2.2.4.4.4H8c.2 0 .4-.2.4-.4V1.6c0-.2-.2-.4-.4-.4h-.8V.5H6v.8H3V.5H1.8zm-.3 3h6.1v4.2H1.5V3.5zm.3.4v1.5h1.5V3.9H1.8zm1.9 0v1.5h1.5V3.9H3.7zm1.9 0v1.5h1.5V3.9H5.6zM1.8 5.8v1.5h1.5V5.8H1.8zm1.9 0v1.5h1.5V5.8H3.7z"/> | |
</symbol> | |
<symbol id="select-icon" viewBox="0 0 9 9"> | |
<path d="M4.5,1L2,3.8h5L4.5,1z M4.5,8L2,5.3h5L4.5,8" fill="currentColor"/> | |
</symbol> | |
<symbol id="bell-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4.5 8.5c-.5 0-.7-.4-.7-.9h1.5c0 .5-.4.9-.8.9zM7 6l.8 1v.3H1.3V7L2 6V4c0-1.3.8-2.2 2-2.5V1c0-.3.2-.5.5-.5s.5.2.5.5v.5c1.2.3 2 1.3 2 2.5v2z"/> | |
</symbol> | |
<symbol id="close-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M8.4 1.4L7.6.6 4.5 3.8 1.4.6l-.8.8 3.2 3.1L.6 7.6l.8.8 3.1-3.2 3.1 3.2.8-.8-3.2-3.1z"/> | |
</symbol> | |
<symbol id="home-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M7.7 8.5c.3 0 .5-.2.5-.5V3.5c0-.1-.1-.3-.2-.4L4.8.6c-.2-.1-.5-.1-.7 0L1 3.1c-.1.1-.2.3-.2.4V8c0 .3.2.5.5.5h6.4zm-4.8-1h-1V3.8l2.6-2.1 2.6 2.1v3.7H2.9z"/> | |
</symbol> | |
<symbol id="favorites-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4.2 8.4C3.8 8 .5 5.2.5 3 .5 1.6 1.6.5 2.9.5c.6 0 1.2.3 1.6.6.4-.4 1-.6 1.6-.6C7.4.5 8.5 1.6 8.5 3c0 2.2-3.3 5-3.7 5.3-.2.2-.5.2-.6.1zM2.9 1.5c-.7 0-1.4.7-1.4 1.5 0 1.1 1.8 3.1 3 4.3 1.1-1 3-3 3-4.3 0-.8-.6-1.5-1.4-1.5-.5 0-.9.3-1.2.7-.2.3-.6.3-.8 0-.3-.4-.7-.7-1.2-.7z"/> | |
</symbol> | |
<symbol id="star-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4.5,7L2,8.5l0.7-3l-2.2-2l2.9-0.3l1.1-2.8l1.1,2.8l2.9,0.3l-2.2,2l0.7,3L4.5,7z"/> | |
</symbol> | |
<symbol id="star-outline-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4.5,1.8l0.8,1.9l2.1,0.2L5.8,5.4l0.5,2.1L4.5,6.4L2.7,7.5l0.5-2.1L1.7,3.9l2.1-0.2L4.5,1.8 M4.5,0.5L3.4,3.3L0.5,3.5l2.2,2 | |
L2,8.5L4.5,7L7,8.5l-0.7-3l2.2-2L5.6,3.3L4.5,0.5L4.5,0.5z"/> | |
</symbol> | |
<symbol id="refresh-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M7.3 1.7L8.5.5V4H5l1.6-1.6c-.6-.6-1.3-.9-2.1-.9-1.7 0-3 1.3-3 3s1.3 3 3 3c1.3 0 2.4-.8 2.8-2h1c-.4 1.8-2 3-3.9 3-2.2 0-4-1.8-4-4s1.8-4 4-4c1.2 0 2.2.4 2.9 1.2z"/> | |
</symbol> | |
<symbol id="refresh-outline-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M7.6 5.5c-.1.4-.4.8-.7 1.1a2.9 2.9 0 01-4.2 0 2.9 2.9 0 010-4.2 3 3 0 014.1-.1H5.5V3h2.1c.2 0 .4-.2.4-.4V.5h-.8v1.1a3.8 3.8 0 00-5.2.5 3.6 3.6 0 00.4 5.2C4 8.6 6.3 8.5 7.6 6.9c.3-.3.5-.7.7-1.2l-.7-.2z"/> | |
</symbol> | |
<symbol id="settings-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M8.2 5.5l-.7-.4c.1-.4.1-.8 0-1.1l.7-.4c.1 0 .1-.1.1-.2-.2-.7-.5-1.2-.9-1.6-.1-.1-.2-.1-.2 0l-.7.3c-.3-.2-.6-.4-1-.6V.8c0-.1-.1-.2-.2-.2C4.7.5 4.1.5 3.5.6c-.1 0-.2.1-.2.2v.8c-.4.1-.7.3-1 .6l-.5-.5h-.2c-.4.5-.7 1-.9 1.6 0 .1 0 .2.1.2l.7.4c-.1.4-.1.8 0 1.1l-.7.5c-.1 0-.1.1-.1.2.2.6.5 1.1.9 1.5.1.1.2.1.2 0l.7-.4c.3.2.6.4 1 .6v.8c0 .1.1.2.2.2.6.1 1.2.1 1.8 0 .1 0 .2-.1.2-.2v-.8c.4-.1.7-.3 1-.6l.7.4h.2c.4-.4.7-.9.9-1.5-.2-.1-.2-.2-.3-.2zm-3.7.3c-.7 0-1.3-.6-1.3-1.3s.6-1.3 1.3-1.3 1.3.6 1.3 1.3-.6 1.3-1.3 1.3z"/> | |
</symbol> | |
<symbol id="store-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4.5 7.2V5.4H1.8v1.8h2.7zm4-1.8h-.4v3.1h-.9V5.4H5.4v3.1H.9V5.4H.5v-.9L1 2.3h7l.5 2.2v.9zM8 .9v1H1v-1h7z"/> | |
</symbol> | |
<symbol id="parcel-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M.5 6.6l3.9 1.9V4.3L.5 2.5v4.1zm1.2-2.5l1.5.7v.6l-1.5-.7v-.6zm2.9.2v4.2l3.9-1.9V2.5L4.6 4.3zM4.5.5l-4 1.8 4 1.7 4-1.8-4-1.7z"/> | |
</symbol> | |
<symbol id="parcel-open-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M.7 5l3.2 1.6.6-1.6-3.2-1.5L.7 5zm3.9 0l.6 1.6L8.4 5l-.6-1.5L4.6 5zM.2 2.2l1.1 1.3 3.2-1.6-1-1.3L.2 2.2zm8.6 0L5.6.5 4.5 1.8l3.2 1.6c.1 0 1.1-1.2 1.1-1.2zM1.1 5.4v1.5l3.4 1.5V5.6L4 6.8 1.1 5.4zm3.5.2v2.9L8 6.9V5.4L5 6.8l-.4-1.2z"/> | |
</symbol> | |
<symbol id="stop-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M8.1 2.3v4.8c0 .7-.6 1.3-1.3 1.3H4.4c-.4.1-.7 0-.9-.3L.8 5.4l.4-.4h.5l1.5.8v-4c0-.3.2-.5.5-.5s.5.2.5.5v2.3h.3V1c0-.3.2-.5.5-.5s.5.2.5.5v3.2h.3V1.4c0-.3.2-.5.5-.5s.5.2.5.5v2.8h.4V2.4c0-.3.2-.5.5-.5.2-.1.5.2.4.4z"/> | |
</symbol> | |
<symbol id="key-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M6 .5C4.6.5 3.5 1.6 3.5 3c0 .3.1.6.1.9L.5 7v1.5H2v-.9h.9v-.9h.9l1.3-1.3c.3.1.6.2.9.2 1.4 0 2.5-1.1 2.5-2.5C8.5 1.6 7.4.5 6 .5zM1.4 7.1L1.3 7l1.4-1.4.1.1-1.4 1.4zm1.7-1.7L3 5.3l.3-.3.1.1-.3.3zm3.6-2.5c-.3 0-.6-.3-.6-.6s.3-.6.6-.6.6.3.6.6-.3.6-.6.6z"/> | |
</symbol> | |
<symbol id="view-grid-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M5,0.5h3.5V4H5V0.5z M0.5,4V0.5H4V4H0.5z M5,5h3.5v3.5H5V5z M0.5,8.5V5H4v3.5H0.5z"/> | |
</symbol> | |
<symbol id="view-list-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M0.5,0.5h8v2h-8V0.5z M0.5,8.5v-2h8v2H0.5z M0.5,5.5v-2h8v2H0.5z"/> | |
</symbol> | |
<symbol id="delete-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M8,1v0.7H1V1h1.9l0.5-0.5h2.2L6.1,1H8z M1.8,2.5h5.5v5.1c0,0.5-0.4,0.9-0.9,0.9H2.7c-0.5,0-0.9-0.4-0.9-0.9L1.8,2.5z"/> | |
</symbol> | |
<symbol id="plus-circle-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4.9 2.5h-.8v1.6H2.5v.8h1.6v1.6h.8V4.9h1.6v-.8H4.9V2.5zm-.4-2c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm0 7.2c-1.8 0-3.2-1.4-3.2-3.2s1.4-3.2 3.2-3.2 3.2 1.4 3.2 3.2-1.4 3.2-3.2 3.2z"/> | |
</symbol> | |
<symbol id="share-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M6.5 5.9a1 1 0 00-.7.3L3.4 4.5l.1-.4v-.2l2.4-1.2c.2.3.5.4.9.4.7 0 1.2-.6 1.2-1.3S7.5.6 6.8.6s-1.3.6-1.3 1.3v.2L3.1 3.3c-.2-.2-.5-.4-.9-.4-.7 0-1.2.6-1.2 1.3s.6 1.3 1.3 1.3c.3 0 .5-.1.7-.3l2.3 1.7-.1.4c0 .7.6 1.3 1.3 1.3S7.8 8 7.8 7.3c-.1-.8-.7-1.4-1.3-1.4z"/> | |
</symbol> | |
<symbol id="print-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M7 4V.6H2V4H1c-.3 0-.5.2-.5.5V7H2v.9l5 .6V7h1.5V4.5c0-.3-.2-.5-.5-.5H7zm-.5 4l-4-.5V6h4v2zm0-4h-4V1.1h4V4zm1 1.3c-.1-.1-.3-.2-.2-.3 0-.1.1-.2.3-.2.1 0 .2.1.2.3 0 0-.2.1-.3.2z"/> | |
</symbol> | |
<symbol id="bookmark-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M2 .5v.8h5V.5H2zm0 8l2.5-2 2.5 2V1.8H2v6.7zm1.9-5l.5-1 .6 1 1 .1-.8.7.2 1.2-.9-.7-1 .7.2-1.2-.7-.7.9-.1z"/> | |
</symbol> | |
<symbol id="fader-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M2.5 6.7h-.7v1.8h-.6V6.7H.5V5.6h2v1.1zM1.8.5h-.6v4.4h.7V.5zM5.5 3h-2v1.1h.7v4.4h.7V4.1h.7V3zM4.8.5h-.6v1.8h.7V.5zm3.7 5.1h-2v1.1h.7v1.8h.7V6.7h.7V5.6zM7.8.5h-.6v4.4h.7V.5z"/> | |
</symbol> | |
<symbol id="pdf-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4.3 1.5c-.1-.1-.2 0-.2 0-.2.3-.1 1 .1 1.4.1-.5.2-1.2.1-1.4zm.2 2.7L4 5.4c.2-.1.6-.2 1.2-.3-.3-.3-.5-.6-.7-.9zM1.6 7.1l.1.1c.1.1.3 0 .5-.2.3-.2.5-.6.6-.8-1 .5-1.2.8-1.2.9zm3-3.3c0-.1 0-.1 0 0zM.5.5v8h8v-8h-8zm6.7 5.7c-.3 0-1-.2-1.7-.8-.7.1-1.3.3-1.8.5h.1c-.1.2-1 1.8-1.9 1.8-.4 0-.6-.2-.6-.5 0-.2.1-.8 1.9-1.5.1-.2.5-1 1-2.2-.2-.2-.5-.9-.5-1.5 0-.7.4-.8.6-.8.1 0 .3 0 .4.2s.3.4.2.8c0 .6-.1 1.1-.3 1.5 0 .1.3.5.9 1.3.5 0 .8-.1 1.2-.1.6 0 1.2.2 1.2.7 0 .6-.5.6-.7.6zm-.5-1c-.3 0-.6 0-.7.1.4.3.8.4 1 .4.3 0 .3-.2.3-.2 0-.1-.2-.3-.6-.3z"/> | |
</symbol> | |
<symbol id="pdf-outline-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M7.1 5.1c-.5 0-.9 0-1.4.1-.8-.9-1.1-1.4-1.1-1.5.2-.6.3-1.2.4-1.9 0-.5-.1-.8-.3-1-.3-.3-.5-.3-.6-.3-.3 0-.7.1-.7 1 0 .8.4 1.6.5 1.8-.6 1.5-1.1 2.6-1.2 2.8C.5 6.9.4 7.7.4 7.9c0 .4.3.6.8.6 1.1 0 2.2-1.9 2.3-2.2h-.1c.7-.3 1.4-.5 2.2-.6.8.8 1.7 1 2 1 .3 0 1 0 1-.7s-.8-.9-1.5-.9zM1.5 7.7c-.2.2-.4.3-.5.3 0 0-.1 0-.2-.1v-.1c0-.1.2-.6 1.5-1.2-.2.4-.5.8-.8 1.1zM3.9 1L4 .9s.1 0 .1.1c.2.2 0 1-.1 1.7-.2-.6-.3-1.4-.1-1.7zm-.1 4.7l.6-1.5c.2.4.5.7.8 1-.6.2-1.1.4-1.4.5zm3.7.4c-.3 0-.8-.1-1.3-.5.2 0 .5-.1.9-.1.6 0 .8.2.8.3-.1.1-.1.3-.4.3z"/> | |
</symbol> | |
<symbol id="mail-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M.5 3v4.3h8V3l-4 2.5L.5 3zm0-1v.5l4 2.5 4-2.5V2h-8z"/> | |
</symbol> | |
<symbol id="mail-outline-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M.5 2.9v3.9l2.4-2.4L.5 2.9zm4 2.5l-1.2-.7L.8 7.2h7.3L5.7 4.7l-1.2.7zm4 1.5v-4L6.1 4.5l2.4 2.4zM.5 2v.4l4 2.5 4-2.5V2h-8z"/> | |
</symbol> | |
<symbol id="swatches-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4 1.1c0-.3-.3-.6-.6-.6H1.1C.8.5.5.8.5 1.1v5.6c0 1 .8 1.8 1.7 1.8 1 0 1.8-.8 1.8-1.7V1.1zM2.2 7.5c-.4 0-.7-.3-.7-.8 0-.4.3-.7.7-.7s.8.3.8.8c0 .4-.3.7-.8.7zm6.3-1.9v2.3c0 .3-.3.6-.6.6H4L7.5 5h.4c.3 0 .6.3.6.6zM5.8 1.5l1.6 1.6c.2.2.2.6 0 .8L4.7 6.8V1.9l.3-.4c.2-.2.6-.2.8 0z"/> | |
</symbol> | |
<symbol id="eyedropper-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M2.2 6.27l-.42.95.95-.42.93-.93-.53-.53-.93.93zM8.06.94C7.48.36 6.53.35 5.94.94l-.91.89-.39-.39c-.22-.22-.57-.22-.79 0-.22.22-.22.58 0 .79l.42.4L1.38 5.5S.64 7.41.51 8.15c-.04.2.14.38.34.35.73-.13 2.62-.85 2.62-.85l2.91-2.89.38.39c.22.22.57.22.79 0 .22-.22.22-.58 0-.79l-.41-.4.91-.9c.59-.59.6-1.54.01-2.12zM2.97 7.09c-.04.04-1.71.65-1.71.65s.61-1.67.65-1.71l2.9-2.9 1.06 1.06-2.9 2.9z"/> | |
</symbol> | |
<symbol id="location-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4.5.5C2.9.5 1.6 1.8 1.6 3.4s2.9 5.1 2.9 5.1S7.4 5 7.4 3.4 6.1.5 4.5.5zm0 4.2c-.7 0-1.3-.6-1.3-1.3S3.8 2 4.5 2s1.3.6 1.3 1.3-.6 1.4-1.3 1.4z"/> | |
</symbol> | |
<symbol id="copy-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M6.3 3V.8H.8v5.5H3v2h5.3V3h-2zm-.5 2.8H1.3V1.3h4.5v4.5z"/> | |
</symbol> | |
<symbol id="copy-outline-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M6.8 6.8V3.5h1.5v4.8H3.5V6.8h3.3zm-1-1V1.3H1.3v4.5h4.5zm.5.5H.8V.8h5.5v5.5z"/> | |
</symbol> | |
<symbol id="code-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M6.4 2l.1.1zM3 2.7l-.6-.5L.5 4.5l2 2.4.5-.5-1.5-1.9zM6.5 2.1l-.5.6 1.5 1.8L6 6.4l.5.5 2-2.4zM3.4 7.9l.8.1 1.4-6.9-.8-.1z"/> | |
</symbol> | |
<symbol id="plus-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M4.1.5v3.6H.5V5h3.6v3.6H5V4.9h3.6v-.8H4.9V.5h-.8z"></path> | |
</symbol> | |
<symbol id="bookmark-simple-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M2.3.5h4.4c.5 0 .9.4.9.9v7.1L4.5 7.2 1.4 8.5V1.4c0-.5.4-.9.9-.9zm2.2 5.7l2.2 1V1.4H2.3v5.8l2.2-1z"/> | |
</symbol> | |
<symbol id="user-icon" viewBox="0 0 9 9" fill="currentColor"> | |
<path d="M5.9 5.3c-.4 0-.7.3-1.4.3s-1-.3-1.4-.3c-1.2 0-2.1.9-2.1 2v.4c0 .4.3.8.8.8h5.5c.4 0 .7-.3.7-.7v-.5c0-1.1-.9-2-2.1-2zm1.4 2.5H1.8v-.5c0-.7.6-1.3 1.3-1.3.2 0 .6.3 1.4.3.8 0 1.2-.3 1.4-.3.7 0 1.3.6 1.3 1.3v.5zM4.5 5c1.2 0 2.3-1 2.3-2.3S5.8.4 4.5.4s-2.3 1-2.3 2.3S3.3 5 4.5 5zm0-3.7c.8 0 1.5.6 1.5 1.5s-.7 1.5-1.5 1.5S3 3.6 3 2.8s.7-1.5 1.5-1.5z"/> | |
</symbol> | |
</svg> | |
<!-- CSS inline (to be removed) --> | |
<style type="text/css"> | |
/* Layout*/ | |
#app {padding-top: 7.25rem; overflow: hidden;} | |
#sidebar { left: 0; top: 0; bottom: 0; width: 15rem; } | |
#header, #nav { position: absolute; display: inline-block;} | |
#nav { width: 100%; top: 4rem;} | |
#nav a .badge{ margin-left: 0.75em;} | |
#header, #main { padding: 0; margin:0; width: 100%;} | |
#main { padding: 2rem 0.5rem 0 0.5rem; display: flex; overflow-y: auto; height: calc(100vh - 7.25rem); } | |
#header { padding: 1rem 0.5rem 0.5rem 0.5rem; top:0;} | |
#header .dropdown { float:right; vertical-align: middle; top: 0.3rem; font-size: 1em; } | |
#logo svg { width: 2rem;} | |
#logo {width: auto; text-align: left; margin:0; padding:0; display: inline-block; } | |
#logo figcaption {position: absolute; margin-left: 0.5rem; font-size: 1.75em; font-weight: bold; display: inline-block; line-height: 1.1;} | |
#icons-wrapper .icons { text-align: center;} | |
#icons-wrapper .icons figure { display: inline-block; margin:0;} | |
#icons-wrapper .icons figcaption { display: block; margin:0; overflow: hidden; text-overflow: ellipsis; padding: .5em 1em; white-space: nowrap; } | |
#icons-wrapper .icon { height: 3em; margin: 0.5em; padding: 0.5em; color: currentColor; border-radius: 0.5em; cursor: pointer; transition: all 0.15s; -webkit-transition: all 0.15s; } | |
#icons-wrapper .icon:hover { color: white; background-color: #333; transform-origin: center center; transform: scale(1.5); } | |
#icons-wrapper .icon::after { content: attr(data-content); display: inline-block; position: absolute; z-index: 1; bottom: .25em; } | |
#dots {border:0; background:none; outline:0; display:block; width: 1em; font-size: 1.5em;} | |
#tooltips-tab fieldset { text-align: center; } | |
#tooltips-tab button { display: inline; min-width: 6em; margin: 0.5rem 0;} | |
#tooltips-tab button:first-of-type, #tooltips-tab button:last-of-type { float: none; clear: right; } | |
#tooltips-tab button:nth-of-type(2), #tooltips-tab button:nth-of-type(4) {float: none; max-width: 47.5%; margin-right:6em; margin-left: 0;} | |
#tooltips-tab button:nth-of-type(3), #tooltips-tab button:nth-of-type(5) {float: none; max-width: 47.5%; margin-left: 0; margin-right: 0; } | |
@media (max-width: 567.98px) { #tooltips-tab button:nth-of-type(2), #tooltips-tab button:nth-of-type(4) {float: left;} #tooltips-tab button:nth-of-type(3), #tooltips-tab button:nth-of-type(5) {float: right;} } | |
#dropdowns-tab form { clear: both; display: inline-block; width: 100%;} | |
#dropdowns-tab fieldset { width: 45%; display:block; float: left; } | |
#dropdowns-tab fieldset:last-child { float: right;} | |
#dropdowns-tab fieldset:last-child button { float: right;} | |
</style> | |
<!-- Ui / App initialisation --> | |
<script type="text/javascript"> | |
document.addEventListener('DOMContentLoaded', function(e){ | |
// Build i18n object for ui | |
var lang = { | |
ok: 'ok', | |
cancel: 'abbrechen', | |
close: 'schliessen', | |
dismiss: 'ablehnen', | |
warning: 'Warnung', | |
alert: 'Hinweis', | |
confirm: 'Bestätigung', | |
prompt: 'Eingabe', | |
permission: 'Berechtigung', | |
error: 'Fehler', | |
success: 'Alles klar' | |
} | |
// Class initialization | |
new UI(lang); | |
// Trigger delayed notification | |
// setTimeout(function (){ notify('Do you really want to do this?', 'alert'); }, 5000) | |
// Icon display | |
Icons('#ui-icons', '#icons-wrapper'); | |
}, false); | |
// Functions | |
// Display SVG icons in a wrapper | |
function Icons (svg, wrap){ | |
var d = document; | |
wrap = typeof wrap === 'string' ? d.querySelector(wrap) : wrap; | |
svg = d.querySelector(svg); | |
var svgurl = svg ? false : true, | |
container = wrap.querySelector('.icons'), | |
search = wrap.querySelector('input[type=search]'); | |
if(!container) { | |
container = d.createElement('div'); | |
wrap.appendChild(container); | |
} | |
container.className += ' icons'; | |
container.innerHTML = ''; // Clean-up | |
if(svgurl){ | |
var xhr = new XMLHttpRequest(); | |
xhr.onreadystatechange = function() { | |
if (xhr.readyState === 4) { | |
svg = xhr.response; | |
console.log(svg); | |
} | |
}; | |
xhr.open('GET', svgurl, true); | |
xhr.url = svgurl; | |
xhr.send(); | |
} | |
var symbols = svg.querySelectorAll('symbol'); | |
[].slice.call(symbols).forEach( function(symbol){ | |
var icon = d.createElementNS('http://www.w3.org/2000/svg', 'svg'), | |
figure = d.createElement('figure'), | |
caption = d.createElement('figcaption'), | |
id = symbol.getAttribute('id'), | |
keywords = id.replace(/-/gi,' '); | |
icon.innerHTML = symbol.innerHTML; | |
icon.setAttribute('viewBox', symbol.getAttribute('viewBox')); | |
icon.id = 'icon-'+ id; | |
icon.setAttribute('class', 'icon'); | |
icon.setAttribute('fill', 'currentColor'); | |
figure.className = 'show'; | |
figure.setAttribute('data-offset', 16); | |
figure.setAttribute('title', 'ID: #'+ id); | |
figure.setAttribute('data-keywords', keywords); | |
caption.innerHTML = keywords.replace(/icon/gi,'').trim(); | |
figure.appendChild(icon); | |
figure.appendChild(caption); | |
container.appendChild(figure); | |
}); | |
// Search function | |
if(search) { | |
search.addEventListener('keyup', function (){ | |
var query = this.value.toLowerCase().replace(/\s+/g, ' '); | |
[].slice.call(container.querySelectorAll('figure')).forEach(function(fig){ | |
var keywords = fig.getAttribute('data-keywords'), | |
match = (keywords.toLowerCase().replace(/\s+/g, '').indexOf(query) != -1); | |
match ? fig.removeAttribute('hidden') : fig.setAttribute('hidden', ''); | |
}); | |
}); | |
search.focus(); | |
} | |
} | |
</script> | |
</body> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Replace Native UI Alert, Prompt & Confirm Dialogs | |
// ------------------------------------------------- | |
// UI: Title, inputs, dialogs, notifications, dropdowns, swipe / drag actions | |
// Compatibility: FF, Chrome, IE 9+, WAI ARIA W3C (a11ya) rich internet applications | |
// recommendations for maximum accessibility. | |
// Language: Internationalisation (i18n) with language object | |
// Note: Adapted Bootstrap 3/4 css selectors to run without it's own css | |
function UI(i18n, icons) { | |
'use strict'; | |
// Monkey patching / adding some functions Element prototypes | |
var d = document, w = window, n = navigator; | |
var raf = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.mozRequestAnimationFrame || function(c){ setTimeout(c, 16, Date.now()); return true;}; | |
var ep = Element.prototype; | |
if(!ep.matches) ep.matches = ep.matchesSelector || ep.msMatchesSelector || ep.webkitMatchesSelector || ep.mozMatchesSelector; | |
if(!ep.closest) ep.closest = function(s){ var el = this; while (el.matches && !el.matches(s)) el = el.parentElement; return el.matches ? el : null; }; | |
if(!ep.setAttributes) ep.setAttributes = function(o) { for(var key in o) this.setAttribute(key, o[key]); }; | |
// Passive listener feature detection | |
var hasPassive = false; | |
try { w.addEventListener('test', null, Object.defineProperty({}, 'passive', { get: function() { hasPassive = { passive: true }; } })); } | |
catch(err) {} | |
// Register changes in document inputs | |
var hasChanged = changed(d, 'hasChanged'); | |
// UI class settings / i18n / SVGs | |
i18n = i18n ? i18n : { | |
ok: 'ok', | |
cancel: 'cancel', | |
close: 'close', | |
dismiss: 'dismiss', | |
alert: 'alert', | |
warning: 'warning', | |
confirm: 'confirm', | |
prompt: 'prompt', | |
error: 'error', | |
success: 'success', | |
permisssion: 'permmission', | |
unload: 'Leave this page?', | |
onunload: 'Changes will not be saved.' | |
}; | |
icons = icons ? icons : { | |
ok: '<path fill="none" stroke="currentColor" d="M8 1L4 8 1 6"/>', | |
warn: '<path d="M4.5,0.5L0.3,8h8.5L4.5,0.5z M5,7.3H4V6.5h1V7.3z M4,6V3h1v3H4z"/>', | |
note: '<path d="M4.5 8.5c-.5 0-.7-.4-.7-.9h1.5c0 .5-.4.9-.8.9zM7 6l.8 1v.3H1.3V7L2 6V4c0-1.3.8-2.2 2-2.5V1c0-.3.2-.5.5-.5s.5.2.5.5v.5c1.2.3 2 1.3 2 2.5v2z"/>', | |
close: '<path d="M8.4 1.4L7.6.6 4.5 3.8 1.4.6l-.8.8 3.2 3.1L.6 7.6l.8.8 3.1-3.2 3.1 3.2.8-.8-3.2-3.1z"/>', | |
reveal: '<path d="M4.5 4.1c-.7 0-1.4.6-1.4 1.4s.6 1.4 1.4 1.4 1.4-.6 1.4-1.4-.7-1.4-1.4-1.4zm0-2.2C2 1.9 0 3.5 0 5.5h1C1 4 2.5 2.9 4.5 2.9 6.4 2.9 8 4 8 5.5h1c0-2-2-3.6-4.5-3.6z"/>', | |
copy: '<path d="M6.8 6.8V3.5h1.5v4.8H3.5V6.8h3.3zm-1-1V1.3H1.3v4.5h4.5zm.5.5H.8V.8h5.5v5.5z"/>' | |
}; | |
// Native UI overwrites | |
w.alert = function(m, o, c) { new Alert(m, o, c); }; | |
w.confirm = function(m, o, c) {new Confirm(m, o, c); }; | |
w.prompt = function(m, v, o, c) { new Prompt(m, v, o, c); }; | |
w.dialog = function(m, v, o, c) { new Dialog(m, v, o, c); }; | |
w.notify = function(m, t, o, c) { new Notify(m, t, o, c); }; | |
w.toast = function(m, t, o) { new Toast(m, t, o); }; | |
w.onbeforeunload = function(m, o, c) { new BeforeUnload(m, o, c); }; | |
// Try hiding address bar | |
w.addEventListener('load', function(e) { | |
setTimeout(function(){ w.scrollTo(0, 1); }, 0); | |
}, hasPassive); | |
// Check DOM for ui element / add functionality to inline trigger | |
w.addEventListener('DOMContentLoaded', function(e) { | |
// Mobile viewport hack | |
Viewport(e); | |
// Native title Overwrite | |
Tooltips(e); | |
// Inline modal dialog triggers | |
[].slice.call(d.querySelectorAll('[data-toggle="modal"]')).forEach(function(mt){ | |
var mo = mt.hash ? d.getElementById(mt.hash.substring(1)) : d.getElementById(mt.getAttribute('data-target')); | |
if (mo) mt.addEventListener('click', function(e){ new Modal(mo, {}); }, false); | |
}); | |
// Dropdown togglers | |
[].slice.call(d.querySelectorAll('[data-toggle="dropdown"]')).forEach(function(dd){ | |
dd.addEventListener('click', function(e){ new Dropdown(e); }, false); | |
}); | |
// Tab togglers | |
[].slice.call(d.querySelectorAll('[data-toggle="tab"]')).forEach(function(tb){ | |
tb.addEventListener('click', function(e){ new Tab(e); }, false); | |
// if(tbs.className.match(/\bactive\b/gi)) tbs.click(); activate tab / swiping | |
}); | |
// Ripples | |
[].slice.call(d.querySelectorAll('.ripple')).forEach(function(rp){ | |
rp.addEventListener('click', function(e){ new Ripple(e); }, false); | |
}); | |
// Collapse togglers | |
[].slice.call(d.querySelectorAll('[data-toggle="collapse"]')).forEach(function(cl){ | |
cl.addEventListener('click', function(e){ new Collapse(e); }, false); | |
}); | |
// Range inputs | |
[].slice.call(d.querySelectorAll('[type="range"]')).forEach(function(rg){ | |
new Range(rg); | |
}); | |
// Form validation | |
[].slice.call(d.querySelectorAll('form[data-validate="true"]')).forEach(function(fm){ | |
new Validation(fm); | |
}); | |
// Tests | |
// Toast(getRootVar('--ui-font')); | |
}, false); | |
// Public Methods: | |
// Alert modal dialog | |
function Alert(message, options, callback) { | |
new Modal('alert', options, message, null, callback); | |
} | |
// Confirm modal dialog | |
function Confirm(message, options, callback) { | |
new Modal('confirm', options, message, null, callback); | |
} | |
// Prompt modal dialog | |
function Prompt(message, value, options, callback) { | |
new Modal('prompt', options, message, value, callback); | |
} | |
// Generic modal dialog | |
function Dialog(content, value, options, callback) { | |
new Modal('dialog', options, content, null, callback); | |
} | |
// Before unload modal dialog | |
function BeforeUnload(e, options, callback ) { | |
if (hasChanged) new Modal('confirm unload', options, null, callback); | |
} | |
// Notifications | |
function Notify(message, type, options, callback) { | |
new Notifications(type, message, options, callback); | |
} | |
// Private methods | |
// Global viewport height CSS var | |
function Viewport (){ | |
w.addEventListener('resize', set, false); | |
w.addEventListener('orientationchange', set, false); | |
set(); | |
function set(){ | |
d.documentElement.style.setProperty('--vh', (w.innerHeight * 0.01) +'px'); | |
} | |
} | |
// Modal dialogs | |
function Modal (type, options, message, value, callback){ | |
// Constructor | |
var origEvent = w.event || d.event; | |
if (origEvent) prevent(origEvent); | |
var modal = typeof type === 'string' ? create(type, options, message, value, callback) : type; | |
if(typeof type !== 'string') type = 'custom'; | |
open(modal, type, origEvent, callback); | |
// Private methods: | |
// Create ui modal dialog | |
function create(type, options, message, value, callback) { | |
switch(type) { | |
case 'alert': i18n.title = 'alert'; break; | |
case 'confirm': i18n.title = 'confirm'; break; | |
case 'prompt': i18n.title = 'prompt'; break; | |
case 'confirm unload': | |
i18n.title = i18n.unload; | |
message = message ? i18n.onunload : null; | |
break; | |
default: i18n.title = 'notification'; | |
} | |
i18n = options ? merge(i18n, options) : i18n; | |
var tpl = [ | |
'<div class="modal-dialog ui-dialog '+ type +'" role="document">', | |
'<div class="modal-content"><div class="modal-header">', | |
'<h3 id="'+ type +'Title">'+ i18n.title +'</h3></div><div class="modal-body">', | |
(type.match(/prompt/gi)) ? '<label for="'+ type +'Input">'+ message +'</label>' : message, | |
(type.match(/prompt/gi)) ? '<input type="text" id="'+ type +'Input" value="'+ value +'" autofocus/>' : '', | |
'</div><div class="modal-footer">', | |
(type.match(/alert|info/gi)) ? '' : '<button type="button" class="btn btn-secondary" data-dismiss="modal">'+ i18n.cancel +'</button>', | |
'<button type="button" class="btn btn-primary">'+ i18n.ok +'</button>', | |
'</div></div></div>' | |
].join(''); | |
var modal = d.createElement('div'); | |
modal.id = 'ui-'+ type; | |
modal.className = 'modal ui-modal'; | |
modal.setAttribute('tabindex', '-1'); | |
modal.setAttribute('aria-hidden', true); | |
modal.setAttribute('aria-labelledby', type +'Title'); | |
modal.addEventListener('click', function(e){ | |
modal.className += ' modal-static'; | |
vibration([500]); | |
setTimeout(function(){ | |
modal.className = modal.className.replace(/\b(modal-static)\b/g, '').trim(); | |
modal.querySelector('button:first-of-type').focus(); | |
}, 500); | |
}, false); | |
modal.innerHTML = tpl; | |
d.body.appendChild(modal); | |
return modal; | |
} | |
// Open modal | |
function open(modal, type, origEvent, callback) { | |
scrollbar(); | |
modal.removeAttribute('aria-hidden'); | |
modal.setAttribute('aria-modal', true); | |
modal.setAttribute('open', ''); | |
// Event listeners | |
modal.addEventListener('blur', focustrap, true); | |
var cls = modal.querySelectorAll('[data-dismiss="modal"], .modal-footer button, [type="submit"]'); | |
for(var i = 0; i < cls.length; i++) { | |
cls[i].addEventListener('click', function(e){ close(modal, origEvent, callback); }, false); | |
} | |
modal.firstChild.addEventListener('click', nopropagate, false); | |
// if(type.match(/(confirm|prompt)/gi)) | |
w.addEventListener('keydown', keylistener, false); | |
// Timeout needed for smooth CSS transitions & effects | |
setTimeout(function() { | |
if(!type.match(/(prompt)/gi)) cls[cls.length - 1].focus(); | |
else modal.querySelector('input').select(); | |
setTimeout(function() { sound(); }, 160); | |
modal.className += ' show'; | |
dispatchEvent('ui.modal.open', modal); | |
}, 1); | |
} | |
// Remove scrollbars if any | |
function scrollbar() { | |
var width = parseInt(w.innerWidth - d.documentElement.clientWidth, 10); | |
if(width > 0) { | |
d.body.style.paddingRight = width +'px'; | |
d.body.className = d.body.className + ' modal-open'.trim() | |
} else if (d.body.className.match(/(modal-open)/gi)) { | |
d.body.style.paddingRight = ''; | |
d.body.className = d.body.className.replace('modal-open','').trim(); | |
} | |
} | |
// Focus trap | |
function focustrap (e) { | |
if (!e.relatedTarget || !modal.contains(e.relatedTarget)) { | |
setTimeout(function() { | |
var f = modal.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'); | |
f[0].focus(); | |
}, 1); | |
} | |
} | |
// Close / hide modal dialog | |
function close (el, event, callback){ | |
var target = (event || w.event).target, // event.originalTarget ||; | |
action = typeof callback === 'function' ? callback : null; | |
el = typeof el ==='string' ? d.getElementById('custom'+ el) : el; | |
el.removeAttribute('aria-modal'); | |
el.removeAttribute('open'); | |
el.setAttribute('aria-hidden', true); | |
el.className = el.className.replace(/\bshow\b/g, '').trim(); | |
// if(el.id.match(/(confirm|prompt)/gi)) | |
w.removeEventListener('keydown', keylistener, false); | |
scrollbar(); | |
if (action) return action.call(); | |
if (el.id.match(/confirm/gi)) { | |
action = target.getAttribute('onclick') || target.onclick; | |
if (typeof action === 'function') target.onclick = false; | |
else target.removeAttribute('onclick'); | |
if('focus' in target) target.focus(); | |
target.click(); | |
if (typeof action === 'function') target.onclick = action; | |
else target.setAttribute('onclick', action); | |
} | |
else if ('focus' in target) target.focus(); | |
} | |
dispatchEvent('ui.modal.close', modal); | |
setTimeout(function(){}, 0) | |
} | |
// Notifications: | |
function Notifications (type, message, options, callback) { | |
var wrap = d.getElementById('ui-notifications'); | |
if(!wrap){ | |
wrap = d.createElement('div'); | |
wrap.id = 'ui-notifications'; | |
wrap.className = 'ui-notifications'; | |
wrap.setAttribute('tabindex', '-1'); | |
wrap.setAttribute('aria-live', 'polite'); | |
wrap.setAttribute('aria-relevant', 'additions removals'); | |
wrap.innerHTML = '<a href="#!" class="counter" role="region" aria-live="polite"></a>' | |
d.body.appendChild(wrap); | |
} | |
create(wrap); | |
// Private methods | |
// Create notification | |
function create (wrap) { | |
type = type ? type : ''; | |
i18n.title = type.match(/(error)/gi) ? 'error' : type.match(/(warn)/gi) ? 'warning' : type.match(/(ok)/gi) ? 'success' : 'notification'; | |
var timed = type.match(/(timed)/gi); | |
var img = options ? (options.image ? options.image : null) : null, | |
tpl = [ | |
'<figure aria-label="icon '+ type +'">', | |
'<svg viewbox="0 0 9 9">'+ icons.note +'</svg>', | |
'</figure>', | |
'<p><b>'+ i18n.title +'</b> '+ message +'</p>', | |
'<a href="#!" class="close" role="button">'+ i18n.close +'</a>', | |
'<time timestamp="'+ Date.now() +'"></time>', | |
'<div class="progress"><i role="progressbar" aria-valuemin="0" aria-valuemax="1"></i></div>' | |
].join(''), | |
note = d.createElement('div'); | |
note.id = 'note-'+ Math.random().toString(36).substr(2, 8); | |
note.className = 'note'; | |
note.className += timed ? ' timed' : ''; | |
note.className += timed ? ' timed' : ''; | |
note.setAttribute('role','alert'); | |
note.setAttribute('aria-live','assertive'); | |
note.setAttribute('aria-atomic', true); | |
note.setAttribute('tabindex', 0); | |
note.setAttribute('draggable',''); | |
note.innerHTML = tpl; | |
var close = note.querySelector('.close'), | |
time = note.querySelector('time'), | |
img = note.querySelector('figure svg, figure img'), | |
progress = note.querySelector('.progress i'); | |
ago(time); | |
close.addEventListener('click', function(e) { remove(note, wrap); }, false); | |
wrap.insertAdjacentElement('afterbegin', note); | |
if(timed) addPrefixedListener(progress, 'AnimationEnd', function() { remove(note, wrap); }); | |
// Timeout needed for smoootth CSS transitions & effects | |
setTimeout(function() { | |
note.className += ' show'; | |
note.focus(); | |
sound(); | |
new Swipe(note, 'x', wrap, function(gesture){ | |
if(gesture === 'left') remove(note, wrap); | |
if(gesture === 'right') hide(note, wrap); | |
}, true); | |
// vibration([400]); | |
if (!d.hasFocus()) notification(type, message, img ? (img.src ? img.src : png64(img)) : null, null, audiopool.pop ); | |
dispatchEvent('ui.notification.show', note); | |
}, 1); | |
} | |
// Delete notification | |
function remove (note, wrap) { | |
note.className = note.className.replace(/\bshow\b/g, '').trim(); | |
setTimeout(function() { | |
wrap.removeChild(note); | |
dispatchEvent('ui.notification.destroy', note); | |
}, 500); | |
} | |
// Hide notification after timeout | |
function hide (note, wrap) { | |
note.className = note.className.replace(/\bshow\b/g, '').trim(); | |
dispatchEvent('ui.notification.hide', note); | |
} | |
} | |
// Dropdown | |
function Dropdown(e) { | |
var trigger = e.target || w.event.target, | |
parent = trigger.parentNode, | |
menu = d.querySelector('[aria-labelledby="'+ trigger.id +'"]'), | |
persist = trigger.getAttribute('data-persist') === 'true', | |
isShown = trigger.getAttribute('aria-expanded') === 'true'; | |
if(menu){ | |
prevent(e); | |
d.addEventListener('scroll', position, hasPassive); | |
w.addEventListener('resize', position, false); | |
w.addEventListener('orientationchange', position, false); | |
if(!persist) d.addEventListener('click', hide, true); | |
if(!persist) menu.addEventListener('click', hide, false); | |
toggle(e); | |
} | |
// Private methods | |
function toggle (e) { | |
isShown ? hide(e) : show(e); | |
} | |
function show (e) { | |
trigger.setAttribute('aria-expanded', true); | |
parent.className += ' show'; | |
menu.className += ' show'; | |
position(e); | |
dispatchEvent('ui.dropdown.show', menu); | |
} | |
function hide (e) { | |
d.removeEventListener('scroll', position, hasPassive); | |
w.removeEventListener('resize', position, false); | |
w.removeEventListener('orientationchange', position, false); | |
if(!persist) d.removeEventListener('click', hide, true); | |
trigger.setAttribute('aria-expanded', false); | |
parent.className = parent.className.replace('show','').trim() | |
menu.className = menu.className.replace('show','').trim(); | |
dispatchEvent('ui.dropdown.hide', menu); | |
} | |
function position (e) { | |
var s = w.getComputedStyle(trigger), | |
align = trigger.getAttribute('data-align') || '', | |
offset = parseInt(trigger.getAttribute('data-offset'),10) || 5, | |
margin = { | |
top: parseInt(s.marginTop,10), | |
right: parseInt(s.marginRight,10), | |
bottom: parseInt(s.marginBottom,10), | |
left: parseInt(s.marginLeft,10) | |
}; | |
var vh = d.documentElement.clientHeight, vw = d.body.clientWidth; | |
var tH = trigger.offsetHeight, tT = trigger.offsetTop, tL = trigger.offsetLeft; | |
var mH = menu.offsetHeight, mW = menu.offsetWidth; | |
var hT, hR, hB, hL; | |
menu.style.top = tH + margin.top + offset +'px'; | |
menu.style.right = 'auto'; | |
menu.style.left = 0; | |
if(!align || align.match(/(top|bottom)/gi)) { | |
if(align.match(/top/gi)) menu.style.top = -(mH + offset - margin.top) +'px'; | |
} | |
if(align && align.match(/(right|left)/gi)) { | |
if(align.match(/left/gi)) menu.style.left = tL - offset +'px'; | |
if(align.match(/right/gi)) {menu.style.left = 'auto'; menu.style.right = 0} | |
} | |
} | |
} | |
// Collapse | |
function Collapse(e) { | |
var trigger = e.target || w.event.target, | |
targets = [], | |
backdrop = d.getElementById('backdrop'), | |
text = trigger.getAttribute('data-expanded'), | |
isExpanded = trigger.getAttribute('aria-expanded') === 'true'; | |
if(text && !trigger.hasAttribute('data-original-text')) trigger.setAttribute('data-original-text', trigger.textContent); | |
if(backdrop) backdrop.addEventListener('click', hide, false); | |
if(trigger.hash) targets.push(d.getElementById(trigger.hash.substr(1))); | |
if(trigger.getAttribute('aria-controls') !== null) { | |
var ctrls = trigger.getAttribute('aria-controls').trim().replace(' ',',').split(','); | |
for(var i = 0; i < ctrls.length; i++) { | |
if(d.getElementById(ctrls[i])) targets.push(d.getElementById(ctrls[i])); | |
} | |
} | |
prevent(e); | |
if (isExpanded) hide(); | |
else { | |
if(text) trigger.textContent = text; | |
for(var i = 0; i < targets.length; i++) show(targets[i]); | |
} | |
// Private methods | |
function show (target){ | |
var dismiss = target.querySelectorAll('[data-dismiss="drawer"]'); | |
trigger.setAttribute('aria-expanded', true); | |
target.className += target.className.match(/\bshow\b/gi) ? '' : ' show'; | |
if(dismiss) { | |
for(var i = 0; i < dismiss.length; i++) dismiss[i].addEventListener('click', hide, false); | |
} | |
dispatchEvent('ui.collapse.show', target); | |
} | |
function hide (){ | |
if(text) trigger.textContent = trigger.getAttribute('data-original-text'); | |
for(var i = 0; i < targets.length; i++){ | |
targets[i].className = targets[i].className.replace(/\bshow\b/gi,'').trim(); | |
dispatchEvent('ui.collapse.hide', targets[i]); | |
} | |
trigger.setAttribute('aria-expanded', false); | |
} | |
} | |
// Tabs | |
function Tab(e) { | |
var tab = e.target || w.event.target, | |
panel = tab.hash ? d.getElementById(tab.hash.substr(1)) : d.querySelector('[aria-labelledby="'+ tab.id +'"]'), | |
isSelected = tab.getAttribute('aria-selected') === 'true' || panel.className.match(/\bshow\b/gi), | |
isBefore = panel.nextElementSibling ? panel.nextElementSibling.className.match(/active/) : false, | |
indicator = tab.parentNode.querySelector('.indicator'), | |
tabs = tab.parentNode.querySelectorAll('[data-toggle="tab"]'), | |
panels = panel.parentNode.querySelectorAll('.tab-panel'); | |
prevent(e); | |
new Swipe(panel, 'x', panel, function(swipe) { | |
var prev = tab.previousElementSibling !== null ? tab.previousElementSibling : tabs[tabs.length - 1]; | |
var next = tab.nextElementSibling.getAttribute('data-toggle') !== null ? tab.nextElementSibling : tabs[0]; | |
if(swipe.direction === 'right') { prev.click(); prev.focus(); return; } | |
else if(swipe.direction === 'left') { next.click(); next.focus(); return;} | |
new Toast(swipe.direction); | |
}, true); | |
position(e); | |
if(isBefore) panel.className += ' slide-before'; | |
if(indicator) indicate(e); | |
if(!isSelected) show(e); | |
// Private methods | |
function show (e) { | |
hide(e); | |
tab.removeAttribute('tabindex'); | |
tab.setAttribute('aria-selected', true); | |
tab.className += ' active'; | |
panel.setAttribute('tabindex', '0'); | |
panel.className += ' active'; | |
setTimeout(function(){ | |
panel.className += ' show'; | |
panel.className = panel.className.replace(/(slide-before)/gi,'').trim(); | |
}, 0); | |
position(e); | |
if(indicator) indicate(e); | |
dispatchEvent('ui.tab.show', panel); | |
} | |
function hide (e) { | |
for(var i = 0; i < panels.length; i++){ | |
panels[i].setAttribute('tabindex', '0'); | |
panels[i].className = panels[i].className.replace(/(active|show)/gi,'').trim(); | |
dispatchEvent('ui.tab.hide', panels[i]); | |
} | |
for(var i = 0; i < tabs.length; i++){ | |
tabs[i].setAttribute('aria-selected', false); | |
tabs[i].setAttribute('tabindex', '-1'); | |
tabs[i].className = tabs[i].className.replace(/(active)/gi,'').trim(); | |
} | |
} | |
function position (e) { | |
// var vw = tab.parentNode.clientWidth, | |
// hidden = (tab.clientWidth + parseInt(tab.getBoundingClientRect().left, 10)) >= vw; | |
tab.parentNode.setAttribute('scrolling',''); | |
tab.parentNode.scrollLeft = tab.offsetLeft; | |
// tab.scrollIntoView({false, 'smooth'}); | |
tab.focus(); | |
tab.parentNode.removeAttribute('scrolling'); | |
} | |
function indicate (e) { | |
var active = tab.parentNode.querySelector('.active'); | |
indicator.style.width = active.offsetWidth +'px'; | |
indicator.style.left = active.offsetLeft +'px'; | |
d.addEventListener('scroll', indicate, hasPassive); | |
w.addEventListener('resize', indicate, false); | |
w.addEventListener('orientationchange', indicate, false); | |
} | |
} | |
// Tooltips | |
function Tooltips (options) { | |
var TIPS = d.querySelectorAll('[title]'); | |
var OFFSET = 9; | |
[].slice.call(TIPS).forEach(function(tip){ | |
if (tip.getAttribute('title') !== null) { | |
tip.addEventListener('mouseenter', show, false); | |
tip.addEventListener('mouseleave', hide, false); | |
tip.addEventListener('focus', show, false); | |
tip.addEventListener('blur', hide, false); | |
} | |
}); | |
// Private methods | |
function remove(e){ | |
var trigger = this || (e || w.event).target, | |
tip = d.getElementById(trigger.getAttribute('aria-describedby')); | |
if(tip){ | |
d.body.removeChild(tip); | |
d.removeEventListener('scroll', function(){ position(trigger, tip); }, hasPassive); | |
d.removeEventListener('resize', function(){ position(trigger, tip); }, false); | |
d.removeEventListener('orientationchange', function(){ position(trigger, tip); }, false); | |
trigger.setAttribute('title', trigger.getAttribute('data-original-title')); | |
trigger.removeAttribute('data-original-title'); | |
dispatchEvent('ui.tooltip.destroy', tip); | |
} | |
} | |
function hide (e){ | |
var trigger = this || (e || w.event).target, | |
tip = d.getElementById(trigger.getAttribute('aria-describedby')); | |
if(tip) tip.setAttribute('aria-hidden', true); | |
dispatchEvent('ui.tooltip.hide', tip); | |
} | |
function show (e){ | |
var trigger = this || (e || w.event).target, | |
tip = d.getElementById(trigger.getAttribute('aria-describedby')); | |
if(!tip) tip = create(trigger); | |
position(trigger, tip); | |
tip.setAttribute('aria-hidden', false); | |
d.addEventListener('scroll', function(){ position(trigger, tip); }, hasPassive); | |
w.addEventListener('resize', function(){ position(trigger, tip); }, false); | |
w.addEventListener('orientationchange', function(){ position(trigger, tip); }, false); | |
dispatchEvent('ui.tooltip.show', tip); | |
} | |
// Helper methods | |
function position(trigger, tip){ | |
var align = trigger.getAttribute('data-tooltip'), | |
vh = d.documentElement.clientHeight, vw = d.body.clientWidth; | |
var sY = w.scrollY || w.pageYOffset; | |
var sX = w.scrollX || w.pageXOffset; | |
var rect = trigger.getBoundingClientRect(); | |
var tW = rect.width; | |
var tH = rect.height; | |
var tL = rect.left + sX; | |
var tT = rect.top + sY; | |
var X = tL + tW/2; | |
var Y = tT + tH/2; | |
var W = tip.offsetWidth; | |
var H = tip.offsetHeight; | |
var hT, hB, hR, hL; | |
var css = tip.style; | |
var icss = tip.querySelector('.indicator').style; | |
var offset = trigger.hasAttribute('data-offset') ? trigger.getAttribute('data-offset') : OFFSET; | |
tip.className = 'ui-tooltip'+ ((align) ? ' '+ align : ''); | |
css.top = (tT - H - offset) +'px'; | |
css.left = (X - W/2) +'px'; | |
if(!align || align.match(/(top|bottom)/gi)) { | |
hT = (tT - sY) - H <= 0; | |
hB = (tT - sY) + (tH + offset + H) >= vh; | |
hR = (X + W/2) >= vw; | |
hL = (X - W/2) <= 0; | |
if(align === 'bottom') { css.top = (tT + tH + offset) +'px'; } | |
if((hT && hB) || (hL && hR)) return; | |
if(hT) { tip.className = 'ui-tooltip bottom'; css.top = (tT + tH + offset) +'px'; } | |
if(hB) { tip.className = 'ui-tooltip'; css.top = (tT - tH - offset) +'px'; } | |
if(hL) { css.left = offset +'px'; icss.left = tW/2 +'px'; } | |
if(hR) { css.left = vw - (offset + W) +'px'; icss.left = 'auto'; icss.right = tW/2 + offset +'px'; } | |
} | |
if(align && align.match(/(right|left)/gi)) { | |
hR = (tL + tW + W + offset) >= vw ; | |
hL = tL - (W + offset) <= 0; | |
if((hL && hR)) return tip.className = 'ui-tooltip'; | |
css.top = (Y - H/2) +'px'; | |
if(align === 'right') css.left = (tL + tW + offset) +'px'; | |
if(align === 'left') css.left = (tL - W - offset) +'px'; | |
if(hR) { tip.className = 'ui-tooltip left'; css.left = (tL - W - offset) +'px'; } | |
if(hL) { tip.className = 'ui-tooltip right'; css.left = (tL + tW + offset) +'px'; } | |
} | |
} | |
function create (trigger){ | |
var tip = d.createElement('div'), | |
content = trigger.getAttribute('title'), | |
sanitized = d.createTextNode(content); | |
tip.id = 'tooltip-'+ Math.random().toString(36).substr(2, 8); | |
tip.setAttribute('role', 'tooltip'); | |
tip.className = 'ui-tooltip'; | |
tip.innerHTML = '<i class="indicator" aria-hidden="true"></i>'; | |
tip.appendChild(sanitized); | |
tip.setAttribute('aria-hidden', true); | |
trigger.setAttribute('aria-describedby', tip.id); | |
trigger.removeAttribute('title'); | |
trigger.setAttribute('data-original-title', sanitized.textContent); | |
d.body.insertAdjacentElement('beforeend', tip); | |
return tip; | |
} | |
} | |
// Toasts | |
function Toast(message, type, ms) { | |
type = type ? type : ''; | |
message = message ? message.message || message.toString() : i18n.unknown; | |
var toast = d.getElementById('ui-toast'), | |
time = ms ? parseInt(ms, 10) : 10000; | |
if(!toast) { | |
toast = d.createElement('div'); | |
toast.id = 'ui-toast'; | |
} | |
clearTimeout(w.toastTimeout); | |
toast.className = type; | |
toast.innerHTML = message; | |
toast.addEventListener('click', close, false); | |
d.body.appendChild(toast); | |
toast.className += ' visible'; | |
dispatchEvent('ui.toast.show', toast); | |
// Autohide error / success toast | |
if(type.match(/(error|success)/gi)) w.toastTimeout = setTimeout(close, time); | |
// Close Toast | |
function close (e){ | |
toast.className += ' closing'; | |
dispatchEvent('ui.toast.hide', toast); | |
setTimeout(function() { toast.removeAttribute('class'); }, 500); | |
clearTimeout(w.toastTimeout); | |
} | |
} | |
// Range | |
function Range(el) { | |
var ini = el.defaultValue || el.value || 0, | |
output = el.parentNode.querySelector('output'), | |
unit = el.getAttribute('data-unit'); | |
if(!output) { | |
output = d.createElement('output'); | |
el.parentNode.appendChild(output); | |
}; | |
set(el, el.value, output); | |
el.addEventListener('input', function(e) { set(el, el.value, output); }, false); | |
el.form.addEventListener('reset', function(e) { set(el, ini, output); }, false); | |
// Private method | |
function set(range, value, output){ | |
if(range === null || value === null) return; | |
var min = parseFloat(range.min) || 0, | |
max = parseFloat(range.max) || 1, | |
r = 100/(max-min); | |
range.style.setProperty('--rangeValue', (value-min)*r); | |
output.setAttribute('aria-live', 'assertive'); | |
output.innerHTML = (value-min)*r + (unit ? unit : ''); | |
} | |
} | |
// Swipe | |
function Swipe (target, axis, zone, callback, remove, minPx) { | |
var self = this, root = d.documentElement; | |
if(!target) return alert('No swipe target defined. Aborting...'); | |
remove = remove ? remove : false; // Remove initial listener from target? | |
axis = axis ? axis : 'y'; // y default, allowed 'x, h, horizontal, horiz' | |
zone = zone ? zone : target; | |
var x, y, sX = 0, sY = 0, eX = 0, eY = 0, | |
minDeg = Math.tan(45*1.5/180 * Math.PI), | |
minPx = minPx ? minPx : 35, minMs = 200, sT = null, eT = null, | |
distance, direction, duration, dragging = false; | |
target.style = ''; | |
// Event mouse listeners | |
zone.addEventListener('mousedown', start, false); | |
// Event touch listeners | |
zone.addEventListener('touchstart', start, hasPassive); | |
// Private methods | |
function start(e) { | |
if(dragging) end(e); | |
var touches = e.changedTouches || e.touches; | |
sX = touches ? touches[0].screenX : e.clientX; | |
sY = touches ? touches[0].screenY : e.clientY; | |
eT = null; sT = e.timeStamp; | |
target.style = ''; | |
dragging = true; | |
zone.setAttribute('dragging', ''); | |
root.setAttribute('manipulating', ''); | |
// target.setAttribute('noanimate', ''); | |
// Event mouse listeners | |
zone.addEventListener('mousemove', move, false); | |
root.addEventListener('mouseup', end, false); | |
zone.addEventListener('mouseleave', end, false); | |
// Event touch listeners | |
zone.addEventListener('touchmove', move, hasPassive); | |
root.addEventListener('touchend', end, false); | |
zone.addEventListener('touchcancel', end, false); | |
} | |
function move(e) { | |
if(!dragging || !sT) return; | |
var touches = e.changedTouches || e.touches; | |
eX = touches ? touches[0].screenX : e.clientX; | |
eY = touches ? touches[0].screenY : e.clientY; | |
x = eX - sX; | |
y = eY - sY; | |
raf(transform); | |
} | |
function end(e) { | |
dragging = false; | |
eT = e.timeStamp; | |
dispatch(e); | |
target.style = ''; | |
zone.removeAttribute('dragging'); | |
root.removeAttribute('manipulating'); | |
// target.removeAttribute('noanimate'); | |
sT = null; eT = null; | |
distance = 0, direction = null; | |
// Remove mouse event listener | |
zone.removeEventListener('mousemove', move, false); | |
root.removeEventListener('mouseup', end, false); | |
zone.removeEventListener('mouseleave', end, false); | |
// Remove touch event listener | |
zone.removeEventListener('touchmove', move, hasPassive); | |
root.removeEventListener('touchend', end, false); | |
zone.removeEventListener('touchcancel', end, false); | |
} | |
function dispatch (e) { | |
duration = eT - sT; | |
var xy = Math.abs(x/y), yx = Math.abs(y/x); | |
if(Math.abs(x) + Math.abs(y) <= minPx/3) { | |
if(duration < minMs) callback({direction: 'tab', distance: 0, duration: duration}); | |
else callback({direction: 'press', distance: 0, duration: duration}); | |
return; | |
} | |
if(axis.match(/(x|h|horiz|horizontal)/gi)) { | |
if (eX <= sX) { distance = sX - eX; direction = 'left'; } | |
if (eX >= sX) { distance = eX - sX; direction = 'right'; } | |
} else { | |
if (eY <= sY) { distance = sY - eY; direction = 'up'; } | |
if (eY >= sY) { distance = eY - sY; direction = 'down'; } | |
} | |
if (distance > minPx && duration > minMs && direction) { | |
act(direction, distance, duration, e); | |
} | |
} | |
function act (direction, distance, duration, e) { | |
callback({ direction: direction, distance: distance, duration: duration }); | |
if (remove) { | |
zone.removeEventListener('mousedown', start, false); | |
zone.removeEventListener('touchstart', start, hasPassive); | |
} | |
} | |
function transform() { | |
if(axis.match(/(x|h|horiz|horizontal)/gi)) y = 0; | |
else x = 0; | |
target.style.webkitTransform = 'translate('+ x +'px,'+ y +'px)'; | |
target.style.mozTransform = 'translate('+ x +'px,'+ y +'px)'; | |
target.style.msTransform = 'translate('+ x +'px,'+ y +'px)'; | |
target.style.oTransform = 'translate('+ x +'px,'+ y +'px)'; | |
target.style.transform = 'translate('+ x +'px,'+ y +'px)'; | |
} | |
} | |
// Form validation | |
function Validation (el){ | |
var errors = [], | |
rx = { | |
email: '\b[\w\.-]+@[\w\.-]+\.\w{2,4}\b', | |
url: '[(http(s)?):\/\/(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)', | |
date: '\d{2,4}(\.|-|\/)\d{2}(\.|-|\/)\d{2,4}$', | |
time: '^((([0-1]?[0-9])|([2][0-3])):)?(([0-5][0-9]):)?([0-5][0-9])(\.\d{1,3})?$|^\d+(\.\d{1,3})?$', | |
datetime: '(0?[1-9]|[12][0-9]|3[01])[\/\-](0?[1-9]|1[012])[\/\-]\d{4}( \d{1,2}[:-]\d{2}([:-]\d{2,3})*)?', | |
number: '(^\d{1,10}$)', | |
tel: '(\+?( |-|\.)?\d{1,2}( |-|\.)?)?(\(?\d{3}\)?|\d{3})( |-|\.)?(\d{3}( |-|\.)?\d{4})', | |
color: '^((rgb|hsl)(a?)\(([\d\.\-\s,]{5,})\)$)|^((#)(([0-9A-F]{3})$|([0-9A-F]{6})$))' | |
}, | |
sets = el.tagName.match(/form/gi) ? [el] : el.querySelectorAll('form'), | |
isTabbed = el.closest('.tabs').contains(el), | |
hasAlert = false; | |
[].slice.call(sets).forEach(function(set) { | |
set.setAttribute('novalidate', true); | |
// Check error handler on form submit / reset | |
set.addEventListener('submit', function(e) { | |
prevent(e); | |
errors = []; // reset errors | |
validate(sets); | |
if (errors) { prevent(e); } | |
return false; | |
}, false); | |
}); | |
// Private methods | |
// Validate forms / sets form parts | |
function validate (sets) { | |
[].slice.call(sets).forEach(function(set) { | |
var inputs = set.querySelectorAll('[required]:not([disabled]), [pattern]:not([disabled])'); | |
[].slice.call(inputs).forEach(function(input) { checkInput(input, set); }); | |
displayErrors(set); | |
}); | |
} | |
// Input validation | |
function checkInput(input, set) { | |
var group = input.closest('.form-group') || set, | |
label = input.closest('label') ? input.closest('label').innerText : input.getAttribute('placeholder') || input.id, | |
value = input.value.trim(), | |
error = input.getAttribute('data-error') || i18n.error +': '+ label, | |
pattern = input.getAttribute('pattern'), | |
min = input.getAttribute('min') || input.getAttribute('minlength'), | |
max = input.getAttribute('max') || input.getAttribute('maxlength'), | |
len = input.getAttribute('type') === ('number' || 'range') ? input.value : input.value.length; | |
if (value === '') setError(input, error, group, set); | |
else if (pattern && !/pattern/.test(value) ) setError(input, error, group, set); | |
else if(min && min > len ) setError(input, error, group, set); | |
else if(max && max < len ) setError(input, error, group, set); | |
else removeError(input, group, set); | |
} | |
// Set error | |
function setError (input, error, group, set) { | |
var hasError = group.className.match(/has-error/gi); | |
if (!hasError) { | |
group.className += ' has-error'; | |
group.setAttribute('title', error); | |
} | |
errors.push({ | |
'set': '#'+ set.id, | |
'input': '#'+ input.id, | |
'message': error | |
}); | |
input.addEventListener('change', function(){checkInput(input, set); }, hasPassive); | |
group.form.addEventListener('reset', function(e) {removeError(input, group, set); }, false); | |
} | |
// Remove error | |
function removeError(input, group, set) { | |
errors.splice(errors.indexOf('#'+ input.id), 1); | |
group.className = group.className.replace(/has-error/gi,'').trim(); | |
input.className = input.className.replace(/is-error/gi,'').trim(); | |
input.removeEventListener('change', function(){checkInput(input, set); }, hasPassive); | |
group.form.removeEventListener('reset', function(e) {removeError(input, group, set); }, false); | |
} | |
// Display error count or error list in set | |
function displayErrors(set){ | |
var count = 1; | |
[].slice.call(errors).forEach(function(error){ if(error.set === '#'+set.id) count++; }); | |
// Display tab badge | |
if (isTabbed) { | |
var panel = set.closest('.tab-panel'), | |
tab = d.querySelector('a[href="#'+ panel.id +'"]'), | |
badge = tab.querySelector('.badge'); | |
if(!badge) badge = d.createElement('b'); | |
if(tab) { | |
badge.setAttributes({ | |
'class': 'badge badge-circle badge-danger scale', | |
'aria-live': 'assertive', | |
'title': count +' '+ i18n.error, | |
'data-tooltip': 'right' | |
}); | |
tab.appendChild(badge); | |
badge.innerText = count; | |
} | |
} | |
// Scroll to first error in set | |
var first = set.querySelector('.has-error'), | |
scroll = scrollParent(first); | |
if(scroll) scroll.setAttribute('scrolling',''); | |
first.scrollIntoView(); | |
if(scroll) scroll.removeAttribute('scrolling'); | |
first.querySelector('input, select, textarea').focus(); | |
} | |
} | |
// Backdrop | |
function Backdrop (color) { | |
var drop = d.getElementById('backdrop'); | |
if(!drop) { drop = d.createElement('div'); drop.id = 'backdrop'; } | |
drop.className = 'visible'; | |
theme(w.getComputedStyle(drop).backgroundColor); | |
// Head methods | |
function theme(color){ | |
var metas = ['theme-color', 'msapplication-navbutton-color', 'apple-mobile-web-app-status-bar-style'], | |
head = d.getElementByTagName('head')[0], | |
icon = head.querySelector('link[rel*=icon]'), | |
oColor = head.querySelector('meta["'+ metas[0] +'"]').getAttribute('content'), | |
oStyle = head.querySelector('meta["'+ metas[2] +'"]').getAttribute('content'), | |
isBlack = oColor.replace(' ','').match(/(#000|#000000|0,0,0)/gi) || oStyle.match(/(black)/gi); | |
function set(){ | |
metas.forEach(function(meta){ | |
var entry = head.querySelector('meta["'+meta+'"]'); | |
if(!entry) head.insertAdjacentElement('beforeend', d.createElement('meta')); | |
entry.setAttribute('name', meta); | |
if(meta.match(/(status-bar)/gi)) entry.setAttribute('content', 'translucent' + isBlack ? '-black' : ''); | |
else entry.setAttribute('content', color); | |
}); | |
} | |
function reset(e){ | |
metas.forEach(function(meta){ | |
var entry = head.querySelector('meta["'+meta+'"]'); | |
if(meta.match(/(status-bar)/gi)) entry.setAttribute('content', oStyle); | |
else entry.setAttribute('content', oColor); | |
}); | |
} | |
} | |
} | |
// Ripple effects | |
function Ripple (e) { | |
var trigger = e.target || w.event.target, | |
touch = e.changedTouches || e.touches, | |
ink = trigger.querySelector('.ink'), x, y; | |
if(!ink) { | |
ink = d.createElement('i'); | |
trigger.appendChild(ink); | |
ink.setAttribute('aria-hidden', true); | |
} | |
ink.className = 'ink'; | |
if(!ink.offsetHeight && !ink.offsetWidth) { | |
var dia = Math.max(trigger.offsetWidth, trigger.offsetHeight); | |
ink.style.cssText = 'height:'+ dia +'px; width:'+ dia +'px;'; | |
} | |
x = (touch ? touch[0].screenX : e.clientX) - trigger.offsetLeft - ink.offsetWidth/2; | |
y = (touch ? touch[0].screenY : e.clientY) - trigger.offsetTop - ink.offsetHeight/2; | |
ink.style.cssText = 'top:'+ y +'px; left:'+ x +'px;'; | |
ink.className += ' animating'; | |
setTimeout(function(){ | |
ink.className = 'ink'; | |
ink.removeAttribute('style'); | |
}, 20000); | |
} | |
// Helpers: | |
// Get closes scrollable parent | |
function scrollParent(node) { | |
if (!node) return null; | |
var oY = w.getComputedStyle(node).overflowY, | |
isScroll = oY !== 'visible' && oY !== 'hidden'; | |
if (isScroll && node.scrollHeight > node.clientHeight) return node; | |
else return scrollParent(node.parentNode); | |
} | |
// Url parts | |
function urlVars() { | |
var vars = {}; | |
w.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, | |
function(m, key, value) { vars[key] = value; } | |
); | |
return vars; | |
} | |
// Get value of css var | |
function getRootVar(name){ | |
var root = d.querySelector(':root'); | |
return w.getComputedStyle(root).getPropertyValue(name); | |
} | |
// Color conversion | |
function rgb2hex(string) { | |
var parts = (string || '').match(/\d+/g); | |
return "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1); | |
} | |
// Color contrast | |
function contrast(color) { | |
var r, g, b, hsp, threshold = 127.5; | |
if (color.match(/^rgb/)) { | |
color = color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/); | |
r = color[1]; | |
g = color[2]; | |
b = color[3]; | |
} else { | |
color = +('0x' + color.slice(1).replace(color.length < 5 && /./g, '$&$&')); | |
r = color >> 16; | |
g = color >> 8 & 255; | |
b = color & 255; | |
} | |
hsp = Math.sqrt(0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b)); | |
if (hsp > threshold) return 'light'; | |
else return 'dark'; | |
} | |
function contrast4hex(hex){ | |
var r = parseInt(hex.substr(0,2),16), g = parseInt(hex.substr(2,2),16), b = parseInt(hex.substr(4,2),16), | |
yiq = ((r*299)+(g*587)+(b*114))/1000; | |
return (yiq >= 128) ? 'dark' : 'light'; | |
} | |
// Remove listenner from element by type | |
function removeListeners(el, event){ | |
var ls = getEventListeners(el)[event]; | |
for(var i = 0; i < ls.length; i++){ | |
removeEventListener(event, ls[i].listener); | |
} | |
} | |
// Replace / refresh / update listenner | |
function replaceListener (event, action, passive, el) { | |
el.removeEventListener(event, action, passive); | |
el.addEventListener(event, action, passive); | |
} | |
// Add event observe | |
function dispatchEvent(name, el) { | |
var e = d.createEvent('Event'); | |
e.initEvent(name, true, true); | |
if(el) el.dispatchEvent(e); | |
} | |
// Prevent event bubbling | |
function prevent(e) { | |
e = (e) ? e : w.event; | |
e.preventDefault(); | |
e.stopPropagation(); | |
} | |
// Prevent event propagation | |
function nopropagate(e) { | |
e = (e) ? e : w.event; | |
e.stopPropagation(); | |
} | |
// Merge objects | |
function merge(obj1, obj2) { | |
for (var key in obj2) obj1[key] = obj2[key]; | |
return obj1; | |
} | |
// Listen to changes in element / document | |
function changed(el, value){ | |
var inputs = el.querySelectorAll('input, select, [contenteditable], textarea'); | |
value = [value] ? [value] : false; | |
for(var i = 0; i < inputs;i++){ | |
inputs[i].addEventListener('change', function(e){ [value] = true; }, false); | |
}; | |
return value; | |
} | |
// Prefixed JS CSS event listener | |
function addPrefixedListener(el, type, callback) { | |
var prefix = ['webkit', 'moz', 'MS', 'o', '']; | |
for (var p = 0; p < prefix.length; p++) { | |
if (!prefix[p]) type = type.toLowerCase(); | |
el.addEventListener(prefix[p]+type, callback, false); | |
} | |
} | |
// Send notification via Notifications API (IE 11 and lower isn't supported.) | |
function notification (title, body, icon, img, sound) { | |
if (!('Notification' in w)) return false; | |
var title = title || 'Undefined title'; | |
var options = { | |
body: body || 'Undefined content', | |
icon: (icon) ? 'notification/'+ icon : 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/515428/skype_icon.png', | |
badge: 'notification/badge.png', | |
image: (img) ? img : '', | |
vibrate: [400], | |
sound: audiopool.pop | |
}; | |
var ask = Notification.requestPermission(); | |
ask.then( function(permission) { | |
if (permission === 'granted') { | |
var n = new Notification(title, options); | |
n.addEventListener('click', function(e) { | |
alert('Click from notification.', {title: 'Notification API'}); | |
}); | |
} else if (permission !== 'denied') { | |
Notification.requestPermission().then(function (permission) { | |
if (permission === 'granted') var n = new Notification(title, options); | |
else return alert('Permission '+ permission +'.', {title: 'Notification API'}); | |
}); | |
} else { | |
return alert('Permission '+ permission +'.', {title: 'Notification API'}); | |
} | |
}); | |
} | |
// IE 9 SVG fix | |
/MSIE|Trident/.test(n.userAgent) && d.addEventListener('DOMContentLoaded', function(){ | |
[].forEach.call(d.querySelectorAll('svg'), function (svg) { | |
var use = svg.querySelector('use'); | |
if (use) { | |
var obj = d.createElement('object'); | |
obj.data = use.getAttribute('xlink:href'); | |
obj.className = svg.getAttribute('class'); | |
svg.parentNode.replaceChild(obj, svg); | |
} | |
}); | |
}); | |
// SVG to PNG | |
function png64(svg) { | |
var fill = w.getComputedStyle(svg).fill || null, | |
stroke = w.getComputedStyle(svg).stroke || null; | |
if(fill) svg.setAttribute('fill', fill); | |
if(stroke) svg.setAttribute('stroke', stroke); | |
var data = new XMLSerializer().serializeToString(svg), | |
canvas = d.createElement('canvas'), | |
ratio = w.devicePixelRatio, | |
size = svg.getBoundingClientRect(), | |
ctx = canvas.getContext('2d'), | |
img = new Image(); | |
canvas.width = size.width * ratio; | |
canvas.height = size.height * ratio; | |
ctx.scale(ratio, ratio); | |
var dataurl = 'data:image/svg+xml,'+ encodeURIComponent(svg); | |
img.setAttribute('src', dataurl); | |
img.onload = function() { | |
ctx.drawImage(img, 0, 0); | |
alert(canvas.toDataURL('image/png')); | |
}; | |
return canvas.toDataURL('image/png'); | |
} | |
// Keyboard listener | |
function keylistener (e) { | |
console.log(e.target) | |
var target = e.target || w.event.target; | |
// if(!target) return; | |
nopropagate(e); | |
var key = e.keyCode ? e.keyCode : e.which; | |
if (key === 13) { // Enter | |
console.log(key) | |
} | |
else if (key === 27) { // Esc | |
console.log(key) | |
} | |
} | |
// Display human readable n time ago | |
function ago(el, int) { | |
var instance, interval = int ? int : 10000, | |
timestamp = parseInt(el.getAttribute('timestamp'), 10), | |
units = i18n.units ? i18n.units : [ | |
{text: 'just now', sec: 0}, | |
{text: '%n second%s ago', sec: 1}, | |
{text: '%n minute%s ago', sec: 60}, | |
{text: '%n hour%s ago', sec: 3600}, | |
{text: '%n day%s ago', sec: 86400}, | |
{text: '%n week%s ago', sec: 604800}, | |
{text: '%n month%s ago', sec: 2592000}, | |
{text: '%n year%s ago', sec: 31536000}, | |
{text: '%n decade%s ago', sec: 315360000} | |
]; | |
// Clear previous interval on element; | |
clearInterval(instance); // if(instance) | |
instance = setInterval(timer, interval); | |
timer(); | |
// Refresh date / time | |
function timer () { | |
var delta = Math.floor((new Date().getTime() - timestamp)/1000); | |
for (var i = 0; i < units.length; i++) { | |
if (delta < units[i].sec) { | |
if (i === 0) el.innerHTML = units[0].text; | |
else { | |
var dif = Math.round(delta/units[i-1].sec); | |
el.innerHTML = units[i-1].text.replace('%n', dif).replace(/%(\w+)/g, (dif <= 1 ? '' : '$1') ); | |
} | |
return; | |
} | |
} | |
} | |
} | |
// Vibrate | |
function vibration (pattern) { | |
pattern = pattern ? pattern : [300, 100, 300]; | |
w.navigator.vibrate(pattern); | |
} | |
// Play sound via HTML element (IE9 support) | |
function sound(url){ | |
url = url ? url : audiopool.pop; | |
var audio = d.createElement('audio'); | |
audio.style.display = 'none'; | |
audio.src = url; | |
audio.autoplay = true; | |
audio.onended = function(){ d.body.removeChild(audio);}; | |
d.body.appendChild(audio); | |
} | |
// Mp3 audiopool for ui | |
var audiopool = { pop: 'data:audio/mpeg;base64,SUQzBAAAAAABAlRYWFgAAAAKAAAAAENPTU1FTlRTVFNTRQAAAA4AAABMYXZmNTguMTIuMTAwVERSQwAAAAUAAAAyMDEzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/80hkAAaQNRYvoYgBBvgR8AFDEAABlG23ePr8RKhOBvESoVd4EEAA5Uc4PvKBjwxlAQ4gd4gdE7yH/Lv9Rz/8H3w//rB9+XP5BECAAYE4eBAEHdYPl4g///8pBwEAx///4gOFAwrdzrgXqaWQgt2h3mYZtQ4CCGedJDIthbIIEBUAhQAoJEIQ+QDBjCILwNz/80hkKgxBE14AzFAADNBy9l+YKQIWAYACdCLAJFAZk4ACRDGN+TpbKzKIVel+gnrUpJX/3QZJkf//UtbJuzv///6BoT6CTGKFf//KmpdlKGwIAAwOAMABgAAOdZ4hQQlZpLGSU+8954f/PQovOnA5xNYS+j/PFjX/zd////rLCGpRpKENtvuABSVbLO1TmbX/80hEDweoU2Ef4xgBDcCqrV/GYAJc4jD5bV6hvV8rzJxIBAJLlSzTCziwCuLFTsSkvUQ9A85U+Y56CygobGU1pN3aLlbYBAAAUAkY056ONRamOw5HPmwkdTclj6BCtVaVgbADAGH7eJAqUeDk+0WnhLQj///8kRDq+mpSNtA9tvsAO3lA7Uy3RJE1LILCI9D/80hkFQlwe1MfGEaRCtBysl4IwFIHCjmOwq8N80c1bxBqfcy8yDJfsloNIa5hl73AAHR4BDTHmcNBwyF1jKSIMblyoaoa++NGaHanJW0wbtv+ABcaVsTiqzGuepZlQijwlBXPEn89rG/1b5up7bfZs7NZ4WIUJmvkQpJJbZxGpxrk7RcX4KReAxwlEzSyBwn/80hkGQgIW0LfCSYFCHiiTABj0uANlUxLj5gok1qyVoIE5h6o7Qv79Viv/o2c6olRYGzLFERIj6H7//oGq63Fix+3dMLvfClPUqk5iZJJoYjgaIxVD07oaA11E2WF1T1abdsj4IyfqoVCryqciUk+c7cOJdwWK9WiHAMaqyWzJeg0JH+g89ditUJNFoVo+rr/80hkMQboRzR/BSYRCKCSNABJnjDdX9/X//rImy05CIdZaWuyTFEi6Slrp1xzVXDCMaErs9hZWgotlH6noQG79t8BhURBUi9KQ1IhpYCERIjU9CStHLHsjfU0ke87rcrtqPfyX/zv/4a8t6JaZPjckk4IkssVAp1DIafW1/iL0VEtaCP2fU//qPfEO3//PFX/80hkUgW4BxQrCCMBCngGNZ4IRgLZXfK8j0Iv+A7TTT////TTTRVVVf//6KqqqqaaaaKqqqrdppo+qqq1NNNFVVVX///yqqqmmmGIf//9NNNv5UqH////4qLCws3+oWFxUVFRX/6hakxBTUUzLjk5LjW='}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@charset "UTF-8"; | |
/*! UI v0.1 - SCSS (https://host-one.ch/) */ | |
/// Variables | |
// Font stacks | |
$font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif !default; | |
$font-stack-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default; | |
// Font size | |
$font-size: 1rem !default; // 16px ua standard | |
$font-size-sm: .875em !default; | |
$font-size-lg: 1.125em !default; | |
$font-size-sub-sup: .75em !default; | |
// Font weight | |
$font-weight-lighter: lighter !default; | |
$font-weight-light: 300 !default; | |
$font-weight-normal: 400 !default; | |
$font-weight-bold: 700 !default; | |
$font-weight-bolder: bolder !default; | |
// Font line height | |
$font-line-height: 1.5; | |
// Gray color system | |
$white: #fff !default; | |
$gray-100: #f8f9fa !default; | |
$gray-200: #e9ecef !default; | |
$gray-300: #dee2e6 !default; | |
$gray-400: #ced4da !default; | |
$gray-500: #adb5bd !default; | |
$gray-600: #6c757d !default; | |
$gray-700: #495057 !default; | |
$gray-800: #343a40 !default; | |
$gray-900: #212529 !default; | |
$black: #000 !default; | |
// Grays map | |
$grays: ( "100": $gray-100, "200": $gray-200, "300": $gray-300, "400": $gray-400,"500": $gray-500, "600": $gray-600, "700": $gray-700, "800": $gray-800, "900": $gray-900) !default; | |
// Theme colors | |
$primary: #007bff !default; | |
$secondary: $gray-600 !default; | |
$success: #43A047 !default; | |
$info: #5C6BC0 !default; | |
$warning: #FFA000 !default; | |
$danger: #E53935 !default; | |
$light: $gray-100 !default; | |
$dark: $gray-800 !default; | |
// Theme colors map | |
$theme-colors: ( "primary": $primary, "secondary": $secondary, "success": $success,"info": $info, "warning": $warning, "danger": $danger, "light": $light, "dark":$dark ) !default; | |
// Customize the light and dark text colors for use in our color contrast function. | |
$color-contrast-dark: $gray-900 !default; | |
$color-contrast-light: $white !default; | |
// Color scheme auto detection via media query | |
$scheme-detection: true !default; | |
// Layout sizing | |
// Breakpoints | |
$breakpoints: ( | |
xs: 0, | |
sm: 576px, | |
md: 768px, | |
lg: 992px, | |
xl: 1200px, | |
xxl: 1400px | |
) !default; | |
$breakpoints-down: ( | |
xs: 384px - 0.02px, // New logic for breakpoint-down | |
sm: map-get($breakpoints, "sm") - 0.02px, | |
md: map-get($breakpoints, "md") - 0.02px, | |
lg: map-get($breakpoints, "lg") - 0.02px, | |
xl: map-get($breakpoints, "xl") - 0.02px, | |
xxl: map-get($breakpoints, "xxl") - 0.02px | |
) !default; | |
// Display | |
$displays: (none inline inline-block block table table-row table-cell flex inline-flex) !default; | |
// Positions | |
$positions: (static relative absolute fixed sticky) !default; | |
// Container | |
$container-max-widths: ( | |
sm: 540px, | |
md: 720px, | |
lg: 960px, | |
xl: 1140px, | |
xxl: 1320px | |
) !default; | |
$container-padding-x: 1rem !default; | |
// Spacing | |
$spacer: 1rem !default; | |
// Spacing map | |
$spacers: ( | |
0: 0, | |
1: $spacer * .25, | |
2: $spacer * .5, | |
3: $spacer, | |
4: $spacer * 1.5, | |
5: $spacer * 3 | |
) !default; | |
// Grid | |
$enable-grid: true !default; // enable / disable | |
$grid-columns: 12 !default; | |
$grid-gutter-width: 0 !default; | |
$grid-row-columns: 6 !default; | |
$gutters: $spacers !default; | |
// Z-indexes | |
$zindex-app: 0 !default; | |
$zindex-main: 1 !default; | |
$zindex-backdrop: 1010 !default; | |
$zindex-sticky: 1020 !default; | |
$zindex-fixed: 1030 !default; | |
$zindex-dropdown: 1040 !default; | |
$zindex-tooltip: 1050 !default; | |
$zindex-drawer: 1060 !default; | |
$zindex-note: 1080 !default; | |
$zindex-toast: 1090 !default; | |
$zindex-modal: 1100 !default; | |
// App / root element HTML | |
$root-bg: $primary !default; | |
// Dark Scheme | |
$root-dark-bg: $primary !default; | |
// Body | |
$body-bg: $white !default; | |
$body-color: $gray-900 !default; | |
$body-text-align: null !default; | |
// Dark Scheme | |
$body-dark-bg: $gray-900 !default; | |
$body-dark-color: $gray-200 !default; | |
// Text | |
$text-muted: $gray-600 !default; | |
// Border | |
$border-width: 1px !default; | |
$border-color: $gray-300 !default; | |
$border-radius: .25rem !default; | |
$border-radius-sm: .2rem !default; | |
$border-radius-lg: .3rem !default; | |
// Global Pointer style | |
$cursor-pointer: true !default; | |
$cursor: if($cursor-pointer, pointer, default) !default; | |
// Shadows | |
$shadow: 0 0.5rem 1rem rgba($black, 0.15) !default; | |
$shadow-lg: 0 1rem 3rem rgba($black, 0.175) !default; | |
$shadow-sm: 0 .125rem .25rem rgba($black, 0.075) !default; | |
$shadow-inset: inset 0 1px 2px rgba($black, .075) !default; | |
$shadow-elevated: 0px 5px 5px -3px rgba($black, 0.2), | |
0px 8px 10px 1px rgba($black, 0.07), | |
0px 3px 14px 2px rgba($black, 0.06) !default; | |
// Transition | |
$enable-transitions: true !default; | |
$enable-reduced-motion: true !default; | |
$transition-base: all .2s ease-in-out !default; | |
$transition-fade: opacity .15s linear !default; | |
$transition-collapse: height .35s ease !default; | |
// SVGs: Characters which are escaped by the escape-svg function | |
$escaped-characters: ( ("<","%3c"), (">","%3e"), ("#","%23"), ("(","%28"), (")","%29") ) !default; | |
/// Functions | |
// String replace | |
@function str-replace($string, $search, $replace: "") { | |
$index: str-index($string, $search); | |
@if $index { | |
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); | |
} | |
@return $string; | |
} | |
// Escape SVG. See https://codepen.io/kevinweber/pen/dXWoRw | |
@function escape-svg($string) { | |
@if str-index($string, "data:image/svg+xml") { | |
@each $char, $encoded in $escaped-characters { | |
// Do not escape the url brackets | |
@if str-index($string, "url(") == 1 { | |
$string: url("#{str-replace(str-slice($string, 6, -3), $char, $encoded)}"); | |
} @else { | |
$string: str-replace($string, $char, $encoded); | |
} | |
} | |
} | |
@return $string; | |
} | |
// The contrast ratio to reach against white | |
@function contrast-color($color) { | |
@if (lightness($color) < 60) { @return $color-contrast-light; } | |
@else { @return $color-contrast-dark; } | |
} | |
// Return valid calc | |
@function add($value1, $value2, $return-calc: true) { | |
@if $value1 == null { @return $value2; } | |
@if $value2 == null { @return $value1; } | |
@if type-of($value1) == number and type-of($value2) == number and comparable($value1, $value2) { | |
@return $value1 + $value2; | |
} | |
@return if($return-calc == true, calc(#{$value1} + #{$value2}), $value1 + unquote(" + ") + $value2); | |
} | |
@function substract($value1, $value2, $return-calc: true) { | |
@if $value1 == null and $value2 == null { @return null; } | |
@if $value1 == null { @return -$value2; } | |
@if $value2 == null { @return $value1; } | |
@if type-of($value1) == number and type-of($value2) == number and comparable($value1, $value2) { | |
@return $value1 - $value2; | |
} | |
@return if($return-calc == true, calc(#{$value1} - #{$value2}), $value1 + unquote(" - ") + $value2); | |
} | |
// Border radius | |
@function valid-radius($radius) { | |
$return: (); | |
@each $value in $radius { | |
@if type-of($value) == number { $return: append($return, max($value, 0)); } | |
@else { $return: append($return, $value); } | |
} | |
@return $return; | |
} | |
// Transparent grid | |
$transparency-bg: transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 2'%3e%3cpath fill='%23eee' d='M0,0v1h1V0H0z M1,1v1h1V1H1z'/%3e%3c/svg%3e") repeat right top/12px 12px !default; | |
/// Components | |
$component-active-color: $white !default; | |
$component-active-bg: $primary !default; | |
$component-inactive-bg: $gray-500 !default; | |
// Links | |
$link-color: currentColor !default; | |
$link-decoration: underline !default; | |
$link-hover-color: $primary !default; | |
$link-hover-decoration: null !default; | |
$link-active-color: darken($primary, 15%) !default; | |
// Backdrop | |
$backdrop-bg: rgba($black, 0.6) !default; | |
// Form control / input & button | |
$input-padding-y: .375rem !default; | |
$input-padding-x: .75rem !default; | |
$input-padding-y-sm: .375rem !default; | |
$input-padding-x-sm: .75rem !default; | |
$input-padding-y-lg: .375rem !default; | |
$input-padding-x-lg: .75rem !default; | |
$input-bg: $white !default; | |
$input-dark-bg: $gray-900 !default; | |
$input-disabled-bg: $gray-200 !default; | |
$input-disabled-border-color: null !default; | |
$input-focus-bg: $body-bg !default; | |
$input-dark-focus-bg: $body-dark-bg !default; | |
$input-color: $gray-800 !default; | |
$input-autofill-color: $gray-800 !default; | |
$input-dark-color: $gray-400 !default; | |
$input-plaintext-color: $body-color !default; | |
$input-focus-color: $primary !default; | |
$input-font-family: $font-stack !default; | |
$input-font-size: $font-size !default; | |
$input-font-size-sm: $font-size-sm !default; | |
$input-font-size-lg: $font-size-lg !default; | |
$input-font-weight: $font-weight-normal !default; | |
$input-placeholder-color: $gray-600 !default; | |
$input-line-height: $font-line-height !default; | |
$input-border-width: $border-width !default; | |
$input-border-color: $border-color !default; | |
$input-focus-border-color: $primary!default; | |
$input-border-radius: $border-radius !default; | |
$input-border-radius-sm:$border-radius-sm !default; | |
$input-border-radius-lg:$border-radius-lg !default; | |
$input-box-shadow: none !default; | |
$input-focus-box-shadow:0 0 0 .25rem rgba($primary, 0.2) !default; | |
$input-error-box-shadow:0 0 0 .25rem rgba($danger, 0.2) !default; | |
$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default; | |
$input-label-uppercase: false !default; | |
$input-label-focus-color: $input-focus-color !default; | |
$input-height: add($input-line-height * 1em, add($input-padding-y * 2, $input-border-width * 2, false)) !default; | |
$input-height-sm: add($input-line-height * 1em, add($input-padding-y-sm * 2, $input-border-width * 2, false)) !default; | |
$input-height-lg: add($input-line-height * 1em, add($input-padding-y-lg * 2, $input-border-width * 2, false)) !default; | |
// Icons backgrounds | |
$input-autofill-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'><path d='M4.5,7L2,8.5l0.7-3l-2.2-2l2.9-0.3l1.1-2.8l1.1,2.8l2.9,0.3l-2.2,2l0.7,3L4.5,7z' fill='#{$input-autofill-color}'/></svg>") !default; | |
$input-autofill-active-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'><path d='M4.5,7L2,8.5l0.7-3l-2.2-2l2.9-0.3l1.1-2.8l1.1,2.8l2.9,0.3l-2.2,2l0.7,3L4.5,7z' fill='#{$input-focus-color}'/></svg>") !default; | |
$input-date-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'><path d='M1.8.5v.8h-.7c-.2 0-.4.2-.4.4v6.5c0 .2.2.4.4.4H8c.2 0 .4-.2.4-.4V1.6c0-.2-.2-.4-.4-.4h-.8V.5H6v.8H3V.5H1.8zm-.3 3h6.1v4.2H1.5V3.5zm.3.4v1.5h1.5V3.9H1.8zm1.9 0v1.5h1.5V3.9H3.7zm1.9 0v1.5h1.5V3.9H5.6zM1.8 5.8v1.5h1.5V5.8H1.8zm1.9 0v1.5h1.5V5.8H3.7z' fill='#{$input-placeholder-color}'/></svg>") !default; | |
$input-date-icon-bg-focus: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'><path d='M1.8.5v.8h-.7c-.2 0-.4.2-.4.4v6.5c0 .2.2.4.4.4H8c.2 0 .4-.2.4-.4V1.6c0-.2-.2-.4-.4-.4h-.8V.5H6v.8H3V.5H1.8zm-.3 3h6.1v4.2H1.5V3.5zm.3.4v1.5h1.5V3.9H1.8zm1.9 0v1.5h1.5V3.9H3.7zm1.9 0v1.5h1.5V3.9H5.6zM1.8 5.8v1.5h1.5V5.8H1.8zm1.9 0v1.5h1.5V5.8H3.7z' fill='#{$primary}'/></svg>") !default; | |
$input-date-icon-bg-error: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'><path d='M1.8.5v.8h-.7c-.2 0-.4.2-.4.4v6.5c0 .2.2.4.4.4H8c.2 0 .4-.2.4-.4V1.6c0-.2-.2-.4-.4-.4h-.8V.5H6v.8H3V.5H1.8zm-.3 3h6.1v4.2H1.5V3.5zm.3.4v1.5h1.5V3.9H1.8zm1.9 0v1.5h1.5V3.9H3.7zm1.9 0v1.5h1.5V3.9H5.6zM1.8 5.8v1.5h1.5V5.8H1.8zm1.9 0v1.5h1.5V5.8H3.7z' fill='#{$danger}'/></svg>") !default; | |
$input-time-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'><path d='M4.5.5c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm1.8 5.2l-.4.1-.2-.1-1.4-1-.1-.1v-.1-.1-.1-.1L5 1.3c0-.2.2-.3.4-.2.2.1.3.3.3.5L5 4.3l1.2.8c.1.2.2.4.1.6z' fill='#{$input-placeholder-color}'/></svg>") !default; | |
$input-time-icon-bg-focus: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'><path d='M4.5.5c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm1.8 5.2l-.4.1-.2-.1-1.4-1-.1-.1v-.1-.1-.1-.1L5 1.3c0-.2.2-.3.4-.2.2.1.3.3.3.5L5 4.3l1.2.8c.1.2.2.4.1.6z' fill='#{$primary}'/></svg>") !default; | |
$input-time-icon-bg-error: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'><path d='M4.5.5c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm1.8 5.2l-.4.1-.2-.1-1.4-1-.1-.1v-.1-.1-.1-.1L5 1.3c0-.2.2-.3.4-.2.2.1.3.3.3.5L5 4.3l1.2.8c.1.2.2.4.1.6z' fill='#{$danger}'/></svg>") !default; | |
$input-select-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'><path d='M4.5,1L2,3.8h5L4.5,1z M4.5,8L2,5.3h5L4.5,8' fill='#{$input-placeholder-color}'/></svg>") !default; | |
$input-select-icon-bg-focus: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'><path d='M4.5,1L2,3.8h5L4.5,1z M4.5,8L2,5.3h5L4.5,8' fill='#{$primary}'/></svg>") !default; | |
$input-select-icon-bg-error: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'><path d='M4.5,1L2,3.8h5L4.5,1z M4.5,8L2,5.3h5L4.5,8' fill='#{$danger}'/></svg>") !default; | |
// Range | |
$form-range-track-width: 100% !default; | |
$form-range-track-height: .5rem !default; | |
$form-range-track-cursor: pointer !default; | |
$form-range-track-bg: $gray-200 !default; | |
$form-range-track-border-radius: 1rem !default; | |
$form-range-track-box-shadow: $shadow-inset !default; | |
$form-range-track-fill-bg: $component-inactive-bg !default; | |
$form-range-track-active-fill-bg: $component-active-bg !default; | |
$form-range-thumb-width: 1rem !default; | |
$form-range-thumb-height: $form-range-thumb-width !default; | |
$form-range-thumb-bg: $component-inactive-bg !default; | |
$form-range-thumb-active-bg: $component-active-bg !default; | |
$form-range-thumb-border: 0 !default; | |
$form-range-thumb-border-radius: 1rem !default; | |
$form-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default; | |
$form-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow !default; | |
$form-range-thumb-focus-box-shadow-width: .2rem !default; // For focus box shadow issue in Edge | |
$form-range-thumb-active-bg: darken($component-active-bg, 15%) !default; | |
$form-range-thumb-disabled-bg: $gray-500 !default; | |
$form-range-thumb-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default; | |
// Input group | |
$input-group-addon-color: $gray-500 !default; | |
$input-group-addon-bg: $gray-200 !default; | |
// Label | |
$form-label-color: null !default; | |
$form-label-margin-bottom:.75rem !default; | |
$form-label-font-size: null !default; | |
$form-label-font-style: null !default; | |
$form-label-font-weight:null !default; | |
$form-label-color: null !default; | |
// Form group | |
$form-group-margin-bottom: $spacer*.75 !default; | |
$form-grid-gutter-width: $spacer/2 !default; | |
// Button | |
$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default; | |
$btn-uppercase: false !default; | |
// Dropdown | |
$dropdown-bg: $white !default; | |
$dropdown-dark-bg: $gray-900 !default; | |
// Modal | |
$modal-bg: $white !default; | |
$modal-dark-bg: $gray-900 !default; | |
$modal-sm: 300px !default; | |
$modal-md: 500px !default; | |
$modal-lg: 800px !default; | |
$modal-xl: 1140px !default; | |
$modal-fade-transform: translate(0, -50px) !default; | |
$modal-show-transform: none !default; | |
$modal-transition: transform .3s ease-out !default; | |
$modal-scale-transform: scale(1.02) !default; | |
// Drawer | |
$drawer-bg: $white !default; | |
$drawer-dark-bg: $gray-900 !default; | |
$drawer-width: 25rem !default; | |
// Sheet | |
$sheet-bg: $white !default; | |
$sheet-dark-bg: $gray-900 !default; | |
// Card | |
$card-bg: $white !default; | |
$card-dark-bg: $gray-900 !default; | |
// Toast | |
$toast-bg: rgba($black, 0.7) !default; | |
// Tooltip | |
$tooltip-bg: rgba($black, 0.7) !default; | |
$tooltip-dark-bg: $gray-900 !default; | |
// Notification | |
$note-bg: $white !default; | |
$note-dark-bg: $gray-900 !default; | |
/// Mixins | |
// Border radius | |
@mixin border-radius($radius: $border-radius) { | |
border-radius: valid-radius($radius); | |
} | |
// Breakpoint media queries | |
@mixin breakpoint-up($name, $points: $breakpoints) { | |
$min: map-get($points, $name); | |
@if $min { @media (min-width: $min) { @content; } } | |
@else { @content; } | |
} | |
@mixin breakpoint-down($name, $points: $breakpoints-down) { | |
$max: map-get($points, $name); | |
@if $max { @media (max-width: $max) { @content; } } | |
@else { @content; } | |
} | |
@mixin breakpoint-between($namemin, $namemax, $points: $breakpoints, $pointsdown: $breakpoints-down) { | |
$min: map-get($points, $namemin); | |
$max: map-get($pointsdown, $namemax); | |
@if $min != null and $max != null { | |
@media (min-width: $min) and (max-width: $max) { @content; } | |
} @else if $max == null { | |
@include breakpoint-up($namemin) { @content; } | |
} @else if $min == null { | |
@include breakpoint-down($namemax) { @content; } | |
} | |
} | |
// Dark scheme property / media query | |
@mixin dark-scheme($root:false) { | |
@if $scheme-detection == true { | |
@media (prefers-dark-interface), (prefers-color-scheme: dark) { @content; } | |
} | |
@if $root == true { &[data-scheme="dark"] { @content; } } | |
@else { [data-scheme="dark"] & { @content; } } | |
} | |
// Grid system | |
@mixin make-row($gutter: $grid-gutter-width) { | |
display: flex; | |
flex-wrap: wrap; | |
margin-top: 0*-1; // logical only | |
margin-right: $gutter/-2; | |
margin-left: $gutter/-2; | |
} | |
@mixin make-col-ready($gutter: $grid-gutter-width) { | |
flex-shrink: 0; | |
width: 100%; | |
max-width: 100%; | |
padding-right: $gutter/2; | |
padding-left: $gutter/2; | |
margin-top: 0; | |
} | |
@mixin make-col($size, $columns: $grid-columns) { | |
flex: 0 0 auto; | |
width: percentage($size / $columns); | |
} | |
@mixin make-col-auto() { | |
flex: 0 0 auto; | |
width: auto; | |
} | |
@mixin make-col-offset($size, $columns: $grid-columns) { | |
$num: $size / $columns; | |
margin-left: if($num == 0, 0, percentage($num)); | |
} | |
@mixin row-cols($count) { | |
& > * { | |
flex: 0 0 auto; | |
width: 100% / $count; | |
} | |
} | |
@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $points: $breakpoints) { | |
@each $breakpoint in map-keys($points) { | |
$infix: breakpoint-infix($breakpoint, $points); | |
@include breakpoint-up($breakpoint, $points) { | |
.col#{$infix} { | |
flex: 1 0 0%; // Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4 | |
min-width: 0; // See https://github.com/twbs/bootstrap/issues/25410 | |
} | |
.row-cols#{$infix}-auto > * { | |
@include make-col-auto(); | |
} | |
@if $grid-row-columns > 0 { | |
@for $i from 1 through $grid-row-columns { | |
.row-cols#{$infix}-#{$i} { | |
@include row-cols($i); | |
} | |
} | |
} | |
.col#{$infix}-auto { | |
@include make-col-auto(); | |
} | |
@if $columns > 0 { | |
@for $i from 1 through $columns { | |
.col#{$infix}-#{$i} { | |
@include make-col($i, $columns); | |
} | |
} | |
@for $i from 0 through ($columns - 1) { | |
@if not ($infix == "" and $i == 0) { | |
.offset#{$infix}-#{$i} { | |
@include make-col-offset($i, $columns); | |
} | |
} | |
} | |
} | |
// Gutters | |
@each $key, $value in $gutters { | |
.g#{$infix}-#{$key}, | |
.gx#{$infix}-#{$key} { | |
--ui-gutter-x: #{$value}; | |
} | |
.g#{$infix}-#{$key}, | |
.gy#{$infix}-#{$key} { | |
--ui-gutter-y: #{$value}; | |
} | |
} | |
} | |
} | |
} | |
// Responsive image | |
@mixin img-fluid { | |
max-width: 100%; | |
height: auto; | |
} | |
// Transition | |
@mixin transition($transition...) { | |
@if length($transition) == 0 { $transition: $transition-base; } | |
@if length($transition) > 1 { | |
@each $value in $transition { | |
@if $value == null or $value == none { | |
@warn "The keyword 'none' or 'null' must be used as a single argument."; | |
} | |
} | |
} | |
@if $enable-transitions { | |
@if nth($transition, 1) != null { transition: $transition; } | |
@if $enable-reduced-motion and nth($transition, 1) != null and nth($transition, 1) != none { | |
@media (prefers-reduced-motion: reduce) { | |
transition: none; | |
} | |
} | |
} | |
} | |
/// Start CSS | |
// Password dot font face | |
@font-face { | |
font-family: 'Dots'; | |
font-style: normal; | |
font-weight: 400; | |
src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAATsAA8AAAAAB2QAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABWAAAABwAAAAcg9+z70dERUYAAAF0AAAAHAAAAB4AJwANT1MvMgAAAZAAAAA/AAAAYH7AkBhjbWFwAAAB0AAAAFkAAAFqZowMx2N2dCAAAAIsAAAABAAAAAQAIgKIZ2FzcAAAAjAAAAAIAAAACAAAABBnbHlmAAACOAAAALkAAAE0MwNYJ2hlYWQAAAL0AAAAMAAAADYPA2KgaGhlYQAAAyQAAAAeAAAAJAU+ATJobXR4AAADRAAAABwAAAAcCPoA6mxvY2EAAANgAAAAEAAAABAA5gFMbWF4cAAAA3AAAAAaAAAAIAAKAE9uYW1lAAADjAAAARYAAAIgB4hZ03Bvc3QAAASkAAAAPgAAAE5Ojr8ld2ViZgAABOQAAAAGAAAABuK7WtIAAAABAAAAANXulPUAAAAA1viLwQAAAADW+JM4eNpjYGRgYOABYjEgZmJgBEI2IGYB8xgAA+AANXjaY2BifMg4gYGVgYVBAwOeYEAFjMgcp8yiFAYHBl7VP8wx/94wpDDHMIoo2DP8B8kx2TLHACkFBkYA8/IL3QB42mNgYGBmgGAZBkYGEEgB8hjBfBYGDyDNx8DBwMTABmTxMigoKKmeV/3z/z9YJTKf8f/X/4/vP7pldosLag4SYATqhgkyMgEJJnQFECcMOGChndEAfOwRuAAAAAAiAogAAQAB//8AD3jaY2BiUGJgYDRiWsXAzMDOoLeRkUHfZhM7C8Nbo41srHdsNjEzAZkMG5lBwqwg4U3sbIx/bDYxgsSNBRUF1Y0FlZUYBd6dOcO06m+YElMa0DiGJIZUxjuM9xjkGRhU2djZlJXU1UDQ1MTcDASNjcTFQFBUBGjYEkkVMJCU4gcCKRTeHCk+fn4+KSllsJiUJEhMUgrMUQbZk8bgz/iA8SRR9qzAY087FjEYD2QPDDAzMFgyAwC39TCRAAAAeNpjYGRgYADid/fqneL5bb4yyLMwgMC1H90HIfRkCxDN+IBpFZDiYGAC8QBbSwuceNpjYGRgYI7594aBgcmOAQgYHzAwMqACdgBbWQN0AAABdgAiAAAAAAAAAAABFAAAAj4AYgI+AGYB9AAAAAAAKgAqACoAKgBeAJIAmnjaY2BkYGBgZ1BgYGIAAUYGBNADEQAFQQBaAAB42o2PwUrDQBCGvzVV9GAQDx485exBY1CU3PQgVgIFI9prlVqDwcZNC/oSPoKP4HNUfQLfxYN/NytCe5GwO9/88+/MBAh5I8C0VoAtnYYNa8oaXpAn9RxIP/XcIqLreZENnjwvyfPieVVdXj2H7DHxPJH/2/M7sVn3/MGyOfb8SWjOGv4K2DRdctpkmtqhos+D6ISh4kiUUXDj1Fr3Bc/Oc0vPqec6A8aUyu1cdTaPZvyXyqz6Fm5axC7bxHOv/r/dnbSRXCk7+mpVrOqVtFqdp3NKxaHUgeod9cm40rtrzfrt2OyQa8fppCO9tk7d1x0rpiQcuDuRkjjtkHt16ctbuf/radZY52/PnEcphXpZOcofiEZNcQAAeNpjYGIAg///GBgZsAF2BgZGJkZmBmaGdkYWRla29JzKggxD9tK8TAMDAxc2D0MLU2NjENfI1M0ZACUXCrsAAAABWtLiugAA) format('woff'); | |
} | |
/// CSS root variables | |
:root { | |
@each $color, $value in $theme-colors { | |
--ui-#{$color}: #{$value}; | |
} | |
@each $gray, $value in $grays { | |
--ui-gray-#{$gray}: #{$value}; | |
} | |
@each $breakpoint, $value in $breakpoints { | |
--ui-breakpoint-#{$breakpoint}: #{$value}; | |
} | |
--ui-font: #{$font-stack}; | |
--ui-font-monospace: #{$font-stack-monospace}; | |
} | |
/// Minimal reset | |
*, *::before, *::after { | |
box-sizing: border-box; | |
} | |
/// HTML | |
html { | |
font-size: $font-size; | |
background-color: $root-bg; | |
-ms-text-size-adjust: 100%; | |
-webkit-text-size-adjust: 100%; | |
-webkit-tap-highlight-color: transparent; | |
} | |
@include breakpoint-up("sm") { html { font-size: 1.0625rem; } } | |
@include breakpoint-up("md") { html { font-size: 1.125rem; } } | |
@include breakpoint-up("lg") { html { font-size: 1.1875rem; } } | |
@include breakpoint-up("xl") { html { font-size: 1.25rem; } } | |
// Body | |
body { | |
margin: 0; | |
font-family: $font-stack; | |
font-size: $font-size; | |
font-weight: $font-weight-normal; | |
line-height: $font-line-height; | |
color: $body-color; | |
text-align: left; | |
background-color: $body-bg; | |
overflow-x: hidden; | |
@include dark-scheme (true){ | |
background-color: $body-dark-bg; | |
color: $body-dark-color; | |
} | |
-webkit-font-smoothing: antialiased; | |
} | |
// Viewport mobile hack | |
.vh { | |
height: 100vh; | |
height: calc(var(--vh, 1vh) * 100); | |
} | |
// Outline normalization | |
* { | |
outline-color: $primary; | |
} | |
// Links | |
a { | |
color: currentColor; | |
text-decoration: $link-decoration; | |
background-color: transparent; | |
cursor: $cursor; | |
transition: color .15s ease; | |
&:hover { | |
color: $link-hover-color; | |
text-decoration: $link-hover-decoration; | |
} | |
&:active { | |
color: $link-active-color; | |
text-decoration: $link-decoration; | |
} | |
} | |
// SVGs | |
svg { | |
fill: currentColor; | |
display: inline-block; | |
a &, button & { | |
pointer-events: none; | |
z-index: -1; | |
} | |
} | |
// Typography | |
legend, p, h1, h2, h3, h4, h5, h6 { | |
margin: 0 0 $spacer 0; | |
} | |
p { | |
display: block; | |
} | |
h1 { | |
font-size: 1.5rem; | |
font-weight: 200; | |
font-weight: lighter; | |
} | |
legend, h2 { | |
font-size: 1.25rem; | |
font-weight: bold; | |
} | |
h3, h4, h5, h6 { | |
font-size: 1.05rem; | |
font-weight: bold; | |
} | |
/// Text classes | |
.text-hide { | |
font: 0/0 a; | |
color: transparent; | |
text-shadow: none; | |
background-color: transparent; | |
border: 0; | |
} | |
.text-mute { | |
} | |
/// Screenreaders | |
.sr-only, | |
.sr-only-focusable:not(:focus) { | |
position: absolute !important; | |
width: 1px !important; | |
height: 1px !important; | |
padding: 0 !important; | |
margin: -1px !important; | |
overflow: hidden !important; | |
clip: rect(0, 0, 0, 0) !important; | |
white-space: nowrap !important; | |
border: 0 !important; | |
} | |
// Icon class | |
.icon { | |
height: 1.5em; | |
width: auto; | |
} | |
/// Float classes | |
.float-left { | |
float: left !important; | |
} | |
.float-right { | |
float: right !important; | |
} | |
.float-none { | |
float: none !important; | |
} | |
.clearfix::after { | |
display: block; | |
clear: both; | |
content: ''; | |
} | |
/// Background mixin | |
@mixin bg-variant($parent, $color) { | |
#{$parent} { | |
background-color: $color !important; | |
} | |
a#{$parent}, | |
button#{$parent} { | |
&:hover, &focus, &:target { | |
background-color: darken($color, 15%) !important; | |
} | |
} | |
} | |
/// Alert mixin | |
@mixin alert-variant($background, $border, $color) { | |
color: $color; | |
background-color: $background; | |
border-color: $border; | |
.alert-link { | |
color: darken($color, 10%); | |
} | |
} | |
/// Shadow classes | |
.shadow-sm { box-shadow: $shadow-sm; } | |
.shadow { box-shadow: $shadow; } | |
.shadow-lg { box-shadow: $shadow-lg; } | |
.shadow-none { box-shadow: none !important; } | |
.shadow-elevated { box-shadow: $shadow-elevated; } | |
/// Rounded classes | |
.rounded-0 { border-radius: 0!important; } | |
.rounded-sm { border-radius: $border-radius/2 !important; } | |
.rounded { border-radius: $border-radius !important; } | |
.rounded-lg { border-radius: $border-radius*2 !important; } | |
.rounded-circle { border-radius: 50% !important; } | |
.rounded-pill { border-radius: 50rem !important; } | |
/// Grid system | |
// Container | |
@mixin make-container($gutter: $container-padding-x) { | |
width: 100%; | |
padding-right: $gutter / 2; | |
padding-left: $gutter / 2; | |
margin-right: auto; | |
margin-left: auto; | |
} | |
// For each breakpoint, define the maximum width of the container in a media query | |
@mixin make-container-max-widths($max-widths: $container-max-widths, $points: $breakpoints) { | |
@each $breakpoint, $container-max-width in $max-widths { | |
@include breakpoint-up($breakpoint) { | |
max-width: $container-max-width; | |
} | |
} | |
} | |
// Minimum breakpoint width. Null for the smallest (first) breakpoint. | |
@function breakpoint-min($name, $points: $breakpoints) { | |
$min: map-get($points, $name); | |
@return if($min != 0, $min, null); | |
} | |
// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front. | |
@function breakpoint-infix($name, $points: $breakpoints) { | |
@return if(breakpoint-min($name, $points) == null, "", "-#{$name}"); | |
} | |
// Single container class with breakpoint max-widths | |
.container { | |
@include make-container(); | |
@include make-container-max-widths(); | |
} | |
// 100% wide container at all breakpoints | |
.container-fluid { | |
@include make-container(); | |
} | |
// Responsive containers that are 100% wide until a breakpoint | |
@each $breakpoint, $container-max-width in $container-max-widths { | |
.container-#{$breakpoint} { | |
@extend .container-fluid; | |
} | |
@include breakpoint-up($breakpoint, $breakpoints) { | |
%responsive-container-#{$breakpoint} { | |
max-width: $container-max-width; | |
} | |
@each $name, $width in $breakpoints { | |
@if ($container-max-width > $width or $breakpoint == $name) { | |
.container#{breakpoint-infix($name)} { | |
@extend %responsive-container-#{$breakpoint}; | |
} | |
} | |
} | |
} | |
} | |
// Grid | |
// Row | |
@if $enable-grid { | |
.row { | |
@include make-row(); | |
> * { | |
@include make-col-ready(); | |
} | |
} | |
} | |
// Columns | |
@if $enable-grid { | |
@include make-grid-columns(); | |
} | |
/// Display | |
@each $breakpoint in map-keys($breakpoints) { | |
@include breakpoint-up($breakpoint) { | |
$infix: breakpoint-infix($breakpoint, $breakpoints); | |
@each $value in $displays { | |
.d#{$infix}-#{$value} { display: $value !important; } | |
} | |
} | |
} | |
@media print { | |
@each $value in $displays { | |
.d-print-#{$value} { display: $value !important; } | |
} | |
} | |
/// Position | |
.fixed-top { | |
position: fixed; | |
top: 0; | |
right: 0; | |
left: 0; | |
z-index: $zindex-fixed; | |
} | |
.fixed-bottom { | |
position: fixed; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
z-index: $zindex-fixed; | |
} | |
// Responsive sticky top | |
@each $breakpoint in map-keys($breakpoints) { | |
@include breakpoint-up($breakpoint) { | |
$infix: breakpoint-infix($breakpoint, $breakpoints); | |
.sticky#{$infix}-top { | |
position: sticky; | |
top: 0; | |
z-index: $zindex-sticky; | |
} | |
} | |
} | |
// Global close X | |
.close { | |
display: inline-block; | |
overflow: hidden; | |
position: relative; | |
font-size: 1rem; | |
width: 2em; | |
height: 2em; | |
border-radius: 1em; | |
border: 0; | |
text-indent: -9999rem; | |
background-color: rgba($white, 0); | |
cursor: $cursor; | |
pointer-events: all; | |
&::before, &::after { | |
content: ''; | |
position: absolute; | |
top: calc(50%); | |
left: 20%; | |
display: inline-block; | |
height: 0.15em; | |
width: 60%; | |
background-color: currentColor; | |
transform-origin: center center; | |
transform: rotate(45deg); | |
pointer-events: none; | |
} | |
&::after { | |
transform: rotate(-45deg); | |
} | |
@include breakpoint-down("xs") { | |
&::before, &::after { | |
transform-origin: right center; | |
width: 40%; | |
right: 30%; | |
} | |
&::before { | |
top: auto; | |
bottom: 20%; | |
} | |
&::after { | |
top: 20%; | |
} | |
} | |
} | |
// Global caret | |
.caret { | |
position: relative; | |
display: inline-block; | |
width: 1em; | |
height: 1em; | |
line-height: 1; | |
margin: 0 0 0 .25em; | |
vertical-align: middle; | |
text-align: center; | |
pointer-events: none; | |
&:empty::before { | |
content: ''; | |
display: inline-block; | |
position: absolute; | |
top: 0; | |
left: .15em; | |
width: .6em; | |
height: .6em; | |
border: 0px solid currentColor; | |
border-width: 0 .1em .1em 0; | |
transform: rotate(45deg); | |
} | |
} | |
// Global hamburger | |
.hamburger { | |
position: relative; | |
display: inline-block; | |
width: 2em; | |
height: 2em; | |
line-height: 1; | |
text-indent: -9999rem; | |
border-radius: 50%; | |
&:focus { | |
background-color: $primary; | |
color: contrast-color($primary); | |
} | |
&::before, &::after { | |
content: ''; | |
position: absolute; | |
top: 25%; | |
left: 25%; | |
width: 50%; | |
height: 10%; | |
background-color: currentColor; | |
} | |
&::before { | |
box-shadow: 0 50% 0 0 currentColor, | |
} | |
&::after { | |
top:65%; | |
} | |
} | |
// Disabled property / pseudo / class | |
[disabled], :disabled, .disabled { | |
cursor: not-allowed; | |
opacity: 0.5; | |
} | |
// Hidden property / pseudo / class | |
[hidden], :hidden, .hidden { | |
display: none!important; | |
} | |
// UI interaction / manipulation properties | |
[scrolling] { | |
scroll-behavior: smooth; | |
} | |
[swiping], [dragging], [paning] { | |
-webkit-overflow-scrolling: none; | |
overscroll-behavior: none; | |
-ms-scroll-chaining: none; | |
/* autoprefixer: off */ | |
-ms-touch-action: none; | |
touch-action: none; | |
} | |
[manipulating] { | |
user-select: none; | |
/* autoprefixer: off */ | |
-ms-touch-action: manipulation; | |
touch-action: manipulation; | |
} | |
[noanimate] { | |
transition: none; | |
animation: none; | |
} | |
@media screen and (prefers-reduced-motion: reduce) { | |
[scrolling], [dragging], [paning] { | |
scroll-behavior: auto; | |
} | |
} | |
// Transitions | |
.fade { | |
@include transition($transition-fade); | |
&:not(.show) { opacity: 0; } | |
} | |
.collapse { | |
&:not(.show) { display: none; } | |
} | |
.collapsing { | |
height: 0; | |
overflow: hidden; | |
@include transition($transition-collapse); | |
} | |
// Form normalization | |
form, fieldset { | |
padding: 0; | |
margin: 0; | |
border: 0; | |
} | |
form { | |
width: 100%; | |
} | |
// Hide spam honey pot & possible token fields | |
input[id*='spam'], label[for*='spam'] {display: none!important; visibility: hidden;} | |
input[id*='token'], label[for*='token'] {display: none!important; visibility: hidden;} | |
button{ | |
&:last-child { | |
margin-right: 0; | |
} | |
&:first-child { | |
margin-left: 0; | |
} | |
} | |
[type=button]:not(:disabled), [type=reset]:not(:disabled), [type=submit]:not(:disabled), button:not(:disabled) { | |
cursor: $cursor; | |
} | |
/// Form control | |
.form-control { | |
display: block; | |
width: 100%; | |
min-height: $input-height; | |
padding: $input-padding-y $input-padding-x; | |
font-family: $input-font-family; | |
font-size: $input-font-size; | |
font-weight: $input-font-weight; | |
line-height: $input-line-height; | |
color: $input-color; | |
caret-color: currentColor; | |
background-color: $input-bg; | |
background-clip: padding-box; | |
border: $input-border-width solid $input-border-color; | |
appearance: none; | |
@include border-radius($input-border-radius); | |
box-shadow: $input-box-shadow; | |
@include transition($input-transition); | |
@include dark-scheme (){ | |
background-color: $input-dark-bg; | |
color: $input-dark-color; | |
} | |
&:focus { | |
color: $input-focus-color; | |
background-color: $input-focus-bg; | |
border-color: $input-focus-border-color; | |
outline: 0; | |
box-shadow: $input-focus-box-shadow; | |
@include dark-scheme (){ | |
background-color: $input-dark-focus-bg; | |
} | |
} | |
// Remove select outline from select box in FF | |
&:-moz-focusring { | |
color: transparent; | |
text-shadow: 0 0 0 $input-color; | |
} | |
// Unstyle the caret on `<select>`s in IE10+. | |
&::-ms-expand { | |
background-color: transparent; | |
border: 0; | |
} | |
&::-ms-clear { | |
display:none; | |
} | |
// Placeholder | |
&::placeholder { | |
font-family: $input-font-family; | |
color: $input-placeholder-color; | |
opacity: 1; | |
} | |
// Disabled and read-only inputs | |
&:disabled, | |
&[readonly] { | |
background-color: $input-disabled-bg; | |
border-color: $input-disabled-border-color; | |
opacity: 1; | |
} | |
// Readonly controls as plain text | |
#{&}-plaintext { | |
display: block; | |
width: 100%; | |
padding: $input-padding-y 0; | |
margin-bottom: 0; // match inputs if this class comes on inputs with default margins | |
line-height: $input-line-height; | |
color: $input-plaintext-color; | |
background-color: transparent; | |
border: solid transparent; | |
border-width: $input-border-width 0; | |
&.form-control-sm, | |
&.form-control-lg { | |
padding-right: 0; | |
padding-left: 0; | |
} | |
} | |
// Form control sizing | |
&-sm { | |
min-height: $input-height-sm; | |
padding: $input-padding-y-sm $input-padding-x-sm; | |
font-size: $input-font-size-sm; | |
@include border-radius($input-border-radius-sm); | |
} | |
&-lg { | |
min-height: $input-height-lg; | |
padding: $input-padding-y-lg $input-padding-x-lg; | |
font-size: $input-font-size-lg; | |
@include border-radius($input-border-radius-lg); | |
} | |
// Textarea | |
@at-root textarea#{&} { | |
height: auto; | |
resize: vertical; | |
} | |
// Password | |
&[type*="password"]{ | |
font-family: 'Dots', $input-font-family; | |
&::-ms-reveal { | |
display:none; | |
} | |
} | |
// Color input | |
&[type*="color"] { | |
max-width: 3rem; | |
padding: $input-padding-y; | |
&:invalid { | |
&::-moz-color-swatch { background: $transparency-bg; } | |
&::-webkit-color-swatch { background: $transparency-bg; } | |
} | |
&::-webkit-color-swatch-wrapper { // remove datalist ui [list="id"] | |
padding:0; | |
} | |
&::-moz-color-swatch { | |
border:0; | |
@include border-radius(0); | |
} | |
&::-webkit-color-swatch { | |
border:0; | |
@include border-radius(0); | |
} | |
} | |
// Range / file input | |
&[type*="file"], | |
&[type*="range"]{ | |
display: block; | |
width: 100%; | |
} | |
// Select | |
@at-root select#{&} { | |
background-image: escape-svg($input-select-icon-bg); | |
background-repeat: no-repeat; | |
background-size: 1em 1em; | |
background-position: substract(100%, $input-padding-x, true) center; | |
&[multiple], | |
&[size]:not([size="1"]) { | |
height: auto; | |
background-image: none; | |
} | |
&:focus { | |
background-image: escape-svg($input-select-icon-bg-focus); | |
&::-ms-value { | |
color: $input-color; | |
background-color: $input-bg; | |
} | |
} | |
optgroup { | |
font-style: normal; | |
} | |
option { | |
font-style: normal; | |
} | |
// W3C recos, Firefox label display | |
optgroup[label], option[label]{ | |
content: attr(label); | |
} | |
option[selected]::before{ | |
display: inline; | |
content: check; | |
} | |
} | |
// Number | |
&[type*="number"]{ | |
-moz-appearance: textfield; | |
&::-webkit-inner-spin-button { | |
display: none; | |
} | |
&::-webkit-clear-button { | |
display: none; | |
} | |
&::-ms-clear { | |
display: none; | |
} | |
} | |
// Date / time / datetime-local / datetime | |
&[type*="date"], &[type="time"], &[type="month"] { | |
appearance: listbox; | |
background-repeat: no-repeat; | |
background-size: 1em 1em; | |
background-position: substract(100%, $input-padding-x, true) center; | |
&::-webkit-inner-spin-button { | |
display: none; | |
} | |
&::-webkit-clear-button { | |
display: none; | |
} | |
&::-ms-clear { | |
display: none; | |
} | |
&::-webkit-calendar-picker-indicator { | |
position: absolute; | |
right: $input-padding-x; | |
width: 1em; | |
opacity: 0; | |
cursor: $cursor; | |
margin:0; | |
} | |
} | |
&[type*="date"], &[type="month"] { | |
background-image: escape-svg($input-date-icon-bg); | |
&:focus { | |
background-image: escape-svg($input-date-icon-bg-focus); | |
} | |
} | |
&[type="time"] { | |
background-image: escape-svg($input-time-icon-bg); | |
&:focus { | |
background-image: escape-svg($input-time-icon-bg-focus); | |
} | |
} | |
// Search | |
&[type="search"]::-webkit-search-cancel-button { | |
display: none; | |
} | |
// Prepended labels | |
& ~ .form-label, & ~ label { | |
position: relative; | |
top: 0; | |
} | |
// Autofill | |
&:-webkit-autofill { | |
color: $input-color !important; | |
-webkit-text-fill-color: $input-color !important; | |
background-color: $input-bg!important; | |
background-image: escape-svg($input-autofill-icon-bg) !important; | |
background-repeat: no-repeat; | |
background-size: 1em 1em; | |
background-position: substract(100%, $input-padding-x, true) center; | |
@include transition($input-transition, background-image .15s linear, background-color 99999s linear 99999s); | |
@include dark-scheme (){ | |
background-color: $input-dark-bg; | |
} | |
&:hover, &:focus, &:active { | |
color: $primary !important; | |
-webkit-text-fill-color: $primary !important; | |
background-image: escape-svg($input-autofill-active-icon-bg) !important; | |
} | |
} | |
&:-internal-autofill-selected, | |
&:-internal-autofill-previewed, | |
&:-internal-input-suggested { | |
font: inherit !important; | |
color: $input-color !important; | |
-webkit-text-fill-color: $input-color !important; | |
background-color: $input-bg!important; | |
background-image: escape-svg($input-autofill-icon-bg) !important; | |
background-repeat: no-repeat; | |
background-size: 1em 1em; | |
background-position: substract(100%, $input-padding-x, true) center; | |
@include transition($input-transition, background-image .15s linear, background-color 99999s linear 99999s); | |
@include dark-scheme (){ | |
background-color: $input-dark-bg; | |
} | |
} | |
// Validation states | |
&.is-validated:invalid{ | |
color: $danger; | |
border-color: $danger; | |
&:focus { | |
box-shadow: $input-error-box-shadow; | |
} | |
} | |
&.is-validated:valid { | |
} | |
// Validation states | |
@at-root .has-error #{&} { | |
color: $danger; | |
border-color: $danger; | |
&:focus { | |
box-shadow: $input-error-box-shadow; | |
} | |
&::placeholder { | |
color: $danger; | |
} | |
&[type*="date"], &[type="month"] { | |
background-image: escape-svg($input-date-icon-bg-error); | |
&:focus { | |
background-image: escape-svg($input-date-icon-bg-error); | |
} | |
} | |
&[type*="time"] { | |
background-image: escape-svg($input-time-icon-bg-error); | |
&:focus { | |
background-image: escape-svg($input-time-icon-bg-error); | |
} | |
} | |
} | |
@at-root .is-valid #{&} { | |
} | |
} | |
// Range | |
.form-range { | |
width: 100%; | |
min-height: $input-height; // Align middle | |
padding: 0; // Need to reset padding | |
background-color: transparent; | |
appearance: none; | |
--rangeValue: calc(attr(value)*100); // Future? | |
& ~ output { | |
position: absolute; | |
top: -1em; | |
left: 50%; | |
display: inline-block; | |
width: auto; height: 2em; | |
padding: 0 .75em; | |
transform: translateX(-50%); | |
background-color: $form-range-thumb-active-bg; | |
color: $white; | |
text-align: center; | |
line-height: 2; | |
border-radius: 1em; | |
opacity: 0; | |
visibility: hidden; | |
transition: opacity .15s linear; | |
} | |
&:focus { | |
outline: none; | |
&::-webkit-slider-thumb { box-shadow: $form-range-thumb-focus-box-shadow; background: $form-range-thumb-active-bg;} | |
&::-moz-range-thumb { box-shadow: $form-range-thumb-focus-box-shadow; background: $form-range-thumb-active-bg;} | |
&::-ms-thumb { box-shadow: $form-range-thumb-focus-box-shadow; background: $form-range-thumb-active-bg;} | |
&::-webkit-slider-runnable-track { | |
background-image: -webkit-linear-gradient(left, $form-range-track-active-fill-bg calc(var(--rangeValue)*1%), transparent calc(var(--rangeValue)*1%)); | |
} | |
&::-moz-range-progress { background-color: $form-range-track-active-fill-bg;} | |
&::-ms-fill-lower { background-color: $form-range-track-active-fill-bg;} | |
// Output | |
& ~ output{ | |
opacity: 1; | |
visibility: visible; | |
} | |
} | |
&:active { | |
&::-webkit-slider-thumb { background: $form-range-thumb-active-bg; } | |
&::-moz-range-thumb { background: $form-range-thumb-active-bg; } | |
&::-ms-thumb { background: $form-range-thumb-active-bg; } | |
} | |
&::-moz-focus-outer { border: 0; } | |
&::-webkit-slider-thumb { | |
width: $form-range-thumb-width; | |
height: $form-range-thumb-height; | |
margin-top: ($form-range-track-height - $form-range-thumb-height) / 2; // Webkit specific | |
background: $form-range-thumb-bg; | |
border: $form-range-thumb-border; | |
@include border-radius($form-range-thumb-border-radius); | |
box-shadow: $form-range-thumb-box-shadow; | |
@include transition($form-range-thumb-transition); | |
appearance: none; | |
} | |
&::-webkit-slider-runnable-track { | |
width: $form-range-track-width; | |
height: $form-range-track-height; | |
color: transparent; // Why? | |
cursor: $form-range-track-cursor; | |
background-image: -webkit-linear-gradient(left, $form-range-track-fill-bg calc(var(--rangeValue)*1%), transparent calc(var(--rangeValue)*1%)); | |
background-color: $form-range-track-bg; | |
border-color: transparent; | |
@include border-radius($form-range-track-border-radius); | |
box-shadow: $form-range-track-box-shadow; | |
} | |
&::-moz-range-thumb { | |
width: $form-range-thumb-width; | |
height: $form-range-thumb-height; | |
background: $form-range-thumb-bg; | |
border: $form-range-thumb-border; | |
@include border-radius($form-range-thumb-border-radius); | |
box-shadow: $form-range-thumb-box-shadow; | |
@include transition($form-range-thumb-transition); | |
appearance: none; | |
} | |
&::-moz-range-track { | |
width: $form-range-track-width; | |
height: $form-range-track-height; | |
color: transparent; | |
cursor: $form-range-track-cursor; | |
background-color: $form-range-track-bg; | |
border-color: transparent; // Firefox specific? | |
@include border-radius($form-range-track-border-radius); | |
box-shadow: $form-range-track-box-shadow; | |
} | |
&::-moz-range-progress { | |
height: $form-range-track-height; | |
background-color: $form-range-track-fill-bg; | |
@include border-radius($form-range-track-border-radius); | |
} | |
&::-ms-thumb { | |
width: $form-range-thumb-width; | |
height: $form-range-thumb-height; | |
margin-top: 0; // Edge specific | |
margin-right: $form-range-thumb-focus-box-shadow-width; // Workaround that overflowed box-shadow is hidden. | |
margin-left: $form-range-thumb-focus-box-shadow-width; // Workaround that overflowed box-shadow is hidden. | |
background: $form-range-thumb-bg; | |
border: $form-range-thumb-border; | |
@include border-radius($form-range-thumb-border-radius); | |
box-shadow: $form-range-thumb-box-shadow; | |
@include transition($form-range-thumb-transition); | |
appearance: none; | |
} | |
&::-ms-track { | |
width: $form-range-track-width; | |
height: $form-range-track-height; | |
color: transparent; | |
cursor: $form-range-track-cursor; | |
background-color: transparent; | |
border-color: transparent; | |
border-width: $form-range-thumb-height / 2; | |
box-shadow: $form-range-track-box-shadow; | |
} | |
&::-ms-fill-lower { | |
background-color: $form-range-track-fill-bg; | |
@include border-radius($form-range-track-border-radius); | |
} | |
&::-ms-fill-upper { | |
margin-right: 15px; // arbitrary? | |
background-color: $form-range-track-bg; | |
@include border-radius($form-range-track-border-radius); | |
} | |
&:disabled { | |
pointer-events: none; | |
&::-webkit-slider-thumb { | |
background-color: $form-range-thumb-disabled-bg; | |
} | |
&::-moz-range-thumb { | |
background-color: $form-range-thumb-disabled-bg; | |
} | |
&::-ms-thumb { | |
background-color: $form-range-thumb-disabled-bg; | |
} | |
} | |
} | |
/// Input group | |
.input-group { | |
position: relative; | |
display: flex; | |
flex-wrap: wrap; // For form validation feedback | |
align-items: stretch; | |
width: 100%; | |
> .form-control, | |
> .form-select, | |
> .form-file { | |
position: relative; // For focus state's z-index | |
flex: 1 1 auto; | |
width: 1%; | |
min-width: 0; | |
} | |
// Bring the "active" form control to the top of surrounding elements | |
> .form-control:focus, | |
> .form-select:focus, | |
> .form-file .form-file-input:focus ~ .form-file-label { | |
z-index: 3; | |
} | |
// Bring the custom file input above the label | |
> .form-file { | |
> .form-file-input:focus { | |
z-index: 4; | |
} | |
&:not(:last-child) > .form-file-label { | |
border-right-radius: 0; | |
border-bottom-radius: 0; | |
} | |
&:not(:first-child) > .form-file-label { | |
border-left-radius: 0; | |
border-top-radius: 0; | |
} | |
} | |
.btn { | |
position: relative; | |
z-index: 2; | |
&:focus { | |
z-index: 3; | |
} | |
} | |
// Border-radius | |
> :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu), | |
> .dropdown-toggle:nth-last-child(n + 3) { | |
border-top-right-radius: 0; | |
border-bottom-right-radius: 0; | |
} | |
> :not(:first-child):not(.dropdown-menu) { | |
margin-left: -$input-border-width; | |
border-top-left-radius: 0; | |
border-bottom-left-radius: 0; | |
} | |
} | |
// Textual addons | |
.input-group-text { | |
display: flex; | |
align-items: center; | |
padding: $input-padding-y $input-padding-x; | |
font-size: $input-font-size; // Match inputs | |
font-weight: $font-weight-normal; | |
line-height: $input-line-height; | |
color: $input-group-addon-color; | |
text-align: center; | |
white-space: nowrap; | |
background-color: $input-group-addon-bg; | |
border: $input-border-width solid $input-border-color; | |
@include border-radius($input-border-radius); | |
} | |
// Prepend / append input group | |
.input-group-prepend, | |
.input-group-append { | |
display: flex; | |
.btn { | |
position: relative; | |
z-index: 2; | |
&:focus { | |
z-index: 3; | |
} | |
& + .btn, | |
& + .input-group-text { | |
margin-left: -$input-border-width; | |
} | |
} | |
.input-group-text + .input-group-text, | |
.input-group-text + .btn { | |
margin-left: -$input-border-width; | |
} | |
} | |
.input-group-prepend { margin-right: -$input-border-width; } | |
.input-group-append { margin-left: -$input-border-width; } | |
// Prepend and append rounded corners | |
.input-group > .input-group-prepend > .btn, | |
.input-group > .input-group-prepend > .input-group-text, | |
.input-group > .input-group-append:not(:last-child) > .btn, | |
.input-group > .input-group-append:not(:last-child) > .input-group-text, | |
.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle), | |
.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) { | |
border-top-right-radius: 0; | |
border-bottom-right-radius: 0; | |
} | |
.input-group > .input-group-append > .btn, | |
.input-group > .input-group-append > .input-group-text, | |
.input-group > .input-group-prepend:not(:first-child) > .btn, | |
.input-group > .input-group-prepend:not(:first-child) > .input-group-text, | |
.input-group > .input-group-prepend:first-child > .btn:not(:first-child), | |
.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) { | |
border-top-left-radius: 0; | |
border-bottom-left-radius: 0; | |
} | |
// Form | |
.form-inline { | |
display: flex; | |
flex-flow: row wrap; | |
align-items: center; | |
.form-check { | |
width: 100%; | |
} | |
} | |
// Form group | |
.form-group, fieldset { | |
position: relative; | |
margin-bottom: $form-group-margin-bottom; | |
} | |
// Form grid | |
.form-row { | |
display: flex; | |
flex-wrap: wrap; | |
margin-right: -$form-grid-gutter-width*.75; | |
margin-left: -$form-grid-gutter-width*.75; | |
> .col, | |
> [class*="col-"] { | |
padding-right: $form-grid-gutter-width*.75; | |
padding-left: $form-grid-gutter-width*.75; | |
} | |
} | |
/// Labels | |
.form-label { | |
margin-bottom: $form-label-margin-bottom; | |
font-size: inherit; | |
font-style: $form-label-font-style; | |
font-weight: $form-label-font-weight; | |
color: $form-label-color; | |
// Validation states | |
@at-root .has-error #{&} { | |
color: $danger; | |
font-weight: $font-weight-bold; | |
} | |
} | |
/// Button | |
.btn { | |
display: inline-block; | |
min-width: 1.25rem; | |
font-size: if($btn-uppercase, 0.85rem, 1rem); | |
font-weight: 600; | |
color: $gray-900; | |
text-align: center; | |
text-decoration: none; | |
text-transform: if($btn-uppercase, uppercase, none); | |
vertical-align: middle; | |
cursor: $cursor; | |
user-select: none; | |
background-color: $gray-200; | |
border: 1px solid transparent; | |
padding: 0.5em 0.75em; | |
line-height: 1.35; | |
border-radius: $border-radius; | |
transition: $btn-transition; | |
&::first-letter { | |
text-transform: uppercase; | |
} | |
&:hover { | |
text-decoration: none; | |
color: #fff; | |
background-color: darken($gray-200, 12%); | |
} | |
&.focus, &:focus, &:target { | |
outline: 0; | |
text-decoration: none; | |
box-shadow: 0 0 0 0.25rem rgba($gray-800, 0.1); | |
} | |
svg, .icon { | |
height: 1em; | |
margin: -.125em 0 0 0; | |
vertical-align: middle; | |
} | |
&.rounded-circle { | |
padding: .5rem .65rem !important; | |
} | |
&.rounded-pill { | |
padding: .5rem .85rem !important; | |
} | |
} | |
// Button theme colors | |
@each $name, $color in $theme-colors { | |
.btn-#{$name} { | |
color: contrast-color($color); | |
background-color: $color; | |
border-color: $color; | |
&:hover { | |
color: contrast-color($color); | |
background-color: darken($color, 12%); | |
border-color: $color; | |
} | |
&.focus, &:focus, &:target { | |
box-shadow: 0 0 0 0.25rem rgba($color, 0.2); | |
} | |
&:not(:disabled):not(.disabled).active, | |
&:not(:disabled):not(.disabled):active, | |
.show > &.dropdown-toggle { | |
color: contrast-color($color); | |
background-color: $color; | |
border-color: $color; | |
} | |
} | |
} | |
// Button outline | |
@each $name, $color in $theme-colors { | |
.btn-outline-#{$name} { | |
color: $color; | |
background-color: transparent; | |
border-color: $color!important; | |
&:hover { | |
color: contrast-color($color); | |
background-color: $color; | |
border-color: $color; | |
} | |
&.focus, &:focus, &:target { | |
box-shadow: 0 0 0 0.25rem rgba($color, 0.2); | |
} | |
&:not(:disabled):not(.disabled).active, | |
&:not(:disabled):not(.disabled):active, | |
.show > &.dropdown-toggle { | |
color: contrast-color($color); | |
background-color: darken($color, 12%); | |
border-color: $color; | |
} | |
} | |
} | |
/// Input group | |
.input-group { | |
position: relative; | |
display: flex; | |
flex-wrap: wrap; // For form validation feedback | |
align-items: stretch; | |
width: 100%; | |
> .form-control, | |
> .form-select, | |
> .form-file { | |
position: relative; // For focus state's z-index | |
flex: 1 1 auto; | |
width: 1%; | |
min-width: 0; | |
} | |
// Bring the "active" form control to the top of surrounding elements | |
> .form-control:focus, | |
> .form-select:focus, | |
> .form-file .form-file-input:focus ~ .form-file-label { | |
z-index: 3; | |
} | |
// Bring the custom file input above the label | |
> .form-file { | |
> .form-file-input:focus { | |
z-index: 4; | |
} | |
&:not(:last-child) > .form-file-label { | |
border-right-radius: 0; | |
border-bottom-radius: 0; | |
} | |
&:not(:first-child) > .form-file-label { | |
border-left-radius: 0; | |
border-top-radius: 0; | |
} | |
} | |
// Ensure buttons are always above inputs for more visually pleasing borders. | |
.btn { | |
position: relative; | |
z-index: 2; | |
&:focus { | |
z-index: 3; | |
} | |
} | |
// Rounded corners | |
> :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu), | |
> .dropdown-toggle:nth-last-child(n + 3) { | |
border-right-radius: 0; | |
border-bottom-radius: 0; | |
} | |
> :not(:first-child):not(.dropdown-menu) { | |
margin-left: -$input-border-width; | |
border-left-radius: 0; | |
border-top-radius: 0; | |
} | |
} | |
/// Card | |
.card { | |
position: relative; | |
display: flex; | |
flex-direction: column; | |
min-width: 0; | |
word-wrap: break-word; | |
background-color: $card-bg; | |
@include dark-scheme() { | |
background-color: $card-dark-bg; | |
} | |
background-clip: border-box; | |
border: 1px solid rgba(222, 226, 230, 0.5); | |
border-radius: 0.3rem; | |
transition: border .15s linear, | |
box-shadow .15s ease-in-out; | |
&:hover { | |
border-color: #dee2e6; | |
box-shadow: $shadow-elevated; | |
} | |
} | |
.card-img, .card-img-bottom, .card-img-top { | |
flex-shrink: 0; | |
width: 100%; | |
} | |
.card-img, .card-img-top { | |
border-top-left-radius: calc(0.3rem - 1px); | |
border-top-right-radius: calc(0.3rem - 1px); | |
} | |
.card-body { | |
flex: 1 1 auto; | |
min-height: 1px; | |
padding: 1.25rem; | |
} | |
.card-title { | |
margin-bottom: .75rem; | |
} | |
.card-text:last-child { | |
margin-bottom: 0; | |
} | |
// Card colums | |
.card-columns .card { | |
margin-bottom: 1.5rem; | |
column-break-inside: avoid; | |
} | |
@include breakpoint-up("sm") { | |
.card-columns { | |
column-count: 2; | |
column-gap: 1rem; | |
orphans: 1; | |
widows: 1; | |
} | |
.card-columns .card { | |
width: 100%; | |
} | |
} | |
@include breakpoint-up("md") { | |
.card-columns { | |
column-count: 3; | |
column-gap: 1.5rem; | |
orphans: 1; | |
widows: 1; | |
} | |
} | |
// Cards deck | |
@include breakpoint-up("sm") { | |
.card-deck { | |
display: flex; | |
flex-flow: row wrap; | |
margin-right: -1rem; | |
margin-left: -1rem; | |
} | |
} | |
/// Badge class | |
.badge { | |
display: inline-block; | |
padding: .25em .5em; | |
font-size: 0.75rem; | |
font-weight: bold; | |
line-height: 1; | |
color: $warning; | |
text-align: center; | |
white-space: nowrap; | |
vertical-align: baseline; | |
border-radius: $border-radius/2; | |
@include transition($transition-base); | |
@at-root a#{&} { | |
&:focus, &:hover { | |
text-decoration: none; | |
} | |
} | |
@at-root .btn #{&}{ | |
position: relative; | |
top: -1px; | |
} | |
&:empty { | |
display: none; | |
} | |
} | |
// Pill | |
.badge-pill { | |
padding-right: .75em; | |
padding-left: .75em; | |
border-radius: .75em; | |
} | |
// Circle | |
.badge-circle { | |
letter-spacing: -.05em; | |
padding: .25em 0; | |
width: 1.5em; | |
height: 1.5em; | |
border-radius: 0.75em; | |
} | |
// Colors | |
@each $color, $value in $theme-colors { | |
.badge-#{$color} { | |
color: contrast-color($value); | |
background-color: $value; | |
@at-root a#{&} { | |
&:hover, &:focus{ | |
color: contrast-color($value); | |
background-color: darken($value, 10%); | |
} | |
&:focus, | |
&.focus { | |
outline: 0; | |
box-shadow: 0 0 0 .25em rgba($value, .5); | |
} | |
} | |
} | |
} | |
// Nav | |
.nav { | |
width: 100%; | |
display: flex; | |
overflow: auto; | |
list-style: none; | |
} | |
// Tab / tablist | |
.tab-list { | |
position: relative; | |
overflow: auto; | |
overflow-y: hidden; | |
overflow-x: hidden; | |
white-space: nowrap; | |
border-bottom: 1px solid #dee2e6; | |
box-shadow: 0 0.25em 0 0.25em rgba(222, 226, 230, 0.25); | |
padding: 0; | |
.indicator { | |
position: absolute; | |
bottom: 0; | |
left: 0; | |
height: 2.5px; | |
width: 0; | |
background: #007bff; | |
will-change: left, width; | |
transition: left .25s ease-out, width .1s linear; | |
z-index: 1; | |
} | |
[role="tab"] { | |
outline: 0; | |
font-size: 0.75em; | |
font-weight: normal; | |
line-height: 1.5; | |
letter-spacing: 0.09em; | |
text-decoration: none; | |
text-transform: uppercase; | |
vertical-align: middle; | |
display: inline-block; | |
margin: 0; | |
padding: 1rem; | |
transition: background-color .3s ease; | |
&:hover { | |
background-color: rgba(222, 226, 230, 0.25); | |
color: #212529; | |
} | |
&:focus, &:active { | |
background-color: rgba(222, 226, 230, 0.75); | |
} | |
&.active { | |
color: $primary; | |
background-color: rgba(222, 226, 230, 0.15); | |
} | |
} | |
} | |
.tabs { | |
width: 100%; | |
position: relative; | |
overflow: hidden; | |
.tab-panel { | |
width: 100%; | |
outline: none; | |
display: none; | |
opacity: 1; | |
will-change: translate; | |
transform: translateX(-100%); | |
&.active, &:target { | |
display: inline-block; | |
transform: translateX(0%); | |
} | |
&.fade { | |
transition: opacity .15s linear; | |
} | |
&.fade:not(.show) { | |
opacity: 0; | |
} | |
&.slide { | |
transition: transform .15s linear, opacity .1s linear; | |
&:not(.show) { | |
transform: translateX(100%); | |
} | |
&.slide-before:not(.show) { | |
transform: translateX(-100%); | |
} | |
} | |
} | |
} | |
// Drawer | |
.drawer { | |
position: absolute; | |
display: inline-block; | |
overflow: visible; | |
will-change: left, width; | |
transition: .2s; | |
background-color: $drawer-bg; | |
@include dark-scheme() { | |
background-color: $drawer-dark-bg; | |
} | |
z-index: $zindex-drawer; | |
@include breakpoint-down("xs") { | |
width: 100% !important; | |
} | |
&:not(.show) { | |
display: none; | |
} | |
&::before { | |
content: none; | |
opacity: 0; | |
visibility: hidden; | |
will-change: opacity; | |
-webkit-transition: opacity .3s linear; | |
transition: opacity .3s linear; | |
} | |
@include breakpoint-down("md") { | |
&::before { | |
position: fixed; | |
content: ''; | |
top: 0; | |
bottom: 0; | |
left: 100%; | |
right: -100%; | |
display: inline-block; | |
width: 100%; | |
opacity: 1; | |
visibility: visible; | |
background: $backdrop-bg; | |
pointer-events: all; | |
} | |
} | |
.close { | |
position: absolute; | |
top: 1rem; | |
right: .5rem; | |
} | |
.drawer-header, .drawer-body, .drawer-footer { | |
padding: 1rem; | |
} | |
.drawer-header { | |
line-height: 2; | |
} | |
.drawer-header h4 { | |
margin: 0; | |
padding: 0; | |
} | |
} | |
// Dropdown | |
.dropdown { | |
position: relative; | |
z-index: $zindex-dropdown; | |
&.dropup .caret:empty::before { | |
top: 0.3em; | |
transform: rotate(-135deg); | |
} | |
} | |
.dropdown-menu { | |
position: absolute; | |
top: 0; | |
left: 0; | |
display: none; | |
overflow: hidden; | |
float: left; | |
min-width: 10rem; | |
font-size: 1rem; | |
text-align: left; | |
list-style: none; | |
background-color: $dropdown-bg; | |
@include dark-scheme() { | |
background-color: $dropdown-dark-bg; | |
} | |
background-clip: padding-box; | |
border: 1px solid rgba($gray-500, 0.1); | |
border-radius: .25rem; | |
will-change: top, left; | |
box-shadow: $shadow-elevated; | |
z-index: $zindex-dropdown + 1; | |
&.show { | |
display: block; | |
} | |
[role="menuitem"] { | |
display: block; | |
width: 100%; | |
padding: .75rem 1.5rem; | |
clear: both; | |
font-weight: normal; | |
text-align: inherit; | |
text-decoration: none; | |
white-space: nowrap; | |
text-overflow: ellipsis; | |
background-color: transparent; | |
border: 0; | |
will-change: background; | |
transition: background .15s linear; | |
&:hover { | |
text-decoration: none; | |
background-color: rgba($gray-500, 0.1); | |
} | |
&.active, &:focus, &:active { | |
outline: none; | |
color: #fff; | |
text-decoration: none!important; | |
background-color: $primary; | |
} | |
} | |
h6, .header { | |
display: block; | |
padding: .75rem 1rem; | |
margin: 0; | |
font-size: .875rem; | |
color: $gray-600; | |
white-space: nowrap; | |
} | |
.divider { | |
height: 0; | |
margin: .5rem 0; | |
overflow: hidden; | |
border-top: 1px solid rgba($gray-500, 0.5); | |
} | |
} | |
// Modal | |
.modal-open { | |
overflow: hidden; | |
} | |
.modal { | |
position: fixed; | |
display: inline-block; | |
top: 0; | |
left: 0; | |
width: 100vw; | |
height: 100vh; | |
font-size: 1rem; | |
background: transparent; | |
transition: opacity .5s ease; | |
user-select: none; | |
opacity: 0; | |
visibility: hidden; | |
z-index: $zindex-modal; | |
&:focus { | |
outline: 0; | |
} | |
&.show { | |
background: $backdrop-bg; | |
visibility: visible; | |
opacity: 1; | |
& .modal-dialog { | |
transition-delay: .25s; | |
opacity: 1; | |
visibility: visible; | |
transform: scale(1) translate(-50%, -50%); | |
} | |
} | |
&.modal-static { | |
cursor: not-allowed; | |
& .modal-dialog { | |
perspective: 1000px; | |
animation: wobble 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; | |
transform: scale(1) translate(-50%, -50%); | |
backface-visibility: hidden; | |
} | |
} | |
} | |
.modal-dialog { | |
position: absolute; | |
left: 50%; | |
top: 50%; | |
display: block; | |
width: 20em; | |
max-height: 95%; | |
background-color: $modal-bg; | |
@include dark-scheme() { | |
background-color: $modal-dark-bg; | |
} | |
border-radius: $border-radius; | |
box-shadow: $shadow-elevated; | |
z-index: $zindex-modal + 1; | |
pointer-events: all; | |
transform-origin: left top; | |
transform: scale(0) translate(-50%, -50%); | |
transition: .15s ease-in; | |
opacity: 0; | |
visibility: hidden; | |
@include breakpoint-down("xs") { | |
width: calc(100% - 2rem); | |
} | |
.modal-content { | |
position: relative; | |
display: inline-block; | |
text-align: center; | |
height: 100%; | |
width: 100%; | |
} | |
.modal-header, .modal-body, .modal-footer { | |
position: relative; | |
padding: $spacer; | |
} | |
.modal-header { | |
line-height: 1.2rem; | |
h3 { | |
overflow: hidden; | |
text-overflow: ellipsis; | |
white-space: nowrap; | |
padding: 0; | |
margin: 0; | |
&:first-letter { | |
text-transform: uppercase; | |
} | |
} | |
.close { | |
position: absolute; | |
top: .5em; | |
right: .5em; | |
} | |
} | |
.modal-body { | |
display: block; | |
bottom: 0; | |
max-height: calc(95vh - 6.4rem); | |
width: 100%; | |
word-break: break-all; | |
overflow: hidden; | |
overflow-y: auto; | |
} | |
.modal-footer { | |
display: inline-block; | |
width: 100%; | |
bottom: 0; | |
text-align: center; | |
button{ | |
&:only-child { | |
float: none; | |
} | |
&:nth-child(2) { | |
float: right; | |
} | |
} | |
} | |
// Overwritten js ui-dialogs | |
&.ui-dialog { | |
.modal-body { | |
padding-bottom: 2rem; | |
& > input { | |
width: 100%; | |
margin: 1rem 0 0 0; | |
font: inherit; | |
padding: .5em .75em; | |
border-radius: 0.15rem; | |
border: 1px solid #dee2e6; | |
transition: .2s; | |
cursor: default; | |
&:focus { | |
outline: none; | |
box-shadow: 0 0 0 0.25em rgba(222, 226, 230, 0.75); | |
} | |
&::placeholder { | |
opacity: 0.5; | |
} | |
} | |
& > label { | |
position: relative; | |
font: inherit; | |
} | |
&:first-letter { | |
text-transform: uppercase; | |
} | |
} | |
.modal-footer { | |
padding: 0; | |
margin: 0; | |
white-space: nowrap; | |
button { | |
position: relative; | |
margin: 0; | |
width: 50%; | |
padding: 1rem .5rem; | |
white-space: nowrap; | |
overflow: hidden; | |
background: transparent; | |
text-overflow: ellipsis; | |
font-family: inherit; | |
font-size: 1rem; | |
line-height: 1.2; | |
font-weight: bolder; | |
color: $primary; | |
border: 0; | |
border-top: 1px solid $gray-300; | |
cursor: pointer; | |
z-index: 0; | |
transition: all .15s ease; | |
&:hover, &:focus { | |
font-weight: bolder; | |
background: rgba(127, 127, 127, 0.15); | |
} | |
&:focus { | |
border-top-color: $gray-300; | |
outline: 0; | |
box-shadow: none; | |
z-index: 3; | |
} | |
&:active { | |
background: rgba(127, 127, 127, 0.3); | |
} | |
&:first-child { | |
border-radius: 0 0 0 $border-radius; | |
font-weight: normal; | |
} | |
&:last-child { | |
border-radius: 0 0 $border-radius 0; | |
border-left: 1px solid $gray-300; | |
} | |
&:only-child { | |
width: 100%; | |
font-weight: bolder; | |
border-left: 0; | |
border-radius: 0 0 $border-radius $border-radius; | |
} | |
&:first-letter { | |
text-transform: uppercase; | |
} | |
} | |
} | |
} | |
} | |
// Notifications | |
.ui-notifications { | |
position: fixed; | |
right: 0; | |
bottom: 0; | |
width: 100%; | |
height: auto; | |
max-width: 25rem; | |
overflow: visible; | |
display: inline-block; | |
padding: 1em; | |
font-size: 1rem; | |
background: transparent; | |
user-select: none; | |
z-index: $zindex-note; | |
counter-reset: notifications; | |
&:focus { | |
outline: 0; | |
} | |
.note { | |
position: relative; | |
background-color: $note-bg; | |
@include dark-scheme() { | |
background-color: $note-dark-bg; | |
} | |
display: block; | |
overflow: hidden; | |
width: 100%; | |
margin: 0 0 1em 0; | |
padding: 0; | |
text-align: left; | |
border-radius: $border-radius; | |
box-shadow: $shadow; | |
transform-origin: left center; | |
transform: scale(0.95) translateX(100%); | |
opacity: 0; | |
visibility: hidden; | |
counter-increment: notifications; | |
transition: .2s; | |
&:focus { | |
outline: none; | |
} | |
&:hover .progress i { | |
animation-play-state: paused; | |
} | |
&:last-child, &:only-child { | |
margin-bottom: 0; | |
} | |
&.show { | |
transform: scale(1) translateX(0%); | |
opacity: 1; | |
visibility: visible; | |
} | |
time { | |
position: absolute; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
text-align: right; | |
display: block; | |
padding: .5rem .75rem; | |
line-height: 1.5; | |
font-size: 0.6em; | |
cursor: default; | |
} | |
figure { | |
position: absolute; | |
max-width: 4em; | |
height: 100%; | |
margin: 0; | |
padding: 0; | |
color: #007bff; | |
text-align: right; | |
z-index: 1; | |
svg { | |
top: 25%; | |
position: relative; | |
width: 70%; | |
fill: currentColor; | |
} | |
img { | |
position: relative; | |
width: 100%; | |
} | |
& + p { | |
margin-left: 4em; | |
} | |
} | |
p { | |
display: block; | |
margin: 0; | |
padding: 1em 1em 2em 1em; | |
z-index: 2; | |
b { | |
display: block; | |
&:first-letter { | |
text-transform: uppercase; | |
} | |
} | |
&:first-letter { | |
text-transform: uppercase; | |
} | |
} | |
.close { | |
position: absolute; | |
top: .25rem; | |
right: .25rem; | |
z-index: 3; | |
font-size: 0.8em; | |
&:hover, &:focus { | |
background: #007bff; | |
color: #FFF; | |
outline: none; | |
} | |
} | |
.progress { | |
position: absolute; | |
bottom: 0; | |
display: block; | |
left: 0; | |
width: 100%; | |
height: 3px; | |
color: #007bff; | |
background: rgba(127, 127, 127, 0.1); | |
i { | |
position: absolute; | |
left: 0; | |
display: inline-block; | |
height: 100%; | |
width: 0; | |
background: currentColor; | |
animation-play-state: play; | |
animation: progress 15s linear forwards; | |
} | |
} | |
} | |
@include breakpoint-down("sm") { | |
left: 0; | |
min-width: 100%; | |
padding: 0; | |
&::before { | |
position: fixed; | |
content: ''; | |
top: 0; | |
bottom: 0; | |
left: 0; | |
display: inline-block; | |
width: 100%; | |
opacity: 0; | |
visibility: hidden; | |
background: $backdrop-bg; | |
pointer-events: none; | |
will-change: opacity; | |
transition: opacity .3s linear; | |
} | |
&:hover, &.hover { | |
&::before { | |
visibility: visible; | |
opacity: 1; | |
} | |
.note { | |
border-radius: 0; | |
position: relative; | |
float: left; | |
box-shadow: none; | |
opacity: 0; | |
transform-origin: top center; | |
transform: scale(0.95) translateY(-1em); | |
&:first-child { | |
opacity: 1; | |
transform: scale(1) translateY(0); | |
transition-delay: .1s; | |
} | |
&:nth-child(1n+2) { | |
opacity: 1; | |
transform: scale(1) translateY(0); | |
transition-delay: .1s; | |
} | |
&:nth-child(1n+3) { | |
visibility: visible; | |
transition-delay: .2s; | |
} | |
&:last-child { | |
transition: none; | |
} | |
} | |
} | |
.note { | |
position: absolute; | |
bottom: 0; | |
display: block; | |
width: 100%; | |
margin: 0; | |
transform-origin: bottom center; | |
transform: scale(1) translateY(-100%); | |
&.show { | |
transform: scale(1) translateY(0%); | |
} | |
&:first-child { | |
transform: scale(1) translateY(0%); | |
border-radius: 0; | |
z-index: 3; | |
} | |
&:nth-child(1n+2) { | |
transform: scale(0.95) translateY(-1em); | |
z-index: 2; | |
} | |
&:nth-child(1n+3) { | |
opacity: 0; | |
visibility: hidden; | |
} | |
} | |
} | |
} | |
// Tooltip | |
.ui-tooltip { | |
position: absolute; | |
background: $tooltip-bg; | |
border-radius: 0.25em; | |
padding: 0.5em 1em; | |
font-size: 0.8rem; | |
color: #fff; | |
overflow: visible; | |
white-space: nowrap; | |
font-style: normal; | |
text-overflow: ellipsis; | |
opacity: 1; | |
vertical-align: middle; | |
pointer-events: none; | |
visibility: visible; | |
transform: scale(1); | |
transform-origin: center bottom; | |
transition: transform 0.1s linear 0.25s, | |
opacity 0.05s ease-in-out 0.25s; | |
&:first-letter { | |
text-transform: uppercase; | |
} | |
.indicator { | |
position: absolute; | |
display: inline-block; | |
bottom: -0.5em; | |
left: calc(50% - 0.5em); | |
width: 0; | |
height: 0; | |
color: rgba(0, 0, 0, 0.7); | |
border: 0.5em solid transparent; | |
border-bottom: 0; | |
border-top: 0.5em solid currentColor; | |
} | |
&.bottom .indicator { | |
top: -0.5em; | |
bottom: auto; | |
border: 0.5em solid transparent; | |
border-top: 0; | |
border-bottom: 0.5em solid currentColor; | |
} | |
&.left .indicator, &.right .indicator { | |
bottom: auto; | |
left: auto; | |
top: calc(50% - 0.5em); | |
border: 0.5em solid transparent; | |
} | |
&.left .indicator { | |
right: -0.5em; | |
border-right: 0; | |
border-left: 0.5em solid currentColor; | |
} | |
&.right .indicator { | |
left: -0.5em; | |
border-left: 0; | |
border-right: 0.5em solid currentColor; | |
} | |
&[aria-hidden='true'] { | |
opacity: 0; | |
visibility: hidden; | |
transform: scale(0.5); | |
} | |
} | |
// Toast | |
#ui-toast { | |
position: absolute; | |
left: 50%; | |
bottom: 3em; | |
right: auto; | |
top: auto; | |
display: inline-block; | |
overflow: hidden; | |
width: auto; | |
max-width: 25rem; | |
height: 3em; | |
padding: 0 1.5em; | |
font-size: .85rem; | |
line-height: 3; | |
text-align: center; | |
white-space: nowrap; | |
text-overflow: ellipsis; | |
font-style: normal; | |
color: #fff; | |
border-radius: 1.5em; | |
background-color: $toast-bg; | |
opacity: 0; | |
visibility: hidden; | |
transform: translate(-50%, 300%); | |
will-change: transform, opacity; | |
transition: opacity .3s ease-in, transform .5s ease-in-out; | |
cursor: $cursor; | |
z-index: $zindex-toast; | |
@include breakpoint-down("sm") { | |
font-size: .75rem; | |
} | |
&:first-letter { | |
text-transform: uppercase; | |
} | |
&.visible { | |
opacity: 1; | |
visibility: visible; | |
transform: translate(-50%, 0%); | |
} | |
&.error, &.success, &.warning { | |
padding: 0 1.5em 0 3em; | |
&::before, &::after { | |
content: ''; | |
display: block; | |
position: absolute; | |
left: 1.25em; | |
top: 1.5em; | |
width: 1em; | |
height: .15em; | |
transform: rotate(-45deg); | |
background-color: #FFF; | |
} | |
&::before { | |
transform: rotate(45deg); | |
width: .5em; | |
} | |
} | |
&.error::before { | |
width: 1em; | |
} | |
&.success::before { | |
left: 1em; | |
top: 1.65em; | |
} | |
&.warning{ | |
&::before { | |
left: 0.95em; | |
top: .15em; | |
width: 0; | |
height: 0; | |
transform: none; | |
background: transparent; | |
border-radius: .15em; | |
border: .7em solid transparent; | |
border-bottom: 1.2em solid $white; | |
} | |
&::after { | |
transform: none; | |
content: '!'; | |
top: 0; | |
left: 1.15em; | |
text-align: center; | |
font-weight: 700; | |
background: transparent; | |
color: rgba($black, 0.7); | |
} | |
} | |
&.closing { | |
opacity: 0; | |
transform: translate(-50%, 300%); | |
} | |
} | |
// Ripple effect | |
.ripple { | |
position: relative; | |
overflow: hidden; | |
.ink { | |
display: block; | |
position: absolute; | |
pointer-events: none; | |
border-radius: 50%; | |
transform: scale(0); | |
background: $gray-700; | |
opacity: 1; | |
&.animating { | |
width: 1px; | |
height: 1px; | |
animation: ripple .5s linear; | |
z-index: 1; | |
} | |
} | |
} | |
// Animations | |
@keyframes ripple { | |
100% { opacity: 0; transform: scale(2.5); } | |
} | |
@keyframes wobble { | |
10%, 90% { transform: translate(-51%, -50%); } | |
20%, 80% { transform: translate(-48%, -50%); } | |
30%, 50%, 70% { transform: translate(-54%, -50%); } | |
40%, 60% { transform: translate(-46%, -50%); } | |
} | |
@keyframes scale { | |
from { transform: scale(0) translate(-50%, -50%); } | |
to { transform: scale(1) translate(-50%, -50%); } | |
} | |
@keyframes progress { | |
from { width: 0%;} | |
to { width: 100%;} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment