Skip to content

Commit

Permalink
feat: expose Tippy.js instance (#2229)
Browse files Browse the repository at this point in the history
  • Loading branch information
kyrie25 committed Mar 30, 2023
1 parent d5c773f commit 63e2d49
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 7 deletions.
5 changes: 4 additions & 1 deletion css-map.json
Expand Up @@ -2165,5 +2165,8 @@
"eZnAGhYcXE4Bt0a7958z": "main-useDropTarget-playlistV2",
"ratGUXdpLCkyXZNaJryg": "main-useDropTarget-show",
"caTDfb6Oj7a5_8jBLUSo": "main-useDropTarget-track",
"aRyoyQFJkzhoSOnf2ERM": "main-useDropTarget-local"
"aRyoyQFJkzhoSOnf2ERM": "main-useDropTarget-local",
"X8yW2lJbFCQfV5GjoRwL": "main-contextMenu-tippy",
"mph1R_QkS44EPi4lrhxd": "main-contextMenu-tippyEnter",
"v5IUMJNPJgol0273zQXD": "main-contextMenu-tippyEnterActive"
}
12 changes: 12 additions & 0 deletions globals.d.ts
Expand Up @@ -1039,6 +1039,7 @@ declare namespace Spicetify {
onClick: (self: Button) => void;
disabled: boolean;
element: HTMLButtonElement;
tippy: any;
}
}

Expand All @@ -1054,6 +1055,7 @@ declare namespace Spicetify {
disabled: boolean;
active: boolean;
element: HTMLButtonElement;
tippy: any;
}
}

Expand Down Expand Up @@ -1081,4 +1083,14 @@ declare namespace Spicetify {
const extensions: string[];
const custom_apps: string[];
}

/**
* Tippy.js instance used by Spotify
*/
const Tippy: any;
/**
* Spicetify's predefined props for Tippy.js
* Used to mimic Spotify's tooltip behavior
*/
const TippyProps: any;
}
64 changes: 59 additions & 5 deletions jsHelper/spicetifyWrapper.js
Expand Up @@ -1204,6 +1204,48 @@ Spicetify.PopupModal = new _HTMLGenericModal();

Spicetify.ReactComponent = {};

Object.defineProperty(Spicetify, "TippyProps", {
value: {
delay: [200, 0],
animation: true,
render(instance) {
const popper = document.createElement('div');
const box = document.createElement('div');

popper.id = "context-menu";
popper.appendChild(box);

box.className = "main-contextMenu-tippy"
box.textContent = instance.props.content;

function onUpdate(prevProps, nextProps) {
if (prevProps.content !== nextProps.content) {
if (nextProps.allowHTML) box.innerHTML = nextProps.content;
else box.textContent = nextProps.content;
}
}

return { popper, onUpdate }
},
onShow(instance) {
instance.popper.firstChild.classList.add("main-contextMenu-tippyEnter");
},
onMount(instance) {
requestAnimationFrame(() => {
instance.popper.firstChild.classList.remove("main-contextMenu-tippyEnter");
instance.popper.firstChild.classList.add("main-contextMenu-tippyEnterActive");
});
},
onHide(instance) {
requestAnimationFrame(() => {
instance.popper.firstChild.classList.remove("main-contextMenu-tippyEnterActive");
instance.unmount();
});
},
},
writable: false,
});

Spicetify.Topbar = (function() {
let leftContainer;
const buttonsStash = new Set();
Expand All @@ -1212,17 +1254,23 @@ Spicetify.Topbar = (function() {
constructor(label, icon, onClick, disabled = false) {
this.element = document.createElement("button");
this.element.classList.add("main-topBar-button");
this.label = label;
this.icon = icon;
this.onClick = onClick;
this.disabled = disabled;
this.tippy = Spicetify.Tippy?.(this.element, {
content: label,
placement: "bottom",
...Spicetify.TippyProps,
});
this.label = label;
buttonsStash.add(this.element);
leftContainer?.append(...buttonsStash);
}
get label() { return this._label; }
set label(text) {
this._label = text;
this.element.setAttribute("title", text);
if (!this.tippy) this.element.setAttribute("title", text);
else this.tippy.setContent(text);
}
get icon() { return this._icon; }
set icon(input) {
Expand Down Expand Up @@ -1289,7 +1337,7 @@ Spicetify.Playbar = (function() {
constructor(label, icon, onClick, disabled = false, active = false) {
this.element = document.createElement("button");
this.element.classList.add("main-genericButton-button");
this.label = label;
this.element.style.display = "block";
this.icon = icon;
this.onClick = onClick;
this.disabled = disabled;
Expand All @@ -1299,13 +1347,19 @@ Spicetify.Playbar = (function() {
this.element.classList.add(className);
}
});
this.tippy = Spicetify.Tippy?.(this.element, {
content: label,
...Spicetify.TippyProps,
});
this.label = label;
buttonsStash.add(this.element);
rightContainer?.prepend(...buttonsStash);
}
get label() { return this._label; }
set label(text) {
this._label = text;
this.element.setAttribute("title", text);
if (!this.tippy) this.element.setAttribute("title", text);
else this.tippy.setContent(text);
}
get icon() { return this._icon; }
set icon(input) {
Expand Down Expand Up @@ -1335,7 +1389,7 @@ Spicetify.Playbar = (function() {

(function waitForPlaybarMounted() {
sibling = document.querySelector(".main-nowPlayingBar-right .main-genericButton-button");
rightContainer = sibling?.parentElement;
rightContainer = document.querySelector(".main-nowPlayingBar-right > div");
if (!rightContainer) {
setTimeout(waitForPlaybarMounted, 300);
return;
Expand Down
7 changes: 6 additions & 1 deletion src/preprocess/preprocess.go
Expand Up @@ -377,7 +377,7 @@ Spicetify.React.useEffect(() => {
`${1}=Spicetify.ReactComponent.PlaylistMenu${2}`)

// React Component: Tooltip Wrapper
utils.Replace(
utils.ReplaceOnce(
&input,
`(\w+)(=(?:function\([\{\w\}:,]+\)|\()\{(?:[\w. =]*(?:label|children|renderInline|showDelay)[\w:]*,?){4})`,
`${1}=Spicetify.ReactComponent.TooltipWrapper${2}`)
Expand Down Expand Up @@ -504,6 +504,11 @@ if (${1}.popper?.firstChild?.id === "context-menu") {
`(\w+ [\w$_]+)=[\w$_]+\([\w$_]+>>>0\)`,
`${1}=Spicetify._getStyledClassName(arguments,this)`)

utils.Replace(
&input,
`([\w$_]+)\.setDefaultProps=`,
`Spicetify.Tippy=${1};${0}`)

return input
}

Expand Down

0 comments on commit 63e2d49

Please sign in to comment.