This commit is contained in:
Paweł Jaśpiński 2021-06-22 11:40:20 +02:00
commit a383b912ad
35 changed files with 2322 additions and 90 deletions

119
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,119 @@
# Contributing guidelines
Here are the guidelines for contributing to this repository.
## Before contributing
For avoiding having too many similar themes with small changes, themes are merged only if they bring **sensitive** changes to default Spotify UI and are different from existing themes.
A theme name (as well as color scheme name) should consist of one word starting with an uppercase letter and shouldn't contain `spicetify` or any whitespace in it; if a "-" is present in the name it must be followed by an uppercase letter.
## How to contribute
If you want to add your theme:
* Fork this repository
* Create another folder named after your theme name
* Create `color.ini` and `user.css` files
* Create a `README.md` in it with the following structure
```markdown
# THEME_NAME
## Screenshots
[Put at least one image per color scheme here]
## More
[Specify any needed font; (optionally) author name and/or any other info about the theme]
```
* Add the theme preview to [THEMES.md](./THEMES.md) (themes are in alphabetical order) following this structure if it has only one color scheme
```markdown
## THEME_NAME
[A single image of the theme]
```
If, instead, more than one color scheme is present
```markdown
## THEME_NAME
#### COLOR_SCHEME1_NAME
[A single image of the theme using the color scheme]
#### COLOR_SCHEME2_NAME
[A single image of the theme using the color scheme]
...
```
* Commit only once, more details in the **Commit Message**
* Open a Pull Request and mention the most important changes you've made to the UI (ignoring the color scheme)
**Thanks to all the contributors.**
## Commit Message
**NOTE: commit only once when you add a new theme or scheme (you can also commit again later, if you need to).**
### Format
<type>(<scope>): <subject>
<BLANK LINE>
<body>[optional]
**Any line of the commit message cannot be longer than 100 characters!**
* **type:** feat | fix | docs | chore
* **feat:** A new theme | A new scheme | A new feature
* **fix:** A bug fix
* **docs:** Change the `README.md` of the theme | Change the `THEMES.md`
* **chore:** Add more screenshots | Change the screentshots | Other things
* **scope:** THEMES | `<ThemeName>`
* THEMES is a fixed format: `docs(THEMES)`
* In other cases, use the theme name
* **subject:** What changes you have done
* Use the imperative, present tense: "change" not "changed" nor "changes"
* Don't capitalize first letter
* No dot (.) at the end
* **body**: More details of your changes, you can mention the most important changes here
### Example (Turntable theme)
* feat
```
feat(Turntable): add Turntable theme
```
```
feat(Turntable): control the rotation of the turntable
Rotate the turntable by playing state.
```
* fix
```
fix(Turntable): show the cursor outside the context menu
```
* docs
```
docs(Turntable): update README.md
```
```
docs(THEMES): add preview for the Turntable
```
* chore
```
chore(Turntable): add screenshots of the Turntable
```
If you want to learn more, view the [Angular - Git Commit Guidelines](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines).

94
Dribbblish/README.md Normal file
View File

@ -0,0 +1,94 @@
# Dribbblish
### Base
![base](base.png)
### White
![white](white.png)
### Dark
![dark](dark.png)
### Nord-Light
![nord-light](nord-light.png)
### Nord-Dark
![nord-dark](nord-dark.png)
### Beach-Sunset
![beach-sunset](beach-sunset.png)
### Purple
![purple](purple.png)
### Samourai
![samourai](samourai.png)
### Gruvbox
![gruvbox](gruvbox.png)
## Features
### Resizable sidebar
<img src="https://i.imgur.com/1zomkmd.png" alt="img" align="center" width="500px">
### Customizable sidebar
Rearrange icons positions, stick icons to header or hide unnecessary to save space.
Turn on Config mode in Profile menu and hover on icon to show control buttons.
After you finish customizing, turn off Config mode in Profile menu to save.
<img src="https://i.imgur.com/86gqPe8.png" alt="img" align="center" width="500px">
### Playlist Folder image
Right click at folder and choose images for your playlist folder. Every image formats supported by Chrome can be used, but do keep image size small and in compressed format.
<img src="https://i.imgur.com/WGQ7Bev.gif" alt="img" align="center" width="500px">
### Left/Right expanded cover
In profile menu, toggle option "Right expanded cover" to change expaned current track cover image to left or right side, whereever you prefer.
## Install
Make sure you are using spicetify v2 and Spotify v1.1.58 or later.
Run these commands:
### Linux and MacOS:
In **Bash**:
```bash
cd "$(dirname "$(spicetify -c)")/Themes/Dribbblish"
mkdir -p ../../Extensions
cp dribbblish.js ../../Extensions/.
spicetify config extensions dribbblish.js
spicetify config current_theme Dribbblish color_scheme base
spicetify config inject_css 1 replace_colors 1 overwrite_assets 1
spicetify apply
```
### Windows
In **Powershell**:
```powershell
cd "$(spicetify -c | Split-Path)\Themes\Dribbblish"
Copy-Item dribbblish.js ..\..\Extensions
spicetify config extensions dribbblish.js
spicetify config current_theme Dribbblish color_scheme base
spicetify config inject_css 1 replace_colors 1 overwrite_assets 1
spicetify apply
```
## Change Color Schemes
There are 9 color schemes you can choose: `base`, `white`, `dark`, `dracula`, `nord-dark`, `nord-light`, `samourai`, `purple`. Change scheme with commands:
```
spicetify config color_scheme <scheme name>
spicetify apply
```
## Hide Window Controls
Windows user, please edit your Spotify shortcut and add flag `--transparent-window-controls` after the Spotify.exe:
![instruction1](./windows-shortcut-instruction.png)
Alternatively, you can use `SpotifyNoControl.exe`, included in this theme package, to completely remove all windows controls and title menu (three dot at top left corner). Title menu still can be access via Alt key. Closing, minimizing can be done via right click menu at top window region.
`SpotifyNoControl.exe` could be used as Spotify launcher, it opens Spotify and hides controls right after. You can drag and drop it to your taskbar but make sure you unpin the original Spotify icon first. Alternatively you can make a shortcut for it and add to desktop or start menu.
Moreover, by default, Spotify adjusted sidebar items and profile menu icon to stay out of Windows native controls region. If you decided to use `SpotifyNoControl.exe` from now on, please open `user.css` file and change variable `--os-windows-icon-dodge` value to 0 as instruction to snap icons back to their original position.
![nocontrol](https://i.imgur.com/qdZyv1t.png)
## Uninstall
Remove the dribbblish script with the following commands
```
spicetify config extensions dribbblish.js-
spicetify apply
```

Binary file not shown.

BIN
Dribbblish/base.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 KiB

BIN
Dribbblish/beach-sunset.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 KiB

180
Dribbblish/color.ini Normal file
View File

@ -0,0 +1,180 @@
[base]
text = FFFFFF
subtext = F0F0F0
sidebar-text = FFFFFF
main = 000000
sidebar = 1ed760
player = 000000
card = 000000
shadow = 202020
selected-row = 797979
button = 1ed760
button-active = 1ed760
button-disabled = 535353
tab-active = 166632
notification = 1db954
notification-error = e22134
misc = BFBFBF
[white]
text = 363636
subtext = 3D3D3D
sidebar-text = FFF9F4
main = FFF9F4
sidebar = FFA789
player = FFF9F4
card = FFF9F4
shadow = d3d3d3
selected-row = 6D6D6D
button = ff8367
button-active = ff8367
button-disabled = 535353
tab-active = ffdace
notification = FFA789
notification-error = e22134
misc = BFBFBF
[dark]
text = F0F0F0
subtext = F0F0F0
sidebar-text = 0a0e14
main = 0a0e14
sidebar = C2D935
player = 0a0e14
card = 0a0e14
shadow = 202020
selected-row = DEDEDE
button = C2D935
button-active = C2D935
button-disabled = 535353
tab-active = 727d2b
notification = C2D935
notification-error = e22134
misc = BFBFBF
[dracula]
text = f8f8f2
subtext = f8f8f2
sidebar-text = F0F0F0
main = 44475a
sidebar = 6272a4
player = 44475a
card = 6272a4
shadow = 000000
selected-row = bd93f9
button = ffb86c
button-active = 8be9fd
button-disabled = 535353
tab-active = 6272a4
notification = bd93f9
notification-error = e22134
misc = BFBFBF
[nord-light]
text = 2e3440
subtext = 3b4252
sidebar-text = ECEFF4
main = ECEFF4
sidebar = 5E81AC
player = ECEFF4
card = ebcb8b
shadow = eceff4
selected-row = 4c566a
button = 81a1c1
button-active = 81a1c1
button-disabled = c0c0c0
tab-active = ebcb8b
notification = a3be8c
notification-error = bf616a
misc = BFBFBF
[nord-dark]
text = ECEFF4
subtext = E5E9F0
sidebar-text = 434c5e
main = 2e3440
sidebar = 88C0D0
player = 2e3440
card = 2e3440
shadow = 2E3440
selected-row = D8DEE9
button = 81A1C1
button-active = 81A1C1
button-disabled = 434C5E
tab-active = 434C5E
notification = A3BE8C
notification-error = BF616A
misc = BFBFBF
[purple]
text = f1eaff
subtext = f1eaff
sidebar-text = e0d0ff
main = 0A0E14
sidebar = 6F3C89
player = 0A0E14
card = 0A0E14
shadow = 3a2645
selected-row = EBDFFF
button = c76af6
button-active = 6F3C89
button-disabled = 535353
tab-active = 58306D
notification = ff9e00
notification-error = f61379
misc = DEDEDE
[samourai]
text = ebdbb2
subtext = ebdbb2
sidebar-text = 461217
main = 461217
sidebar = ebdbb2
player = 461217
card = 461217
shadow = 3a2645
selected-row = 909090
button = e7a52d
button-active = e7a52d
button-disabled = 535353
tab-active = e7a52d
notification = e7a52d
notification-error = e22134
misc = BFBFBF
[beach-sunset]
text = FFFFFF
subtext = F0F0F0
sidebar-text = F0F0F0
main = 262626
sidebar = bd3e3e
player = 262626
card = 262626
shadow = 000000
selected-row = d1d6e2
button = f1a84f
button-active = c98430
button-disabled = 535353
tab-active = f1a84f
notification = c98430
notification-error = e22134
misc = BFBFBF
[gruvbox]
text = fbf1c7
subtext = d5c4a1
sidebar-text = 32302f
main = 292828
sidebar = 689d6a
player = 292828
card = 3c3836
shadow = 202020
selected-row = d5c4a1
button = fb4934
button-active = cc241d
button-disabled = bdae93
tab-active = fb4934
notification = 8ec07c
notification-error = d79921
misc = BFBFBF

BIN
Dribbblish/dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB

400
Dribbblish/dribbblish.js Normal file
View File

@ -0,0 +1,400 @@
// Hide popover message
// document.getElementById("popover-container").style.height = 0;
const DribbblishShared = {
configMenu: new Spicetify.Menu.SubMenu("Dribbblish", []),
rightBigCover: localStorage.getItem("dribs-right-big-cover") === "true",
setRightBigCover: () => {
if (DribbblishShared.rightBigCover) {
document.documentElement.classList.add("right-expanded-cover");
} else {
document.documentElement.classList.remove("right-expanded-cover");
}
}
};
DribbblishShared.configMenu.register();
DribbblishShared.configMenu.subItems.push(new Spicetify.Menu.Item(
"Right expanded cover",
DribbblishShared.rightBigCover,
(self) => {
self.isEnabled = !self.isEnabled;
DribbblishShared.rightBigCover = self.isEnabled;
localStorage.setItem("dribs-right-big-cover", self.isEnabled);
DribbblishShared.setRightBigCover();
}
));
DribbblishShared.setRightBigCover();
function waitForElement(els, func, timeout = 100) {
const queries = els.map(el => document.querySelector(el));
if (queries.every(a => a)) {
func(queries);
} else if (timeout > 0) {
setTimeout(waitForElement, 300, els, func, --timeout);
}
}
waitForElement([".main-rootlist-rootlistPlaylistsScrollNode ul"], ([query]) => {
/** Replace Playlist name with their pictures */
function loadPlaylistImage() {
const sidebarItem = query.querySelectorAll("li.GlueDropTarget");
for (let i = 0; i < sidebarItem.length; i++) {
const item = sidebarItem[i];
let link = item.querySelector("a");
if (!link) continue;
let [_, app, uid ] = link.pathname.split("/");
let uri;
if (app === "playlist") {
uri = Spicetify.URI.playlistV2URI(uid);
} else if (app === "folder") {
const base64 = localStorage.getItem("dribbblish:folder-image:" + uid);
let img = link.querySelector("img");
if (!img) {
img = document.createElement("img");
img.classList.add("playlist-picture");
link.prepend(img);
}
if (base64) {
img.src = base64;
} else {
img.src = "";
}
continue;
}
Spicetify.CosmosAsync.get(
`sp://core-playlist/v1/playlist/${uri.toURI()}/metadata`,
{ policy: { picture: true } }
).then(res => {
const meta = res.metadata;
let img = link.querySelector("img");
if (!img) {
img = document.createElement("img");
img.classList.add("playlist-picture");
link.prepend(img);
}
img.src = meta.picture || "/images/tracklist-row-song-fallback.svg";
});
}
}
DribbblishShared.loadPlaylistImage = loadPlaylistImage;
loadPlaylistImage();
new MutationObserver(loadPlaylistImage)
.observe(query, {childList: true});
});
waitForElement([".Root__main-view"], ([mainView]) => {
const shadow = document.createElement("div");
shadow.id = "dribbblish-back-shadow";
mainView.prepend(shadow);
});
waitForElement([".main-rootlist-rootlistPlaylistsScrollNode"], (queries) => {
const fade = document.createElement("div");
fade.id = "dribbblish-sidebar-fade-in";
queries[0].append(fade);
});
waitForElement([
".main-navBar-entryPoints",
".main-rootlist-rootlistPlaylistsScrollNode .os-content",
".main-rootlist-rootlistContent"
], ([appItems, playlistItems, personalLibrary]) => {
const HIDDEN = 0, SHOW = 1, STICKY = 2;
let buttons = [];
let storage = [];
let ordered;
const list = document.createElement("ul");
const hiddenList = document.createElement("ul");
hiddenList.id = "dribs-hidden-list";
hiddenList.classList.add("hidden-visually");
const playlistList = playlistItems.querySelector("ul");
playlistList.id = "dribs-playlist-list";
playlistItems.prepend(list, hiddenList);
const up = document.createElement("button"); up.innerText = "Up";
const down = document.createElement("button"); down.innerText = "Down";
const hide = document.createElement("button");
const stick = document.createElement("button");
const container = document.createElement("div");
container.id = "dribs-sidebar-config";
container.append(up, down, hide, stick);
for (const ele of appItems.children) {
ele.dataset.id = ele.querySelector("a").pathname;
buttons.push(ele);
}
for (const ele of personalLibrary.querySelectorAll("div.GlueDropTarget")) {
const link = ele.querySelector("a");
if (!link) {
ele.dataset.id = "/add";
} else {
ele.dataset.id = link.pathname;
}
ele.classList.add("personal-library");
buttons.push(ele);
}
try {
storage = JSON.parse(localStorage.getItem("dribs-sidebar-config"))
if (!Array.isArray(storage)) throw "";
} catch {
storage = buttons.map(el => [el.dataset.id, SHOW]);
}
function arrangeItems() {
const newButtons = [...buttons];
const orderedButtons = [];
for (const ele of storage) {
const index = newButtons.findIndex(a => ele[0] === a?.dataset.id);
if (index !== -1) {
orderedButtons.push([newButtons[index], ele[1]]);
newButtons[index] = undefined;
}
}
newButtons
.filter(a => a)
.forEach(a => orderedButtons.push([a, STICKY]));
ordered = orderedButtons;
}
function appendItems() {
const toShow = [], toHide = [], toStick = [];
for (const el of ordered) {
const [ item, status ] = el;
if (status === STICKY) {
appItems.append(item);
toStick.push(el);
} else if (status === SHOW) {
list.append(item);
toShow.push(el);
} else {
hiddenList.append(item);
toHide.push(el);
}
}
ordered = [ ...toStick, ...toShow, ...toHide ];
}
function writeStorage() {
const array = ordered.map(a => [a[0].dataset.id, a[1]]);
console.log(array);
localStorage.setItem("dribs-sidebar-config", JSON.stringify(array));
}
arrangeItems();
appendItems();
const observer = new MutationObserver(() => {
const residues = personalLibrary.querySelectorAll(".main-rootlist-rootlistContent > div.GlueDropTarget");
for (const ele of residues) {
ele.dataset.id = ele.querySelector("a").pathname;
ele.classList.add("personal-library");
buttons.push(ele);
}
arrangeItems();
appendItems();
});
observer.observe(personalLibrary, { childList: true });
setTimeout(() => observer.disconnect(), 10000);
function onSwap(item, dir) {
container.remove();
const curPos = ordered.findIndex(e => e[0] === item);
const newPos = curPos + dir;
if (newPos < 0 || newPos > (ordered.length - 1)) return;
if (ordered[curPos][1] !== ordered[newPos][1]) return;
[ordered[curPos], ordered[newPos]] = [ordered[newPos], ordered[curPos]];
appendItems();
}
function onChangeStatus(item, status) {
container.remove();
const curPos = ordered.findIndex(e => e[0] === item);
ordered[curPos][1] = ordered[curPos][1] === status ? SHOW : status;
appendItems();
}
function injectInteraction() {
document.documentElement.style.setProperty("--sidebar-width", "280px");
document.documentElement.classList.remove("sidebar-hide-text");
hiddenList.classList.remove("hidden-visually");
for (const el of ordered) {
el[0].onmouseover = () => {
const [ item, status ] = el;
const index = ordered.findIndex(a => a === el);
if (index === 0 || ordered[index][1] !== ordered[index - 1][1]) {
up.disabled = true;
} else {
up.disabled = false;
up.onclick = () => onSwap(item, -1);
}
if (index === (ordered.length - 1) || ordered[index][1] !== ordered[index + 1][1]) {
down.disabled = true;
} else {
down.disabled = false;
down.onclick = () => onSwap(item, 1);
}
stick.innerText = status === STICKY ? "Unstick" : "Stick";
hide.innerText = status === HIDDEN ? "Unhide" : "Hide";
hide.onclick = () => onChangeStatus(item, HIDDEN);
stick.onclick = () => onChangeStatus(item, STICKY);
item.append(container);
};
}
}
function removeInteraction() {
hiddenList.classList.add("hidden-visually");
container.remove();
ordered.forEach(a => a[0].onmouseover = undefined);
writeStorage();
}
DribbblishShared.configMenu.subItems.push(new Spicetify.Menu.Item(
"Sidebar config",
false,
(self) => {
self.isEnabled = !self.isEnabled;
if (self.isEnabled) {
injectInteraction();
} else {
removeInteraction();
}
}
));
});
waitForElement([
".Root__nav-bar .LayoutResizer__input, .Root__nav-bar .LayoutResizer__resize-bar input"
], ([resizer]) => {
const observer = new MutationObserver(updateVariable);
observer.observe(resizer, { attributes: true, attributeFilter: ["value"]});
function updateVariable() {
let value = resizer.value;
if (value < 121) {
value = 72;
document.documentElement.classList.add("sidebar-hide-text");
} else {
document.documentElement.classList.remove("sidebar-hide-text");
}
document.documentElement.style.setProperty(
"--sidebar-width", value + "px");
}
updateVariable();
});
waitForElement([".Root__main-view .os-resize-observer-host"], ([resizeHost]) => {
const observer = new ResizeObserver(updateVariable);
observer.observe(resizeHost);
function updateVariable([ event ]) {
document.documentElement.style.setProperty(
"--main-view-width", event.contentRect.width + "px");
document.documentElement.style.setProperty(
"--main-view-height", event.contentRect.height + "px");
if (event.contentRect.width < 700) {
document.documentElement.classList.add("minimal-player");
} else {
document.documentElement.classList.remove("minimal-player");
}
if (event.contentRect.width < 550) {
document.documentElement.classList.add("extra-minimal-player");
} else {
document.documentElement.classList.remove("extra-minimal-player");
}
}
});
(function Dribbblish() {
const progBar = document.querySelector(".playback-bar");
if (!Spicetify.Player.origin || !progBar) {
setTimeout(Dribbblish, 300);
return;
}
const tooltip = document.createElement("div");
tooltip.className = "prog-tooltip";
progBar.append(tooltip);
const progKnob = progBar.querySelector(".progress-bar__slider");
Spicetify.Player.addEventListener("onprogress", ({ data: e }) => {
const offsetX = progKnob.offsetLeft + progKnob.offsetWidth / 2;
const maxWidth = progBar.offsetWidth;
const curWidth = Spicetify.Player.getProgressPercent() * maxWidth;
const ttWidth = tooltip.offsetWidth / 2;
if (curWidth < ttWidth) {
tooltip.style.left = String(offsetX) + "px";
} else if (curWidth > maxWidth - ttWidth) {
tooltip.style.left = String(offsetX - ttWidth * 2) + "px";
} else {
tooltip.style.left = String(offsetX - ttWidth) + "px";
}
tooltip.innerText = Spicetify.Player.formatTime(e) + " / " +
Spicetify.Player.formatTime(Spicetify.Player.getDuration());
});
const filePickerForm = document.createElement("form");
filePickerForm.setAttribute("aria-hidden", true);
filePickerForm.innerHTML = '<input type="file" class="hidden-visually" />';
document.body.appendChild(filePickerForm);
/** @type {HTMLInputElement} */
const filePickerInput = filePickerForm.childNodes[0];
filePickerInput.accept = [
"image/jpeg",
"image/apng",
"image/avif",
"image/gif",
"image/png",
"image/svg+xml",
"image/webp"
].join(",");
filePickerInput.onchange = () => {
if (!filePickerInput.files.length) return;
const file = filePickerInput.files[0];
const reader = new FileReader;
reader.onload = (event) => {
const result = event.target.result;
const id = Spicetify.URI.from(filePickerInput.uri).id;
try {
localStorage.setItem(
"dribbblish:folder-image:" + id,
result
);
} catch {
Spicetify.showNotification("File too large");
}
DribbblishShared.loadPlaylistImage?.call();
}
reader.readAsDataURL(file);
}
new Spicetify.ContextMenu.Item("Remove folder image",
([uri]) => {
const id = Spicetify.URI.from(uri).id;
localStorage.removeItem("dribbblish:folder-image:" + id);
DribbblishShared.loadPlaylistImage?.call();
},
([uri]) => Spicetify.URI.isFolder(uri),
"x",
).register();
new Spicetify.ContextMenu.Item("Choose folder image",
([uri]) => {
filePickerInput.uri = uri;
filePickerForm.reset();
filePickerInput.click();
},
([uri]) => Spicetify.URI.isFolder(uri),
"edit",
).register();
})();

BIN
Dribbblish/gruvbox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 KiB

BIN
Dribbblish/nord-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 919 KiB

BIN
Dribbblish/nord-light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

BIN
Dribbblish/purple.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 KiB

BIN
Dribbblish/samourai.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

846
Dribbblish/user.css Normal file
View File

@ -0,0 +1,846 @@
:root {
--bar-height: 70px;
--bar-cover-art-size: 40px;
--main-gap: 10px;
--main-corner-radius: 10px;
--scrollbar-vertical-size: 8px;
--cover-border-radius: 8px;
--os-windows-icon-dodge: 0;
}
@font-face {
font-family: "Google Sans Display";
src: url("https://local_resource_host/fonts/GoogleSansDisplayRegular.woff2") format("woff2");
font-style: normal;
font-weight: 400;
}
@font-face {
font-family: "Google Sans Display";
src: url("https://local_resource_host/fonts/GoogleSansDisplayMedium.woff2") format("woff2");
font-style: normal;
font-weight: 500;
}
@font-face {
font-family: "Roboto";
src: url("https://local_resource_host/fonts/Roboto.woff2") format("woff2");
font-style: normal;
font-weight: 400;
}
@font-face {
font-family: "Roboto";
src: url("https://local_resource_host/fonts/RobotoMedium.woff2") format("woff2");
font-style: normal;
font-weight: 500;
}
body {
--glue-font-family: "Google Sans Display","Roboto",spotify-circular,spotify-circular-cyrillic,spotify-circular-arabic,spotify-circular-hebrew,Helvetica Neue,helvetica,arial,Hiragino Kaku Gothic Pro,Meiryo,MS Gothic,sans-serif;
--info-font-family: "Roboto",spotify-circular,spotify-circular-cyrillic,spotify-circular-arabic,spotify-circular-hebrew,Helvetica Neue,helvetica,arial,Hiragino Kaku Gothic Pro,Meiryo,MS Gothic,sans-serif;
font-family: var(--glue-font-family);
letter-spacing: normal;
}
.main-type-mesto,
.main-type-mestoBold,
.main-type-ballad,
.main-type-balladBold,
.main-type-canon {
font-family: var(--info-font-family);
letter-spacing: normal;
}
.main-type-ballad {
font-weight: 500;
}
.lyrics-lyricsContainer-LyricsLine {
font-family: var(--glue-font-family);
letter-spacing: -.03em !important;
}
.main-rootlist-rootlistDivider {
display: none;
}
input {
background-color: unset !important;
border-bottom: solid 1px var(--spice-text) !important;
border-radius: 0 !important;
padding: 6px 10px 6px 48px;
color: var(--spice-text) !important;
}
.x-searchInput-searchInputSearchIcon,
.x-searchInput-searchInputClearButton {
color: var(--spice-text) !important;
}
.main-home-homeHeader,
.x-entityHeader-overlay,
.x-actionBarBackground-background,
.main-actionBarBackground-background,
.main-entityHeader-overlay,
.main-entityHeader-backgroundColor
{
background-color: unset !important;
background-image: unset !important;
}
.main-playButton-PlayButton.main-playButton-primary {
color: white;
}
.connect-title, .connect-header {
display: none;
}
.connect-device-list {
margin: 0px -5px;
}
/* Remove Topbar background colour */
.main-topBar-background {
background-color: unset !important;
}
.main-topBar-overlay {
background-color: var(--spice-main);
}
.main-entityHeader-shadow,
.main-contextMenu-menu,
.connect-device-list-container {
box-shadow: 0 4px 20px #21212130;
}
.main-trackList-playingIcon {
filter: grayscale(1);
}
span.artist-artistVerifiedBadge-badge svg > path:first-of-type {
fill: var(--spice-button);
}
span.artist-artistVerifiedBadge-badge svg > path:last-of-type {
fill: var(--spice-text);
}
/* Full window artist background */
.main-entityHeader-background.main-entityHeader-gradient {
opacity: 0.3;
}
.main-entityHeader-container.main-entityHeader-withBackgroundImage,
.main-entityHeader-background,
.main-entityHeader-background.main-entityHeader-overlay:after {
height: 100vh;
}
.main-entityHeader-withBackgroundImage .main-entityHeader-headerText {
justify-content: center;
}
.main-entityHeader-container.main-entityHeader-nonWrapped.main-entityHeader-withBackgroundImage {
padding-left: 9%;
}
.main-entityHeader-background.main-entityHeader-overlay:after {
background-image: linear-gradient(transparent,transparent),linear-gradient(var(--spice-main), var(--spice-main));
}
.artist-artistOverview-overview .main-entityHeader-withBackgroundImage h1 {
font-size: 120px !important;
line-height: 120px !important;
}
/** Hightlight selected playlist */
.main-rootlist-rootlistItemLink.main-rootlist-rootlistItemLinkActive {
background: var(--spice-button);
border-radius: 4px;
}
.main-navBar-navBarLinkActive {
background: var(--spice-button);
}
.main-contextMenu-menu {
background-color: var(--spice-button);
}
.main-contextMenu-menuHeading,
.main-contextMenu-menuItemButton,
.main-contextMenu-menuItemButton:not(.main-contextMenu-disabled):focus,
.main-contextMenu-menuItemButton:not(.main-contextMenu-disabled):hover {
color: var(--spice-main);
}
.main-playPauseButton-button {
background-color: var(--spice-button);
color: white;
}
/** Queue page header */
.queue-queue-title,
.queue-playHistory-title {
color: var(--spice-text) !important;
}
/** Artist page */
.artist-artistOverview-heading {
color: var(--spice-text) !important;
}
.artist-artistAbout-content .artist-artistAbout-cityBlock div,
.artist-artistAbout-content .artist-artistAbout-stats div {
color: var(--spice-text) !important;
}
.artist-artistAbout-content div {
color: var(--spice-text) !important;
}
/** Cards */
.main-cardImage-imageWrapper {
background-color: transparent;
box-shadow: unset;
-webkit-box-shadow: unset;
}
.main-cardImage-imagePlaceholder, .main-cardImage-image {
border-radius: var(--cover-border-radius);
}
.main-rootlist-rootlistDivider {
background-color: unset;
}
.main-nowPlayingBar-nowPlayingBar {
height: var(--bar-height);
}
.Root__top-bar {
border-radius: var(--main-corner-radius) var(--main-corner-radius) 0 0;
}
.main-topBar-background {
border-radius: var(--main-corner-radius) var(--main-corner-radius) 0 0;
}
.Root__main-view {
background-color: var(--spice-main);
border-radius: var(--main-corner-radius) var(--main-corner-radius) 0 0;
overflow: hidden;
}
.main-buddyFeed-buddyFeed {
box-shadow: unset;
-webkit-box-shadow: unset;
z-index: 0;
}
.main-buddyFeed-headerTitle,
.main-buddyFeed-activityMetadata .main-buddyFeed-username a {
color: var(--spice-sidebar-text);
}
.main-buddyFeed-activityMetadata .main-buddyFeed-artistAndTrackName a,
.main-buddyFeed-activityMetadata .main-buddyFeed-playbackContextLink,
.main-buddyFeed-activityMetadata .main-buddyFeed-timestamp {
color: rgba(var(--spice-rgb-sidebar-text), 0.8);
}
.main-buddyFeed-buddyFeedRoot .main-avatar-avatar,
.main-buddyFeed-buddyFeedRoot .main-buddyFeed-overlay {
width: 32px !important;
height: 32px !important;
}
.main-avatar-avatar.main-avatar-withBadge:after {
box-shadow: 0 0 0 2px var(--spice-sidebar);
background-color: var(--spice-notification);
right: 0;
}
.Root__now-playing-bar {
border-radius: 0 0 var(--main-corner-radius) var(--main-corner-radius);
background-color: unset;
}
.main-nowPlayingBar-container {
border-radius: 0 0 var(--main-corner-radius) var(--main-corner-radius);
background-color: unset;
background: radial-gradient(ellipse at right 50% bottom -80px, rgba(var(--spice-rgb-sidebar), 0.55), var(--spice-main) 60%);
border-top: 0;
min-width: 518px;
}
.main-connectBar-connectBar {
border-radius: 0 0 var(--main-corner-radius) var(--main-corner-radius);
border: 2px solid var(--spice-main);
border-top: 0;
color: var(--spice-sidebar-text);
}
.Root__nav-bar {
height: 100%;
z-index: 1;
width: var(--sidebar-width) !important;
}
.main-buddyFeed-buddyFeedRoot {
height: 100%;
}
.main-buddyFeed-buddyFeedRoot .os-content {
padding-top: 0 !important;
}
html,
.Root__nav-bar,
.main-buddyFeed-buddyFeed {
background-color: var(--spice-sidebar) !important;
}
html {
background-image: url("http://local_resource_host/dribbblish.svg");
background-position: center;
background-repeat: no-repeat;
}
.Root__nav-bar .link-subtle,
.main-rootlist-rootlistItemLink:link,
.main-rootlist-rootlistItemLink:visited,
.main-rootlist-rootlistContent span,
.main-navBar-entryPoints span {
color: var(--spice-sidebar-text)
}
.main-navBar-navBarItem svg {
width: 24px !important;
height: 24px !important;
}
.main-navBar-navBarItem {
padding: 0 8px;
}
.main-rootlist-statusIcons {
color: var(--spice-sidebar-text);
padding-right: 16px;
}
.main-rootlist-statusIcons .main-playButton-button {
color: var(--spice-sidebar-text);
}
.main-rootlist-expandArrow {
position: absolute;
top: 20px;
right: 4px;
width: 16px;
height: 16px;
color: var(--spice-sidebar-text) !important;
background-color: var(--spice-button);
border-radius: 50%;
box-shadow: 0 0 0 2px var(--spice-sidebar);
opacity: 0;
}
li.GlueDropTarget:hover .main-rootlist-expandArrow {
opacity: 1;
}
html:not(.sidebar-hide-text) .main-rootlist-expandArrow {
opacity: 1;
}
.main-rootlist-expandArrow::before {
font-size: 10px;
padding-bottom: 3px;
}
html.sidebar-hide-text .main-navBar-navBarItem span,
html.sidebar-hide-text .main-rootlist-rootlistContent span,
html.sidebar-hide-text .main-rootlist-rootlistItem span,
html.sidebar-hide-text .main-rootlist-statusIcons,
html.sidebar-hide-text .GlueDropTarget span {
display: none;
}
.main-rootlist-rootlist {
margin-top: 0;
}
.Root__nav-bar .os-scrollbar-vertical,
.main-buddyFeed-buddyFeedRoot .os-scrollbar-vertical {
display: none;
}
/** */
.main-topBar-historyButtons .main-topBar-button {
background-color: unset;
width: 24px;
height: 24px;
}
.main-topBar-historyButtons svg {
color: var(--spice-button);
fill: var(--spice-button);
}
.playback-bar__progress-time,
.main-playbackBarRemainingTime-container {
display: none;
}
.playback-bar {
position: absolute;
width: var(--main-view-width);
left: var(--sidebar-width);
bottom: calc(var(--main-gap) + var(--bar-height) - 12px / 2);
}
.Root.is-connectBarVisible .playback-bar {
bottom: calc(var(--main-gap) + var(--bar-height) + 24px - 12px / 2);
}
.main-nowPlayingWidget-coverArt .cover-art {
width: var(--bar-cover-art-size) !important;
height: var(--bar-cover-art-size) !important;
}
.player-controls__buttons {
margin-bottom: 0;
width: 192px;
}
.progress-bar {
--progress-bar-height: 2px;
--fg-color: var(--spice-button);
--bg-color: rgba(var(--spice-rgb-text), .2);
}
.minimal-player .player-controls__buttons {
width: 120px;
gap: 0px;
}
.minimal-player .player-controls__left,
.minimal-player .player-controls__right {
--button-size: 16px !important;
gap: 0px;
}
.minimal-player .volume-bar {
flex: 0 1 70px;
}
.extra-minimal-player .player-controls__buttons {
width: 64px;
}
.extra-minimal-player .main-shuffleButton-button,
.extra-minimal-player .main-repeatButton-button,
.extra-minimal-player .ExtraControls__connect-device-picker,
.extra-minimal-player .volume-bar .progress-bar-wrapper {
display: none;
}
.extra-minimal-player .volume-bar {
flex: 0 0 32px;
}
.main-trackInfo-name {
font-weight: 500;
}
.main-topBar-topbarContent .main-playButton-PlayButton {
--size: 35px !important;
}
.main-entityHeader-image {
border-radius: 5px;
}
.main-entityHeader-metaDataText,
.main-duration-container {
color: var(--spice-subtext);
}
/** Sidebar */
.main-rootlist-rootlist .os-content {
padding: 0 0 8px 0 !important;
}
.main-rootlist-rootlistDividerContainer {
display: none;
}
.main-rootlist-rootlistItem a {
align-items: center;
border-radius: 4px;
display: flex;
height: 56px;
padding: 0 12px;
}
img.playlist-picture {
width: 32px;
height: 32px;
flex: 0 0 32px;
background-size: cover;
background-position: center;
border-radius: 50%;
}
.main-rootlist-rootlistItem a span {
margin-left: 24px;
}
.main-rootlist-rootlistItem {
padding-left: calc(var(--indentation)*var(--left-sidebar-item-indentation-width));
padding-right: 0;
}
html.sidebar-hide-text .main-rootlist-rootlistItem {
padding: 0;
}
.main-rootlist-dropIndicator {
background: var(--spice-selected-row);
height: 2px;
}
.main-navBar-navBarLink {
height: 56px;
}
.main-navBar-navBarLink .icon,
.main-collectionLinkButton-icon,
.main-createPlaylistButton-icon,
.main-collectionLinkButton-icon {
margin-right: 24px;
}
li.GlueDropTarget {
padding: 0 8px;
}
/** OS-specific window controls dodge */
.spotify__os--is-windows .main-navBar-navBar {
padding-top: calc(var(--os-windows-icon-dodge) * 24px);
}
.spotify__container--is-desktop:not(.fullscreen).spotify__os--is-windows .main-navBar-entryPoints {
padding-top: calc(var(--os-windows-icon-dodge) * 12px + 12px);
}
.spotify__os--is-windows .main-buddyFeed-header {
padding-top: calc(var(--os-windows-icon-dodge) * 32px);
}
.spotify__container--is-desktop.spotify__os--is-windows[dir=ltr] .main-topBar-container {
padding-right: calc(var(--os-windows-icon-dodge) * 135px + 32px);
}
.main-topBar-container {
max-width: unset;
}
/** Custom elements */
#dribbblish-sidebar-fade-in {
position: absolute;
bottom: 0;
width: 100%;
height: 20%;
background: linear-gradient(to top, var(--spice-sidebar) 10%, transparent);
z-index: 3;
pointer-events: none;
}
#dribs-playlist-list {
padding-bottom: 56px;
}
#dribbblish-back-shadow {
position: fixed;
width: var(--main-view-width);
height: calc(var(--main-view-height) + var(--bar-height));
box-shadow: 0 0 10px 3px #0000003b;
border-radius: var(--main-corner-radius);
z-index: 2;
pointer-events: none;
}
.playback-bar .prog-tooltip {
position: absolute;
min-width: 100px;
width: unset;
height: 25px;
top: -35px;
padding: 0 5px;
border-radius: 4px;
text-align: center;
color: var(--spice-text);
background-color: var(--spice-button);
opacity: 0;
transition: opacity,left 0.2s ease;
}
.playback-bar:hover .prog-tooltip {
opacity: 1;
}
/** Rearrange player bar */
.main-nowPlayingBar-left {
order: 1;
flex: 1;
width: auto;
min-width: 0 !important;
}
.main-nowPlayingBar-center {
order: 0;
flex: 1;
width: auto;
min-width: unset !important;
}
.main-nowPlayingBar-right {
order: 2;
flex: 1;
width: auto;
min-width: unset !important;
}
.main-nowPlayingWidget-nowPlaying {
justify-content: center;
}
.player-controls {
justify-content: flex-start;
flex-direction: row;
}
.main-playPauseButton-button {
background-color: transparent;
}
.main-playPauseButton-button svg {
width: 32px !important;
height: 32px !important;
color: var(--spice-button);
}
/** Main container */
.contentSpacing {
padding-left: 64px;
padding-right: 64px;
}
@media (min-width: 1024px) {
.contentSpacing {
padding-left: 128px;
padding-right: 128px;
}
}
.main-collectionLinkButton-collectionLinkButton .main-collectionLinkButton-icon,
.main-collectionLinkButton-collectionLinkButton .main-collectionLinkButton-collectionLinkText,
.main-createPlaylistButton-button {
opacity: 1;
}
.main-likedSongsButton-likedSongsIcon,
.main-yourEpisodesButton-yourEpisodesIcon,
.main-createPlaylistButton-createPlaylistIcon {
background: unset !important;
}
.main-createPlaylistButton-icon,
.main-collectionLinkButton-icon,
.main-createPlaylistButton-icon {
height: 40px;
}
.main-likedSongsButton-likedSongsIcon svg,
.main-yourEpisodesButton-yourEpisodesIcon svg,
.main-createPlaylistButton-createPlaylistIcon svg {
fill: var(--spice-sidebar-text);
width: 32px;
height: 32px;
}
.main-yourEpisodesButton-yourEpisodesIcon svg path {
fill: var(--spice-sidebar-text);
}
/** Grid */
.Root__top-container {
grid-template-areas:
"nav-bar main-view buddy-feed"
"nav-bar now-playing-bar buddy-feed";
padding: var(--main-gap) 0;
}
html:not(.buddyfeed-visible) .Root__top-container {
padding-right: var(--main-gap);
}
/** Minimal profile button */
span.main-userWidget-displayName,
.main-userWidget-box svg {
display: none;
}
/** Sidebar config */
#dribs-hidden-list {
background-color: rgba(var(--spice-rgb-main), .3);
}
#dribs-sidebar-config {
position: relative;
width: 100%;
height: 0;
display: flex;
justify-content: space-evenly;
align-items: center;
top: -30px;
left: 0;
}
#dribs-sidebar-config button {
min-width: 60px;
border-radius: 3px;
background-color: var(--spice-main);
color: var(--spice-text);
border: 1px solid var(--spice-text);
}
#dribs-sidebar-config button:disabled {
color: var(--spice-button-disabled);
}
.main-navBar-entryPoints {
--left-sidebar-padding-left: 24px;
--left-sidebar-padding-right: 24px;
}
div.GlueDropTarget.personal-library {
padding: 0 8px;
}
div.GlueDropTarget.personal-library >* {
padding: 0 16px;
height: 56px;
border-radius: 4px;
}
div.GlueDropTarget.personal-library >*.active {
background: var(--spice-button);
}
/** Big cover, small cover */
.main-coverSlotExpanded-container {
position: fixed;
z-index: 2;
width: 250px;
height: 250px;
bottom: calc(var(--main-gap) + var(--bar-height) + 10px);
left: calc(var(--sidebar-width) + 10px);
}
.Root.is-connectBarVisible .main-coverSlotExpanded-container {
bottom: calc(var(--main-gap) + var(--bar-height) + 24px + 10px);
}
html.right-expanded-cover .main-coverSlotExpanded-container {
right: calc(var(--main-gap) + 10px);
left: unset;
}
html.right-expanded-cover.buddyfeed-visible .main-coverSlotExpanded-container {
right: calc(var(--main-gap) + var(--buddy-feed-width) + 10px);
left: unset;
}
.main-coverSlotExpanded-container img {
border-radius: 4px;
}
.cover-art {
border-radius: 4px;
}
.main-nowPlayingWidget-coverExpanded .main-coverSlotCollapsed-container {
opacity: 0;
}
.main-nowPlayingWidget-coverExpanded {
transform: translateX(-27px);
}
/** Mini dribbblish */
.x-categoryCard-CategoryCard > div {
background-color: var(--spice-main);
width: calc(100% - 14px);
height: calc(100% - 6px);
margin: 3px 10px;
border-radius: 5px;
}
.x-categoryCard-CategoryCard {
height: 100px;
}
.x-categoryCard-image {
width: 50px !important;
height: 50px !important;
}
.x-heroCategoryCard-HeroCategoryCard > div {
background-color: var(--spice-main);
width: calc(100% - 20px);
height: calc(100% - 6px);
margin: 3px 16px;
border-radius: 5px;
}
.main-dropDown-dropDown,
.x-sortBox-sortDropdown {
background-color: rgba(var(--spice-rgb-selected-row), .1) !important;
}
.connect-device-list-item:focus,
.connect-device-list-item:hover {
background-color: rgba(var(--spice-rgb-selected-row), .3);
}
/* 1.1.56 */
.main-navBar-navBar {
width: var(--sidebar-width) !important;
}
.main-entityHeader-container.main-entityHeader-nonWrapped {
padding-left: 64px;
padding-right: 64px;
}
@media (min-width: 1024px) {
.main-entityHeader-container.main-entityHeader-nonWrapped {
padding-left: 128px;
padding-right: 128px;
}
}
.main-userWidget-dropDownMenu > context-menu-item > li > a.main-contextMenu-menuItemButton {
color: rgba(var(--spice-rgb-selected-row), .7);
padding-left: 8px;
text-decoration: none;
}
.main-userWidget-dropDownMenu > context-menu-item > li > a.main-contextMenu-menuItemButton:hover,
.main-userWidget-dropDownMenu > context-menu-item > li > a.main-contextMenu-menuItemButton:focus {
color: var(--spice-text);
}
.main-userWidget-dropDownMenu svg {
position: unset;
}
.main-userWidget-dropDownMenu > li svg {
position: absolute;
}
.main-buddyFeed-buddyFeed.main-buddyFeed-buddyFeed-expanded {
z-index: 4;
}

BIN
Dribbblish/white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

View File

@ -6,9 +6,9 @@ extratext = d3869b
main = 1d2021
sidebar = 1d2021
player = 1d2021
sec-player = 3c3836
sec-player = 32302f
card = fb4934
sec-card = 665c54
sec-card = 32302f
shadow = 000000
selected-row = d3869b
button = 8ec07c
@ -28,9 +28,9 @@ extratext = 8f3f71
main = f9f5d7
sidebar = f9f5d7
player = f9f5d7
sec-player = ebdbb2
sec-player = f2e5bc
card = 9d0006
sec-card = bdae93
sec-card = f2e5bc
shadow = d5c4a1
selected-row = 8f3f71
button = 427b58

View File

@ -255,7 +255,6 @@ input {
.main-userWidget-box:focus,
.main-userWidget-box:hover,
.main-userWidget-box[data-context-menu-open=true] {
background-color: rgba(var(--spice-rgb-button), .5) !important;
border-radius: 10px !important;
}
@ -282,11 +281,30 @@ input {
background-color: var(--spice-sec-card) !important;
}
.main-keyboardShortcutsHelpModal-container {
.main-keyboardShortcutsHelpModal-container,
.main-trackCreditsModal-container {
background-color: var(--spice-main) !important;
color: var(--spice-text) !important;
}
.main-keyboardShortcutsHelpModal-header,
.main-trackCreditsModal-header {
color: var(--spice-notification) !important;
}
.main-trackCreditsModal-sectionTitle {
color: var(--spice-subtext) !important;
}
.main-type-canon {
color: var(--spice-extratext) !important;
}
/* profile page edits */
.main-cardImage-imageWrapper {
background-color: var(--spice-sec-card) !important;
}
/* mini player edits */
.progress-bar--is-active .progress-bar__fg,

View File

@ -24,65 +24,13 @@ Some themes have 2 or more different color schemes. You can switch between them,
## Contributions
### Before contributing
For avoiding having too many similar themes with small changes, themes are merged only if they bring **sensitive** changes to default Spotify UI and are different from existing themes.
A theme name (as well as color scheme name) should consist of one word starting with an uppercase letter and shouldn't contain `spicetify` or any whitespace in it; if a "-" is present in the name it must be followed by an uppercase letter.
### How to contribute
If you want to add your theme:
* Fork this repository
* Create another folder named after your theme name
* Create `color.ini` and `user.css` files
* Create a `README.md` in it with the following structure
```markdown
# THEME_NAME
## Screenshots
[Put at least one image per color scheme here]
## More
[Specify any needed font; (optionally) author name and/or any other info about the theme]
```
* Add the theme preview to [THEMES.md](./THEMES.md) (themes are in alphabetical order) following this structure if it has only one color scheme
```markdown
## THEME_NAME
[A single image of the theme]
```
If, instead, more than one color scheme is present
```markdown
## THEME_NAME
#### COLOR_SCHEME1_NAME
[A single image of the theme using the color scheme]
#### COLOR_SCHEME2_NAME
[A single image of the theme using the color scheme]
...
```
* Open a Pull Request and mention the most important changes you've made to the UI (ignoring the color scheme)
**Thanks to all the contributors.**
We've set up a separate document for our [contribution guidelines](./CONTRIBUTING.md).
## Troubleshooting
If you find problems when using or installing these themes, or you need help in modifying a theme use the [Spectrum](https://spectrum.chat/spicetify) chat.
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests. If you find problems when using or installing these themes, or you need help in modifying a theme use the [Spectrum](https://spectrum.chat/spicetify) chat.
For bugs and requesting new features use the GitHub issues.
Use GitHub issues ONLY for bugs and requesting new features.
If you are unsure about which channel to use, go for Spectrum.

View File

@ -2,12 +2,19 @@
## Screenshots
### Psycho
![Psycho Screenshot](psycho.png)
### BIB
![BIB Screenshot](bib.png)
### Deep
![Deep Screenshot](deep.png)
### Psycho
![Psycho Screenshot](psycho.png)
### Deeper
![Deeper Screenshot](deeper.png)
## More
A simple and sleek theme that builds on the basic Spotify UI.
BIB color scheme based on original [BIB-Green](https://github.com/morpheusthewhite/spicetify-themes/tree/master/BIB-Green)

BIN
Sleek/bib.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

View File

@ -1,32 +1,57 @@
[Psycho]
;Red on dark background
text = d00000
subtext = c0c0c0
main = 050505
sidebar = 0a0a0a
player = 0a0a0a
card = 101010
; Red on dark grey background
text = e00000
subtext = ffffff
button-text = ffffff
main = 101010
sidebar = 171717
player = 171717
card = 171717
shadow = 000000
selected-row = 900000
button = d00000
button-active = d00000
button-disabled = 353535
tab-active = 101010
notification = 400000
notification-error = b23030
playback-bar = d03a00
misc = BFBFBF
selected-row = 330d0d
sub-button = a20606
button = e00000
button-active = e00000
button-disabled = 404040
tab-active = 171717
notification = 5e0000
notification-error = 5e0000
playback-bar = ff4700
misc = adadad
[Deeper]
; Light blue on Dark Background
text = 4f9a87
subtext = 4f9a87
button-text = 4f9a87
main = 040614
sidebar = 0F111A
player = 0F111A
card = 0C1C19
shadow = 0C1C19
selected-row = 040614
sub-button = 4f9a87
button = 4f9a87
button-active = 4a99e9
button-disabled = 0C1C19
tab-active = 0a1527
notification = 051024
notification-error = 051024
playback-bar = 4f9a87
misc = 0C1C19
[Deep]
;White on deep blue background
; White on dark blue background
text = ffffff
subtext = ffffff
button-text = ffffff
main = 020816
sidebar = 051024
player = 030b1e
card = 0a1527
shadow = 000000
selected-row = 1464b5
selected-row = 09162e
sub-button = ffffff
button = 1464b5
button-active = 4a99e9
button-disabled = 353535
@ -34,4 +59,46 @@ tab-active = 0a1527
notification = 051024
notification-error = 051024
playback-bar = 37b778
misc = BFBFBF
misc = BFBFBF
[BIB]
; Green on dark grey background
text = 8bc34a
subtext = b4b4b4
button-text = 202020
main = 202020
sidebar = 202020
player = 242424
card = 242424
shadow = 000000
selected-row = 2a3c17
sub-button = 6a913d
button = 8bc34a
button-active = 98da4b
button-disabled = 353535
tab-active = 303030
notification = 242424
notification-error = 242424
playback-bar = 8bc34a
misc = FFFFFF
; Description
; text = main text, playlist names in main field, name of playlist selected in sidebar, headings
; subtext = text in main buttons in sidebar, playlist names in sidebar, artist names, and mini infos
; button-text = text in main buttons in sidebar when active
; main = main field or main bg
; sidebar = sidebar bg
; player = player bg
; card = card bg
; shadow = bg of buttons like account, pop-up lyrics, full app display in main field
; selected-row = color of the song selected
; sub-button = caption and details of playlist, download and options button
; button = playlist buttons bg in sidebar, drop-down menus, now playing song, like button
; button-active = hover on song selected
; button-disabled = seekbar bg, volume bar bg, scrollbar
; tab-active = button bg in main field (playlists, podcasts, artists, albums)
; notification = notification ('Added to liked songs' etc.)
; notification-error = error
; playback-bar = seekbar fg, main play/pause button bg
; misc = miscellaneous

BIN
Sleek/deeper.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 KiB

After

Width:  |  Height:  |  Size: 294 KiB

View File

@ -124,7 +124,7 @@ span.artist-artistVerifiedBadge-badge svg:nth-child(1) {
}
.player-controls__buttons {
transform: translateY(10px);
transform: translateY(6px);
}
.main-playPauseButton-button {
@ -187,12 +187,12 @@ span.artist-artistVerifiedBadge-badge svg:nth-child(1) {
.main-trackList-trackListRow.main-trackList-selected,
.main-trackList-trackListRow.main-trackList-selected:hover {
background-color: rgba(var(--spice-rgb-selected-row),.1) !important;
background-color: rgba(var(--spice-rgb-selected-row),.8) !important;
}
.main-trackList-trackListRow:focus-within,
.main-trackList-trackListRow:hover {
background-color: rgba(var(--spice-rgb-selected-row),.05);
background-color: rgba(var(--spice-rgb-selected-row),.4);
}
.main-duplicateTracksDialog-container {
@ -248,13 +248,78 @@ span.artist-artistVerifiedBadge-badge svg:nth-child(1) {
}
.main-navBar-navBarLinkActive, .main-navBar-navBarLinkActive:focus, .main-navBar-navBarLinkActive:hover, .logo {
color: var(--spice-subtext);
}
.main-navBar-navBarLink:focus, .main-navBar-navBarLink:hover {
color: var(--spice-subtext);
color: var(--spice-button-text) !important;
}
.progress-bar__slider {
background-color: var(--spice-subtext);
}
a.x-categoryCard-CategoryCard, a.x-heroCategoryCard-HeroCategoryCard {
color: var(--spice-subtext);
}
.main-heroCard-card a,
.collection-collectionEntityHeroCard-descriptionContainer {
color: var(--spice-subtext) !important;
}
.main-buddyFeed-activityMetadata .main-buddyFeed-artistAndTrackName a, .main-buddyFeed-activityMetadata .main-buddyFeed-username a, .main-buddyFeed-activityMetadata .main-buddyFeed-playbackContextLink,
p.main-buddyFeed-timestamp.main-type-finale,
.main-buddyFeed-findFriendsButton .main-buddyFeed-findFriendsIcon {
color: var(--spice-subtext);
}
/* Recolor sub-buttons */
.main-moreButton-button {
color: var(--spice-sub-button);
}
.x-downloadButton-button {
color: var(--spice-sub-button) !important;
}
.x-downloadButton-button:hover {
color: var(--spice-text) !important;
}
.main-addButton-button {
color: var(--spice-sub-button);
}
.main-entityHeader-metaDataText {
color: var(--spice-sub-button);
}
.main-duration-container {
color: var(--spice-sub-button);
}
.main-tag-container {
background-color: var(--spice-sub-button);
}
.x-sortBox-sortDropdown {
background-color: var(--spice-selected-row) !important;
}
.x-filterBox-searchIconContainer {
color: var(--spice-sub-button) !important;
}
.x-filterBox-expandButton:focus, .x-filterBox-expandButton:hover {
background-color: var(--spice-selected-row) !important;
}
.main-contextMenu-menuItemButton:not(.main-contextMenu-disabled):focus, .main-contextMenu-menuItemButton:not(.main-contextMenu-disabled):hover {
background-color: var(--spice-selected-row) !important;
}
.view-homeShortcutsGrid-shortcut {
background-color: rgba(var(--spice-rgb-selected-row),0.6) !important;
}
.view-homeShortcutsGrid-shortcut:focus-within, .view-homeShortcutsGrid-shortcut:hover, .view-homeShortcutsGrid-shortcut[data-context-menu-open=true] {
background-color: var(--spice-selected-row) !important;
}

View File

@ -6,12 +6,50 @@ Here you can find a preview of all the themes. Some of them may have different c
![Ocean Screenshot](Default/ocean.png)
## Dribbblish
#### Base
![base](Dribbblish/base.png)
#### White
![white](Dribbblish/white.png)
#### Dark
![dark](Dribbblish/dark.png)
#### Nord-Light
![nord-light](Dribbblish/nord-light.png)
#### Nord-Dark
![nord-dark](Dribbblish/nord-dark.png)
#### Beach-Sunset
![beach-sunset](Dribbblish/beach-sunset.png)
#### Purple
![purple](Dribbblish/purple.png)
#### Samourai
![samourai](Dribbblish/samourai.png)
## Onepunch
![Onepunch Screenshot](Onepunch/__Home.png)
## Sleek
#### BIB
![BIB Screenshot](Sleek/bib.png)
#### Deep
![Deep Screenshot](Sleek/deep.png)
@ -20,6 +58,14 @@ Here you can find a preview of all the themes. Some of them may have different c
![Psycho Screenshot](Sleek/psycho.png)
#### Deeper
![Deeper Screenshot](Sleek/deeper.png)
## Turntable
https://user-images.githubusercontent.com/19476925/119483404-84223100-bd87-11eb-8dfa-5af9f7a2e925.mov
## Burnt Sienna
![Burnt Sienna Screenshot](BurntSienna/screenshot.png)

21
Turntable/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Grason Chan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

86
Turntable/README.md Normal file
View File

@ -0,0 +1,86 @@
# Turntable
Based on Spotify original theme.
**Note:** Require Spicetify **v2.2.0** or higher! Otherwise, performance problems will happen when the turntable rotate!
## Screenshots
<div align="center">
<img src="screenshots/turntable.png" alt="turntable">
</div>
<div align="center">
<img src="screenshots/full_app_display.png" alt="full app display">
</div>
<div align="center">
<img src="screenshots/full_app_display_vertical_mode.png" alt="full app display - vertical mode">
</div>
## More
### About Turntable
Use CSS to achieve, not picture. This means it can be scaled to any size, but make sure the album cover is not blurry.
Actually, the rotation of the turntable was created at spicetify v1, but in some cases, animation is affected by other factors. I think "fullAppDisplay.js high GPU usage" is the reason. Fortunately, it's normal now!
### Info
Designed and developed by [Grason Chan](https://github.com/grasonchan).
The turntable inspired by [Netease Music](https://music.163.com) and [Smartisan OS build-in Music Player](https://www.smartisan.com/os/#/beauty) (not include code).
Develop and test on macOS. If there's any problem, please open issue or PR.
### Installation
1. add extension - [Full App Display](https://github.com/khanhas/spicetify-cli/wiki/Extensions#full-app-display)
```shell
spicetify config extensions fullAppDisplay.js
spicetify apply
```
2. put **Turntable** and **rotateTurntable.js** into the **spicetify_data**
```shell
cd spicetify-themes
cp -r Turntable ~/spicetify_data/Themes
cp Turntable/rotateTurntable.js ~/spicetify_data/Extensions
```
3. select the theme and extension, then apply
```shell
spicetify config current_theme Turntable
spicetify config extensions rotateTurntable.js
spicetify apply
```
### How to Uninstall
1. remove **Turntable** and **rotateTurntable.js**
```shell
rm -r ~/spicetify_data/Themes/Turntable
rm ~/spicetify_data/Extensions/rotateTurntable.js
```
2. config to spicetify default theme
```shell
spicetify config current_theme SpicetifyDefault
```
3. remove extension - Full App Display (optional)
```shell
spicetify config extensions fullAppDisplay.js-
```
4. apply
```shell
spicetify apply
```

View File

@ -0,0 +1,30 @@
window.addEventListener("load", () => {
(function rotateTurntable() {
if (!Spicetify.Player.origin || !document.querySelector("#fad-art-image")) {
setTimeout(rotateTurntable, 250);
return;
}
const fullAppDisplay = document.querySelector("#full-app-display");
function handleRotate() {
const fadArt = document.querySelector("#fad-art-image");
Spicetify.Player.isPlaying()
? fadArt.style.animationPlayState = "running"
: fadArt.style.animationPlayState = "paused";
}
handleRotate();
Spicetify.Player.addEventListener("onplaypause", () => setTimeout(handleRotate));
fullAppDisplay.addEventListener("contextmenu", () => {
const configSwitchBtns = document.querySelectorAll("#popup-config-container button.switch");
for (const configSwitch of configSwitchBtns) {
configSwitch.addEventListener("click", handleRotate);
}
});
})();
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

305
Turntable/user.css Normal file
View File

@ -0,0 +1,305 @@
:root {
--spotify-main-color: #1db954;
--round-value: 50%;
--main-blur-backdrop: blur(20px) saturate(180%)
}
/* remove upgrade button, user name */
.main-topBar-UpgradeButton,
.main-userWidget-displayName {
display: none
}
/* Navbar */
.Root__nav-bar {
background-color: #0f0f0f
}
.main-rootlist-rootlistDividerGradient {
display: none
}
/* Search Input */
.x-searchInput-searchInputInput {
background-color: #2a2a2a
}
.x-searchInput-searchInputInput,
.x-searchInput-searchInputSearchIcon,
.x-searchInput-searchInputClearButton {
color: #c0c0c0 !important
}
.x-searchInput-searchInputInput::placeholder {
color: #888
}
/* Playlist */
.main-entityHeader-backgroundColor,
.main-actionBarBackground-background,
.main-topBar-overlay {
background-color: unset !important
}
.main-entityHeader-overlay {
background: unset
}
.main-actionBarBackground-background {
background-image: unset
}
.main-entityHeader-shadow {
box-shadow: unset
}
.main-topBar-background {
background-color: #181818 !important
}
.main-virtualScrollList-wrapper [role="row"]:nth-child(odd) {
background: linear-gradient(to right, #121212, #191919, #121212)
}
/* cover image */
.main-nowPlayingWidget-coverExpanded{
transform: translateX(-78px)
}
.main-coverSlotCollapsed-container {
margin-right: 5px
}
.main-nowPlayingWidget-coverArt .cover-art.shadow,
.main-nowPlayingWidget-coverArt .cover-art-image {
border-radius: var(--round-value)
}
.main-nowPlayingWidget-coverArt .cover-art.shadow {
box-shadow: unset
}
.main-nowPlayingWidget-coverArt .cover-art-image {
border: 2px solid #aaa;
transform: scale(1.1);
box-shadow: 0 0 5px rgba(200, 200, 200, .4)
}
/* expand & collapse button */
.main-coverSlotCollapsed-expandButton {
top: 50%;
left: 50%;
transform: translate(-50%, -50%) !important
}
.main-coverSlotCollapsed-expandButton,
.main-coverSlotExpandedCollapseButton-collapseButton {
backdrop-filter: var(--main-blur-backdrop);
background: unset;
background-color: rgba(9, 9, 9, .2);
transition: background-color .5s, opacity .5s;
border-radius: var(--round-value)
}
.main-coverSlotCollapsed-expandButton:hover,
.main-coverSlotExpandedCollapseButton-collapseButton:hover {
background: unset;
background-color: rgba(9, 9, 9, .3);
transform: unset
}
.main-coverSlotCollapsed-chevron,
.main-coverSlotExpandedCollapseButton-chevron {
padding: 5px;
fill: #fff;
transition: fill .5s
}
.main-coverSlotCollapsed-expandButton:hover .main-coverSlotCollapsed-chevron,
.main-coverSlotExpandedCollapseButton-collapseButton:hover .main-coverSlotExpandedCollapseButton-chevron {
fill: #ddd
}
/* progress bar */
.Root__now-playing-bar {
position: relative
}
.playback-bar {
width: 100%;
position: absolute;
top: 0;
left: 0
}
.progress-bar-wrapper {
height: 4px
}
.playback-bar .progress-bar__fg {
background-color: var(--spotify-main-color)
}
.playback-bar__progress-time,
.main-playbackBarRemainingTime-container {
position: absolute;
top: 12px;
left: 50%
}
.playback-bar__progress-time {
transform: translateX(-45px)
}
.playback-bar__progress-time::after {
position: absolute;
right: -5px;
font-weight: bold;
color: var(--spotify-main-color);
content: "/"
}
.main-playbackBarRemainingTime-container {
transform: translateX(-1px)
}
.player-controls {
margin-top: 38px
}
/* modal backdrop */
.GenericModal__overlay {
backdrop-filter: var(--main-blur-backdrop);
background-color: rgba(9, 9, 9, .2)
}
/* full app display */
#full-app-display {
background-color: #222
}
#fad-background {
display: none
}
#fad-art,
#fad-art-image,
#fad-art-inner {
border-radius: var(--round-value) !important
}
#fad-art {
width: 300px !important;
margin: 60px 80px;
position: relative;
transform: scale(.85)
}
#fad-art-image {
box-shadow: 0 0 10px rgba(3, 3, 3, .5) inset
}
#fad-art-inner {
display: none
}
#fad-art::before, #fad-art::after {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
border-radius: 50%;
content: ''
}
#fad-art::before {
background: radial-gradient(#333, #000);
box-shadow: 0 0 10px #000;
transform: scale(1.5)
}
#fad-art::after {
background-color: #252525;
transform: scale(1.65);
z-index: -1
}
#fad-details {
max-width: 520px !important
}
#fad-details #fad-title {
font-size: 38px
}
#fad-details #fad-artist {
margin-top: 10px;
font-size: 24px
}
#fad-details #fad-album {
margin-top: 6px;
font-size: 16px
}
#fad-details #fad-artist > *,
#fad-details #fad-album > *,
#fad-details #fad-status > #fad-controls > * > svg {
vertical-align: middle
}
#fad-details #fad-artist > svg {
width: 24px;
height: 24px
}
#fad-details #fad-album > svg {
width: 16px;
height: 16px;
margin-left: 4px;
margin-right: 9px
}
#fad-play > svg {
width: 24px;
height: 24px
}
#fad-controls > button > svg {
fill: #ccc
}
#fad-controls > button:hover > svg {
fill: #fff
}
@media (min-width: 1460px) and (min-height: 960px) {
#fad-foreground {
transform: scale(1.2)
}
}
/* rotate turntable */
#fad-art-image {
animation: rotate-cover_img 20s linear infinite paused
}
@keyframes rotate-cover_img {
from {
transform: rotate(0)
}
to {
transform: rotate(360deg)
}
}