Skip to content

Commit

Permalink
Styling with tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
oskarrough committed Jun 28, 2024
1 parent 5cb99e2 commit 2f73382
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 28 deletions.
Binary file modified bun.lockb
Binary file not shown.
49 changes: 39 additions & 10 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,56 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="data:;base64,iVBORw0KGgo=" />
<title>Spotify to YouTube</title>
<title>Spotify to YouTube to Text/CSV & Radio4000</title>
<link rel="stylesheet" href="./src/index.css" />
<script type="module" src="./src/main.js"></script>
</head>
<body>
<header>
<h1>Convert Spotify playlist &rarr;<br />YouTube videos &rarr;<br />Radio4000 tracks</h1>
<p>Did you just find a good Spotify playlist, but don't want to listen on Spotify?</p>
<p>
This tool helps you create a matching list of YouTube videos. Save as .txt and pipe it to
<code>yt-dlp</code>, or copy/paste as text or .csv, or even import directly into beta.radio4000.com.
</p>
<h1>
Convert music playlists &rarr;<br />Text, CSV, Spotify, YouTube
& Radio4000.
</h1>
<ul>
<li>Convert Spotify playlists to YouTube videos</li>
<li>Find matching YouTube videos from text playlists</li>
</ul>
<p>And then you could</p>
<ul>
<li>Save as .txt or .csv files for easy storage and sharing</li>
<li>Pipe to <code>yt-dlp</code> to download audio locally</li>
<li>Import your results to Radio4000</li>
</ul>
</header>

<main>
<text-to-youtube></text-to-youtube>
<spotify-to-youtube></spotify-to-youtube>
<tab-container>
<button
type="button"
id="tab-one"
role="tab"
aria-selected="true"
>
Spotify to YouTube
</button>
<button type="button" id="tab-two" role="tab" tabindex="-1">
Text to YouTube
</button>
<div role="tabpanel" aria-labelledby="tab-one">
<spotify-to-youtube></spotify-to-youtube>
</div>
<div role="tabpanel" aria-labelledby="tab-two" hidden>
<text-to-youtube></text-to-youtube>
</div>
</tab-container>
</main>

<footer>
<p><a href="https://github.com/oskarrough/spotify-to-youtube">View source</a></p>
<p>
<a href="https://github.com/oskarrough/spotify-to-youtube"
>View source</a
>
</p>
</footer>
</body>
</html>
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"preview": "vite preview"
},
"dependencies": {
"@github/tab-container-element": "^4.8.2",
"lit": "^3.1.4"
},
"devdependencies": {
Expand Down
36 changes: 27 additions & 9 deletions src/index.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@import url("tabs.css");

:root {
font-family: system-ui, sans-serif;
line-height: 1.25;
Expand Down Expand Up @@ -46,62 +48,73 @@ spotify-to-youtube ul {
.tracks {
display: flex;
flex-direction: column;
/* gap: 1em; */
padding-left: 2rem;
}

.results {
display: flex;
flex-direction: column;
margin: 1rem 0 1rem 1rem;
padding: 0;
margin: 1rem 0 1rem 0.5rem;
}

.results > li {
display: flex;
gap: 1em;
gap: 0.5em;
margin-bottom: 1px;
font-size: 14px;
}

.results:has(input[type='radio']:checked) li ul {
.results:has(input[type="radio"]:checked) li ul {
opacity: 0.25;
}

.results li ul {
padding: 0.2em;
padding: 0.3em;
margin: auto 0;
}

.results li:has(input[type='radio']:checked) ul {
.results li:has(input[type="radio"]:checked) ul {
outline: 1px solid darkgreen;
opacity: 1;
border-radius: 0.3em;
}

.results img {
width: 5rem;
width: 3rem;
height: 3rem;
object-fit: cover;
/* display: none; */
vertical-align: top;
}

input:not([type='radio']) {
input:not([type="radio"]) {
width: 20rem;
max-width: 100%;
margin-bottom: 0.5em;
padding: 0.2rem 0.4em;
min-height: 1.5em;
}

[type="submit"] {
/* font-size: 1em; */
}

details {
margin-bottom: 1rem;
}

textarea {
min-width: 40em;
field-sizing: content;
}

section summary {
user-select: none;
min-height: 2em;
line-height: 2;
padding-left: 0.5em;
margin-bottom: 1em;
/* margin-bottom: 1em; */
}
section[spotify] summary {
background: #1abd55;
Expand All @@ -118,3 +131,8 @@ section[r4] summary {
background: #5e1ae6;
color: white;
}
details[open] summary {
position: sticky;
top: 0;
margin-bottom: 1rem;
}
1 change: 1 addition & 0 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'https://cdn.jsdelivr.net/npm/@radio4000/components/dist/r4.js'
import 'https://cdn.jsdelivr.net/gh/oskarrough/rough-spinner/rough-spinner.js'
import '@github/tab-container-element'

import SpotifyToYoutube from './spotify-to-youtube.js'
import TextToYoutube from './text-to-youtube.js'
Expand Down
83 changes: 83 additions & 0 deletions src/tabs.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
tab-container {
/* width: 100%; */
--tab-hover-color: orange;
--tab-selected-color: green;
--tab-border-color: hsl(219, 1%, 72%);
--tab-background-color: hsl(220, 20%, 94%);
--tab-selected-background-color: hsl(220, 43%, 99%);
--tabpanel-background-color: hsl(220, 43%, 99%);
--tabpanel-focus-border-color: hsl(20, 96%, 48%);
}

tab-container > [role="tablist"][aria-orientation="vertical"] {
display: flex;
flex-direction: column;
}
tab-container:has([aria-orientation="vertical"]) {
display: flex;
flex-direction: row;
}
tab-container:has([aria-orientation="vertical"]) [role="tabpanel"] {
flex: 1;
}

[role="tab"] {
position: relative;
margin: 0;
padding: 0.3em 0.5em 0.4em;
border: 1px solid var(--tab-border-color);
border-radius: 0.2em 0.2em 0 0;
overflow: visible;
font-family: inherit;
font-size: inherit;
background: var(--tab-background-color);
}

[role="tab"][aria-selected="true"] {
border-radius: 0;
background: var(--tab-selected-background-color);
outline: 0;
}

[role="tab"][aria-selected="true"]::after {
position: absolute;
z-index: 3;
bottom: -1px;
right: 0;
left: 0;
height: 0.3em;
background: var(--tab-selected-background-color);
content: "";
}

[role="tab"]:hover,
[role="tab"]:focus,
[role="tab"]:active {
outline: 0;
border-radius: 0;
color: inherit;
}

[role="tabpanel"] {
position: relative;
z-index: 2;
padding: 0.5em 0.5em 0;
border: 1px solid var(--tab-border-color);
border-radius: 0 0.2em 0.2em 0.2em;
background: var(--tabpanel-background-color);
}

[role="tabpanel"]:focus {
border-color: var(--tabpanel-focus-border-color);
outline: 0;
}

[role="tabpanel"]:focus::after {
position: absolute;
bottom: 0;
right: -1px;
left: -1px;
border-bottom: 3px solid var(--tabpanel-focus-border-color);
border-radius: 0 0 0.2em 0.2em;
content: "";
}
17 changes: 8 additions & 9 deletions src/text-to-youtube.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,16 @@ export default class TextToYoutube extends LitElement {
return html`
<section>
<details open>
<summary>Step 1. Write the tracks you want</summary>
<summary>Step 1. Enter your playlist as text</summary>
<form @submit=${this.findMatches}>
<label for="text_playlist">Text playlist</label><br />
<textarea name="text_playlist" id="text_playlist" rows="20" required>
<label for="text_playlist">One track per line</label><br />
<textarea name="text_playlist" id="text_playlist" required>
joy orbison in drink
tierra hungry hippo
burger ink elvism
</textarea
><br />
<button type="submit" ?disabled=${this.loading}>Import</button>
<button type="submit" ?disabled=${this.loading}>Search YouTube for matching videos</button>
</form>
${this.error
? html` <p>Error! Could not fetch this playlist. Is it public?<br /><code>${this.error}</code></p> `
Expand All @@ -120,9 +120,8 @@ burger ink elvism
${this.inputLines?.map(
(track, i) => html`
<li>
<strong>${i + 1}. ${track.title}</strong>
<button @click=${(event) => this.skipTrack(event, track)}>Skip</button>
<strong>${i}. ${track.artist} - ${track.title}</strong>
<a target="_blank" href=${track.url}>link</a>
<ul class="results">
${track.searchResults.map((video, i) =>
searchResultTemplate(track, i, video, this.youtubeResults),
Expand Down Expand Up @@ -154,16 +153,16 @@ burger ink elvism
`,
)}
</ul>
<p>Copy paste as CSV</p>
<p>CSV</p>
<textarea rows=${this.youtubeResults?.length}>
title;youtube
${this.youtubeResults?.map((m) => `${m.title.replace(';', '')};${m.youtubeId}\n`)}</textarea
>
<p>Copy paste the YouTube IDs</p>
<p>YouTube IDs</p>
<textarea rows=${this.youtubeResults?.length}>
${this.youtubeResults?.map((m) => m.youtubeId + '\n')}</textarea
>
<p>Copy paste the YouTube URLs</p>
<p>YouTube URLs</p>
<textarea rows=${this.youtubeResults?.length}>
${this.youtubeResults?.map((m) => 'https://www.youtube.com/watch?v=' + m.youtubeId + '\n')}</textarea
>
Expand Down

0 comments on commit 2f73382

Please sign in to comment.