From 439968d04fd7880f76e7fff027bf618a12ee887b Mon Sep 17 00:00:00 2001 From: Native Muttaqien Date: Mon, 17 Aug 2026 22:31:02 +0700 Subject: [PATCH] Fix landing page install UX and hero alignment - Remove redundant install pill from nav (desktop + mobile) - Add beginner install walkthrough, ARL cookie gloss, and fix duplicate Docs/grab-yours link - Unify install command into one copy-to-clipboard control - Fix hero content column misaligned with rest of page at desktop widths (mx-auto + lg:w-[54%] was centering it independently instead of anchoring to the shared max-w-[1440px] rail) Co-Authored-By: Claude Sonnet 5 --- web/src/App.tsx | 116 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 18 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 2b6c588..7dfe092 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,9 +1,11 @@ -import { useEffect, useState } from 'react' +import { useEffect, useRef, useState } from 'react' const INSTALL = 'npm i -g plx-converter' const GITHUB = 'https://github.com/samlehoy/plx' const NPM = 'https://www.npmjs.com/package/plx-converter' const DOCS = 'https://github.com/samlehoy/plx/tree/master/docs' +const ARL_GUIDE = 'https://github.com/samlehoy/plx/blob/master/docs/CONFIG.md#getting-the-cookies' +const NODEJS = 'https://nodejs.org' type Tier = { id: string @@ -99,6 +101,64 @@ function useReducedMotion(): boolean { return reduce } +async function copyToClipboard(text: string): Promise { + try { + await navigator.clipboard.writeText(text) + return true + } catch { + try { + const ta = document.createElement('textarea') + ta.value = text + ta.style.position = 'fixed' + ta.style.opacity = '0' + document.body.appendChild(ta) + ta.select() + document.execCommand('copy') + document.body.removeChild(ta) + return true + } catch { + return false + } + } +} + +function CopyInstallPill({ size, scrollToId }: { size: 'sm' | 'lg'; scrollToId?: string }) { + const [copied, setCopied] = useState(false) + const timeoutRef = useRef(undefined) + + useEffect(() => () => window.clearTimeout(timeoutRef.current), []) + + const handleClick = async () => { + const ok = await copyToClipboard(INSTALL) + if (ok) { + setCopied(true) + window.clearTimeout(timeoutRef.current) + timeoutRef.current = window.setTimeout(() => setCopied(false), 1400) + } + if (scrollToId) { + const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches + document.getElementById(scrollToId)?.scrollIntoView({ behavior: reduce ? 'auto' : 'smooth' }) + } + } + + const base = size === 'lg' ? 'pill meta h-12 px-6' : 'pill meta h-11 px-5' + const color = copied ? 'bg-signal text-ground' : 'bg-ink text-ground hover:bg-signal' + + return ( + + ) +} + export default function App() { const reduce = useReducedMotion() const [tierIdx, setTierIdx] = useState(0) @@ -227,9 +287,6 @@ export default function App() { Spec Install Github - - {INSTALL} -
@@ -253,9 +310,6 @@ export default function App() { Github
- - {INSTALL} -
@@ -266,7 +320,8 @@ export default function App() { className="hero-stage relative bg-stage pt-16" style={{ minHeight: 'calc(100svh)' }} > -
+
+

Spotify ⇄ Deezer

Move your playlist. @@ -278,9 +333,7 @@ export default function App() { no OAuth app. One Deezer ARL cookie is enough. Reverse (Deezer → Spotify) is planned.

+
{/* pinned edge metadata */} +
+ + + → + + New to the command line? Four steps. + +
    +
  1. + Install{' '} + + Node.js + {' '} + — version 22 or later. +
  2. +
  3. Open Terminal (macOS/Linux) or Command Prompt / PowerShell (Windows).
  4. +
  5. + Paste {INSTALL} and + press Enter. +
  6. +
  7. + Run plx --version — + if it prints a version number, the install worked. +
  8. +
+
+
- Github + Github Npm Docs © plx · local-first · no telemetry