This commit is contained in:
Wessel T 2020-07-20 23:39:31 +02:00
parent 6b447e1c68
commit b15b42ab61
No known key found for this signature in database
GPG Key ID: 0DD4FF3D9DF8027F
17 changed files with 126 additions and 91 deletions

View File

@ -5,7 +5,7 @@
[![License](https://img.shields.io/badge/license-BSD%203-blue?style=flat-square)](/LICENSE) [![Discord](https://img.shields.io/discord/659129207208804381?label=discord&color=7289DA&style=flat-square)](https://discord.gg/zv8C9F8) [![Code Size]( https://img.shields.io/github/languages/code-size/mue/mue?color=green&label=size&style=flat-square)]()
<br>
[![Microsoft Edge](https://img.shields.io/badge/dynamic/json?style=flat-square&label=microsoft%20edge&query=%24.version&url=https%3A%2F%2Fmicrosoftedge.microsoft.com%2Faddons%2Fgetproductdetailsbycrxid%2Faepnglgjfokepefimhbnibfjekidhmja)]() [![](https://img.shields.io/amo/v/mue?label=firefox&style=flat-square)]() [![](https://img.shields.io/chrome-web-store/v/bngmbednanpcfochchhgbkookpiaiaid?label=chrome&style=flat-square)]()
[![Microsoft Edge](https://img.shields.io/badge/dynamic/json?style=flat-square&label=microsoft%20edge&query=%24.version&url=https%3A%2F%2Fmicrosoftedge.microsoft.com%2Faddons%2Fgetproductdetailsbycrxid%2Faepnglgjfokepefimhbnibfjekidhmja)](https://microsoftedge.microsoft.com/addons/detail/aepnglgjfokepefimhbnibfjekidhmja) [![Firefox](https://img.shields.io/amo/v/mue?label=firefox&style=flat-square)](https://addons.mozilla.org/firefox/addon/mue) [![Chrome](https://img.shields.io/chrome-web-store/v/bngmbednanpcfochchhgbkookpiaiaid?label=chrome&style=flat-square)](https://chrome.google.com/webstore/detail/mue/bngmbednanpcfochchhgbkookpiaiaid)
Mue is a fast, open and free-to-use browser extension that gives a new, fresh and customizable tab page to most modern browsers
@ -39,12 +39,12 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an
* Fast and free
* Supports multiple browsers
* Actively developed and open source
* Automatically updating API (with no tracking!) with new photos, quotes and offline mode
* Automatically updating API (no tracking) with new photos, quotes and offline mode
* Search bar
* Settings - enable/disable various features and customise parts of Mue
* Update modal, copy button and more!
## Planned Features
* Settings - enable/disable features!
* Update modal, copy button and more!
* Multilingual support
## Installation
@ -63,7 +63,7 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an
[Microsoft Edge Addons](https://microsoftedge.microsoft.com/addons/detail/aepnglgjfokepefimhbnibfjekidhmja)
### Opera/Other
Link: [GitHub Releases](https://github.com/mue/mue/releases)
[GitHub Releases](https://github.com/mue/mue/releases)
### Development
#### Requirements
@ -79,7 +79,7 @@ Link: [GitHub Releases](https://github.com/mue/mue/releases)
<li> run <code>yarn start</code> or <code>npm start</code> to start testing
<li> Code your heart out! (See the sections below for how to build the extension)
</ol>
<h2>Building</h5>
<h2>Building</h2>
<details>
<summary><b>Chrome/Edge (Chromium)</b> (Click to expand)</summary>
<ol>
@ -95,7 +95,7 @@ Link: [GitHub Releases](https://github.com/mue/mue/releases)
<ol>
<li> <code>yarn run build</code> or <code>npm run build</code>
<li> Rename <code>manifest-opera.json</code> in the "manfiest" folder to <code>manifest.json</code> in "build"
<li> Copy <codebackground-opera.js</code> in the "manifest" folder to "build"
<li> Copy <code>background-opera.js</code> in the "manifest" folder to "build"
<li> Visit <code>about://extensions</code> in Opera
<li> Click <b>Load unpacked extension...</b> (Make sure <b>Developer Mode</b> is on)
<li> Go to the directory containing Mue and click <b>ok</b>
@ -127,7 +127,12 @@ Link: [GitHub Releases](https://github.com/mue/mue/releases)
## Credits
### Maintainers
[ohlookitsderpy](https://github.com/ohlookitsderpy) - Founder, Lead development, Photographer <br>
[TurboMarshmello](https://github.com/TurboMarshmello) - Name, Lead design, <br>
[TurboMarshmello](https://github.com/TurboMarshmello) - Name, Lead design, Photographer <br>
### Contributors
[Wessel](https://github.com/Wessel) - Development <br>
[Isaac](https://github.com/eartharoid) - QA, Development, Photographer <br>
[Chris](https://github.com/auguwu) - Development <br>
### Other
[Pexels](https://pexels.com) - Stock photos used for offline mode
@ -135,9 +140,4 @@ Link: [GitHub Releases](https://github.com/mue/mue/releases)
[Opera Forum](https://forums.opera.com/topic/25046/how-to-disable-completely-the-speed-dial/14) - Portions of code to add Opera support <br>
[Google Fonts](https://fonts.google.com/specimen/Lexend+Deca) - Lexend Deca font
### Contributors
[Wessel](https://github.com/Wessel) - Development <br>
[Isaac](https://github.com/eartharoid) - Development <br>
[Chris](https://github.com/auguwu) - Development <br>
And many thanks to [Highholding](https://discord.bio/p/highholding), [Noa Shapira](#), [Roee Lupo](https://github.com/MrSheldon), [Jeroen](#), [Glasvegas](https://twitter.com/_glasvegas), [Anders](https://github.com/FuryingFox/), [Oded Shapira](https://twitter.com/dondishdev) and [Nikka Lai](#) for letting us use their wonderful photographs

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 KiB

After

Width:  |  Height:  |  Size: 276 KiB

View File

@ -3,7 +3,7 @@
"offline_enabled": true,
"name": "Mue",
"description": "Fast, open and free-to-use new tab page for most modern browsers.",
"version": "0.7.1",
"version": "3.0.1",
"browser_action": {
"default_icon": "./icons/extension-icon.png"
},

View File

@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "Mue",
"description": "Fast, open and free-to-use new tab page for most modern browsers.",
"version": "0.7.2",
"version": "3.0.1",
"browser_action": {
"default_icon": "./icons/extension-icon.png"
},

View File

@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "Mue",
"description": "Fast, open and free-to-use new tab page for most modern browsers.",
"version": "0.7.1",
"version": "3.0.1",
"browser_action": {
"default_icon": "./icons/extension-icon.png"
},

View File

@ -13,7 +13,7 @@
"homepage": "https://muetab.xyz",
"bugs": "https://github.com/mue/mue/issues/new?assignees=&labels=bug&template=bug-report.md&title=%5BBUG%5D",
"license": "BSD-3-Clause",
"version": "3.0",
"version": "3.0.1",
"dependencies": {
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@ -26,7 +26,6 @@
"supports-webp": "^2.0.1"
},
"devDependencies": {
"eslint": "^7.3.0",
"node-sass": "^4.14.1"
},
"scripts": {

View File

@ -42,10 +42,14 @@ export default class App extends React.Component {
localStorage.setItem('offlineMode', false);
localStorage.setItem('webp', false);
localStorage.setItem('events', true);
localStorage.setItem('customBackgroundColour', '');
localStorage.setItem('customBackground', '');
localStorage.setItem('greetingName', '');
// Set theme depending on user preferred
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) localStorage.setItem('darkTheme', true);
else localStorage.setItem('darkTheme', false);
localStorage.setItem('darkTheme', false);
// Finally we set this to true so it doesn't run the function on every load
localStorage.setItem('firstRun', true);

View File

@ -23,7 +23,7 @@ export default class Background extends React.Component {
document.getElementById('photographer').innerText = `Photo by ${photographer} (Pexels)`; // Set the credit
}
async setBackground() {
async setBackground() {
const enabled = localStorage.getItem('offlineMode');
if (enabled === 'true') return this.doOffline();
@ -45,7 +45,7 @@ export default class Background extends React.Component {
if (await supportsWebP && enabled === 'true') requestURL = 'https://api.muetab.xyz/getImage?webp=true';
else requestURL = 'https://api.muetab.xyz/getImage?category=Outdoors';
let data = await fetch(requestURL);
data = await data.json();
data = await data.json();
document.getElementById('backgroundImage').setAttribute('style', `-webkit-filter:blur(${localStorage.getItem('blur')}px); background-image: url(${data.file})`); // Set background and blur etc
document.getElementById('photographer').innerText = `Photo by ${data.photographer}`; // Set the credit
@ -58,7 +58,7 @@ export default class Background extends React.Component {
componentDidMount() {
const enabled = localStorage.getItem('background');
if (enabled === 'false') {
document.getElementById('backgroundCredits').style.display = 'none';
document.getElementById('backgroundCredits').style.display = 'none';
return;
}
this.setBackground();

View File

@ -10,26 +10,26 @@ export default class Clock extends React.Component {
ampm: ''
};
}
startTime(time = localStorage.getItem('seconds') === 'true' ? (1000 - Date.now() % 1000) : (60000 - Date.now() % 60000)) {
this.timer = setTimeout(() => {
const now = new Date();
let sec = '';
if (localStorage.getItem('seconds') === 'true') sec = `:${('00' + now.getSeconds()).slice(-2)}`;
if (localStorage.getItem('24hour') === 'true') {
this.setState({
this.setState({
date: `${('00' + now.getHours()).slice(-2)}:${('00' + now.getMinutes()).slice(-2)}${sec}`
});
});
} else {
// 12 hour support
let hours = now.getHours();
if (hours > 12) hours -= 12;
this.setState({
this.setState({
date: `${('00' + hours).slice(-2)}:${('00' + now.getMinutes()).slice(-2)}${sec}`,
ampm: now.getHours() > 11 ? 'PM' : 'AM'
ampm: now.getHours() > 11 ? 'PM' : 'AM'
});
}
@ -47,7 +47,7 @@ export default class Clock extends React.Component {
return <h1 className='clock'>
{this.state.date}
<span className='ampm'>
{this.state.ampm}
{this.state.ampm}
</span>
</h1>;
}

View File

@ -19,7 +19,7 @@ export default class Greeting extends React.Component {
if (m === 11 && d === 25) message = 'Merry Christmas'; // If it's December 25th, set the greeting string to "Merry Christmas"
else if (m === 0 && d === 1) message = 'Happy new year'; // If the date is January 1st, set the greeting string to "Happy new year"
else if (m === 9 && d === 31) message = 'Happy Halloween'; // If it's October 31st, set the greeting string to "Happy Halloween"
return message;
}
@ -27,7 +27,7 @@ export default class Greeting extends React.Component {
const now = new Date();
const hour = now.getHours();
let message = 'Good evening'; // Set the default greeting string to "Good evening"
let message = 'Good evening'; // Set the default greeting string to "Good evening"
if (hour < 12) message = 'Good morning'; // If it's before 12am, set the greeting string to "Good morning"
else if (hour < 18) message = 'Good afternoon'; // If it's before 6pm, set the greeting string to "Good afternoon"
@ -39,12 +39,13 @@ export default class Greeting extends React.Component {
let data = localStorage.getItem('greetingName');
if (typeof data === 'string') {
data = data.replace(/\s/g, ' ');
if (data.length > 0) name = `, ${data}`;
if (data.replace(/\s/g, '').length > 0) {
name = `, ${data.trim()}`;
}
}
// Set the state to the greeting string
this.setState({
this.setState({
greeting: `${message}${name}`
});
}
@ -54,7 +55,7 @@ export default class Greeting extends React.Component {
if (enabled === 'false') return;
this.getGreeting();
}
render() {
return <h1 className='greeting'>
{this.state.greeting}

View File

@ -15,23 +15,23 @@ export default class Quote extends React.Component {
doOffline() {
const quote = Quotes.random(); // Get a random quote from our local package
this.setState({
quote: '"' + quote.quote + '"',
author: quote.author
this.setState({
quote: '"' + quote.quote + '"',
author: quote.author
}); // Set the quote
}
async getQuote() {
const enabled = localStorage.getItem('offlineMode');
if (enabled === 'true') return this.doOffline();
try { // First we try and get a quote from the API...
let data = await fetch('https://api.muetab.xyz/getQuote');
data = await data.json();
if (data.statusCode === 429) this.doOffline(); // If we hit the ratelimit, we fallback to local quotes
this.setState({
quote: '"' + data.quote + '"',
author: data.author
this.setState({
quote: '"' + data.quote + '"',
author: data.author
});
} catch (e) { // ..and if that fails we load one locally
this.doOffline();
@ -43,7 +43,7 @@ export default class Quote extends React.Component {
let toast = document.getElementById('toast');
toast.className = 'show';
setTimeout(() => { toast.className = toast.className.replace('show', ''); }, 3000);
}
}
componentDidMount() {
const enabled = localStorage.getItem('quote');

View File

@ -3,7 +3,7 @@ import React from 'react';
export default class Search extends React.Component {
render() {
const enabled = localStorage.getItem('searchbar');
const enabled = localStorage.getItem('searchBar');
if (enabled === 'false') return (<div></div>);
const searchEngine = localStorage.getItem('searchEngine');
@ -18,7 +18,7 @@ export default class Search extends React.Component {
return (
<div id='searchBar' className='searchbar'>
<form id='searchBar' className='searchbarform' action={url}>
<form id='searchBar' className='searchbarform' action={url}>
<input type='text' placeholder='Search' name='q' id='searchtext' className='searchtext'/>
<div className='blursearcbBG'/>
</form>

View File

@ -1,3 +1,4 @@
// eslint-disable
import React from 'react';
import ExpandMore from '@material-ui/icons/ExpandMore';
@ -25,31 +26,24 @@ export default class Settings extends React.Component {
localStorage.setItem('blur', document.getElementById('blurRange').value); // this is better than inline onChange for performance
localStorage.setItem('greetingName', document.getElementById('greetingName').value);
localStorage.setItem('customBackground', document.getElementById('customBackground').value);
if (!document.getElementById('customBackgroundColour').enabled === 'false') localStorage.setItem('customBackgroundColour', document.getElementById('customBackgroundColour').value);
//if (!document.getElementById('customBackgroundColour').enabled === 'false') localStorage.setItem('customBackgroundColour', document.getElementById('customBackgroundColour').value);
window.location.reload();
}
resetItem(key) {
switch (key) {
case 'greetingName':
localStorage.setItem('greetingName', '');
document.getElementById('greetingName').value = '';
break;
case 'greetingName': document.getElementById('greetingName').value = ''; break;
case 'customBackgroundColour':
localStorage.setItem('customBackgroundColour', '');
document.getElementById('customBackgroundColour').enabled = 'false';
break;
case 'customBackground':
localStorage.setItem('customBackground', '');
document.getElementById('customBackground').value = '';
break;
case 'customBackground': document.getElementById('customBackground').value = ''; break;
case 'blur':
localStorage.setItem('blur', 0);
document.getElementById('blurRange').value = 0;
document.getElementById('blurAmount').innerText = '0';
break;
default:
console.log('[ERROR] resetItem requires a key!');
default: console.log('[ERROR] resetItem requires a key!');
}
this.showToast();
}
@ -63,6 +57,12 @@ export default class Settings extends React.Component {
componentDidMount() {
document.getElementById('greetingName').value = localStorage.getItem('greetingName');
document.getElementById('customBackground').value = localStorage.getItem('customBackground');
/*const hex = localStorage.getItem('customBackgroundColour');
if (!hex === '') {
document.getElementById('customBackgroundColour').value = hex;
document.getElementById('customBackgroundHex').innerText = hex;
}*/
for (const key of Object.keys(localStorage)) {
let value = localStorage.getItem(key);
@ -71,14 +71,14 @@ export default class Settings extends React.Component {
document.getElementById('blurAmount').innerText = value;
document.getElementById('blurRange').value = value;
}
const tag = document.getElementById(`${key}Status`);
if (tag) {
switch (value) {
case 'true': value = true; break;
case 'false': value = false; break;
default: value = true;
default: value = true;
}
tag.checked = value;
@ -88,6 +88,12 @@ export default class Settings extends React.Component {
document.addEventListener('keyup', (event) => {
if (event.keyCode === 13) this.saveStuff();
});
const darkTheme = localStorage.getItem('darkTheme');
if (darkTheme === 'true') {
document.getElementById('customBackground').style.color = 'white';
document.getElementById('greetingName').style.color = 'white';
}
}
render() {
@ -98,7 +104,7 @@ export default class Settings extends React.Component {
<div className='columns'>
<div className='group'>
<div className='section'>
<h4>Time</h4>
<h4>Time</h4>
<ExpandMore className='expandIcons' onClick={() => this.toggleExtra(document.getElementsByClassName('extraSettings')[0], document.getElementsByClassName('expandIcons')[0])} />
<label className="switch">
<input type="checkbox" onClick={()=> this.setItem('time')} id='timeStatus' />
@ -106,18 +112,18 @@ export default class Settings extends React.Component {
</label>
<li className="extraSettings">
<ul>
<input id="1" type="checkbox" onClick={()=> this.setItem('seconds')} id='secondsStatus' />
<input name="1" type="checkbox" onClick={()=> this.setItem('seconds')} id='secondsStatus' />
<label htmlFor="1">Seconds</label>
</ul>
<ul>
<input id="2" type="checkbox" onClick={()=> this.setItem('24hour')} id='24hourStatus' />
<input name="2" type="checkbox" onClick={()=> this.setItem('24hour')} id='24hourStatus' />
<label htmlFor="2">24 Hour</label>
</ul>
</li>
</div>
</div>
<div style={{ "lineHeight": "1px" }} className='section'>
<h4>Greeting</h4>
<h4>Greeting</h4>
<ExpandMore className='expandIcons' onClick={() => this.toggleExtra(document.getElementsByClassName('extraSettings')[1], document.getElementsByClassName('expandIcons')[1])} />
<label className="switch">
<input type="checkbox" onClick={()=> this.setItem('greeting')} id='greetingStatus' />
@ -125,11 +131,11 @@ export default class Settings extends React.Component {
</label>
<li className="extraSettings">
<ul>
<input id="3" type="checkbox" onClick={()=> this.setItem('events')} id='eventsStatus' />
<input name="3" type="checkbox" onClick={()=> this.setItem('events')} id='eventsStatus' />
<label htmlFor="3">Events</label>
</ul>
<ul>
<p>Name for greeting <a className="modalLink" onClick={() => this.resetItem('greetingName')}>Reset</a></p>
<p>Name for greeting <span className="modalLink" onClick={() => this.resetItem('greetingName')}>Reset</span></p>
<input type='text' id='greetingName'></input>
</ul>
</li>
@ -138,12 +144,12 @@ export default class Settings extends React.Component {
<h4>Quote</h4>
<ExpandMore className='expandIcons' onClick={() => this.toggleExtra(document.getElementsByClassName('extraSettings')[2], document.getElementsByClassName('expandIcons')[2])} />
<label className="switch">
<input id="quoteStatus" type="checkbox" onClick={()=> this.setItem('quote')} id='quoteStatus' />
<input type="checkbox" onClick={()=> this.setItem('quote')} id='quoteStatus' />
<span className="slider"></span>
</label>
<li className="extraSettings">
<ul>
<input id="5" type="checkbox" onClick={()=> this.setItem('copyButton')} id='copyButtonStatus' />
<input name="5" type="checkbox" onClick={()=> this.setItem('copyButton')} id='copyButtonStatus' />
<label htmlFor="5">Copy Button</label>
</ul>
</li>
@ -157,19 +163,20 @@ export default class Settings extends React.Component {
</label>
<li className="extraSettings">
<ul>
<p>Adjust Blur (<span id='blurAmount'></span>%) <a className="modalLink" onClick={() => this.resetItem('blur')}>Reset</a></p>
<p>Adjust Blur (<span id='blurAmount'></span>%) <span className="modalLink" onClick={() => this.resetItem('blur')}>Reset</span></p>
</ul>
<ul>
<input className="range" type="range" min="0" max="100" id='blurRange' onInput={() => document.getElementById('blurAmount').innerText = document.getElementById('blurRange').value} />
</ul>
<ul>
<p>Custom Background URL <a className="modalLink" onClick={() => this.resetItem('customBackground')}>Reset</a></p>
<p>Custom Background URL <span className="modalLink" onClick={() => this.resetItem('customBackground')}>Reset</span></p>
<input type='text' id='customBackground'></input>
</ul>
<ul>
<p>Custom Background Colour <a className="modalLink" onClick={() => this.resetItem('customBackgroundColour')}>Reset</a></p>
<input type='color' id='customBackgroundColour'></input>
</ul>
{ /*<ul>
<p>Custom Background Colour <span className="modalLink" onClick={() => this.resetItem('customBackgroundColour')}>Reset</span></p>
<input name='colour' type='color' id='customBackgroundColour' onChange={() => document.getElementById('customBackgroundHex').innerText = document.getElementById('customBackgroundColour').value}></input>
<label for='colour' id='customBackgroundHex'>#00000</label>
</ul> */}
</li>
</div>
<div className='section'>
@ -198,15 +205,16 @@ export default class Settings extends React.Component {
<span className="slider"></span>
</label>
</div>
<h3>Experimental</h3>
<div className='section'>
<h4>Enable WebP (experimental)</h4>
<h4>Enable WebP</h4>
<label className="switch">
<input type="checkbox" onClick={()=> this.setItem('webp')} id='webpStatus' />
<span className="slider"></span>
</label>
</div>
<div className='section'>
<h4>Dark Theme (experimental)</h4>
<h4>Dark Theme</h4>
<label className="switch">
<input type="checkbox" onClick={()=> this.setItem('darkTheme')} id='darkThemeStatus' />
<span className="slider"></span>
@ -215,7 +223,7 @@ export default class Settings extends React.Component {
<button className="apply" onClick={() => this.saveStuff()}>Apply</button>
<button className="reset" onClick={() => this.props.setDefaultSettings()}>Reset</button>
</div>
</div>;
}
}

View File

@ -20,8 +20,8 @@ export default class Update extends React.Component {
try { // First we try and get a quote from the API...
let data = await fetch('https://api.muetab.xyz/getUpdate');
data = await data.json();
this.setState({
title: data.title,
this.setState({
title: data.title,
content: data.content
});
} catch (e) {

View File

@ -13,24 +13,18 @@
}
}
a.modalLink {
.modalLink {
color: #5352ed;
cursor: pointer;
}
.Overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
&:hover {
opacity: 0.8;
}
}
.closeModal {
float: right;
font-size: 2em;
cursor: pointer;
&:hover {
color: grey;
}
@ -46,11 +40,13 @@ a.modalLink {
overflow: hidden; /* prevents background page from scrolling when the modal is open */
}
.ReactModal__Overlay {
.Overlay {
position: fixed;
z-index: 999999;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100vw;
height: 90vh;
display: flex;

View File

@ -6,7 +6,7 @@
flex-direction: row;
display: block;
color: #ffff;
font-family: 'Lexend Deca';
font-family: 'Lexend Deca', sans-serif;;
input[type=text] {
font-size: calc(5px + 1.2vmin);

View File

@ -22,8 +22,6 @@ $gradient: linear-gradient(90deg, #ffb032 0%, #dd3b67 100%);
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
border-radius: 34px;
&:before {
@ -102,6 +100,7 @@ h4, #engines {
box-shadow: 20px #000;
font-size: 1.3em;
position: relative;
font-family: 'Lexend Deca', sans-serif;
&:hover {
transform: translateY(-0.10em);
@ -170,6 +169,10 @@ h4, #engines {
ul {
padding-left: 5px;
margin: 0;
> label {
vertical-align: middle;
}
}
li {
@ -204,4 +207,28 @@ li {
background: $gradient;
cursor: pointer;
}
}
input[type=color] {
border-radius: 100%;
height: 30px;
width: 30px;
box-shadow: 0 0 1rem 0 rgba(0, 0, 0, .2);
border: none;
outline: none;
-webkit-appearance: none;
vertical-align: middle;
&::-webkit-color-swatch-wrapper {
padding: 0;
}
&::-webkit-color-swatch {
border: none;
border-radius: 100%;
}
}
input[type=checkbox] {
vertical-align: middle;
}