Skip to content

Instantly share code, notes, and snippets.

@KevinBatdorf
Last active May 7, 2024 18:51
Show Gist options
  • Save KevinBatdorf/8bd5f808fff6a59e100dfa08a7431822 to your computer and use it in GitHub Desktop.
Save KevinBatdorf/8bd5f808fff6a59e100dfa08a7431822 to your computer and use it in GitHub Desktop.
Auto copy the Alpine code from Tailwind UI's copy button
// ==UserScript==
// @name Add AlpineJs to Tailwind UI
// @namespace http://tampermonkey.net/
// @version 3.0
// @description Add Alpine JS code to Tailwind Ui copy/paste
// @author https://gist.github.com/KevinBatdorf/8bd5f808fff6a59e100dfa08a7431822
// @match https://tailwindui.com/components/*
// @grant none
// ==/UserScript==
// Requires Tampermonkey
// Chrome - https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en
// FF - https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/
// Find me on Twitter: https://twitter.com/kevinbatdorf
// Get the version that downloads the code into a file here:
// https://gist.github.com/KevinBatdorf/322c68f532af6a4cc6773f906da0684d
// If it seems to not be working, check the classes here are matching
const code = Array.from(document.querySelectorAll('button')).filter(
b => b.classList.value === 'group relative ml-2 hidden h-9 w-9 items-center justify-center sm:flex'
);
code.forEach(node => {
node.addEventListener('click', function(event) {
event.preventDefault();
// This is the iFrame the component is in
const iFrame = event.target.closest('[id^=component-]').querySelector('[name][id^=frame]');
const contentArea = iFrame.contentWindow.document.querySelector('body > div');
const markup = contentArea.innerHTML;
// This will attempt to extract the function used in the x-data, like x-data="Component.popover"
const scripts = Array.from(contentArea.querySelectorAll('[x-data]'))
.filter((n) => /\(.*\)/.test(n.getAttribute('x-data').toString()))
.map((n) => {
const fnNameSplit = n
.getAttribute('x-data')
.replace('window.', '')
.replace(/\(.*\)/, '')
.split('.');
// We need to get the string representation of the method
const method = new Function(`return ${iFrame.contentWindow[fnNameSplit[0]][fnNameSplit[1]]};`);
// This adds checks to create the global object then register it.
return `
window.${fnNameSplit[0]} = window.${fnNameSplit[0]} ?? {}
window.${fnNameSplit[0]}['${fnNameSplit[1]}'] = ${method}()
`
})
.join(';')
.toString();
const textarea = document.createElement('textarea');
textarea.textContent = scripts ? `<script>${scripts}</script>` + markup : markup;
document.body.appendChild(textarea);
setTimeout(() => {
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
}, 50);
})
})
@KevinBatdorf
Copy link
Author

@aitoehigie I just tried it on a dropdown and it worked. Which componen isn't working?

@morgler
Copy link

morgler commented May 7, 2024

I can confirm, it worked for me on the full Application UI Sidebar layout

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment