Merge branch 'v2' of https://github.com/pjaspinski/spicetify-themes into v2
119
CONTRIBUTING.md
Normal 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
@ -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
|
||||
```
|
BIN
Dribbblish/assets/glue-resources/fonts/Roboto.woff2
Normal file
BIN
Dribbblish/assets/glue-resources/fonts/RobotoMedium.woff2
Normal file
BIN
Dribbblish/base.png
Normal file
After Width: | Height: | Size: 772 KiB |
BIN
Dribbblish/beach-sunset.png
Normal file
After Width: | Height: | Size: 532 KiB |
180
Dribbblish/color.ini
Normal 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
After Width: | Height: | Size: 262 KiB |
400
Dribbblish/dribbblish.js
Normal 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
After Width: | Height: | Size: 426 KiB |
BIN
Dribbblish/nord-dark.png
Normal file
After Width: | Height: | Size: 919 KiB |
BIN
Dribbblish/nord-light.png
Normal file
After Width: | Height: | Size: 224 KiB |
BIN
Dribbblish/purple.png
Normal file
After Width: | Height: | Size: 657 KiB |
BIN
Dribbblish/samourai.png
Normal file
After Width: | Height: | Size: 169 KiB |
846
Dribbblish/user.css
Normal 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
After Width: | Height: | Size: 136 KiB |
@ -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
|
||||
|
@ -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,
|
||||
|
58
README.md
@ -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.
|
||||
|
||||
|
@ -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
After Width: | Height: | Size: 267 KiB |
105
Sleek/color.ini
@ -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
After Width: | Height: | Size: 1.8 MiB |
BIN
Sleek/psycho.png
Before Width: | Height: | Size: 290 KiB After Width: | Height: | Size: 294 KiB |
@ -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;
|
||||
}
|
46
THEMES.md
@ -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
@ -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
@ -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
|
||||
```
|
30
Turntable/rotateTurntable.js
Normal 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);
|
||||
}
|
||||
});
|
||||
})();
|
||||
});
|
BIN
Turntable/screenshots/full_app_display.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
Turntable/screenshots/full_app_display_vertical_mode.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
Turntable/screenshots/turntable.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
305
Turntable/user.css
Normal 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)
|
||||
}
|
||||
}
|