Skip to content
Snippets Groups Projects
Commit ce093ccc authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Fix #756: Dark Theme

parent ca5b068a
No related branches found
No related tags found
No related merge requests found
Dark theme (#756)
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<title>Funkwhale</title> <title>Funkwhale</title>
</head> </head>
<body> <body class="theme-light" id="body">
<noscript> <noscript>
<strong>We're sorry but Funkwhale doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> <strong>We're sorry but Funkwhale doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript> </noscript>
......
...@@ -251,6 +251,14 @@ export default { ...@@ -251,6 +251,14 @@ export default {
this.$store.dispatch('instance/fetchSettings') this.$store.dispatch('instance/fetchSettings')
this.fetchNodeInfo() this.fetchNodeInfo()
}, },
'$store.state.ui.theme': {
immediate: true,
handler (newValue, oldValue) {
let oldTheme = oldValue || 'light'
document.body.classList.remove(`theme-${oldTheme}`)
document.body.classList.add(`theme-${newValue}`)
},
},
'$store.state.auth.authenticated' (newValue) { '$store.state.auth.authenticated' (newValue) {
if (!newValue) { if (!newValue) {
this.disconnect() this.disconnect()
......
...@@ -33,6 +33,14 @@ ...@@ -33,6 +33,14 @@
<a href="https://funkwhale.audio/apps" class="item" target="_blank"><translate translate-context="Footer/*/List item.Link">Mobile and desktop apps</translate></a> <a href="https://funkwhale.audio/apps" class="item" target="_blank"><translate translate-context="Footer/*/List item.Link">Mobile and desktop apps</translate></a>
<div role="button" class="item" @click="$emit('show:shortcuts-modal')"><translate translate-context="*/*/*/Noun">Keyboard shortcuts</translate></div> <div role="button" class="item" @click="$emit('show:shortcuts-modal')"><translate translate-context="*/*/*/Noun">Keyboard shortcuts</translate></div>
</div> </div>
<div class="ui form">
<div class="ui field">
<label><translate translate-context="Footer/Settings/Dropdown.Label/Short, Verb">Change theme</translate></label>
<select class="ui dropdown" :value="$store.state.ui.theme" @change="$store.commit('ui/theme', $event.target.value)">
<option v-for="theme in themes" :key="theme.key" :value="theme.key">{{ theme.name }}</option>
</select>
</div>
</div>
</section> </section>
<section class="four wide column"> <section class="four wide column">
<h4 v-translate translate-context="Footer/*/Link" class="ui header">Getting help</h4> <h4 v-translate translate-context="Footer/*/Link" class="ui header">Getting help</h4>
...@@ -76,15 +84,18 @@ export default { ...@@ -76,15 +84,18 @@ export default {
parser.href = url parser.href = url
return parser.hostname return parser.hostname
}, },
themes () {
return [
{
name: this.$pgettext('Footer/Settings/Dropdown.Label/Theme name', 'Light'),
key: 'light'
},
{
name: this.$pgettext('Footer/Settings/Dropdown.Label/Theme name', 'Dark'),
key: 'dark'
}
]
}
} }
} }
</script> </script>
<style scoped>
footer p {
color: grey;
}
footer#footer div.item:hover {
color: rgba(0, 0, 0, 0.87);
}
</style>
...@@ -126,7 +126,4 @@ export default { ...@@ -126,7 +126,4 @@ export default {
.read > span { .read > span {
cursor: pointer; cursor: pointer;
} }
.disabled-row {
color: rgba(40, 40, 40, 0.3);
}
</style> </style>
...@@ -59,12 +59,10 @@ export default { ...@@ -59,12 +59,10 @@ export default {
<!-- Add "scoped" attribute to limit CSS to this component only --> <!-- Add "scoped" attribute to limit CSS to this component only -->
<style> <style>
.playlist.card .header .ellipsis.vertical.large.grey { .playlist.card .header .ellipsis.vertical.large.grey {
font-size: 1.2em; font-size: 1.2em;
margin-right: 0; margin-right: 0;
} }
</style> </style>
<style scoped> <style scoped>
.card .header { .card .header {
...@@ -72,8 +70,7 @@ export default { ...@@ -72,8 +70,7 @@ export default {
} }
.attached.button { .attached.button {
background-color: rgb(243, 244, 245); background-size: 25%;
background-size: 25% ;
background-repeat: no-repeat; background-repeat: no-repeat;
background-origin: border-box; background-origin: border-box;
background-position: 0 0, 33.33% 0, 66.67% 0, 100% 0; background-position: 0 0, 33.33% 0, 66.67% 0, 100% 0;
...@@ -82,5 +79,4 @@ export default { ...@@ -82,5 +79,4 @@ export default {
font-size: 4em; font-size: 4em;
box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.15) inset !important; box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.15) inset !important;
} }
</style> </style>
...@@ -40,7 +40,7 @@ export default new Vuex.Store({ ...@@ -40,7 +40,7 @@ export default new Vuex.Store({
}), }),
createPersistedState({ createPersistedState({
key: 'ui', key: 'ui',
paths: ['ui.currentLanguage', 'ui.momentLocale'] paths: ['ui.currentLanguage', 'ui.momentLocale', 'ui.theme']
}), }),
createPersistedState({ createPersistedState({
key: 'radios', key: 'radios',
......
...@@ -10,6 +10,7 @@ export default { ...@@ -10,6 +10,7 @@ export default {
maxMessages: 100, maxMessages: 100,
messageDisplayDuration: 10000, messageDisplayDuration: 10000,
messages: [], messages: [],
theme: 'light',
notifications: { notifications: {
inbox: 0, inbox: 0,
pendingReviewEdits: 0, pendingReviewEdits: 0,
...@@ -39,6 +40,9 @@ export default { ...@@ -39,6 +40,9 @@ export default {
computeLastDate: (state) => { computeLastDate: (state) => {
state.lastDate = new Date() state.lastDate = new Date()
}, },
theme: (state, value) => {
state.theme = value
},
addMessage (state, message) { addMessage (state, message) {
state.messages.push(message) state.messages.push(message)
if (state.messages.length > state.maxMessages) { if (state.messages.length > state.maxMessages) {
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
Import this file into your LESS project to use Semantic UI without build tools Import this file into your LESS project to use Semantic UI without build tools
*/ */
// Those semantic-ui-css/*.scss don't exist in the package, but we create them
// via scripts/link-scss-files.sh on postinstall, so we can include theme
// under a class namespace
/* Global */ /* Global */
@import "~semantic-ui-css/components/reset.css"; @import "~semantic-ui-css/components/reset.css";
// we use our custom site css here to avoid loading google font // we use our custom site css here to avoid loading google font
...@@ -96,6 +100,7 @@ body { ...@@ -96,6 +100,7 @@ body {
#app > main, #app > .main { #app > main, #app > .main {
flex: 1; flex: 1;
} }
.instance-chooser { .instance-chooser {
margin-top: 2em; margin-top: 2em;
} }
...@@ -126,14 +131,10 @@ body { ...@@ -126,14 +131,10 @@ body {
margin-left: 0; margin-left: 0;
margin-right: 0; margin-right: 0;
border: none; border: none;
box-shadow: inset 0px -2px 0px 0px rgba(34, 36, 38, 0.15);
.ui.item { .ui.item {
border: none; border: none;
border-bottom-style: none; border-bottom-style: none;
margin-bottom: 0px; margin-bottom: 0px;
&.active {
box-shadow: inset 0px -2px 0px 0px #000;
}
} }
@include media(">tablet") { @include media(">tablet") {
padding: 0 2.5rem; padding: 0 2.5rem;
...@@ -148,7 +149,6 @@ body { ...@@ -148,7 +149,6 @@ body {
@include media(">widedesktop") { @include media(">widedesktop") {
left: $widedesktop-sidebar-width; left: $widedesktop-sidebar-width;
} }
background-color: white;
.item { .item {
padding-top: 1.5em; padding-top: 1.5em;
padding-bottom: 1.5em; padding-bottom: 1.5em;
...@@ -208,9 +208,6 @@ body { ...@@ -208,9 +208,6 @@ body {
} }
} }
.discrete {
color: rgba(0, 0, 0, 0.87);
}
.link { .link {
cursor: pointer; cursor: pointer;
} }
...@@ -355,3 +352,8 @@ input + .help { ...@@ -355,3 +352,8 @@ input + .help {
.table td .ui.dropdown { .table td .ui.dropdown {
min-width: 150px; min-width: 150px;
} }
@import "./themes/_light.scss";
@import "./themes/_dark.scss";
$background-color: rgb(43, 58, 66);
$button-hover-color: rgb(33, 48, 56);
$light-background-color: rgb(51, 71, 82);
$input-background-color: rgb(189, 211, 222);
$loading-background-color: rgba(43, 58, 66, 0.9);
$text-color: rgb(223, 235, 240);
$discrete-text-color: rgba(223, 235, 240, 0.904);
$border-color: rgb(63, 88, 102);
$light-shadow-color: rgba(223, 235, 240, 0.15);
$shadow-color: rgba(63, 102, 97, 0.95);
$box-shadow: 0px 1px 3px 0px rgba(63, 88, 102, 0.95), 0px 0px 0px 1px rgba(63, 88, 102, 0.98);
$link-color: rgb(255, 144, 0);
.theme-dark {
background-color: $background-color;
.ui.labeled.input {
input, .label {
background-color: $input-background-color;
&::placeholder {
color: $light-background-color;
}
}
}
.ui.statistics .statistic {
> .label, > .value {
color: $text-color;
}
}
.ui.link.list.list .active.item, .ui.link.list.list .active.item a:not(.ui) {
color: inherit;
}
.ui.form textarea, .ui.form select, .ui.selection.dropdown, .ui.dropdown.selected, .ui.dropdown .menu .selected.item, .ui.form input:not([type]), .ui.form input[type="date"], .ui.form input[type="datetime-local"], .ui.form input[type="email"], .ui.form input[type="number"], .ui.form input[type="password"], .ui.form input[type="search"], .ui.form input[type="tel"], .ui.form input[type="time"], .ui.form input[type="text"], .ui.form input[type="file"], .ui.form input[type="url"] {
background-color: $input-background-color;
&::placeholder {
color: $light-background-color;
}
}
.ui.dropdown .menu .item:hover {
background-color: $light-background-color;
color: $text-color;
}
.main.pusher > .ui.secondary.menu {
background-color: $background-color;
box-shadow: inset 0px -2px 0px 0px $light-background-color;
.ui.item {
color: $text-color;
&.active {
box-shadow: inset 0px -2px 0px 0px $shadow-color;
}
}
}
.ui.modal {
> .header, > .content, > .actions {
background-color: $background-color;
}
> .header {
border-bottom: 1px solid $border-color;
}
> .actions {
border-top: 1px solid $border-color;
}
}
main, .main, footer, .modal {
.ui.menu {
background-color: $light-background-color;
.item {
color: $text-color;
}
}
.ui.secondary.menu .dropdown.item:hover, .ui.secondary.menu .link.item:hover, .ui.secondary.menu a.item:hover {
background: $background-color;
color: $text-color;
}
.header, .ui.form .field > label, .sub.header {
color: $text-color;
}
.ui.attached.header {
background-color: transparent;
}
.ui.toggle.checkbox input:checked ~ .box, .ui.toggle.checkbox input:checked ~ label {
color: $text-color !important;
}
.ui.toggle.checkbox .box::before, .ui.toggle.checkbox label::before {
background-color: $light-background-color;
}
a:not(.ui):not(.discrete) {
color: $link-color;
}
.ui.segment:not(.basic) {
background-color: $light-background-color;
}
.ui.list, .ui.dropdown {
.item, div.item, a.item, .button.item {
background-color: $background-color;
color: $discrete-text-color;
}
.selected.item:not(:hover) {
color: $background-color;
}
}
.ui.divided.items > .item:not(:first-child) {
border-top: 1px solid $border-color;
}
.ui.items {
.extra {
color: $discrete-text-color;
}
}
label, .toggle label {
color: $text-color !important;
}
&, .main.pusher, .ui.vertical.segment {
color: $text-color;
background-color: $background-color;
}
.discrete {
color: $discrete-text-color;
}
.ui.table thead th, .ui.table {
color: $text-color;
}
.ui.divider:not(.vertical):not(.horizontal) {
border-top: 1px solid $border-color;
border-bottom: 1px solid $border-color;
}
.ui.cards > .card, .ui.card {
color: $text-color;
background-color: $background-color;
box-shadow: $box-shadow;
.content, .header, .description {
color: $text-color;
}
.extra, .meta {
color: $discrete-text-color;
}
}
.playlist.card {
.attached.button {
background-color: $light-background-color;
}
}
// buttons
[class='ui button ui button'], [class='ui button'], [class='ui icon button'], [class='ui fluid button'], [class='ui cancel button'] {
background-color: $light-background-color;
color: $text-color;
&:hover {
background-color: $button-hover-color;
}
}
.ui.buttons > .ui.button:not(.basic):not(.inverted), .ui.buttons:not(.basic):not(.inverted) > .button {
box-shadow: 0px 0px 0px 1px $light-shadow-color inset;
}
.ui.basic.buttons:not(:hover):not(.green):not(.orange):not(.yellow):not(.red) .button, .ui.basic.button {
box-shadow: 0px 0px 0px 1px $text-color inset;
&:not(:hover):not(.green):not(.orange):not(.yellow):not(.red) {
color: $text-color !important;
}
}
.ui.basic.buttons .button, .ui.basic.button {
&:hover {
color: $text-color !important;
}
}
.ui.basic.buttons:not(.green):not(.orange):not(.yellow):not(.red) .button:hover, .ui.basic.button:not(.green):not(.orange):not(.yellow):not(.red):hover, .ui.basic.button:not(.green):not(.orange):not(.yellow):not(.red):active, .ui.basic.button:not(.green):not(.orange):not(.yellow):not(.red):focus {
color: $background-color !important;
}
// loading /dimmers
.ui.loading.form::before {
background-color: $loading-background-color;
}
.ui.inverted.dimmer {
background-color: $loading-background-color;
}
// table
.ui.basic.table tbody tr, .ui.table tr td {
border-bottom: 1px solid $border-color;
}
.ui.table thead th {
border-bottom: 1px solid $border-color;
}
.ui.table {
&:not(.basic) {
&, thead th {
background-color: $light-background-color;
}
}
}
}
.ui.link.list.list a.item:hover, .ui.link.list.list .item a:not(.ui):not(.button):hover {
color: $link-color;
}
[data-tooltip]::after {
background-color: $light-background-color;
color: $text-color;
}
.ui.progress > .label {
color: $text-color;
}
i.grey.icon {
color: $text-color !important;
}
input {
&::selection, &::-moz-selection {
background: $background-color;
color: $text-color;
}
}
}
.theme-light {
.main.pusher > .ui.secondary.menu {
box-shadow: inset 0px -2px 0px 0px rgba(34, 36, 38, 0.15);
background-color: white;
.ui.item {
&.active {
box-shadow: inset 0px -2px 0px 0px #000;
}
}
}
.discrete {
color: rgba(0, 0, 0, 0.87);
}
.playlist.card {
.attached.button {
background-color: rgb(243, 244, 245);
}
}
.disabled-row {
color: rgba(40, 40, 40, 0.3);
}
footer p {
color: grey;
}
footer#footer div.item:hover {
color: rgba(0, 0, 0, 0.87);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment