├── .gitignore ├── .prettierrc ├── LICENCE ├── README.md ├── demo ├── assets │ ├── css │ │ ├── fontawesome-all.min.css │ │ └── main.css │ ├── js │ │ ├── breakpoints.min.js │ │ ├── browser.min.js │ │ ├── index.js │ │ ├── jquery.min.js │ │ ├── main.js │ │ └── util.js │ ├── sass │ │ ├── base │ │ │ ├── _page.scss │ │ │ ├── _reset.scss │ │ │ └── _typography.scss │ │ ├── components │ │ │ ├── _actions.scss │ │ │ ├── _box.scss │ │ │ ├── _button.scss │ │ │ ├── _contact.scss │ │ │ ├── _features.scss │ │ │ ├── _form.scss │ │ │ ├── _icon.scss │ │ │ ├── _icons.scss │ │ │ ├── _image.scss │ │ │ ├── _list.scss │ │ │ ├── _mini-posts.scss │ │ │ ├── _pagination.scss │ │ │ ├── _posts.scss │ │ │ ├── _row.scss │ │ │ ├── _section.scss │ │ │ └── _table.scss │ │ ├── layout │ │ │ ├── _banner.scss │ │ │ ├── _footer.scss │ │ │ ├── _header.scss │ │ │ ├── _main.scss │ │ │ ├── _menu.scss │ │ │ ├── _sidebar.scss │ │ │ └── _wrapper.scss │ │ ├── libs │ │ │ ├── _breakpoints.scss │ │ │ ├── _functions.scss │ │ │ ├── _html-grid.scss │ │ │ ├── _mixins.scss │ │ │ ├── _vars.scss │ │ │ └── _vendor.scss │ │ └── main.scss │ └── webfonts │ │ ├── fa-brands-400.eot │ │ ├── fa-brands-400.svg │ │ ├── fa-brands-400.ttf │ │ ├── fa-brands-400.woff │ │ ├── fa-brands-400.woff2 │ │ ├── fa-regular-400.eot │ │ ├── fa-regular-400.svg │ │ ├── fa-regular-400.ttf │ │ ├── fa-regular-400.woff │ │ ├── fa-regular-400.woff2 │ │ ├── fa-solid-900.eot │ │ ├── fa-solid-900.svg │ │ ├── fa-solid-900.ttf │ │ ├── fa-solid-900.woff │ │ └── fa-solid-900.woff2 ├── elements.html ├── generic.html ├── images │ ├── pic01.jpg │ ├── pic02.jpg │ ├── pic03.jpg │ ├── pic04.jpg │ ├── pic05.jpg │ ├── pic06.jpg │ ├── pic07.jpg │ ├── pic08.jpg │ ├── pic09.jpg │ ├── pic10.jpg │ └── pic11.jpg └── index.html ├── package-lock.json ├── package.json ├── postcss.config.cjs ├── src ├── index.js ├── style.css └── template.js └── vite.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist-ssr 12 | *.local 13 | 14 | # Editor directories and files 15 | .vscode/* 16 | !.vscode/extensions.json 17 | .idea 18 | .DS_Store 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | dist -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "printWidth": 120 4 | } 5 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 CMarghin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # theme-toggle 2 | 3 | [![npm version](https://badge.fury.io/js/theme-toggle.svg)](https://badge.fury.io/js/theme-toggle) 4 | 5 | > **theme-toggle** is a simple component that can help you add different themes to your web app. 6 | 7 | it uses css `invert()` and `hue-rotate()` functions to change the look of your entire html document so It may gives unexpected changes .. in the next version there will be some more customization 8 | 9 | The theme switcher icon is used from [Adam Argyle](https://twitter.com/argyleink)'s [Article](https://web.dev/building-a-theme-switch-component/) 10 | 11 | - [**Demo**](https://gui-challenges.web.app/theme-switch/dist/) of icon 12 | 13 | ## Getting started 14 | 15 | This is a simple custom component, you only need to import it (or bu using external link), and add `` custom element where you want to see the toggle button 16 | 17 | ## installation 18 | 19 | ### npm 20 | 21 | you can Install it via npm 22 | 23 | ```shell 24 | npm install theme-toggle 25 | ``` 26 | 27 | then import it 28 | 29 | ```jsx 30 | import "theme-toggle"; 31 | ``` 32 | 33 | now you can use the `` custom element wherever you want 34 | 35 | > `` doesn't have any children element's 36 | > 37 | > `theme` attribute is required, you can see attributes table below 38 | 39 | ### cdn 40 | 41 | you can also use a cdn link to use `theme-toggle` in your project 42 | 43 | ```html 44 | 45 | ``` 46 | 47 | ## Settings 48 | 49 | you can use some custom changes to change the default behavior of `theme-toggle`, we are working on adding more customization later 50 | 51 | | Attribute | Values | Required | default | example | 52 | | :-------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------: | :-----: | :------------------------------------------------------------: | 53 | | theme | sets the initial theme of your page, and the correct theme icon, there are 2 available values
- _dark_: sets the initial theme to dark, and theme-icon to light
- _light_: sets the initial theme to light, and theme-icon to dark | `YES` | - | `` | 54 | | width | you con control the square container's width using this attribute, it takes number string, do not add units .. by default it uses `px` | `NO` | `2rem` | `` | 55 | | storable | this attributes controls if the current theme is stored so when you refresh the page it loads the last used theme, the theme is storable by default and it accepts 2 different values, `true` or `false` | `NO` | `true` | `` | 56 | 57 | ## Contributing 58 | 59 | This tools needs a lot of contribution, and it's open for contributing :) 60 | 61 | 1. Fork it! 62 | 2. Create your feature branch: `git checkout -b my-new-feature` 63 | 3. Add your changes: `git add .` 64 | 4. Commit your changes: `git commit -am 'Add some feature'` 65 | 5. Push to the branch: `git push origin my-new-feature` 66 | 6. Submit a pull request :sunglasses: 67 | -------------------------------------------------------------------------------- /demo/assets/js/breakpoints.min.js: -------------------------------------------------------------------------------- 1 | /* breakpoints.js v1.0 | @ajlkn | MIT licensed */ 2 | var breakpoints=function(){"use strict";function e(e){t.init(e)}var t={list:null,media:{},events:[],init:function(e){t.list=e,window.addEventListener("resize",t.poll),window.addEventListener("orientationchange",t.poll),window.addEventListener("load",t.poll),window.addEventListener("fullscreenchange",t.poll)},active:function(e){var n,a,s,i,r,d,c;if(!(e in t.media)){if(">="==e.substr(0,2)?(a="gte",n=e.substr(2)):"<="==e.substr(0,2)?(a="lte",n=e.substr(2)):">"==e.substr(0,1)?(a="gt",n=e.substr(1)):"<"==e.substr(0,1)?(a="lt",n=e.substr(1)):"!"==e.substr(0,1)?(a="not",n=e.substr(1)):(a="eq",n=e),n&&n in t.list)if(i=t.list[n],Array.isArray(i)){if(r=parseInt(i[0]),d=parseInt(i[1]),isNaN(r)){if(isNaN(d))return;c=i[1].substr(String(d).length)}else c=i[0].substr(String(r).length);if(isNaN(r))switch(a){case"gte":s="screen";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: -1px)";break;case"not":s="screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (max-width: "+d+c+")"}else if(isNaN(d))switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen";break;case"gt":s="screen and (max-width: -1px)";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+")";break;default:s="screen and (min-width: "+r+c+")"}else switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+"), screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (min-width: "+r+c+") and (max-width: "+d+c+")"}}else s="("==i.charAt(0)?"screen and "+i:i;t.media[e]=!!s&&s}return t.media[e]!==!1&&window.matchMedia(t.media[e]).matches},on:function(e,n){t.events.push({query:e,handler:n,state:!1}),t.active(e)&&n()},poll:function(){var e,n;for(e=0;elarge', function() { 82 | $sidebar.removeClass('inactive'); 83 | }); 84 | 85 | // Hack: Workaround for Chrome/Android scrollbar position bug. 86 | if (browser.os == 'android' 87 | && browser.name == 'chrome') 88 | $('') 89 | .appendTo($head); 90 | 91 | // Toggle. 92 | $('Toggle') 93 | .appendTo($sidebar) 94 | .on('click', function(event) { 95 | 96 | // Prevent default. 97 | event.preventDefault(); 98 | event.stopPropagation(); 99 | 100 | // Toggle. 101 | $sidebar.toggleClass('inactive'); 102 | 103 | }); 104 | 105 | // Events. 106 | 107 | // Link clicks. 108 | $sidebar.on('click', 'a', function(event) { 109 | 110 | // >large? Bail. 111 | if (breakpoints.active('>large')) 112 | return; 113 | 114 | // Vars. 115 | var $a = $(this), 116 | href = $a.attr('href'), 117 | target = $a.attr('target'); 118 | 119 | // Prevent default. 120 | event.preventDefault(); 121 | event.stopPropagation(); 122 | 123 | // Check URL. 124 | if (!href || href == '#' || href == '') 125 | return; 126 | 127 | // Hide sidebar. 128 | $sidebar.addClass('inactive'); 129 | 130 | // Redirect to href. 131 | setTimeout(function() { 132 | 133 | if (target == '_blank') 134 | window.open(href); 135 | else 136 | window.location.href = href; 137 | 138 | }, 500); 139 | 140 | }); 141 | 142 | // Prevent certain events inside the panel from bubbling. 143 | $sidebar.on('click touchend touchstart touchmove', function(event) { 144 | 145 | // >large? Bail. 146 | if (breakpoints.active('>large')) 147 | return; 148 | 149 | // Prevent propagation. 150 | event.stopPropagation(); 151 | 152 | }); 153 | 154 | // Hide panel on body click/tap. 155 | $body.on('click touchend', function(event) { 156 | 157 | // >large? Bail. 158 | if (breakpoints.active('>large')) 159 | return; 160 | 161 | // Deactivate. 162 | $sidebar.addClass('inactive'); 163 | 164 | }); 165 | 166 | // Scroll lock. 167 | // Note: If you do anything to change the height of the sidebar's content, be sure to 168 | // trigger 'resize.sidebar-lock' on $window so stuff doesn't get out of sync. 169 | 170 | $window.on('load.sidebar-lock', function() { 171 | 172 | var sh, wh, st; 173 | 174 | // Reset scroll position to 0 if it's 1. 175 | if ($window.scrollTop() == 1) 176 | $window.scrollTop(0); 177 | 178 | $window 179 | .on('scroll.sidebar-lock', function() { 180 | 181 | var x, y; 182 | 183 | // <=large? Bail. 184 | if (breakpoints.active('<=large')) { 185 | 186 | $sidebar_inner 187 | .data('locked', 0) 188 | .css('position', '') 189 | .css('top', ''); 190 | 191 | return; 192 | 193 | } 194 | 195 | // Calculate positions. 196 | x = Math.max(sh - wh, 0); 197 | y = Math.max(0, $window.scrollTop() - x); 198 | 199 | // Lock/unlock. 200 | if ($sidebar_inner.data('locked') == 1) { 201 | 202 | if (y <= 0) 203 | $sidebar_inner 204 | .data('locked', 0) 205 | .css('position', '') 206 | .css('top', ''); 207 | else 208 | $sidebar_inner 209 | .css('top', -1 * x); 210 | 211 | } 212 | else { 213 | 214 | if (y > 0) 215 | $sidebar_inner 216 | .data('locked', 1) 217 | .css('position', 'fixed') 218 | .css('top', -1 * x); 219 | 220 | } 221 | 222 | }) 223 | .on('resize.sidebar-lock', function() { 224 | 225 | // Calculate heights. 226 | wh = $window.height(); 227 | sh = $sidebar_inner.outerHeight() + 30; 228 | 229 | // Trigger scroll. 230 | $window.trigger('scroll.sidebar-lock'); 231 | 232 | }) 233 | .trigger('resize.sidebar-lock'); 234 | 235 | }); 236 | 237 | // Menu. 238 | var $menu = $('#menu'), 239 | $menu_openers = $menu.children('ul').find('.opener'); 240 | 241 | // Openers. 242 | $menu_openers.each(function() { 243 | 244 | var $this = $(this); 245 | 246 | $this.on('click', function(event) { 247 | 248 | // Prevent default. 249 | event.preventDefault(); 250 | 251 | // Toggle. 252 | $menu_openers.not($this).removeClass('active'); 253 | $this.toggleClass('active'); 254 | 255 | // Trigger resize (sidebar lock). 256 | $window.triggerHandler('resize.sidebar-lock'); 257 | 258 | }); 259 | 260 | }); 261 | 262 | })(jQuery); -------------------------------------------------------------------------------- /demo/assets/js/util.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | 3 | /** 4 | * Generate an indented list of links from a nav. Meant for use with panel(). 5 | * @return {jQuery} jQuery object. 6 | */ 7 | $.fn.navList = function() { 8 | 9 | var $this = $(this); 10 | $a = $this.find('a'), 11 | b = []; 12 | 13 | $a.each(function() { 14 | 15 | var $this = $(this), 16 | indent = Math.max(0, $this.parents('li').length - 1), 17 | href = $this.attr('href'), 18 | target = $this.attr('target'); 19 | 20 | b.push( 21 | '' + 26 | '' + 27 | $this.text() + 28 | '' 29 | ); 30 | 31 | }); 32 | 33 | return b.join(''); 34 | 35 | }; 36 | 37 | /** 38 | * Panel-ify an element. 39 | * @param {object} userConfig User config. 40 | * @return {jQuery} jQuery object. 41 | */ 42 | $.fn.panel = function(userConfig) { 43 | 44 | // No elements? 45 | if (this.length == 0) 46 | return $this; 47 | 48 | // Multiple elements? 49 | if (this.length > 1) { 50 | 51 | for (var i=0; i < this.length; i++) 52 | $(this[i]).panel(userConfig); 53 | 54 | return $this; 55 | 56 | } 57 | 58 | // Vars. 59 | var $this = $(this), 60 | $body = $('body'), 61 | $window = $(window), 62 | id = $this.attr('id'), 63 | config; 64 | 65 | // Config. 66 | config = $.extend({ 67 | 68 | // Delay. 69 | delay: 0, 70 | 71 | // Hide panel on link click. 72 | hideOnClick: false, 73 | 74 | // Hide panel on escape keypress. 75 | hideOnEscape: false, 76 | 77 | // Hide panel on swipe. 78 | hideOnSwipe: false, 79 | 80 | // Reset scroll position on hide. 81 | resetScroll: false, 82 | 83 | // Reset forms on hide. 84 | resetForms: false, 85 | 86 | // Side of viewport the panel will appear. 87 | side: null, 88 | 89 | // Target element for "class". 90 | target: $this, 91 | 92 | // Class to toggle. 93 | visibleClass: 'visible' 94 | 95 | }, userConfig); 96 | 97 | // Expand "target" if it's not a jQuery object already. 98 | if (typeof config.target != 'jQuery') 99 | config.target = $(config.target); 100 | 101 | // Panel. 102 | 103 | // Methods. 104 | $this._hide = function(event) { 105 | 106 | // Already hidden? Bail. 107 | if (!config.target.hasClass(config.visibleClass)) 108 | return; 109 | 110 | // If an event was provided, cancel it. 111 | if (event) { 112 | 113 | event.preventDefault(); 114 | event.stopPropagation(); 115 | 116 | } 117 | 118 | // Hide. 119 | config.target.removeClass(config.visibleClass); 120 | 121 | // Post-hide stuff. 122 | window.setTimeout(function() { 123 | 124 | // Reset scroll position. 125 | if (config.resetScroll) 126 | $this.scrollTop(0); 127 | 128 | // Reset forms. 129 | if (config.resetForms) 130 | $this.find('form').each(function() { 131 | this.reset(); 132 | }); 133 | 134 | }, config.delay); 135 | 136 | }; 137 | 138 | // Vendor fixes. 139 | $this 140 | .css('-ms-overflow-style', '-ms-autohiding-scrollbar') 141 | .css('-webkit-overflow-scrolling', 'touch'); 142 | 143 | // Hide on click. 144 | if (config.hideOnClick) { 145 | 146 | $this.find('a') 147 | .css('-webkit-tap-highlight-color', 'rgba(0,0,0,0)'); 148 | 149 | $this 150 | .on('click', 'a', function(event) { 151 | 152 | var $a = $(this), 153 | href = $a.attr('href'), 154 | target = $a.attr('target'); 155 | 156 | if (!href || href == '#' || href == '' || href == '#' + id) 157 | return; 158 | 159 | // Cancel original event. 160 | event.preventDefault(); 161 | event.stopPropagation(); 162 | 163 | // Hide panel. 164 | $this._hide(); 165 | 166 | // Redirect to href. 167 | window.setTimeout(function() { 168 | 169 | if (target == '_blank') 170 | window.open(href); 171 | else 172 | window.location.href = href; 173 | 174 | }, config.delay + 10); 175 | 176 | }); 177 | 178 | } 179 | 180 | // Event: Touch stuff. 181 | $this.on('touchstart', function(event) { 182 | 183 | $this.touchPosX = event.originalEvent.touches[0].pageX; 184 | $this.touchPosY = event.originalEvent.touches[0].pageY; 185 | 186 | }) 187 | 188 | $this.on('touchmove', function(event) { 189 | 190 | if ($this.touchPosX === null 191 | || $this.touchPosY === null) 192 | return; 193 | 194 | var diffX = $this.touchPosX - event.originalEvent.touches[0].pageX, 195 | diffY = $this.touchPosY - event.originalEvent.touches[0].pageY, 196 | th = $this.outerHeight(), 197 | ts = ($this.get(0).scrollHeight - $this.scrollTop()); 198 | 199 | // Hide on swipe? 200 | if (config.hideOnSwipe) { 201 | 202 | var result = false, 203 | boundary = 20, 204 | delta = 50; 205 | 206 | switch (config.side) { 207 | 208 | case 'left': 209 | result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX > delta); 210 | break; 211 | 212 | case 'right': 213 | result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX < (-1 * delta)); 214 | break; 215 | 216 | case 'top': 217 | result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY > delta); 218 | break; 219 | 220 | case 'bottom': 221 | result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY < (-1 * delta)); 222 | break; 223 | 224 | default: 225 | break; 226 | 227 | } 228 | 229 | if (result) { 230 | 231 | $this.touchPosX = null; 232 | $this.touchPosY = null; 233 | $this._hide(); 234 | 235 | return false; 236 | 237 | } 238 | 239 | } 240 | 241 | // Prevent vertical scrolling past the top or bottom. 242 | if (($this.scrollTop() < 0 && diffY < 0) 243 | || (ts > (th - 2) && ts < (th + 2) && diffY > 0)) { 244 | 245 | event.preventDefault(); 246 | event.stopPropagation(); 247 | 248 | } 249 | 250 | }); 251 | 252 | // Event: Prevent certain events inside the panel from bubbling. 253 | $this.on('click touchend touchstart touchmove', function(event) { 254 | event.stopPropagation(); 255 | }); 256 | 257 | // Event: Hide panel if a child anchor tag pointing to its ID is clicked. 258 | $this.on('click', 'a[href="#' + id + '"]', function(event) { 259 | 260 | event.preventDefault(); 261 | event.stopPropagation(); 262 | 263 | config.target.removeClass(config.visibleClass); 264 | 265 | }); 266 | 267 | // Body. 268 | 269 | // Event: Hide panel on body click/tap. 270 | $body.on('click touchend', function(event) { 271 | $this._hide(event); 272 | }); 273 | 274 | // Event: Toggle. 275 | $body.on('click', 'a[href="#' + id + '"]', function(event) { 276 | 277 | event.preventDefault(); 278 | event.stopPropagation(); 279 | 280 | config.target.toggleClass(config.visibleClass); 281 | 282 | }); 283 | 284 | // Window. 285 | 286 | // Event: Hide on ESC. 287 | if (config.hideOnEscape) 288 | $window.on('keydown', function(event) { 289 | 290 | if (event.keyCode == 27) 291 | $this._hide(event); 292 | 293 | }); 294 | 295 | return $this; 296 | 297 | }; 298 | 299 | /** 300 | * Apply "placeholder" attribute polyfill to one or more forms. 301 | * @return {jQuery} jQuery object. 302 | */ 303 | $.fn.placeholder = function() { 304 | 305 | // Browser natively supports placeholders? Bail. 306 | if (typeof (document.createElement('input')).placeholder != 'undefined') 307 | return $(this); 308 | 309 | // No elements? 310 | if (this.length == 0) 311 | return $this; 312 | 313 | // Multiple elements? 314 | if (this.length > 1) { 315 | 316 | for (var i=0; i < this.length; i++) 317 | $(this[i]).placeholder(); 318 | 319 | return $this; 320 | 321 | } 322 | 323 | // Vars. 324 | var $this = $(this); 325 | 326 | // Text, TextArea. 327 | $this.find('input[type=text],textarea') 328 | .each(function() { 329 | 330 | var i = $(this); 331 | 332 | if (i.val() == '' 333 | || i.val() == i.attr('placeholder')) 334 | i 335 | .addClass('polyfill-placeholder') 336 | .val(i.attr('placeholder')); 337 | 338 | }) 339 | .on('blur', function() { 340 | 341 | var i = $(this); 342 | 343 | if (i.attr('name').match(/-polyfill-field$/)) 344 | return; 345 | 346 | if (i.val() == '') 347 | i 348 | .addClass('polyfill-placeholder') 349 | .val(i.attr('placeholder')); 350 | 351 | }) 352 | .on('focus', function() { 353 | 354 | var i = $(this); 355 | 356 | if (i.attr('name').match(/-polyfill-field$/)) 357 | return; 358 | 359 | if (i.val() == i.attr('placeholder')) 360 | i 361 | .removeClass('polyfill-placeholder') 362 | .val(''); 363 | 364 | }); 365 | 366 | // Password. 367 | $this.find('input[type=password]') 368 | .each(function() { 369 | 370 | var i = $(this); 371 | var x = $( 372 | $('
') 373 | .append(i.clone()) 374 | .remove() 375 | .html() 376 | .replace(/type="password"/i, 'type="text"') 377 | .replace(/type=password/i, 'type=text') 378 | ); 379 | 380 | if (i.attr('id') != '') 381 | x.attr('id', i.attr('id') + '-polyfill-field'); 382 | 383 | if (i.attr('name') != '') 384 | x.attr('name', i.attr('name') + '-polyfill-field'); 385 | 386 | x.addClass('polyfill-placeholder') 387 | .val(x.attr('placeholder')).insertAfter(i); 388 | 389 | if (i.val() == '') 390 | i.hide(); 391 | else 392 | x.hide(); 393 | 394 | i 395 | .on('blur', function(event) { 396 | 397 | event.preventDefault(); 398 | 399 | var x = i.parent().find('input[name=' + i.attr('name') + '-polyfill-field]'); 400 | 401 | if (i.val() == '') { 402 | 403 | i.hide(); 404 | x.show(); 405 | 406 | } 407 | 408 | }); 409 | 410 | x 411 | .on('focus', function(event) { 412 | 413 | event.preventDefault(); 414 | 415 | var i = x.parent().find('input[name=' + x.attr('name').replace('-polyfill-field', '') + ']'); 416 | 417 | x.hide(); 418 | 419 | i 420 | .show() 421 | .focus(); 422 | 423 | }) 424 | .on('keypress', function(event) { 425 | 426 | event.preventDefault(); 427 | x.val(''); 428 | 429 | }); 430 | 431 | }); 432 | 433 | // Events. 434 | $this 435 | .on('submit', function() { 436 | 437 | $this.find('input[type=text],input[type=password],textarea') 438 | .each(function(event) { 439 | 440 | var i = $(this); 441 | 442 | if (i.attr('name').match(/-polyfill-field$/)) 443 | i.attr('name', ''); 444 | 445 | if (i.val() == i.attr('placeholder')) { 446 | 447 | i.removeClass('polyfill-placeholder'); 448 | i.val(''); 449 | 450 | } 451 | 452 | }); 453 | 454 | }) 455 | .on('reset', function(event) { 456 | 457 | event.preventDefault(); 458 | 459 | $this.find('select') 460 | .val($('option:first').val()); 461 | 462 | $this.find('input,textarea') 463 | .each(function() { 464 | 465 | var i = $(this), 466 | x; 467 | 468 | i.removeClass('polyfill-placeholder'); 469 | 470 | switch (this.type) { 471 | 472 | case 'submit': 473 | case 'reset': 474 | break; 475 | 476 | case 'password': 477 | i.val(i.attr('defaultValue')); 478 | 479 | x = i.parent().find('input[name=' + i.attr('name') + '-polyfill-field]'); 480 | 481 | if (i.val() == '') { 482 | i.hide(); 483 | x.show(); 484 | } 485 | else { 486 | i.show(); 487 | x.hide(); 488 | } 489 | 490 | break; 491 | 492 | case 'checkbox': 493 | case 'radio': 494 | i.attr('checked', i.attr('defaultValue')); 495 | break; 496 | 497 | case 'text': 498 | case 'textarea': 499 | i.val(i.attr('defaultValue')); 500 | 501 | if (i.val() == '') { 502 | i.addClass('polyfill-placeholder'); 503 | i.val(i.attr('placeholder')); 504 | } 505 | 506 | break; 507 | 508 | default: 509 | i.val(i.attr('defaultValue')); 510 | break; 511 | 512 | } 513 | }); 514 | 515 | }); 516 | 517 | return $this; 518 | 519 | }; 520 | 521 | /** 522 | * Moves elements to/from the first positions of their respective parents. 523 | * @param {jQuery} $elements Elements (or selector) to move. 524 | * @param {bool} condition If true, moves elements to the top. Otherwise, moves elements back to their original locations. 525 | */ 526 | $.prioritize = function($elements, condition) { 527 | 528 | var key = '__prioritize'; 529 | 530 | // Expand $elements if it's not already a jQuery object. 531 | if (typeof $elements != 'jQuery') 532 | $elements = $($elements); 533 | 534 | // Step through elements. 535 | $elements.each(function() { 536 | 537 | var $e = $(this), $p, 538 | $parent = $e.parent(); 539 | 540 | // No parent? Bail. 541 | if ($parent.length == 0) 542 | return; 543 | 544 | // Not moved? Move it. 545 | if (!$e.data(key)) { 546 | 547 | // Condition is false? Bail. 548 | if (!condition) 549 | return; 550 | 551 | // Get placeholder (which will serve as our point of reference for when this element needs to move back). 552 | $p = $e.prev(); 553 | 554 | // Couldn't find anything? Means this element's already at the top, so bail. 555 | if ($p.length == 0) 556 | return; 557 | 558 | // Move element to top of parent. 559 | $e.prependTo($parent); 560 | 561 | // Mark element as moved. 562 | $e.data(key, $p); 563 | 564 | } 565 | 566 | // Moved already? 567 | else { 568 | 569 | // Condition is true? Bail. 570 | if (condition) 571 | return; 572 | 573 | $p = $e.data(key); 574 | 575 | // Move element back to its original location (using our placeholder). 576 | $e.insertAfter($p); 577 | 578 | // Unmark element as moved. 579 | $e.removeData(key); 580 | 581 | } 582 | 583 | }); 584 | 585 | }; 586 | 587 | })(jQuery); -------------------------------------------------------------------------------- /demo/assets/sass/base/_page.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Basic */ 8 | 9 | // MSIE: Required for IEMobile. 10 | @-ms-viewport { 11 | width: device-width; 12 | } 13 | 14 | // MSIE: Prevents scrollbar from overlapping content. 15 | body { 16 | -ms-overflow-style: scrollbar; 17 | } 18 | 19 | // Ensures page width is always >=320px. 20 | @include breakpoint('<=xsmall') { 21 | html, body { 22 | min-width: 320px; 23 | } 24 | } 25 | 26 | // Set box model to border-box. 27 | // Based on css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice 28 | html { 29 | box-sizing: border-box; 30 | } 31 | 32 | *, *:before, *:after { 33 | box-sizing: inherit; 34 | } 35 | 36 | body { 37 | background: _palette(bg); 38 | 39 | // Stops initial animations until page loads or stops resizing. 40 | &.is-preload, 41 | &.is-resizing { 42 | *, *:before, *:after { 43 | @include vendor('animation', 'none !important'); 44 | @include vendor('transition', 'none !important'); 45 | } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /demo/assets/sass/base/_reset.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | // Reset. 8 | // Based on meyerweb.com/eric/tools/css/reset (v2.0 | 20110126 | License: public domain) 9 | 10 | html, body, div, span, applet, object, 11 | iframe, h1, h2, h3, h4, h5, h6, p, blockquote, 12 | pre, a, abbr, acronym, address, big, cite, 13 | code, del, dfn, em, img, ins, kbd, q, s, samp, 14 | small, strike, strong, sub, sup, tt, var, b, 15 | u, i, center, dl, dt, dd, ol, ul, li, fieldset, 16 | form, label, legend, table, caption, tbody, 17 | tfoot, thead, tr, th, td, article, aside, 18 | canvas, details, embed, figure, figcaption, 19 | footer, header, hgroup, menu, nav, output, ruby, 20 | section, summary, time, mark, audio, video { 21 | margin: 0; 22 | padding: 0; 23 | border: 0; 24 | font-size: 100%; 25 | font: inherit; 26 | vertical-align: baseline; 27 | } 28 | 29 | article, aside, details, figcaption, figure, 30 | footer, header, hgroup, menu, nav, section { 31 | display: block; 32 | } 33 | 34 | body { 35 | line-height: 1; 36 | } 37 | 38 | ol, ul { 39 | list-style:none; 40 | } 41 | 42 | blockquote, q { 43 | quotes: none; 44 | 45 | &:before, 46 | &:after { 47 | content: ''; 48 | content: none; 49 | } 50 | } 51 | 52 | table { 53 | border-collapse: collapse; 54 | border-spacing: 0; 55 | } 56 | 57 | body { 58 | -webkit-text-size-adjust: none; 59 | } 60 | 61 | mark { 62 | background-color: transparent; 63 | color: inherit; 64 | } 65 | 66 | input::-moz-focus-inner { 67 | border: 0; 68 | padding: 0; 69 | } 70 | 71 | input, select, textarea { 72 | -moz-appearance: none; 73 | -webkit-appearance: none; 74 | -ms-appearance: none; 75 | appearance: none; 76 | } -------------------------------------------------------------------------------- /demo/assets/sass/base/_typography.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Type */ 8 | 9 | body, input, select, textarea { 10 | color: _palette(fg); 11 | font-family: _font(family); 12 | font-size: 13pt; 13 | font-weight: _font(weight); 14 | line-height: 1.65; 15 | 16 | @include breakpoint('<=xlarge') { 17 | font-size: 11pt; 18 | } 19 | 20 | @include breakpoint('<=large') { 21 | font-size: 10pt; 22 | } 23 | 24 | @include breakpoint('<=xxsmall') { 25 | font-size: 9pt; 26 | } 27 | } 28 | 29 | a { 30 | @include vendor('transition', ( 31 | 'color #{_duration(transition)} ease-in-out', 32 | 'border-bottom-color #{_duration(transition)} ease-in-out' 33 | )); 34 | border-bottom: dotted 1px; 35 | color: _palette(accent); 36 | text-decoration: none; 37 | 38 | &:hover { 39 | border-bottom-color: _palette(accent); 40 | color: _palette(accent) !important; 41 | 42 | strong { 43 | color: inherit; 44 | } 45 | } 46 | } 47 | 48 | strong, b { 49 | color: _palette(fg-bold); 50 | font-weight: _font(weight-bold); 51 | } 52 | 53 | em, i { 54 | font-style: italic; 55 | } 56 | 57 | p { 58 | margin: 0 0 _size(element-margin) 0; 59 | } 60 | 61 | h1, h2, h3, h4, h5, h6 { 62 | color: _palette(fg-bold); 63 | font-family: _font(family-heading); 64 | font-weight: _font(weight-heading); 65 | line-height: 1.5; 66 | margin: 0 0 (_size(element-margin) * 0.5) 0; 67 | 68 | a { 69 | color: inherit; 70 | text-decoration: none; 71 | border-bottom: 0; 72 | } 73 | } 74 | 75 | h1 { 76 | font-size: 4em; 77 | margin: 0 0 (_size(element-margin) * 0.25) 0; 78 | line-height: 1.3; 79 | } 80 | 81 | h2 { 82 | font-size: 1.75em; 83 | } 84 | 85 | h3 { 86 | font-size: 1.25em; 87 | } 88 | 89 | h4 { 90 | font-size: 1.1em; 91 | } 92 | 93 | h5 { 94 | font-size: 0.9em; 95 | } 96 | 97 | h6 { 98 | font-size: 0.7em; 99 | } 100 | 101 | @include breakpoint('<=xlarge') { 102 | h1 { 103 | font-size: 3.5em; 104 | } 105 | } 106 | 107 | @include breakpoint('<=medium') { 108 | h1 { 109 | font-size: 3.25em; 110 | } 111 | } 112 | 113 | @include breakpoint('<=small') { 114 | h1 { 115 | font-size: 2em; 116 | line-height: 1.4; 117 | } 118 | 119 | h2 { 120 | font-size: 1.5em; 121 | } 122 | } 123 | 124 | sub { 125 | font-size: 0.8em; 126 | position: relative; 127 | top: 0.5em; 128 | } 129 | 130 | sup { 131 | font-size: 0.8em; 132 | position: relative; 133 | top: -0.5em; 134 | } 135 | 136 | blockquote { 137 | border-left: solid 3px _palette(border); 138 | font-style: italic; 139 | margin: 0 0 _size(element-margin) 0; 140 | padding: (_size(element-margin) / 4) 0 (_size(element-margin) / 4) _size(element-margin); 141 | } 142 | 143 | code { 144 | background: _palette(border-bg); 145 | border-radius: _size(border-radius); 146 | border: solid 1px _palette(border); 147 | font-family: _font(family-fixed); 148 | font-size: 0.9em; 149 | margin: 0 0.25em; 150 | padding: 0.25em 0.65em; 151 | } 152 | 153 | pre { 154 | -webkit-overflow-scrolling: touch; 155 | font-family: _font(family-fixed); 156 | font-size: 0.9em; 157 | margin: 0 0 _size(element-margin) 0; 158 | 159 | code { 160 | display: block; 161 | line-height: 1.75; 162 | padding: 1em 1.5em; 163 | overflow-x: auto; 164 | } 165 | } 166 | 167 | hr { 168 | border: 0; 169 | border-bottom: solid 1px _palette(border); 170 | margin: _size(element-margin) 0; 171 | 172 | &.major { 173 | margin: (_size(element-margin) * 1.5) 0; 174 | } 175 | } 176 | 177 | .align-left { 178 | text-align: left; 179 | } 180 | 181 | .align-center { 182 | text-align: center; 183 | } 184 | 185 | .align-right { 186 | text-align: right; 187 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_actions.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Actions */ 8 | 9 | ul.actions { 10 | @include vendor('display', 'flex'); 11 | cursor: default; 12 | list-style: none; 13 | margin-left: (_size(element-margin) * -0.5); 14 | padding-left: 0; 15 | 16 | li { 17 | padding: 0 0 0 (_size(element-margin) * 0.5); 18 | vertical-align: middle; 19 | } 20 | 21 | &.special { 22 | @include vendor('justify-content', 'center'); 23 | width: 100%; 24 | margin-left: 0; 25 | 26 | li { 27 | &:first-child { 28 | padding-left: 0; 29 | } 30 | } 31 | } 32 | 33 | &.stacked { 34 | @include vendor('flex-direction', 'column'); 35 | margin-left: 0; 36 | 37 | li { 38 | padding: (_size(element-margin) * 0.65) 0 0 0; 39 | 40 | &:first-child { 41 | padding-top: 0; 42 | } 43 | } 44 | } 45 | 46 | &.fit { 47 | width: calc(100% + #{_size(element-margin) * 0.5}); 48 | 49 | li { 50 | @include vendor('flex-grow', '1'); 51 | @include vendor('flex-shrink', '1'); 52 | width: 100%; 53 | 54 | > * { 55 | width: 100%; 56 | } 57 | } 58 | 59 | &.stacked { 60 | width: 100%; 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_box.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Box */ 8 | 9 | .box { 10 | border-radius: _size(border-radius); 11 | border: solid 1px _palette(border); 12 | margin-bottom: _size(element-margin); 13 | padding: 1.5em; 14 | 15 | > :last-child, 16 | > :last-child > :last-child, 17 | > :last-child > :last-child > :last-child { 18 | margin-bottom: 0; 19 | } 20 | 21 | &.alt { 22 | border: 0; 23 | border-radius: 0; 24 | padding: 0; 25 | } 26 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_button.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Button */ 8 | 9 | input[type="submit"], 10 | input[type="reset"], 11 | input[type="button"], 12 | button, 13 | .button { 14 | @include vendor('appearance', 'none'); 15 | @include vendor('transition', ( 16 | 'background-color #{_duration(transition)} ease-in-out', 17 | 'color #{_duration(transition)} ease-in-out' 18 | )); 19 | background-color: transparent; 20 | border-radius: _size(border-radius); 21 | border: 0; 22 | box-shadow: inset 0 0 0 2px _palette(accent); 23 | color: _palette(accent) !important; 24 | cursor: pointer; 25 | display: inline-block; 26 | font-family: _font(family-heading); 27 | font-size: 0.8em; 28 | font-weight: _font(weight-heading); 29 | height: 3.5em; 30 | letter-spacing: _font(kerning-heading); 31 | line-height: 3.5em; 32 | padding: 0 2.25em; 33 | text-align: center; 34 | text-decoration: none; 35 | text-transform: uppercase; 36 | white-space: nowrap; 37 | 38 | &:hover { 39 | background-color: transparentize(_palette(accent), 0.95); 40 | } 41 | 42 | &:active { 43 | background-color: transparentize(_palette(accent), 0.85); 44 | } 45 | 46 | &.icon { 47 | &:before { 48 | margin-right: 0.5em; 49 | } 50 | } 51 | 52 | &.fit { 53 | width: 100%; 54 | } 55 | 56 | &.small { 57 | font-size: 0.6em; 58 | } 59 | 60 | &.large { 61 | font-size: 1em; 62 | height: 3.65em; 63 | line-height: 3.65em; 64 | } 65 | 66 | &.primary { 67 | background-color: _palette(accent); 68 | box-shadow: none; 69 | color: _palette(bg) !important; 70 | 71 | &:hover { 72 | background-color: lighten(_palette(accent), 3); 73 | } 74 | 75 | &:active { 76 | background-color: darken(_palette(accent), 3); 77 | } 78 | } 79 | 80 | &.disabled, 81 | &:disabled { 82 | @include vendor('pointer-events', 'none'); 83 | opacity: 0.25; 84 | } 85 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_contact.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Contact */ 8 | 9 | ul.contact { 10 | list-style: none; 11 | padding: 0; 12 | 13 | li { 14 | @include icon; 15 | border-top: solid 1px _palette(border); 16 | margin: 1.5em 0 0 0; 17 | padding: 1.5em 0 0 3em; 18 | position: relative; 19 | 20 | &:before { 21 | color: _palette(accent); 22 | display: inline-block; 23 | font-size: 1.5em; 24 | height: 1.125em; 25 | left: 0; 26 | line-height: 1.125em; 27 | position: absolute; 28 | text-align: center; 29 | top: (1.5em / 1.5); 30 | width: 1.5em; 31 | } 32 | 33 | &:first-child { 34 | border-top: 0; 35 | margin-top: 0; 36 | padding-top: 0; 37 | 38 | &:before { 39 | top: 0; 40 | } 41 | } 42 | 43 | a { 44 | color: inherit; 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_features.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Features */ 8 | 9 | .features { 10 | $gutter: _size(gutter); 11 | 12 | @include vendor('display', 'flex'); 13 | @include vendor('flex-wrap', 'wrap'); 14 | margin: 0 0 _size(element-margin) ($gutter * -1); 15 | width: calc(100% + #{$gutter}); 16 | 17 | article { 18 | @include vendor('align-items', 'center'); 19 | @include vendor('display', 'flex'); 20 | margin: 0 0 $gutter $gutter; 21 | position: relative; 22 | width: calc(50% - #{$gutter}); 23 | 24 | &:nth-child(2n - 1) { 25 | margin-right: ($gutter * 0.5); 26 | } 27 | 28 | &:nth-child(2n) { 29 | margin-left: ($gutter * 0.5); 30 | } 31 | 32 | &:nth-last-child(1), 33 | &:nth-last-child(2) { 34 | margin-bottom: 0; 35 | } 36 | 37 | .icon { 38 | @include vendor('flex-grow', '0'); 39 | @include vendor('flex-shrink', '0'); 40 | display: block; 41 | height: 10em; 42 | line-height: 10em; 43 | margin: 0 _size(element-margin) 0 0; 44 | text-align: center; 45 | width: 10em; 46 | 47 | &:before { 48 | color: _palette(accent); 49 | font-size: 2.75rem; 50 | position: relative; 51 | top: 0.05em; 52 | } 53 | 54 | &:after { 55 | @include vendor('transform', 'rotate(45deg)'); 56 | border-radius: 0.25rem; 57 | border: solid 2px _palette(border); 58 | content: ''; 59 | display: block; 60 | height: 7em; 61 | left: 50%; 62 | margin: -3.5em 0 0 -3.5em; 63 | position: absolute; 64 | top: 50%; 65 | width: 7em; 66 | } 67 | } 68 | 69 | .content { 70 | @include vendor('flex-grow', '1'); 71 | @include vendor('flex-shrink', '1'); 72 | width: 100%; 73 | 74 | > :last-child { 75 | margin-bottom: 0; 76 | } 77 | } 78 | } 79 | 80 | @include breakpoint('<=medium') { 81 | margin: 0 0 _size(element-margin) 0; 82 | width: 100%; 83 | 84 | article { 85 | margin: 0 0 $gutter 0; 86 | width: 100%; 87 | 88 | &:nth-child(2n - 1) { 89 | margin-right: 0; 90 | } 91 | 92 | &:nth-child(2n) { 93 | margin-left: 0; 94 | } 95 | 96 | &:nth-last-child(1), 97 | &:nth-last-child(2) { 98 | margin-bottom: $gutter; 99 | } 100 | 101 | &:last-child { 102 | margin-bottom: 0; 103 | } 104 | 105 | .icon { 106 | height: 8em; 107 | line-height: 8em; 108 | width: 8em; 109 | 110 | &:before { 111 | font-size: 2.25rem; 112 | } 113 | 114 | &:after { 115 | height: 6em; 116 | margin: -3em 0 0 -3em; 117 | width: 6em; 118 | } 119 | } 120 | } 121 | } 122 | 123 | @include breakpoint('<=xsmall') { 124 | article { 125 | @include vendor('flex-direction', 'column'); 126 | @include vendor('align-items', 'flex-start'); 127 | 128 | .icon { 129 | height: 6em; 130 | line-height: 6em; 131 | margin: 0 0 (_size(element-margin) * 0.75) 0; 132 | width: 6em; 133 | 134 | &:before { 135 | font-size: 1.5rem; 136 | } 137 | 138 | &:after { 139 | height: 4em; 140 | margin: -2em 0 0 -2em; 141 | width: 4em; 142 | } 143 | } 144 | } 145 | } 146 | 147 | @include breakpoint('<=xsmall') { 148 | article { 149 | .icon { 150 | &:before { 151 | font-size: 1.25rem; 152 | } 153 | } 154 | } 155 | } 156 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_form.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Form */ 8 | 9 | form { 10 | margin: 0 0 _size(element-margin) 0; 11 | } 12 | 13 | label { 14 | color: _palette(fg-bold); 15 | display: block; 16 | font-size: 0.9em; 17 | font-weight: _font(weight-bold); 18 | margin: 0 0 (_size(element-margin) * 0.5) 0; 19 | } 20 | 21 | input[type="text"], 22 | input[type="password"], 23 | input[type="email"], 24 | input[type="tel"], 25 | input[type="search"], 26 | input[type="url"], 27 | select, 28 | textarea { 29 | @include vendor('appearance', 'none'); 30 | background: _palette(bg); 31 | border-radius: _size(border-radius); 32 | border: none; 33 | border: solid 1px _palette(border); 34 | color: inherit; 35 | display: block; 36 | outline: 0; 37 | padding: 0 1em; 38 | text-decoration: none; 39 | width: 100%; 40 | 41 | &:invalid { 42 | box-shadow: none; 43 | } 44 | 45 | &:focus { 46 | border-color: _palette(accent); 47 | box-shadow: 0 0 0 1px _palette(accent); 48 | } 49 | } 50 | 51 | select { 52 | background-image: svg-url(""); 53 | background-size: 1.25em; 54 | background-repeat: no-repeat; 55 | background-position: calc(100% - 1em) center; 56 | height: _size(element-height); 57 | padding-right: _size(element-height); 58 | text-overflow: ellipsis; 59 | 60 | option { 61 | color: _palette(fg-bold); 62 | background: _palette(bg); 63 | } 64 | 65 | &:focus { 66 | &::-ms-value { 67 | background-color: transparent; 68 | } 69 | } 70 | 71 | &::-ms-expand { 72 | display: none; 73 | } 74 | } 75 | 76 | input[type="text"], 77 | input[type="password"], 78 | input[type="email"], 79 | input[type="tel"], 80 | input[type="search"], 81 | input[type="url"], 82 | select { 83 | height: _size(element-height); 84 | } 85 | 86 | textarea { 87 | padding: 0.75em 1em; 88 | } 89 | 90 | input[type="checkbox"], 91 | input[type="radio"], { 92 | @include vendor('appearance', 'none'); 93 | display: block; 94 | float: left; 95 | margin-right: -2em; 96 | opacity: 0; 97 | width: 1em; 98 | z-index: -1; 99 | 100 | & + label { 101 | @include icon(false, solid); 102 | color: _palette(fg); 103 | cursor: pointer; 104 | display: inline-block; 105 | font-size: 1em; 106 | font-weight: _font(weight); 107 | padding-left: (_size(element-height) * 0.6) + 0.75em; 108 | padding-right: 0.75em; 109 | position: relative; 110 | 111 | &:before { 112 | background: _palette(bg); 113 | border-radius: _size(border-radius); 114 | border: solid 1px _palette(border); 115 | content: ''; 116 | display: inline-block; 117 | font-size: 0.8em; 118 | height: (_size(element-height) * 0.75); 119 | left: 0; 120 | line-height: (_size(element-height) * 0.75); 121 | position: absolute; 122 | text-align: center; 123 | top: 0; 124 | width: (_size(element-height) * 0.75); 125 | } 126 | } 127 | 128 | &:checked + label { 129 | &:before { 130 | background: _palette(fg-bold); 131 | border-color: _palette(fg-bold); 132 | color: _palette(bg); 133 | content: '\f00c'; 134 | } 135 | } 136 | 137 | &:focus + label { 138 | &:before { 139 | border-color: _palette(accent); 140 | box-shadow: 0 0 0 1px _palette(accent); 141 | } 142 | } 143 | } 144 | 145 | input[type="checkbox"] { 146 | & + label { 147 | &:before { 148 | border-radius: _size(border-radius); 149 | } 150 | } 151 | } 152 | 153 | input[type="radio"] { 154 | & + label { 155 | &:before { 156 | border-radius: 100%; 157 | } 158 | } 159 | } 160 | 161 | ::-webkit-input-placeholder { 162 | color: _palette(fg-light) !important; 163 | opacity: 1.0; 164 | } 165 | 166 | :-moz-placeholder { 167 | color: _palette(fg-light) !important; 168 | opacity: 1.0; 169 | } 170 | 171 | ::-moz-placeholder { 172 | color: _palette(fg-light) !important; 173 | opacity: 1.0; 174 | } 175 | 176 | :-ms-input-placeholder { 177 | color: _palette(fg-light) !important; 178 | opacity: 1.0; 179 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_icon.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Icon */ 8 | 9 | .icon { 10 | @include icon; 11 | border-bottom: none; 12 | position: relative; 13 | 14 | > .label { 15 | display: none; 16 | } 17 | 18 | &:before { 19 | line-height: inherit; 20 | } 21 | 22 | &.solid { 23 | &:before { 24 | font-weight: 900; 25 | } 26 | } 27 | 28 | &.brands { 29 | &:before { 30 | font-family: 'Font Awesome 5 Brands'; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_icons.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Icons */ 8 | 9 | ul.icons { 10 | cursor: default; 11 | list-style: none; 12 | padding-left: 0; 13 | 14 | li { 15 | display: inline-block; 16 | padding: 0 1em 0 0; 17 | 18 | &:last-child { 19 | padding-right: 0; 20 | } 21 | 22 | .icon { 23 | color: inherit; 24 | 25 | &:before { 26 | font-size: 1.25em; 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_image.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Image */ 8 | 9 | .image { 10 | border-radius: _size(border-radius); 11 | border: 0; 12 | display: inline-block; 13 | position: relative; 14 | 15 | img { 16 | border-radius: _size(border-radius); 17 | display: block; 18 | } 19 | 20 | &.left, 21 | &.right { 22 | max-width: 40%; 23 | 24 | img { 25 | width: 100%; 26 | } 27 | } 28 | 29 | &.left { 30 | float: left; 31 | padding: 0 1.5em 1em 0; 32 | top: 0.25em; 33 | } 34 | 35 | &.right { 36 | float: right; 37 | padding: 0 0 1em 1.5em; 38 | top: 0.25em; 39 | } 40 | 41 | &.fit { 42 | display: block; 43 | margin: 0 0 _size(element-margin) 0; 44 | width: 100%; 45 | 46 | img { 47 | width: 100%; 48 | } 49 | } 50 | 51 | &.main { 52 | display: block; 53 | margin: 0 0 (_size(element-margin) * 1.5) 0; 54 | width: 100%; 55 | 56 | img { 57 | width: 100%; 58 | } 59 | } 60 | } 61 | 62 | a.image { 63 | overflow: hidden; 64 | 65 | img { 66 | @include vendor('transition', 'transform #{_duration(transition)} ease'); 67 | } 68 | 69 | &:hover { 70 | img { 71 | @include vendor('transform', 'scale(1.075)'); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_list.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* List */ 8 | 9 | ol { 10 | list-style: decimal; 11 | margin: 0 0 _size(element-margin) 0; 12 | padding-left: 1.25em; 13 | 14 | li { 15 | padding-left: 0.25em; 16 | } 17 | } 18 | 19 | ul { 20 | list-style: disc; 21 | margin: 0 0 _size(element-margin) 0; 22 | padding-left: 1em; 23 | 24 | li { 25 | padding-left: 0.5em; 26 | } 27 | 28 | &.alt { 29 | list-style: none; 30 | padding-left: 0; 31 | 32 | li { 33 | border-top: solid 1px _palette(border); 34 | padding: 0.5em 0; 35 | 36 | &:first-child { 37 | border-top: 0; 38 | padding-top: 0; 39 | } 40 | } 41 | } 42 | } 43 | 44 | dl { 45 | margin: 0 0 _size(element-margin) 0; 46 | 47 | dt { 48 | display: block; 49 | font-weight: _font(weight-bold); 50 | margin: 0 0 (_size(element-margin) * 0.5) 0; 51 | } 52 | 53 | dd { 54 | margin-left: _size(element-margin); 55 | } 56 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_mini-posts.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Mini Posts */ 8 | 9 | .mini-posts { 10 | article { 11 | border-top: solid 1px _palette(border); 12 | margin-top: _size(element-margin); 13 | padding-top: _size(element-margin); 14 | 15 | .image { 16 | display: block; 17 | margin: 0 0 (_size(element-margin) * 0.75) 0; 18 | 19 | img { 20 | display: block; 21 | width: 100%; 22 | } 23 | } 24 | 25 | &:first-child { 26 | border-top: 0; 27 | margin-top: 0; 28 | padding-top: 0; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_pagination.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Pagination */ 8 | 9 | ul.pagination { 10 | cursor: default; 11 | list-style: none; 12 | padding-left: 0; 13 | 14 | li { 15 | display: inline-block; 16 | padding-left: 0; 17 | vertical-align: middle; 18 | 19 | > .page { 20 | @include vendor('transition', ( 21 | 'background-color #{_duration(transition)} ease-in-out', 22 | 'color #{_duration(transition)} ease-in-out' 23 | )); 24 | border-bottom: 0; 25 | border-radius: _size(border-radius); 26 | display: inline-block; 27 | font-size: 0.8em; 28 | font-weight: _font(weight-bold); 29 | height: 2em; 30 | line-height: 2em; 31 | margin: 0 0.125em; 32 | min-width: 2em; 33 | padding: 0 0.5em; 34 | text-align: center; 35 | 36 | &.active { 37 | background-color: _palette(accent); 38 | color: _palette(bg) !important; 39 | 40 | &:hover { 41 | background-color: lighten(_palette(accent), 3); 42 | } 43 | 44 | &:active { 45 | background-color: darken(_palette(accent), 3); 46 | } 47 | } 48 | } 49 | 50 | &:first-child { 51 | padding-right: 0.75em; 52 | } 53 | 54 | &:last-child { 55 | padding-left: 0.75em; 56 | } 57 | } 58 | 59 | @include breakpoint('<=xsmall') { 60 | li { 61 | &:nth-child(n+2):nth-last-child(n+2) { 62 | display: none; 63 | } 64 | 65 | &:first-child { 66 | padding-right: 0; 67 | } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_posts.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Posts */ 8 | 9 | .posts { 10 | $gutter: (_size(gutter) * 2); 11 | 12 | @include vendor('display', 'flex'); 13 | @include vendor('flex-wrap', 'wrap'); 14 | margin: 0 0 _size(element-margin) ($gutter * -1); 15 | width: calc(100% + #{$gutter}); 16 | 17 | article { 18 | @include vendor('flex-grow', '0'); 19 | @include vendor('flex-shrink', '1'); 20 | margin: 0 0 $gutter $gutter; 21 | position: relative; 22 | width: calc(#{(100% / 3)} - #{$gutter}); 23 | 24 | &:before { 25 | background: _palette(border); 26 | content: ''; 27 | display: block; 28 | height: calc(100% + #{$gutter}); 29 | left: ($gutter * -0.5); 30 | position: absolute; 31 | top: 0; 32 | width: 1px; 33 | } 34 | 35 | &:after { 36 | background: _palette(border); 37 | bottom: ($gutter * -0.5); 38 | content: ''; 39 | display: block; 40 | height: 1px; 41 | position: absolute; 42 | right: 0; 43 | width: calc(100% + #{$gutter}); 44 | } 45 | 46 | > :last-child { 47 | margin-bottom: 0; 48 | } 49 | 50 | .image { 51 | display: block; 52 | margin: 0 0 _size(element-margin) 0; 53 | 54 | img { 55 | display: block; 56 | width: 100%; 57 | } 58 | } 59 | } 60 | 61 | @include breakpoint('xlarge-to-max') { 62 | article { 63 | &:nth-child(3n + 1) { 64 | &:before { 65 | display: none; 66 | } 67 | 68 | &:after { 69 | width: 100%; 70 | } 71 | } 72 | 73 | &:nth-last-child(1), 74 | &:nth-last-child(2), 75 | &:nth-last-child(3) { 76 | margin-bottom: 0; 77 | 78 | &:before { 79 | height: 100%; 80 | } 81 | 82 | &:after { 83 | display: none; 84 | } 85 | } 86 | } 87 | } 88 | 89 | @include breakpoint('<=xlarge') { 90 | article { 91 | width: calc(50% - #{$gutter}); 92 | 93 | &:nth-last-child(3) { 94 | margin-bottom: $gutter; 95 | } 96 | } 97 | } 98 | 99 | @include breakpoint('small-to-xlarge') { 100 | article { 101 | &:nth-child(2n + 1) { 102 | &:before { 103 | display: none; 104 | } 105 | 106 | &:after { 107 | width: 100%; 108 | } 109 | } 110 | 111 | &:nth-last-child(1), 112 | &:nth-last-child(2) { 113 | margin-bottom: 0; 114 | 115 | &:before { 116 | height: 100%; 117 | } 118 | 119 | &:after { 120 | display: none; 121 | } 122 | } 123 | } 124 | } 125 | 126 | @include breakpoint('<=small') { 127 | $gutter: _size(gutter) * 1.5; 128 | 129 | margin: 0 0 _size(element-margin) ($gutter * -1); 130 | width: calc(100% + #{$gutter}); 131 | 132 | article { 133 | margin: 0 0 $gutter $gutter; 134 | width: calc(50% - #{$gutter}); 135 | 136 | &:before { 137 | height: calc(100% + #{$gutter}); 138 | left: ($gutter * -0.5); 139 | } 140 | 141 | &:after { 142 | bottom: ($gutter * -0.5); 143 | width: calc(100% + #{$gutter}); 144 | } 145 | 146 | &:nth-last-child(3) { 147 | margin-bottom: $gutter; 148 | } 149 | } 150 | } 151 | 152 | @include breakpoint('<=xsmall') { 153 | $gutter: _size(gutter) * 1.5; 154 | 155 | margin: 0 0 _size(element-margin) 0; 156 | width: 100%; 157 | 158 | article { 159 | margin: 0 0 $gutter 0; 160 | width: 100%; 161 | 162 | &:before { 163 | display: none; 164 | } 165 | 166 | &:after { 167 | width: 100%; 168 | } 169 | 170 | &:last-child { 171 | margin-bottom: 0; 172 | 173 | &:after { 174 | display: none; 175 | } 176 | } 177 | } 178 | } 179 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_row.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Row */ 8 | 9 | .row { 10 | @include html-grid(1.5em); 11 | 12 | @include breakpoint('<=xlarge') { 13 | @include html-grid(1.5em, 'xlarge'); 14 | } 15 | 16 | @include breakpoint('<=large') { 17 | @include html-grid(1.5em, 'large'); 18 | } 19 | 20 | @include breakpoint('<=medium') { 21 | @include html-grid(1.5em, 'medium'); 22 | } 23 | 24 | @include breakpoint('<=small') { 25 | @include html-grid(1.5em, 'small'); 26 | } 27 | 28 | @include breakpoint('<=xsmall') { 29 | @include html-grid(1.5em, 'xsmall'); 30 | } 31 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_section.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Section/Article */ 8 | 9 | section, article { 10 | &.special { 11 | text-align: center; 12 | } 13 | } 14 | 15 | header { 16 | p { 17 | font-family: _font(family-heading); 18 | font-size: 1em; 19 | font-weight: _font(weight-heading-alt); 20 | letter-spacing: _font(kerning-heading); 21 | margin-top: -0.5em; 22 | text-transform: uppercase; 23 | } 24 | 25 | &.major { 26 | > :last-child { 27 | border-bottom: solid 3px _palette(accent); 28 | display: inline-block; 29 | margin: 0 0 _size(element-margin) 0; 30 | padding: 0 0.75em 0.5em 0; 31 | } 32 | } 33 | 34 | &.main { 35 | > :last-child { 36 | margin: 0 0 (_size(element-margin) * 0.5) 0; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /demo/assets/sass/components/_table.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Table */ 8 | 9 | .table-wrapper { 10 | -webkit-overflow-scrolling: touch; 11 | overflow-x: auto; 12 | } 13 | 14 | table { 15 | margin: 0 0 _size(element-margin) 0; 16 | width: 100%; 17 | 18 | tbody { 19 | tr { 20 | border: solid 1px _palette(border); 21 | border-left: 0; 22 | border-right: 0; 23 | 24 | &:nth-child(2n + 1) { 25 | background-color: _palette(border-bg); 26 | } 27 | } 28 | } 29 | 30 | td { 31 | padding: 0.75em 0.75em; 32 | } 33 | 34 | th { 35 | color: _palette(fg-bold); 36 | font-size: 0.9em; 37 | font-weight: _font(weight-bold); 38 | padding: 0 0.75em 0.75em 0.75em; 39 | text-align: left; 40 | } 41 | 42 | thead { 43 | border-bottom: solid 2px _palette(border); 44 | } 45 | 46 | tfoot { 47 | border-top: solid 2px _palette(border); 48 | } 49 | 50 | &.alt { 51 | border-collapse: separate; 52 | 53 | tbody { 54 | tr { 55 | td { 56 | border: solid 1px _palette(border); 57 | border-left-width: 0; 58 | border-top-width: 0; 59 | 60 | &:first-child { 61 | border-left-width: 1px; 62 | } 63 | } 64 | 65 | &:first-child { 66 | td { 67 | border-top-width: 1px; 68 | } 69 | } 70 | } 71 | } 72 | 73 | thead { 74 | border-bottom: 0; 75 | } 76 | 77 | tfoot { 78 | border-top: 0; 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /demo/assets/sass/layout/_banner.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Banner */ 8 | 9 | #banner { 10 | @include padding(6em, 0); 11 | @include vendor('display', 'flex'); 12 | 13 | h1 { 14 | margin-top: -0.125em; 15 | } 16 | 17 | .content { 18 | @include vendor('flex-grow', '1'); 19 | @include vendor('flex-shrink', '1'); 20 | width: 50%; 21 | } 22 | 23 | .image { 24 | @include vendor('flex-grow', '0'); 25 | @include vendor('flex-shrink', '0'); 26 | display: block; 27 | margin: 0 0 _size(element-margin) (_size(element-margin) * 2); 28 | width: 50%; 29 | 30 | img { 31 | height: 100%; 32 | -moz-object-fit: cover; 33 | -webkit-object-fit: cover; 34 | -ms-object-fit: cover; 35 | object-fit: cover; 36 | -moz-object-position: center; 37 | -webkit-object-position: center; 38 | -ms-object-position: center; 39 | object-position: center; 40 | width: 100%; 41 | } 42 | } 43 | 44 | @include orientation(portrait) { 45 | @include vendor('flex-direction', 'column-reverse'); 46 | 47 | h1 { 48 | br { 49 | display: none; 50 | } 51 | } 52 | 53 | .content { 54 | @include vendor('flex-grow', '0'); 55 | @include vendor('flex-shrink', '0'); 56 | width: 100%; 57 | } 58 | 59 | .image { 60 | @include vendor('flex-grow', '0'); 61 | @include vendor('flex-shrink', '0'); 62 | margin: 0 0 (_size(element-margin) * 2) 0; 63 | height: 25em; 64 | max-height: 50vh; 65 | min-height: 18em; 66 | width: 100%; 67 | } 68 | 69 | @include breakpoint('<=xsmall') { 70 | .image { 71 | max-height: 35vh; 72 | } 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /demo/assets/sass/layout/_footer.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Footer */ 8 | 9 | #footer { 10 | .copyright { 11 | color: _palette(fg-light); 12 | font-size: 0.9em; 13 | 14 | a { 15 | color: inherit; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /demo/assets/sass/layout/_header.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Header */ 8 | 9 | #header { 10 | @include vendor('display', 'flex'); 11 | border-bottom: solid 5px _palette(accent); 12 | padding: 6em 0 1em 0; 13 | position: relative; 14 | 15 | > * { 16 | @include vendor('flex', '1'); 17 | margin-bottom: 0; 18 | } 19 | 20 | .logo { 21 | border-bottom: 0; 22 | color: inherit; 23 | font-family: _font(family-heading); 24 | font-size: 1.125em; 25 | } 26 | 27 | .icons { 28 | text-align: right; 29 | } 30 | 31 | @include breakpoint('<=xlarge') { 32 | padding-top: 5em; 33 | } 34 | 35 | @include breakpoint('<=small') { 36 | padding-top: 6.5em; 37 | 38 | .logo { 39 | font-size: 1.25em; 40 | margin: 0; 41 | } 42 | 43 | .icons { 44 | height: (6.25em / 1.25); 45 | line-height: (6.25em / 1.25); 46 | position: absolute; 47 | right: (-0.625em / 1.25); 48 | top: 0; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /demo/assets/sass/layout/_main.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Main */ 8 | 9 | #main { 10 | @include vendor('flex-grow', '1'); 11 | @include vendor('flex-shrink', '1'); 12 | width: 100%; 13 | 14 | > .inner { 15 | @include padding(0, 6em); 16 | margin: 0 auto; 17 | max-width: 110em; 18 | 19 | > section { 20 | @include padding(6em, 0); 21 | border-top: solid 2px _palette(border); 22 | 23 | &:first-of-type { 24 | border-top: 0 !important; 25 | } 26 | } 27 | } 28 | 29 | @include breakpoint('<=xlarge') { 30 | > .inner { 31 | @include padding(0, 5em); 32 | 33 | > section { 34 | @include padding(5em, 0); 35 | } 36 | } 37 | } 38 | 39 | @include breakpoint('<=large') { 40 | > .inner { 41 | @include padding(0, 4em); 42 | 43 | > section { 44 | @include padding(4em, 0); 45 | } 46 | } 47 | } 48 | 49 | @include breakpoint('<=small') { 50 | > .inner { 51 | @include padding(0, 2em); 52 | 53 | > section { 54 | @include padding(3em, 0); 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /demo/assets/sass/layout/_menu.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Menu */ 8 | 9 | #menu { 10 | ul { 11 | @include vendor('user-select', 'none'); 12 | color: _palette(fg-bold); 13 | font-family: _font(family-heading); 14 | font-weight: _font(weight-heading-alt); 15 | letter-spacing: _font(kerning-heading); 16 | list-style: none; 17 | margin-bottom: 0; 18 | padding: 0; 19 | text-transform: uppercase; 20 | 21 | a, span { 22 | border-bottom: 0; 23 | color: inherit; 24 | cursor: pointer; 25 | display: block; 26 | font-size: 0.9em; 27 | padding: 0.625em 0; 28 | 29 | &:hover { 30 | color: _palette(accent); 31 | } 32 | 33 | &.opener { 34 | @include vendor('transition', 'color #{_duration(transition)} ease-in-out'); 35 | @include icon(false, solid); 36 | -webkit-tap-highlight-color: rgba(255,255,255,0); 37 | position: relative; 38 | 39 | &:before { 40 | @include vendor('transition', ( 41 | 'color #{_duration(transition)} ease-in-out', 42 | 'transform #{_duration(transition)} ease-in-out' 43 | )); 44 | color: _palette(fg-light); 45 | content: '\f078'; 46 | position: absolute; 47 | right: 0; 48 | } 49 | 50 | &:hover { 51 | &:before { 52 | color: _palette(accent); 53 | } 54 | } 55 | 56 | &.active { 57 | & + ul { 58 | display: block; 59 | } 60 | 61 | &:before { 62 | @include vendor('transform', 'rotate(-180deg)'); 63 | } 64 | } 65 | } 66 | } 67 | } 68 | 69 | > ul { 70 | > li { 71 | border-top: solid 1px _palette(border); 72 | margin: 0.5em 0 0 0; 73 | padding: 0.5em 0 0 0; 74 | 75 | > ul { 76 | color: _palette(fg-light); 77 | display: none; 78 | margin: 0.5em 0 1.5em 0; 79 | padding-left: 1em; 80 | 81 | a, span { 82 | font-size: 0.8em; 83 | } 84 | 85 | > li { 86 | margin: 0.125em 0 0 0; 87 | padding: 0.125em 0 0 0; 88 | } 89 | } 90 | 91 | &:first-child { 92 | border-top: 0; 93 | margin-top: 0; 94 | padding-top: 0; 95 | } 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /demo/assets/sass/layout/_sidebar.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Sidebar */ 8 | 9 | #search { 10 | form { 11 | @include icon(false, solid); 12 | position: relative; 13 | 14 | &:before { 15 | @include vendor('transform', 'scaleX(-1)'); 16 | color: _palette(fg); 17 | content: '\f002'; 18 | cursor: default; 19 | display: block; 20 | font-size: 1.5em; 21 | height: _size(element-height) / 1.375; 22 | line-height: _size(element-height) / 1.375; 23 | opacity: 0.325; 24 | position: absolute; 25 | right: 0; 26 | text-align: center; 27 | top: 0; 28 | width: _size(element-height) / 1.375; 29 | } 30 | 31 | input[type="text"] { 32 | padding-right: _size(element-height); 33 | } 34 | } 35 | } 36 | 37 | #sidebar { 38 | $pad: 2em / 0.9; 39 | 40 | @include vendor('flex-grow', '0'); 41 | @include vendor('flex-shrink', '0'); 42 | @include vendor('transition', ( 43 | 'margin-left 0.5s ease', 44 | 'box-shadow 0.5s ease' 45 | )); 46 | background-color: _palette(bg-alt); 47 | font-size: 0.9em; 48 | position: relative; 49 | width: _size(sidebar-width); 50 | 51 | h2 { 52 | font-size: (1.25em / 0.9); 53 | } 54 | 55 | > .inner { 56 | @include padding($pad, $pad, (0, 0, $pad, 0)); 57 | position: relative; 58 | width: _size(sidebar-width); 59 | 60 | > * { 61 | border-bottom: solid 2px _palette(border); 62 | margin: 0 0 (_size(element-margin) * 1.75) 0; 63 | padding: 0 0 (_size(element-margin) * 1.75) 0; 64 | 65 | > :last-child { 66 | margin-bottom: 0; 67 | } 68 | 69 | &:last-child { 70 | border-bottom: 0; 71 | margin-bottom: 0; 72 | padding-bottom: 0; 73 | } 74 | } 75 | 76 | > .alt { 77 | background-color: darken(_palette(bg-alt), 2); 78 | border-bottom: 0; 79 | margin: ($pad * -1) 0 ($pad * 2) ($pad * -1); 80 | padding: $pad; 81 | width: calc(100% + #{$pad * 2}); 82 | } 83 | } 84 | 85 | .toggle { 86 | @include icon(false, solid); 87 | @include vendor('transition', 'left 0.5s ease'); 88 | -webkit-tap-highlight-color: rgba(255,255,255,0); 89 | border: 0; 90 | display: block; 91 | height: 7.5em; 92 | left: _size(sidebar-width); 93 | line-height: 7.5em; 94 | outline: 0; 95 | overflow: hidden; 96 | position: absolute; 97 | text-align: center; 98 | text-indent: -15em; 99 | white-space: nowrap; 100 | top: 0; 101 | width: 6em; 102 | z-index: _misc(z-index-base); 103 | 104 | &:before { 105 | content: '\f0c9'; 106 | font-size: 2rem; 107 | height: inherit; 108 | left: 0; 109 | line-height: inherit; 110 | position: absolute; 111 | text-indent: 0; 112 | top: 0; 113 | width: inherit; 114 | } 115 | } 116 | 117 | &.inactive { 118 | margin-left: (_size(sidebar-width) * -1); 119 | } 120 | 121 | @include breakpoint('<=xlarge') { 122 | $pad: 1.5em / 0.9; 123 | 124 | width: _size(sidebar-width-alt); 125 | 126 | > .inner { 127 | @include padding($pad, $pad, (0, 0, $pad, 0)); 128 | width: _size(sidebar-width-alt); 129 | 130 | > .alt { 131 | margin: ($pad * -1) 0 ($pad * 2) ($pad * -1); 132 | padding: $pad; 133 | width: calc(100% + #{$pad * 2}); 134 | } 135 | } 136 | 137 | .toggle { 138 | height: 6.25em; 139 | left: _size(sidebar-width-alt); 140 | line-height: 6.25em; 141 | text-indent: 5em; 142 | width: 5em; 143 | 144 | &:before { 145 | font-size: 1.5rem; 146 | } 147 | } 148 | 149 | &.inactive { 150 | margin-left: (_size(sidebar-width-alt) * -1); 151 | } 152 | } 153 | 154 | @include breakpoint('<=large') { 155 | box-shadow: 0 0 5em 0 rgba(0, 0, 0, 0.175); 156 | height: 100%; 157 | left: 0; 158 | position: fixed; 159 | top: 0; 160 | z-index: _misc(z-index-base); 161 | 162 | &.inactive { 163 | box-shadow: none; 164 | } 165 | 166 | > .inner { 167 | -webkit-overflow-scrolling: touch; 168 | height: 100%; 169 | left: 0; 170 | overflow-x: hidden; 171 | overflow-y: auto; 172 | position: absolute; 173 | top: 0; 174 | 175 | &:after { 176 | content: ''; 177 | display: block; 178 | height: 4em; 179 | width: 100%; 180 | } 181 | } 182 | 183 | .toggle { 184 | text-indent: 6em; 185 | width: 6em; 186 | 187 | &:before { 188 | font-size: 1.5rem; 189 | margin-left: (-0.875em / 2); 190 | } 191 | } 192 | 193 | body.is-preload & { 194 | display: none; 195 | } 196 | } 197 | 198 | @include breakpoint('<=small') { 199 | .toggle { 200 | text-indent: 7.25em; 201 | width: 7.25em; 202 | 203 | &:before { 204 | color: _palette(fg); 205 | margin-left: (-0.125em / 2); 206 | margin-top: (-0.5em / 2); 207 | font-size: 1.1rem; 208 | z-index: 1; 209 | } 210 | 211 | &:after { 212 | background: transparentize(lighten(_palette(fg), 35), 0.25); 213 | border-radius: _size(border-radius); 214 | content: ''; 215 | height: 3.5em; 216 | left: 1em; 217 | position: absolute; 218 | top: 1em; 219 | width: 5em; 220 | } 221 | } 222 | } 223 | } -------------------------------------------------------------------------------- /demo/assets/sass/layout/_wrapper.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Wrapper */ 8 | 9 | #wrapper { 10 | @include vendor('display', 'flex'); 11 | @include vendor('flex-direction', 'row-reverse'); 12 | min-height: 100vh; 13 | } -------------------------------------------------------------------------------- /demo/assets/sass/libs/_breakpoints.scss: -------------------------------------------------------------------------------- 1 | // breakpoints.scss v1.0 | @ajlkn | MIT licensed */ 2 | 3 | // Vars. 4 | 5 | /// Breakpoints. 6 | /// @var {list} 7 | $breakpoints: () !global; 8 | 9 | // Mixins. 10 | 11 | /// Sets breakpoints. 12 | /// @param {map} $x Breakpoints. 13 | @mixin breakpoints($x: ()) { 14 | $breakpoints: $x !global; 15 | } 16 | 17 | /// Wraps @content in a @media block targeting a specific orientation. 18 | /// @param {string} $orientation Orientation. 19 | @mixin orientation($orientation) { 20 | @media screen and (orientation: #{$orientation}) { 21 | @content; 22 | } 23 | } 24 | 25 | /// Wraps @content in a @media block using a given query. 26 | /// @param {string} $query Query. 27 | @mixin breakpoint($query: null) { 28 | 29 | $breakpoint: null; 30 | $op: null; 31 | $media: null; 32 | 33 | // Determine operator, breakpoint. 34 | 35 | // Greater than or equal. 36 | @if (str-slice($query, 0, 2) == '>=') { 37 | 38 | $op: 'gte'; 39 | $breakpoint: str-slice($query, 3); 40 | 41 | } 42 | 43 | // Less than or equal. 44 | @elseif (str-slice($query, 0, 2) == '<=') { 45 | 46 | $op: 'lte'; 47 | $breakpoint: str-slice($query, 3); 48 | 49 | } 50 | 51 | // Greater than. 52 | @elseif (str-slice($query, 0, 1) == '>') { 53 | 54 | $op: 'gt'; 55 | $breakpoint: str-slice($query, 2); 56 | 57 | } 58 | 59 | // Less than. 60 | @elseif (str-slice($query, 0, 1) == '<') { 61 | 62 | $op: 'lt'; 63 | $breakpoint: str-slice($query, 2); 64 | 65 | } 66 | 67 | // Not. 68 | @elseif (str-slice($query, 0, 1) == '!') { 69 | 70 | $op: 'not'; 71 | $breakpoint: str-slice($query, 2); 72 | 73 | } 74 | 75 | // Equal. 76 | @else { 77 | 78 | $op: 'eq'; 79 | $breakpoint: $query; 80 | 81 | } 82 | 83 | // Build media. 84 | @if ($breakpoint and map-has-key($breakpoints, $breakpoint)) { 85 | 86 | $a: map-get($breakpoints, $breakpoint); 87 | 88 | // Range. 89 | @if (type-of($a) == 'list') { 90 | 91 | $x: nth($a, 1); 92 | $y: nth($a, 2); 93 | 94 | // Max only. 95 | @if ($x == null) { 96 | 97 | // Greater than or equal (>= 0 / anything) 98 | @if ($op == 'gte') { 99 | $media: 'screen'; 100 | } 101 | 102 | // Less than or equal (<= y) 103 | @elseif ($op == 'lte') { 104 | $media: 'screen and (max-width: ' + $y + ')'; 105 | } 106 | 107 | // Greater than (> y) 108 | @elseif ($op == 'gt') { 109 | $media: 'screen and (min-width: ' + ($y + 1) + ')'; 110 | } 111 | 112 | // Less than (< 0 / invalid) 113 | @elseif ($op == 'lt') { 114 | $media: 'screen and (max-width: -1px)'; 115 | } 116 | 117 | // Not (> y) 118 | @elseif ($op == 'not') { 119 | $media: 'screen and (min-width: ' + ($y + 1) + ')'; 120 | } 121 | 122 | // Equal (<= y) 123 | @else { 124 | $media: 'screen and (max-width: ' + $y + ')'; 125 | } 126 | 127 | } 128 | 129 | // Min only. 130 | @else if ($y == null) { 131 | 132 | // Greater than or equal (>= x) 133 | @if ($op == 'gte') { 134 | $media: 'screen and (min-width: ' + $x + ')'; 135 | } 136 | 137 | // Less than or equal (<= inf / anything) 138 | @elseif ($op == 'lte') { 139 | $media: 'screen'; 140 | } 141 | 142 | // Greater than (> inf / invalid) 143 | @elseif ($op == 'gt') { 144 | $media: 'screen and (max-width: -1px)'; 145 | } 146 | 147 | // Less than (< x) 148 | @elseif ($op == 'lt') { 149 | $media: 'screen and (max-width: ' + ($x - 1) + ')'; 150 | } 151 | 152 | // Not (< x) 153 | @elseif ($op == 'not') { 154 | $media: 'screen and (max-width: ' + ($x - 1) + ')'; 155 | } 156 | 157 | // Equal (>= x) 158 | @else { 159 | $media: 'screen and (min-width: ' + $x + ')'; 160 | } 161 | 162 | } 163 | 164 | // Min and max. 165 | @else { 166 | 167 | // Greater than or equal (>= x) 168 | @if ($op == 'gte') { 169 | $media: 'screen and (min-width: ' + $x + ')'; 170 | } 171 | 172 | // Less than or equal (<= y) 173 | @elseif ($op == 'lte') { 174 | $media: 'screen and (max-width: ' + $y + ')'; 175 | } 176 | 177 | // Greater than (> y) 178 | @elseif ($op == 'gt') { 179 | $media: 'screen and (min-width: ' + ($y + 1) + ')'; 180 | } 181 | 182 | // Less than (< x) 183 | @elseif ($op == 'lt') { 184 | $media: 'screen and (max-width: ' + ($x - 1) + ')'; 185 | } 186 | 187 | // Not (< x and > y) 188 | @elseif ($op == 'not') { 189 | $media: 'screen and (max-width: ' + ($x - 1) + '), screen and (min-width: ' + ($y + 1) + ')'; 190 | } 191 | 192 | // Equal (>= x and <= y) 193 | @else { 194 | $media: 'screen and (min-width: ' + $x + ') and (max-width: ' + $y + ')'; 195 | } 196 | 197 | } 198 | 199 | } 200 | 201 | // String. 202 | @else { 203 | 204 | // Missing a media type? Prefix with "screen". 205 | @if (str-slice($a, 0, 1) == '(') { 206 | $media: 'screen and ' + $a; 207 | } 208 | 209 | // Otherwise, use as-is. 210 | @else { 211 | $media: $a; 212 | } 213 | 214 | } 215 | 216 | } 217 | 218 | // Output. 219 | @media #{$media} { 220 | @content; 221 | } 222 | 223 | } -------------------------------------------------------------------------------- /demo/assets/sass/libs/_functions.scss: -------------------------------------------------------------------------------- 1 | /// Removes a specific item from a list. 2 | /// @author Hugo Giraudel 3 | /// @param {list} $list List. 4 | /// @param {integer} $index Index. 5 | /// @return {list} Updated list. 6 | @function remove-nth($list, $index) { 7 | 8 | $result: null; 9 | 10 | @if type-of($index) != number { 11 | @warn "$index: #{quote($index)} is not a number for `remove-nth`."; 12 | } 13 | @else if $index == 0 { 14 | @warn "List index 0 must be a non-zero integer for `remove-nth`."; 15 | } 16 | @else if abs($index) > length($list) { 17 | @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`."; 18 | } 19 | @else { 20 | 21 | $result: (); 22 | $index: if($index < 0, length($list) + $index + 1, $index); 23 | 24 | @for $i from 1 through length($list) { 25 | 26 | @if $i != $index { 27 | $result: append($result, nth($list, $i)); 28 | } 29 | 30 | } 31 | 32 | } 33 | 34 | @return $result; 35 | 36 | } 37 | 38 | /// Gets a value from a map. 39 | /// @author Hugo Giraudel 40 | /// @param {map} $map Map. 41 | /// @param {string} $keys Key(s). 42 | /// @return {string} Value. 43 | @function val($map, $keys...) { 44 | 45 | @if nth($keys, 1) == null { 46 | $keys: remove-nth($keys, 1); 47 | } 48 | 49 | @each $key in $keys { 50 | $map: map-get($map, $key); 51 | } 52 | 53 | @return $map; 54 | 55 | } 56 | 57 | /// Gets a duration value. 58 | /// @param {string} $keys Key(s). 59 | /// @return {string} Value. 60 | @function _duration($keys...) { 61 | @return val($duration, $keys...); 62 | } 63 | 64 | /// Gets a font value. 65 | /// @param {string} $keys Key(s). 66 | /// @return {string} Value. 67 | @function _font($keys...) { 68 | @return val($font, $keys...); 69 | } 70 | 71 | /// Gets a misc value. 72 | /// @param {string} $keys Key(s). 73 | /// @return {string} Value. 74 | @function _misc($keys...) { 75 | @return val($misc, $keys...); 76 | } 77 | 78 | /// Gets a palette value. 79 | /// @param {string} $keys Key(s). 80 | /// @return {string} Value. 81 | @function _palette($keys...) { 82 | @return val($palette, $keys...); 83 | } 84 | 85 | /// Gets a size value. 86 | /// @param {string} $keys Key(s). 87 | /// @return {string} Value. 88 | @function _size($keys...) { 89 | @return val($size, $keys...); 90 | } -------------------------------------------------------------------------------- /demo/assets/sass/libs/_html-grid.scss: -------------------------------------------------------------------------------- 1 | // html-grid.scss v1.0 | @ajlkn | MIT licensed */ 2 | 3 | // Mixins. 4 | 5 | /// Initializes the current element as an HTML grid. 6 | /// @param {mixed} $gutters Gutters (either a single number to set both column/row gutters, or a list to set them individually). 7 | /// @param {mixed} $suffix Column class suffix (optional; either a single suffix or a list). 8 | @mixin html-grid($gutters: 1.5em, $suffix: '') { 9 | 10 | // Initialize. 11 | $cols: 12; 12 | $multipliers: 0, 0.25, 0.5, 1, 1.50, 2.00; 13 | $unit: 100% / $cols; 14 | 15 | // Suffixes. 16 | $suffixes: null; 17 | 18 | @if (type-of($suffix) == 'list') { 19 | $suffixes: $suffix; 20 | } 21 | @else { 22 | $suffixes: ($suffix); 23 | } 24 | 25 | // Gutters. 26 | $guttersCols: null; 27 | $guttersRows: null; 28 | 29 | @if (type-of($gutters) == 'list') { 30 | 31 | $guttersCols: nth($gutters, 1); 32 | $guttersRows: nth($gutters, 2); 33 | 34 | } 35 | @else { 36 | 37 | $guttersCols: $gutters; 38 | $guttersRows: 0; 39 | 40 | } 41 | 42 | // Row. 43 | display: flex; 44 | flex-wrap: wrap; 45 | box-sizing: border-box; 46 | align-items: stretch; 47 | 48 | // Columns. 49 | > * { 50 | box-sizing: border-box; 51 | } 52 | 53 | // Gutters. 54 | &.gtr-uniform { 55 | > * { 56 | > :last-child { 57 | margin-bottom: 0; 58 | } 59 | } 60 | } 61 | 62 | // Alignment. 63 | &.aln-left { 64 | justify-content: flex-start; 65 | } 66 | 67 | &.aln-center { 68 | justify-content: center; 69 | } 70 | 71 | &.aln-right { 72 | justify-content: flex-end; 73 | } 74 | 75 | &.aln-top { 76 | align-items: flex-start; 77 | } 78 | 79 | &.aln-middle { 80 | align-items: center; 81 | } 82 | 83 | &.aln-bottom { 84 | align-items: flex-end; 85 | } 86 | 87 | // Step through suffixes. 88 | @each $suffix in $suffixes { 89 | 90 | // Suffix. 91 | @if ($suffix != '') { 92 | $suffix: '-' + $suffix; 93 | } 94 | @else { 95 | $suffix: ''; 96 | } 97 | 98 | // Row. 99 | 100 | // Important. 101 | > .imp#{$suffix} { 102 | order: -1; 103 | } 104 | 105 | // Columns, offsets. 106 | @for $i from 1 through $cols { 107 | > .col-#{$i}#{$suffix} { 108 | width: $unit * $i; 109 | } 110 | 111 | > .off-#{$i}#{$suffix} { 112 | margin-left: $unit * $i; 113 | } 114 | } 115 | 116 | // Step through multipliers. 117 | @each $multiplier in $multipliers { 118 | 119 | // Gutters. 120 | $class: null; 121 | 122 | @if ($multiplier != 1) { 123 | $class: '.gtr-' + ($multiplier * 100); 124 | } 125 | 126 | &#{$class} { 127 | margin-top: ($guttersRows * $multiplier * -1); 128 | margin-left: ($guttersCols * $multiplier * -1); 129 | 130 | > * { 131 | padding: ($guttersRows * $multiplier) 0 0 ($guttersCols * $multiplier); 132 | } 133 | 134 | // Uniform. 135 | &.gtr-uniform { 136 | margin-top: $guttersCols * $multiplier * -1; 137 | 138 | > * { 139 | padding-top: $guttersCols * $multiplier; 140 | } 141 | } 142 | 143 | } 144 | 145 | } 146 | 147 | } 148 | 149 | } -------------------------------------------------------------------------------- /demo/assets/sass/libs/_mixins.scss: -------------------------------------------------------------------------------- 1 | /// Makes an element's :before pseudoelement a FontAwesome icon. 2 | /// @param {string} $content Optional content value to use. 3 | /// @param {string} $category Optional category to use. 4 | /// @param {string} $where Optional pseudoelement to target (before or after). 5 | @mixin icon($content: false, $category: regular, $where: before) { 6 | 7 | text-decoration: none; 8 | 9 | &:#{$where} { 10 | 11 | @if $content { 12 | content: $content; 13 | } 14 | 15 | -moz-osx-font-smoothing: grayscale; 16 | -webkit-font-smoothing: antialiased; 17 | display: inline-block; 18 | font-style: normal; 19 | font-variant: normal; 20 | text-rendering: auto; 21 | line-height: 1; 22 | text-transform: none !important; 23 | 24 | @if ($category == brands) { 25 | font-family: 'Font Awesome 5 Brands'; 26 | } 27 | @elseif ($category == solid) { 28 | font-family: 'Font Awesome 5 Free'; 29 | font-weight: 900; 30 | } 31 | @else { 32 | font-family: 'Font Awesome 5 Free'; 33 | font-weight: 400; 34 | } 35 | 36 | } 37 | 38 | } 39 | 40 | /// Applies padding to an element, taking the current element-margin value into account. 41 | /// @param {mixed} $tb Top/bottom padding. 42 | /// @param {mixed} $lr Left/right padding. 43 | /// @param {list} $pad Optional extra padding (in the following order top, right, bottom, left) 44 | /// @param {bool} $important If true, adds !important. 45 | @mixin padding($tb, $lr, $pad: (0,0,0,0), $important: null) { 46 | 47 | @if $important { 48 | $important: '!important'; 49 | } 50 | 51 | $x: 0.1em; 52 | 53 | @if unit(_size(element-margin)) == 'rem' { 54 | $x: 0.1rem; 55 | } 56 | 57 | padding: ($tb + nth($pad,1)) ($lr + nth($pad,2)) max($x, $tb - _size(element-margin) + nth($pad,3)) ($lr + nth($pad,4)) #{$important}; 58 | 59 | } 60 | 61 | /// Encodes a SVG data URL so IE doesn't choke (via codepen.io/jakob-e/pen/YXXBrp). 62 | /// @param {string} $svg SVG data URL. 63 | /// @return {string} Encoded SVG data URL. 64 | @function svg-url($svg) { 65 | 66 | $svg: str-replace($svg, '"', '\''); 67 | $svg: str-replace($svg, '%', '%25'); 68 | $svg: str-replace($svg, '<', '%3C'); 69 | $svg: str-replace($svg, '>', '%3E'); 70 | $svg: str-replace($svg, '&', '%26'); 71 | $svg: str-replace($svg, '#', '%23'); 72 | $svg: str-replace($svg, '{', '%7B'); 73 | $svg: str-replace($svg, '}', '%7D'); 74 | $svg: str-replace($svg, ';', '%3B'); 75 | 76 | @return url("data:image/svg+xml;charset=utf8,#{$svg}"); 77 | 78 | } -------------------------------------------------------------------------------- /demo/assets/sass/libs/_vars.scss: -------------------------------------------------------------------------------- 1 | // Misc. 2 | $misc: ( 3 | z-index-base: 10000, 4 | ); 5 | 6 | // Duration. 7 | $duration: ( 8 | nav: 0.5s, 9 | transition: 0.2s, 10 | ); 11 | 12 | // Size. 13 | $size: ( 14 | border-radius: 0.375em, 15 | element-height: 2.75em, 16 | element-margin: 2em, 17 | sidebar-width: 26em, 18 | sidebar-width-alt: 24em, 19 | gutter: 3em, 20 | ); 21 | 22 | // Font. 23 | $font: ( 24 | family: ( 25 | "Open Sans", 26 | sans-serif, 27 | ), 28 | family-heading: ( 29 | "Roboto Slab", 30 | serif, 31 | ), 32 | family-fixed: ( 33 | "Courier New", 34 | monospace, 35 | ), 36 | weight: 400, 37 | weight-bold: 600, 38 | weight-heading: 700, 39 | weight-heading-alt: 400, 40 | kerning-heading: 0.075em, 41 | ); 42 | 43 | // Palette. 44 | $palette: ( 45 | bg: #222222, 46 | bg-alt: #303030, 47 | fg: #7f888f, 48 | fg-bold: #3d4449, 49 | fg-light: #9fa3a6, 50 | border: rgba(210, 215, 217, 0.75), 51 | border-bg: transparentize(#e6ebed, 0.75), 52 | accent: #f56a6a, 53 | ); 54 | -------------------------------------------------------------------------------- /demo/assets/sass/libs/_vendor.scss: -------------------------------------------------------------------------------- 1 | // vendor.scss v1.0 | @ajlkn | MIT licensed */ 2 | 3 | // Vars. 4 | 5 | /// Vendor prefixes. 6 | /// @var {list} 7 | $vendor-prefixes: ( 8 | '-moz-', 9 | '-webkit-', 10 | '-ms-', 11 | '' 12 | ); 13 | 14 | /// Properties that should be vendorized. 15 | /// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org 16 | /// @var {list} 17 | $vendor-properties: ( 18 | 19 | // Animation. 20 | 'animation', 21 | 'animation-delay', 22 | 'animation-direction', 23 | 'animation-duration', 24 | 'animation-fill-mode', 25 | 'animation-iteration-count', 26 | 'animation-name', 27 | 'animation-play-state', 28 | 'animation-timing-function', 29 | 30 | // Appearance. 31 | 'appearance', 32 | 33 | // Backdrop filter. 34 | 'backdrop-filter', 35 | 36 | // Background image options. 37 | 'background-clip', 38 | 'background-origin', 39 | 'background-size', 40 | 41 | // Box sizing. 42 | 'box-sizing', 43 | 44 | // Clip path. 45 | 'clip-path', 46 | 47 | // Filter effects. 48 | 'filter', 49 | 50 | // Flexbox. 51 | 'align-content', 52 | 'align-items', 53 | 'align-self', 54 | 'flex', 55 | 'flex-basis', 56 | 'flex-direction', 57 | 'flex-flow', 58 | 'flex-grow', 59 | 'flex-shrink', 60 | 'flex-wrap', 61 | 'justify-content', 62 | 'order', 63 | 64 | // Font feature. 65 | 'font-feature-settings', 66 | 'font-language-override', 67 | 'font-variant-ligatures', 68 | 69 | // Font kerning. 70 | 'font-kerning', 71 | 72 | // Fragmented borders and backgrounds. 73 | 'box-decoration-break', 74 | 75 | // Grid layout. 76 | 'grid-column', 77 | 'grid-column-align', 78 | 'grid-column-end', 79 | 'grid-column-start', 80 | 'grid-row', 81 | 'grid-row-align', 82 | 'grid-row-end', 83 | 'grid-row-start', 84 | 'grid-template-columns', 85 | 'grid-template-rows', 86 | 87 | // Hyphens. 88 | 'hyphens', 89 | 'word-break', 90 | 91 | // Masks. 92 | 'mask', 93 | 'mask-border', 94 | 'mask-border-outset', 95 | 'mask-border-repeat', 96 | 'mask-border-slice', 97 | 'mask-border-source', 98 | 'mask-border-width', 99 | 'mask-clip', 100 | 'mask-composite', 101 | 'mask-image', 102 | 'mask-origin', 103 | 'mask-position', 104 | 'mask-repeat', 105 | 'mask-size', 106 | 107 | // Multicolumn. 108 | 'break-after', 109 | 'break-before', 110 | 'break-inside', 111 | 'column-count', 112 | 'column-fill', 113 | 'column-gap', 114 | 'column-rule', 115 | 'column-rule-color', 116 | 'column-rule-style', 117 | 'column-rule-width', 118 | 'column-span', 119 | 'column-width', 120 | 'columns', 121 | 122 | // Object fit. 123 | 'object-fit', 124 | 'object-position', 125 | 126 | // Regions. 127 | 'flow-from', 128 | 'flow-into', 129 | 'region-fragment', 130 | 131 | // Scroll snap points. 132 | 'scroll-snap-coordinate', 133 | 'scroll-snap-destination', 134 | 'scroll-snap-points-x', 135 | 'scroll-snap-points-y', 136 | 'scroll-snap-type', 137 | 138 | // Shapes. 139 | 'shape-image-threshold', 140 | 'shape-margin', 141 | 'shape-outside', 142 | 143 | // Tab size. 144 | 'tab-size', 145 | 146 | // Text align last. 147 | 'text-align-last', 148 | 149 | // Text decoration. 150 | 'text-decoration-color', 151 | 'text-decoration-line', 152 | 'text-decoration-skip', 153 | 'text-decoration-style', 154 | 155 | // Text emphasis. 156 | 'text-emphasis', 157 | 'text-emphasis-color', 158 | 'text-emphasis-position', 159 | 'text-emphasis-style', 160 | 161 | // Text size adjust. 162 | 'text-size-adjust', 163 | 164 | // Text spacing. 165 | 'text-spacing', 166 | 167 | // Transform. 168 | 'transform', 169 | 'transform-origin', 170 | 171 | // Transform 3D. 172 | 'backface-visibility', 173 | 'perspective', 174 | 'perspective-origin', 175 | 'transform-style', 176 | 177 | // Transition. 178 | 'transition', 179 | 'transition-delay', 180 | 'transition-duration', 181 | 'transition-property', 182 | 'transition-timing-function', 183 | 184 | // Unicode bidi. 185 | 'unicode-bidi', 186 | 187 | // User select. 188 | 'user-select', 189 | 190 | // Writing mode. 191 | 'writing-mode', 192 | 193 | ); 194 | 195 | /// Values that should be vendorized. 196 | /// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org 197 | /// @var {list} 198 | $vendor-values: ( 199 | 200 | // Cross fade. 201 | 'cross-fade', 202 | 203 | // Element function. 204 | 'element', 205 | 206 | // Filter function. 207 | 'filter', 208 | 209 | // Flexbox. 210 | 'flex', 211 | 'inline-flex', 212 | 213 | // Grab cursors. 214 | 'grab', 215 | 'grabbing', 216 | 217 | // Gradients. 218 | 'linear-gradient', 219 | 'repeating-linear-gradient', 220 | 'radial-gradient', 221 | 'repeating-radial-gradient', 222 | 223 | // Grid layout. 224 | 'grid', 225 | 'inline-grid', 226 | 227 | // Image set. 228 | 'image-set', 229 | 230 | // Intrinsic width. 231 | 'max-content', 232 | 'min-content', 233 | 'fit-content', 234 | 'fill', 235 | 'fill-available', 236 | 'stretch', 237 | 238 | // Sticky position. 239 | 'sticky', 240 | 241 | // Transform. 242 | 'transform', 243 | 244 | // Zoom cursors. 245 | 'zoom-in', 246 | 'zoom-out', 247 | 248 | ); 249 | 250 | // Functions. 251 | 252 | /// Removes a specific item from a list. 253 | /// @author Hugo Giraudel 254 | /// @param {list} $list List. 255 | /// @param {integer} $index Index. 256 | /// @return {list} Updated list. 257 | @function remove-nth($list, $index) { 258 | 259 | $result: null; 260 | 261 | @if type-of($index) != number { 262 | @warn "$index: #{quote($index)} is not a number for `remove-nth`."; 263 | } 264 | @else if $index == 0 { 265 | @warn "List index 0 must be a non-zero integer for `remove-nth`."; 266 | } 267 | @else if abs($index) > length($list) { 268 | @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`."; 269 | } 270 | @else { 271 | 272 | $result: (); 273 | $index: if($index < 0, length($list) + $index + 1, $index); 274 | 275 | @for $i from 1 through length($list) { 276 | 277 | @if $i != $index { 278 | $result: append($result, nth($list, $i)); 279 | } 280 | 281 | } 282 | 283 | } 284 | 285 | @return $result; 286 | 287 | } 288 | 289 | /// Replaces a substring within another string. 290 | /// @author Hugo Giraudel 291 | /// @param {string} $string String. 292 | /// @param {string} $search Substring. 293 | /// @param {string} $replace Replacement. 294 | /// @return {string} Updated string. 295 | @function str-replace($string, $search, $replace: '') { 296 | 297 | $index: str-index($string, $search); 298 | 299 | @if $index { 300 | @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); 301 | } 302 | 303 | @return $string; 304 | 305 | } 306 | 307 | /// Replaces a substring within each string in a list. 308 | /// @param {list} $strings List of strings. 309 | /// @param {string} $search Substring. 310 | /// @param {string} $replace Replacement. 311 | /// @return {list} Updated list of strings. 312 | @function str-replace-all($strings, $search, $replace: '') { 313 | 314 | @each $string in $strings { 315 | $strings: set-nth($strings, index($strings, $string), str-replace($string, $search, $replace)); 316 | } 317 | 318 | @return $strings; 319 | 320 | } 321 | 322 | // Mixins. 323 | 324 | /// Wraps @content in vendorized keyframe blocks. 325 | /// @param {string} $name Name. 326 | @mixin keyframes($name) { 327 | 328 | @-moz-keyframes #{$name} { @content; } 329 | @-webkit-keyframes #{$name} { @content; } 330 | @-ms-keyframes #{$name} { @content; } 331 | @keyframes #{$name} { @content; } 332 | 333 | } 334 | 335 | /// Vendorizes a declaration's property and/or value(s). 336 | /// @param {string} $property Property. 337 | /// @param {mixed} $value String/list of value(s). 338 | @mixin vendor($property, $value) { 339 | 340 | // Determine if property should expand. 341 | $expandProperty: index($vendor-properties, $property); 342 | 343 | // Determine if value should expand (and if so, add '-prefix-' placeholder). 344 | $expandValue: false; 345 | 346 | @each $x in $value { 347 | @each $y in $vendor-values { 348 | @if $y == str-slice($x, 1, str-length($y)) { 349 | 350 | $value: set-nth($value, index($value, $x), '-prefix-' + $x); 351 | $expandValue: true; 352 | 353 | } 354 | } 355 | } 356 | 357 | // Expand property? 358 | @if $expandProperty { 359 | @each $vendor in $vendor-prefixes { 360 | #{$vendor}#{$property}: #{str-replace-all($value, '-prefix-', $vendor)}; 361 | } 362 | } 363 | 364 | // Expand just the value? 365 | @elseif $expandValue { 366 | @each $vendor in $vendor-prefixes { 367 | #{$property}: #{str-replace-all($value, '-prefix-', $vendor)}; 368 | } 369 | } 370 | 371 | // Neither? Treat them as a normal declaration. 372 | @else { 373 | #{$property}: #{$value}; 374 | } 375 | 376 | } -------------------------------------------------------------------------------- /demo/assets/sass/main.scss: -------------------------------------------------------------------------------- 1 | @import "libs/vars"; 2 | @import "libs/functions"; 3 | @import "libs/mixins"; 4 | @import "libs/vendor"; 5 | @import "libs/breakpoints"; 6 | @import "libs/html-grid"; 7 | @import "fontawesome-all.min.css"; 8 | @import url("https://fonts.googleapis.com/css?family=Open+Sans:400,600,400italic,600italic|Roboto+Slab:400,700"); 9 | 10 | /* 11 | Editorial by HTML5 UP 12 | html5up.net | @ajlkn 13 | Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 14 | */ 15 | 16 | // Breakpoints. 17 | 18 | @include breakpoints( 19 | ( 20 | xlarge: ( 21 | 1281px, 22 | 1680px, 23 | ), 24 | large: ( 25 | 981px, 26 | 1280px, 27 | ), 28 | medium: ( 29 | 737px, 30 | 980px, 31 | ), 32 | small: ( 33 | 481px, 34 | 736px, 35 | ), 36 | xsmall: ( 37 | 361px, 38 | 480px, 39 | ), 40 | xxsmall: ( 41 | null, 42 | 360px, 43 | ), 44 | xlarge-to-max: "(min-width: 1681px)", 45 | small-to-xlarge: "(min-width: 481px) and (max-width: 1680px)", 46 | ) 47 | ); 48 | 49 | // Base. 50 | 51 | @import "base/reset"; 52 | @import "base/page"; 53 | @import "base/typography"; 54 | 55 | // Component. 56 | 57 | @import "components/row"; 58 | @import "components/section"; 59 | @import "components/form"; 60 | @import "components/box"; 61 | @import "components/icon"; 62 | @import "components/image"; 63 | @import "components/list"; 64 | @import "components/actions"; 65 | @import "components/icons"; 66 | @import "components/contact"; 67 | @import "components/pagination"; 68 | @import "components/table"; 69 | @import "components/button"; 70 | @import "components/mini-posts"; 71 | @import "components/features"; 72 | @import "components/posts"; 73 | 74 | // Layout. 75 | 76 | @import "layout/wrapper"; 77 | @import "layout/main"; 78 | @import "layout/sidebar"; 79 | @import "layout/header"; 80 | @import "layout/banner"; 81 | @import "layout/footer"; 82 | @import "layout/menu"; 83 | -------------------------------------------------------------------------------- /demo/assets/webfonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/assets/webfonts/fa-brands-400.eot -------------------------------------------------------------------------------- /demo/assets/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/assets/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /demo/assets/webfonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/assets/webfonts/fa-brands-400.woff -------------------------------------------------------------------------------- /demo/assets/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/assets/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /demo/assets/webfonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/assets/webfonts/fa-regular-400.eot -------------------------------------------------------------------------------- /demo/assets/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/assets/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /demo/assets/webfonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/assets/webfonts/fa-regular-400.woff -------------------------------------------------------------------------------- /demo/assets/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/assets/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /demo/assets/webfonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/assets/webfonts/fa-solid-900.eot -------------------------------------------------------------------------------- /demo/assets/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/assets/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /demo/assets/webfonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/assets/webfonts/fa-solid-900.woff -------------------------------------------------------------------------------- /demo/assets/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/assets/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /demo/elements.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | Elements - Editorial by HTML5 UP 10 | 11 | 12 | 13 | 18 | 19 | 20 | 21 |
22 | 23 |
24 |
25 | 26 | 49 | 50 | 51 |
52 |
53 |

Elements

54 |
55 | 56 | 57 |

Sample Content

58 |

59 | Praesent ac adipiscing ullamcorper semper ut amet ac risus. Lorem sapien ut odio odio nunc. Ac adipiscing 60 | nibh porttitor erat risus justo adipiscing adipiscing amet placerat accumsan. Vis. Faucibus odio magna 61 | tempus adipiscing a non. In mi primis arcu ut non accumsan vivamus ac blandit adipiscing adipiscing arcu 62 | metus praesent turpis eu ac lacinia nunc ac commodo gravida adipiscing eget accumsan ac nunc adipiscing 63 | adipiscing lorem ipsum dolor sit amet nullam veroeros adipiscing. 64 |

65 |
66 |
67 |

Sem turpis amet semper

68 |

69 | Nunc lacinia ante nunc ac lobortis. Interdum adipiscing gravida odio porttitor sem non mi integer non 70 | faucibus ornare mi ut ante amet placerat aliquet. Volutpat commodo eu sed ante lacinia. Sapien a lorem 71 | in integer ornare praesent commodo adipiscing arcu in massa commodo lorem accumsan at odio massa ac 72 | ac. Semper adipiscing varius montes viverra nibh in adipiscing blandit tempus accumsan. 73 |

74 |
75 |
76 |

Magna odio tempus commodo

77 |

78 | In arcu accumsan arcu adipiscing accumsan orci ac. Felis id enim aliquet. Accumsan ac integer lobortis 79 | commodo ornare aliquet accumsan erat tempus amet porttitor. Ante commodo blandit adipiscing integer 80 | semper orci eget. Faucibus commodo adipiscing mi eu nullam accumsan morbi arcu ornare odio mi 81 | adipiscing nascetur lacus ac interdum morbi accumsan vis mi accumsan. 82 |

83 |
84 | 85 |
86 |

Interdum sapien gravida

87 |

88 | Nunc lacinia ante nunc ac lobortis. Interdum adipiscing gravida odio porttitor sem non mi integer non 89 | faucibus ornare mi ut ante amet placerat aliquet. Volutpat eu sed ante lacinia sapien lorem accumsan 90 | varius montes viverra nibh in adipiscing blandit. 91 |

92 |
93 |
94 |

Faucibus consequat lorem

95 |

96 | Nunc lacinia ante nunc ac lobortis. Interdum adipiscing gravida odio porttitor sem non mi integer non 97 | faucibus ornare mi ut ante amet placerat aliquet. Volutpat eu sed ante lacinia sapien lorem accumsan 98 | varius montes viverra nibh in adipiscing blandit. 99 |

100 |
101 |
102 |

Accumsan montes viverra

103 |

104 | Nunc lacinia ante nunc ac lobortis. Interdum adipiscing gravida odio porttitor sem non mi integer non 105 | faucibus ornare mi ut ante amet placerat aliquet. Volutpat eu sed ante lacinia sapien lorem accumsan 106 | varius montes viverra nibh in adipiscing blandit. 107 |

108 |
109 |
110 | 111 |
112 | 113 | 114 |

Elements

115 |
116 |
117 | 118 |

Text

119 |

120 | This is bold and this is strong. This is italic and this is 121 | emphasized. This is superscript text and this is subscript text. This 122 | is underlined and this is code: for (;;) { ... }. Finally, this is a 123 | link. 124 |

125 |
126 |

Heading Level 2

127 |

Heading Level 3

128 |

Heading Level 4

129 |
130 |

131 | Nunc lacinia ante nunc ac lobortis. Interdum adipiscing gravida odio porttitor sem non mi integer non 132 | faucibus ornare mi ut ante amet placerat aliquet. Volutpat eu sed ante lacinia sapien lorem accumsan 133 | varius montes viverra nibh in adipiscing blandit tempus accumsan. 134 |

135 | 136 | 137 |

Lists

138 |
139 |
140 |

Unordered

141 |
    142 |
  • Dolor etiam magna etiam.
  • 143 |
  • Sagittis lorem eleifend.
  • 144 |
  • Felis dolore viverra.
  • 145 |
146 | 147 |

Alternate

148 |
    149 |
  • Dolor etiam magna etiam.
  • 150 |
  • Sagittis lorem eleifend.
  • 151 |
  • Felis feugiat viverra.
  • 152 |
153 |
154 |
155 |

Ordered

156 |
    157 |
  1. Dolor etiam magna etiam.
  2. 158 |
  3. Etiam vel lorem sed viverra.
  4. 159 |
  5. Felis dolore viverra.
  6. 160 |
  7. Dolor etiam magna etiam.
  8. 161 |
  9. Etiam vel lorem sed viverra.
  10. 162 |
  11. Felis dolore viverra.
  12. 163 |
164 | 165 |

Icons

166 | 186 |
187 |
188 |

Definition

189 |
190 |
Item1
191 |
192 |

193 | Lorem ipsum dolor vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis 194 | iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent. Lorem ipsum 195 | dolor. 196 |

197 |
198 |
Item2
199 |
200 |

201 | Lorem ipsum dolor vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis 202 | iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent. Lorem ipsum 203 | dolor. 204 |

205 |
206 |
Item3
207 |
208 |

209 | Lorem ipsum dolor vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis 210 | iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent. Lorem ipsum 211 | dolor. 212 |

213 |
214 |
215 | 216 |

Actions

217 | 221 | 225 |
226 |
227 | 231 |
232 |
233 | 237 |
238 |
239 | 243 |
244 |
245 | 249 |
250 |
251 | 252 |

Pagination

253 |
    254 |
  • Prev
  • 255 |
  • 1
  • 256 |
  • 2
  • 257 |
  • 3
  • 258 |
  • 259 |
  • 8
  • 260 |
  • 9
  • 261 |
  • 10
  • 262 |
  • Next
  • 263 |
264 | 265 | 266 |

Blockquote

267 |
268 | Lorem ipsum dolor vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis 269 | iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent. Lorem ipsum 270 | dolor. Lorem ipsum dolor vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu 271 | felis iaculis volutpat ac adipiscing accumsan eu faucibus. 272 |
273 | 274 | 275 |

Table

276 | 277 |

Default

278 |
279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 |
NameDescriptionPrice
Item1Ante turpis integer aliquet porttitor.29.99
Item2Vis ac commodo adipiscing arcu aliquet.19.99
Item3Morbi faucibus arcu accumsan lorem.29.99
Item4Vitae integer tempus condimentum.19.99
Item5Ante turpis integer aliquet porttitor.29.99
100.00
321 |
322 | 323 |

Alternate

324 |
325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 |
NameDescriptionPrice
Item1Ante turpis integer aliquet porttitor.29.99
Item2Vis ac commodo adipiscing arcu aliquet.19.99
Item3Morbi faucibus arcu accumsan lorem.29.99
Item4Vitae integer tempus condimentum.19.99
Item5Ante turpis integer aliquet porttitor.29.99
100.00
367 |
368 |
369 |
370 | 371 |

Buttons

372 | 376 | 381 | 386 | 390 | 394 | 398 |
    399 |
  • Primary
  • 400 |
  • Default
  • 401 |
402 | 403 | 404 |

Form

405 | 406 |
407 |
408 |
409 | 410 |
411 |
412 | 413 |
414 | 415 |
416 | 423 |
424 | 425 |
426 | 427 | 428 |
429 |
430 | 431 | 432 |
433 |
434 | 435 | 436 |
437 | 438 |
439 | 440 | 441 |
442 |
443 | 444 | 445 |
446 | 447 |
448 | 454 |
455 | 456 |
457 |
    458 |
  • 459 |
  • 460 |
461 |
462 |
463 |
464 | 465 | 466 |

Image

467 | 468 |

Fit

469 | 470 |
471 |
472 |
473 | 474 |
475 |
476 | 477 |
478 |
479 | 480 |
481 | 482 |
483 | 484 |
485 |
486 | 487 |
488 |
489 | 490 |
491 | 492 |
493 | 494 |
495 |
496 | 497 |
498 |
499 | 500 |
501 |
502 |
503 | 504 |

Left & Right

505 |

506 | Lorem ipsum dolor sit accumsan 507 | interdum nisi, quis tincidunt felis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in 508 | faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan eu faucibus. 509 | Integer ac pellentesque praesent tincidunt felis sagittis eget. tempus euismod. Vestibulum ante ipsum 510 | primis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit 511 | adipiscing eu felis iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque 512 | praesent. 513 |

514 |

515 | Lorem ipsum dolor sit accumsan 516 | interdum nisi, quis tincidunt felis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in 517 | faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan eu faucibus. 518 | Integer ac pellentesque praesent tincidunt felis sagittis eget. tempus euismod. Vestibulum ante ipsum 519 | primis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit 520 | adipiscing eu felis iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque 521 | praesent. 522 |

523 | 524 | 525 |

Box

526 |
527 |

528 | Felis sagittis eget tempus primis in faucibus vestibulum. Blandit adipiscing eu felis iaculis 529 | volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent tincidunt felis 530 | sagittis eget. tempus euismod. Magna sed etiam ante ipsum primis in faucibus vestibulum. 531 |

532 |
533 | 534 | 535 |

Preformatted

536 |
i = 0;
537 | 
538 | while (!deck.isInOrder()) {
539 |     print 'Iteration ' + i;
540 |     deck.shuffle();
541 |     i++;
542 | }
543 | 
544 | print 'It took ' + i + ' iterations to sort the deck.';
545 | 
546 |
547 |
548 |
549 |
550 |
551 | 552 | 553 | 650 |
651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | -------------------------------------------------------------------------------- /demo/generic.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | Generic - Editorial by HTML5 UP 10 | 11 | 12 | 13 | 18 | 19 | 20 | 21 |
22 | 23 |
24 |
25 | 26 | 49 | 50 | 51 |
52 |
53 |

Generic

54 |
55 | 56 | 57 | 58 |

59 | Donec eget ex magna. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque venenatis 60 | dolor imperdiet dolor mattis sagittis. Praesent rutrum sem diam, vitae egestas enim auctor sit amet. 61 | Pellentesque leo mauris, consectetur id ipsum sit amet, fergiat. Pellentesque in mi eu massa lacinia 62 | malesuada et a elit. Donec urna ex, lacinia in purus ac, pretium pulvinar mauris. Curabitur sapien risus, 63 | commodo eget turpis at, elementum convallis elit. Pellentesque enim turpis, hendrerit. 64 |

65 |

66 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis dapibus rutrum facilisis. Class aptent 67 | taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Etiam tristique libero eu 68 | nibh porttitor fermentum. Nullam venenatis erat id vehicula viverra. Nunc ultrices eros ut ultricies 69 | condimentum. Mauris risus lacus, blandit sit amet venenatis non, bibendum vitae dolor. Nunc lorem mauris, 70 | fringilla in aliquam at, euismod in lectus. Pellentesque habitant morbi tristique senectus et netus et 71 | malesuada fames ac turpis egestas. In non lorem sit amet elit placerat maximus. Pellentesque aliquam 72 | maximus risus, vel sed vehicula. 73 |

74 |

75 | Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque venenatis dolor imperdiet dolor 76 | mattis sagittis. Praesent rutrum sem diam, vitae egestas enim auctor sit amet. Pellentesque leo mauris, 77 | consectetur id ipsum sit amet, fersapien risus, commodo eget turpis at, elementum convallis elit. 78 | Pellentesque enim turpis, hendrerit tristique lorem ipsum dolor. 79 |

80 | 81 |
82 | 83 |

Interdum sed dapibus

84 |

85 | Donec eget ex magna. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque venenatis 86 | dolor imperdiet dolor mattis sagittis. Praesent rutrum sem diam, vitae egestas enim auctor sit amet. 87 | Pellentesque leo mauris, consectetur id ipsum sit amet, fergiat. Pellentesque in mi eu massa lacinia 88 | malesuada et a elit. Donec urna ex, lacinia in purus ac, pretium pulvinar mauris. Curabitur sapien risus, 89 | commodo eget turpis at, elementum convallis elit. Pellentesque enim turpis, hendrerit. 90 |

91 |

92 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis dapibus rutrum facilisis. Class aptent 93 | taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Etiam tristique libero eu 94 | nibh porttitor fermentum. Nullam venenatis erat id vehicula viverra. Nunc ultrices eros ut ultricies 95 | condimentum. Mauris risus lacus, blandit sit amet venenatis non, bibendum vitae dolor. Nunc lorem mauris, 96 | fringilla in aliquam at, euismod in lectus. Pellentesque habitant morbi tristique senectus et netus et 97 | malesuada fames ac turpis egestas. In non lorem sit amet elit placerat maximus. Pellentesque aliquam 98 | maximus risus, vel sed vehicula. Interdum et malesuada fames ac ante ipsum primis in faucibus. 99 | Pellentesque venenatis dolor imperdiet dolor mattis sagittis. Praesent rutrum sem diam, vitae egestas enim 100 | auctor sit amet. Pellentesque leo mauris, consectetur id ipsum sit amet, fersapien risus, commodo eget 101 | turpis at, elementum convallis elit. Pellentesque enim turpis, hendrerit tristique lorem ipsum dolor. 102 |

103 | 104 |
105 | 106 |

Magna etiam veroeros

107 |

108 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis dapibus rutrum facilisis. Class aptent 109 | taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Etiam tristique libero eu 110 | nibh porttitor fermentum. Nullam venenatis erat id vehicula viverra. Nunc ultrices eros ut ultricies 111 | condimentum. Mauris risus lacus, blandit sit amet venenatis non, bibendum vitae dolor. Nunc lorem mauris, 112 | fringilla in aliquam at, euismod in lectus. Pellentesque habitant morbi tristique senectus et netus et 113 | malesuada fames ac turpis egestas. In non lorem sit amet elit placerat maximus. Pellentesque aliquam 114 | maximus risus, vel sed vehicula. 115 |

116 |

117 | Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque venenatis dolor imperdiet dolor 118 | mattis sagittis. Praesent rutrum sem diam, vitae egestas enim auctor sit amet. Pellentesque leo mauris, 119 | consectetur id ipsum sit amet, fersapien risus, commodo eget turpis at, elementum convallis elit. 120 | Pellentesque enim turpis, hendrerit tristique lorem ipsum dolor. 121 |

122 | 123 |
124 | 125 |

Lorem aliquam bibendum

126 |

127 | Donec eget ex magna. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque venenatis 128 | dolor imperdiet dolor mattis sagittis. Praesent rutrum sem diam, vitae egestas enim auctor sit amet. 129 | Pellentesque leo mauris, consectetur id ipsum sit amet, fergiat. Pellentesque in mi eu massa lacinia 130 | malesuada et a elit. Donec urna ex, lacinia in purus ac, pretium pulvinar mauris. Curabitur sapien risus, 131 | commodo eget turpis at, elementum convallis elit. Pellentesque enim turpis, hendrerit. 132 |

133 |

134 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis dapibus rutrum facilisis. Class aptent 135 | taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Etiam tristique libero eu 136 | nibh porttitor fermentum. Nullam venenatis erat id vehicula viverra. Nunc ultrices eros ut ultricies 137 | condimentum. Mauris risus lacus, blandit sit amet venenatis non, bibendum vitae dolor. Nunc lorem mauris, 138 | fringilla in aliquam at, euismod in lectus. Pellentesque habitant morbi tristique senectus et netus et 139 | malesuada fames ac turpis egestas. In non lorem sit amet elit placerat maximus. Pellentesque aliquam 140 | maximus risus, vel sed vehicula. 141 |

142 |
143 |
144 |
145 | 146 | 147 | 244 |
245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | -------------------------------------------------------------------------------- /demo/images/pic01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/images/pic01.jpg -------------------------------------------------------------------------------- /demo/images/pic02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/images/pic02.jpg -------------------------------------------------------------------------------- /demo/images/pic03.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/images/pic03.jpg -------------------------------------------------------------------------------- /demo/images/pic04.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/images/pic04.jpg -------------------------------------------------------------------------------- /demo/images/pic05.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/images/pic05.jpg -------------------------------------------------------------------------------- /demo/images/pic06.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/images/pic06.jpg -------------------------------------------------------------------------------- /demo/images/pic07.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/images/pic07.jpg -------------------------------------------------------------------------------- /demo/images/pic08.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/images/pic08.jpg -------------------------------------------------------------------------------- /demo/images/pic09.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/images/pic09.jpg -------------------------------------------------------------------------------- /demo/images/pic10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/images/pic10.jpg -------------------------------------------------------------------------------- /demo/images/pic11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH4R4F/theme-toggle/d5b16ebb9e8e27219eaf167cf444dc6238a01807/demo/images/pic11.jpg -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | Editorial by HTML5 UP 10 | 11 | 12 | 13 | 18 | 19 | 20 | 21 |
22 | 23 |
24 |
25 | 26 | 49 | 50 | 51 | 74 | 75 | 76 |
77 |
78 |

Erat lacinia

79 |
80 |
81 |
82 | 83 |
84 |

Portitor ullamcorper

85 |

86 | Aenean ornare velit lacus, ac varius enim lorem ullamcorper dolore. Proin aliquam facilisis ante 87 | interdum. Sed nulla amet lorem feugiat tempus aliquam. 88 |

89 |
90 |
91 |
92 | 93 |
94 |

Sapien veroeros

95 |

96 | Aenean ornare velit lacus, ac varius enim lorem ullamcorper dolore. Proin aliquam facilisis ante 97 | interdum. Sed nulla amet lorem feugiat tempus aliquam. 98 |

99 |
100 |
101 |
102 | 103 |
104 |

Quam lorem ipsum

105 |

106 | Aenean ornare velit lacus, ac varius enim lorem ullamcorper dolore. Proin aliquam facilisis ante 107 | interdum. Sed nulla amet lorem feugiat tempus aliquam. 108 |

109 |
110 |
111 |
112 | 113 |
114 |

Sed magna finibus

115 |

116 | Aenean ornare velit lacus, ac varius enim lorem ullamcorper dolore. Proin aliquam facilisis ante 117 | interdum. Sed nulla amet lorem feugiat tempus aliquam. 118 |

119 |
120 |
121 |
122 |
123 | 124 | 125 |
126 |
127 |

Ipsum sed dolor

128 |
129 |
130 |
131 | 132 |

Interdum aenean

133 |

134 | Aenean ornare velit lacus, ac varius enim lorem ullamcorper dolore. Proin aliquam facilisis ante 135 | interdum. Sed nulla amet lorem feugiat tempus aliquam. 136 |

137 | 140 |
141 |
142 | 143 |

Nulla amet dolore

144 |

145 | Aenean ornare velit lacus, ac varius enim lorem ullamcorper dolore. Proin aliquam facilisis ante 146 | interdum. Sed nulla amet lorem feugiat tempus aliquam. 147 |

148 | 151 |
152 |
153 | 154 |

Tempus ullamcorper

155 |

156 | Aenean ornare velit lacus, ac varius enim lorem ullamcorper dolore. Proin aliquam facilisis ante 157 | interdum. Sed nulla amet lorem feugiat tempus aliquam. 158 |

159 | 162 |
163 |
164 | 165 |

Sed etiam facilis

166 |

167 | Aenean ornare velit lacus, ac varius enim lorem ullamcorper dolore. Proin aliquam facilisis ante 168 | interdum. Sed nulla amet lorem feugiat tempus aliquam. 169 |

170 | 173 |
174 |
175 | 176 |

Feugiat lorem aenean

177 |

178 | Aenean ornare velit lacus, ac varius enim lorem ullamcorper dolore. Proin aliquam facilisis ante 179 | interdum. Sed nulla amet lorem feugiat tempus aliquam. 180 |

181 | 184 |
185 |
186 | 187 |

Amet varius aliquam

188 |

189 | Aenean ornare velit lacus, ac varius enim lorem ullamcorper dolore. Proin aliquam facilisis ante 190 | interdum. Sed nulla amet lorem feugiat tempus aliquam. 191 |

192 | 195 |
196 |
197 |
198 |
199 |
200 | 201 | 202 | 299 |
300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "theme-toggle", 3 | "discription": "A simple theme (dark/light) toggle", 4 | "version": "1.0.0", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/CH4R4F/theme-toggle" 8 | }, 9 | "type": "module", 10 | "main": "./dist/theme-toggle.umd.cjs", 11 | "scripts": { 12 | "dev": "vite", 13 | "build": "vite build", 14 | "preview": "vite preview" 15 | }, 16 | "devDependencies": { 17 | "cssnano": "^5.1.13", 18 | "postcss": "^8.4.16", 19 | "postcss-cli": "^10.0.0", 20 | "postcss-import": "^15.0.0", 21 | "postcss-nesting": "^10.1.10", 22 | "postcss-preset-env": "^7.8.1", 23 | "vite": "^3.1.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | const postcssPresetEnv = require("postcss-preset-env"); 2 | const cssnano = require("cssnano"); 3 | const postcssImport = require("postcss-import"); 4 | const postcssNesting = require("postcss-nesting"); 5 | 6 | module.exports = { 7 | plugins: [ 8 | postcssPresetEnv({ 9 | stage: 0, 10 | features: { 11 | "logical-properties-and-values": false, 12 | "prefers-color-scheme-query": false, 13 | "gap-properties": false, 14 | "custom-properties": false, 15 | "dir-pseudo-class": false, 16 | "focus-within-pseudo-class": false, 17 | "focus-visible-pseudo-class": false, 18 | "color-functional-notation": false, 19 | }, 20 | }), 21 | postcssImport(), 22 | cssnano(), 23 | postcssNesting(), 24 | ], 25 | }; 26 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // theme initial template; 2 | import template from "./template"; 3 | 4 | class ThemeToggle extends HTMLElement { 5 | /** 6 | * @var {string} _initialTheme 7 | */ 8 | _initialTheme = ""; 9 | 10 | constructor() { 11 | super(); 12 | 13 | // append the css file to the shadow dom 14 | this.attachShadow({ mode: "open" }); 15 | 16 | // get the initial theme 17 | this._initialTheme = this.initTheme(); 18 | } 19 | 20 | /** 21 | * @returns {string} theme 22 | */ 23 | get theme() { 24 | return this.getAttribute("theme"); 25 | } 26 | 27 | /** 28 | * @return {?string|number} width 29 | */ 30 | get width() { 31 | return this.getAttribute("width"); 32 | } 33 | 34 | /** 35 | * @returns {?string|boolean} storable 36 | */ 37 | get storable() { 38 | return this.getAttribute("storable"); 39 | } 40 | 41 | /** 42 | * @param {string} theme 43 | * @returns {void} 44 | */ 45 | set theme(theme) { 46 | this.setAttribute("theme", theme); 47 | } 48 | 49 | /** 50 | * Get the initial theme 51 | * @returns {string} theme 52 | */ 53 | initTheme() { 54 | let initTheme = null; 55 | const savedTheme = localStorage.getItem("theme"); 56 | if (savedTheme) { 57 | initTheme = savedTheme; 58 | } else { 59 | const theme = this.theme; 60 | // so defalt theme is light 61 | initTheme = theme === "dark" ? "dark" : "light"; 62 | } 63 | 64 | if (initTheme === "dark") { 65 | this.changeTheme("dark"); 66 | } 67 | 68 | return initTheme; 69 | } 70 | 71 | /** 72 | * @param {string} theme 73 | * @returns {void} 74 | */ 75 | changeThemeIcon(theme) { 76 | this.shadowRoot.querySelector("#theme-toggle").setAttribute("data-theme", theme); 77 | this.shadowRoot.querySelector("#theme-toggle").setAttribute("aria-label", theme); 78 | } 79 | 80 | /** 81 | * @returns {array} array of attributes to observe 82 | */ 83 | static get observedAttributes() { 84 | return ["theme", "width", "storable"]; 85 | } 86 | 87 | /** 88 | * @param {string} name 89 | * @param {?string} oldValue 90 | * @param {?string} newValue 91 | * @returns {void} 92 | */ 93 | attributeChangedCallback(name, oldValue, newValue) { 94 | if (name === "theme" && oldValue !== null) { 95 | if (newValue === "dark") { 96 | this.changeThemeIcon("light"); 97 | if (oldValue === "light") { 98 | this.changeTheme("dark"); 99 | } 100 | } else { 101 | this.changeThemeIcon("dark"); 102 | if (oldValue === "dark") { 103 | this.changeTheme("light"); 104 | } 105 | } 106 | } 107 | } 108 | 109 | /** 110 | * @returns {void} 111 | */ 112 | connectedCallback() { 113 | if (!this.theme) { 114 | return; 115 | } 116 | this.render(); 117 | this.theme = this._initialTheme; 118 | 119 | // add event listener 120 | const themeButton = this.shadowRoot.querySelector("#theme-toggle"); 121 | if (themeButton.isConnected) { 122 | themeButton.addEventListener("click", this.toggleTheme); 123 | } 124 | } 125 | 126 | /** 127 | * Toggle the theme 128 | * @returns {void} 129 | */ 130 | toggleTheme = () => { 131 | const theme = this.getAttribute("theme"); 132 | if (theme === "dark") { 133 | this.setAttribute("theme", "light"); 134 | } else { 135 | this.setAttribute("theme", "dark"); 136 | } 137 | }; 138 | 139 | /** 140 | * 141 | * @param {string} theme 142 | * @returns {void} 143 | */ 144 | changeTheme(theme) { 145 | let root = document.documentElement; 146 | const media = document.querySelectorAll("img, video, iframe, embed, picture, svg"); 147 | if (theme === "light") { 148 | root.style.filter = "invert(0) hue-rotate(0deg)"; 149 | media.forEach((el) => { 150 | el.style.filter = "invert(0) hue-rotate(0deg)"; 151 | }); 152 | } else { 153 | root.style.filter = "invert(1) hue-rotate(180deg)"; 154 | media.forEach((el) => { 155 | el.style.filter = "invert(1) hue-rotate(180deg)"; 156 | }); 157 | } 158 | if (this.storable !== "false" && this.storable !== false) { 159 | localStorage.setItem("theme", theme); 160 | } else { 161 | localStorage.removeItem("theme"); 162 | } 163 | } 164 | 165 | /** 166 | * Render the template and append it to the shadow dom 167 | * @returns {void} 168 | */ 169 | render() { 170 | // get the template 171 | this.shadowRoot.appendChild(template.content.cloneNode(true)); 172 | 173 | // button element 174 | const themeToggle = this.shadowRoot.querySelector("#theme-toggle"); 175 | // regex to validate colors 176 | const HEX_REGEX = /^#(?:[0-9a-fA-F]{3}){1,2}$/g; 177 | // set the width if provided 178 | if (this.width && !isNaN(this.width)) { 179 | themeToggle.style.setProperty("--size", `${this.width}px`); 180 | } 181 | } 182 | } 183 | 184 | export default customElements.define("theme-toggle", ThemeToggle); 185 | -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | .theme-toggle { 2 | --ease-3: cubic-bezier(0.25, 0, 0.3, 1); 3 | --ease-out-5: cubic-bezier(0, 0, 0, 1); 4 | --ease-elastic-3: cubic-bezier(0.5, 1.25, 0.75, 1.25); 5 | --ease-elastic-4: cubic-bezier(0.5, 1.5, 0.75, 1.25); 6 | --size: 2rem; 7 | --icon-fill: #454d54; 8 | --icon-fill-hover: #22262a; 9 | -webkit-tap-highlight-color: transparent; 10 | aspect-ratio: 1; 11 | background: none; 12 | block-size: var(--size); 13 | border: none; 14 | border-radius: 50%; 15 | cursor: pointer; 16 | inline-size: var(--size); 17 | outline-offset: 5px; 18 | padding: 0; 19 | touch-action: manipulation; 20 | } 21 | .theme-toggle > svg { 22 | stroke-linecap: round; 23 | block-size: 100%; 24 | inline-size: 100%; 25 | } 26 | [data-theme="dark"] .theme-toggle { 27 | --icon-fill: #abb3ba; 28 | --icon-fill-hover: #e2e6e9; 29 | } 30 | @media (hover: none) { 31 | .theme-toggle { 32 | --size: 48px; 33 | } 34 | } 35 | .sun-and-moon > .moon, 36 | .sun-and-moon > .sun, 37 | .sun-and-moon > .sun-beams { 38 | transform-origin: center center; 39 | } 40 | .sun-and-moon > .moon, 41 | .sun-and-moon > .sun { 42 | fill: var(--icon-fill); 43 | } 44 | .theme-toggle:hover > .sun-and-moon > .moon, 45 | .theme-toggle:hover > .sun-and-moon > .sun { 46 | fill: var(--icon-fill-hover); 47 | } 48 | .theme-toggle:focus-visible > .sun-and-moon > .moon { 49 | fill: var(--icon-fill-hover); 50 | } 51 | .theme-toggle:focus-visible > .sun-and-moon > .sun { 52 | fill: var(--icon-fill-hover); 53 | } 54 | .sun-and-moon > .sun-beams { 55 | stroke: var(--icon-fill); 56 | stroke-width: 2px; 57 | } 58 | .theme-toggle:hover .sun-and-moon > .sun-beams { 59 | stroke: var(--icon-fill-hover); 60 | } 61 | .theme-toggle:focus-visible .sun-and-moon > .sun-beams { 62 | stroke: var(--icon-fill-hover); 63 | } 64 | [data-theme="dark"] .sun-and-moon > .sun { 65 | transform: scale(1.75); 66 | } 67 | [data-theme="dark"] .sun-and-moon > .sun-beams { 68 | opacity: 0; 69 | } 70 | [data-theme="dark"] .sun-and-moon > .moon > circle { 71 | transform: translate(-7px); 72 | } 73 | @supports (cx: 1) { 74 | [data-theme="dark"] .sun-and-moon > .moon > circle { 75 | cx: 17; 76 | transform: translate(0); 77 | } 78 | } 79 | @media (prefers-reduced-motion: no-preference) { 80 | .sun-and-moon > .sun { 81 | transition: transform 0.5s var(--ease-elastic-3); 82 | } 83 | .sun-and-moon > .sun-beams { 84 | transition: transform 0.5s var(--ease-elastic-4), opacity 0.5s var(--ease-3); 85 | } 86 | .sun-and-moon .moon > circle { 87 | transition: transform 0.25s var(--ease-out-5); 88 | } 89 | @supports (cx: 1) { 90 | .sun-and-moon .moon > circle { 91 | transition: cx 0.25s var(--ease-out-5); 92 | } 93 | } 94 | [data-theme="dark"] .sun-and-moon > .sun { 95 | transform: scale(1.75); 96 | transition-duration: 0.25s; 97 | transition-timing-function: var(--ease-3); 98 | } 99 | [data-theme="dark"] .sun-and-moon > .sun-beams { 100 | transform: rotate(-25deg); 101 | transition-duration: 0.15s; 102 | } 103 | [data-theme="dark"] .sun-and-moon > .moon > circle { 104 | transition-delay: 0.25s; 105 | transition-duration: 0.5s; 106 | } 107 | } 108 | .theme-toggle { 109 | --ease-3: cubic-bezier(0.25, 0, 0.3, 1); 110 | --ease-out-5: cubic-bezier(0, 0, 0, 1); 111 | --ease-elastic-3: cubic-bezier(0.5, 1.25, 0.75, 1.25); 112 | --ease-elastic-4: cubic-bezier(0.5, 1.5, 0.75, 1.25); 113 | --size: 2rem; 114 | --icon-fill: #454d54; 115 | --icon-fill-hover: #22262a; 116 | -webkit-tap-highlight-color: transparent; 117 | aspect-ratio: 1; 118 | background: none; 119 | block-size: var(--size); 120 | border: none; 121 | border-radius: 50%; 122 | cursor: pointer; 123 | inline-size: var(--size); 124 | outline-offset: 5px; 125 | padding: 0; 126 | touch-action: manipulation; 127 | } 128 | .theme-toggle > svg { 129 | stroke-linecap: round; 130 | block-size: 100%; 131 | inline-size: 100%; 132 | } 133 | [data-theme="dark"] .theme-toggle { 134 | --icon-fill: #abb3ba; 135 | --icon-fill-hover: #e2e6e9; 136 | } 137 | @media (hover: none) { 138 | .theme-toggle { 139 | --size: 48px; 140 | } 141 | } 142 | .sun-and-moon > .moon, 143 | .sun-and-moon > .sun, 144 | .sun-and-moon > .sun-beams { 145 | transform-origin: center center; 146 | } 147 | .sun-and-moon > .moon, 148 | .sun-and-moon > .sun { 149 | fill: var(--icon-fill); 150 | } 151 | .theme-toggle:hover > .sun-and-moon > .moon, 152 | .theme-toggle:hover > .sun-and-moon > .sun { 153 | fill: var(--icon-fill-hover); 154 | } 155 | .theme-toggle:focus-visible > .sun-and-moon > .moon { 156 | fill: var(--icon-fill-hover); 157 | } 158 | .theme-toggle:focus-visible > .sun-and-moon > .sun { 159 | fill: var(--icon-fill-hover); 160 | } 161 | .sun-and-moon > .sun-beams { 162 | stroke: var(--icon-fill); 163 | stroke-width: 2px; 164 | } 165 | .theme-toggle:hover .sun-and-moon > .sun-beams { 166 | stroke: var(--icon-fill-hover); 167 | } 168 | .theme-toggle:focus-visible .sun-and-moon > .sun-beams { 169 | stroke: var(--icon-fill-hover); 170 | } 171 | [data-theme="dark"] .sun-and-moon > .sun { 172 | transform: scale(1.75); 173 | } 174 | [data-theme="dark"] .sun-and-moon > .sun-beams { 175 | opacity: 0; 176 | } 177 | [data-theme="dark"] .sun-and-moon > .moon > circle { 178 | transform: translate(-7px); 179 | } 180 | @supports (cx: 1) { 181 | [data-theme="dark"] .sun-and-moon > .moon > circle { 182 | cx: 17; 183 | transform: translate(0); 184 | } 185 | } 186 | @media (prefers-reduced-motion: no-preference) { 187 | .sun-and-moon > .sun { 188 | transition: transform 0.5s var(--ease-elastic-3); 189 | } 190 | .sun-and-moon > .sun-beams { 191 | transition: transform 0.5s var(--ease-elastic-4), opacity 0.5s var(--ease-3); 192 | } 193 | .sun-and-moon .moon > circle { 194 | transition: transform 0.25s var(--ease-out-5); 195 | } 196 | @supports (cx: 1) { 197 | .sun-and-moon .moon > circle { 198 | transition: cx 0.25s var(--ease-out-5); 199 | } 200 | } 201 | [data-theme="dark"] .sun-and-moon > .sun { 202 | transform: scale(1.75); 203 | transition-duration: 0.25s; 204 | transition-timing-function: var(--ease-3); 205 | } 206 | [data-theme="dark"] .sun-and-moon > .sun-beams { 207 | transform: rotate(-25deg); 208 | transition-duration: 0.15s; 209 | } 210 | [data-theme="dark"] .sun-and-moon > .moon > circle { 211 | transition-delay: 0.25s; 212 | transition-duration: 0.5s; 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /src/template.js: -------------------------------------------------------------------------------- 1 | const template = document.createElement("template"); 2 | template.innerHTML = ` 3 | 6 | 25 | `; 26 | 27 | export default template; 28 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | 3 | export default defineConfig({ 4 | build: { 5 | outDir: "dist", 6 | emptyOutDir: true, 7 | polyfillModulePreload: true, 8 | lib: { 9 | entry: "src/index.js", 10 | name: "theme-toggle", 11 | fileName: "theme-toggle", 12 | }, 13 | minify: "esbuild", 14 | }, 15 | }); 16 | --------------------------------------------------------------------------------