aboutsummaryrefslogtreecommitdiffstats
path: root/src/app/page.tsx
diff options
context:
space:
mode:
authorPinapelz <yukais@pinapelz.com>2026-04-15 23:45:04 -0700
committerPinapelz <yukais@pinapelz.com>2026-04-15 23:45:04 -0700
commit30d2ca8480caea1ce76cc1ec29d454e3a669c638 (patch)
treecf4e846151601d568d12f2ec7b1f4c003282325e /src/app/page.tsx
parent6b168927b8995d428d243052e93713a2ab86cff9 (diff)
refactor: move styled components to their own style.ts file
Diffstat (limited to 'src/app/page.tsx')
-rw-r--r--src/app/page.tsx370
1 files changed, 30 insertions, 340 deletions
diff --git a/src/app/page.tsx b/src/app/page.tsx
index a278f78..fbe91be 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,9 +1,37 @@
"use client";
import { useState, useEffect } from "react";
-import styled from "styled-components";
-import Link from "next/link";
import { FaPlay, FaMusic, FaSearch, FaUserCircle } from "react-icons/fa";
import { MdLibraryMusic } from "react-icons/md";
+import { Root, Navbar, Logo, LogoIcon, NavLink } from "./styles/shared";
+import {
+ NavLeft,
+ NavCenter,
+ SearchBox,
+ SearchInput,
+ SearchButton,
+ NavRight,
+ Avatar,
+ ChipsBar,
+ Chip,
+ GridContainer,
+ CardGrid,
+ Card,
+ ThumbnailWrapper,
+ Thumbnail,
+ PlayOverlay,
+ PlayCircle,
+ BadgeRow,
+ Badge,
+ CardMeta,
+ CardInfo,
+ CardTitle,
+ CardSub,
+ EmptyState,
+ CtaSection,
+ SectionHeading,
+ OpenPlayerLink,
+ PlayerDescription,
+} from "./page.styles";
interface KaraokeEntry {
title: string;
@@ -16,344 +44,6 @@ interface KaraokeEntry {
type KaraokeData = Record<string, KaraokeEntry[]>;
-const Root = styled.div`
- min-height: 100vh;
- background-color: #f9f9f9;
- color: #1a1a1a;
- font-family: "Roboto", "Segoe UI", Arial, sans-serif;
-`;
-
-const Navbar = styled.nav`
- position: sticky;
- top: 0;
- z-index: 100;
- display: flex;
- align-items: center;
- justify-content: space-between;
- height: 56px;
- padding: 0 20px;
- background-color: #ffffffee;
- backdrop-filter: blur(12px);
- border-bottom: 1px solid #e5e5e5;
-`;
-
-const NavLeft = styled.div`
- display: flex;
- align-items: center;
- gap: 14px;
-`;
-
-const Logo = styled(Link)`
- font-size: 17px;
- font-weight: 800;
- letter-spacing: 0.3px;
- color: #1a1a1a;
- text-decoration: none;
- display: flex;
- align-items: center;
- gap: 7px;
- user-select: none;
-`;
-
-const LogoIcon = styled.span`
- display: inline-flex;
- align-items: center;
- justify-content: center;
- background-color: #1a1a1a;
- color: #fff;
- border-radius: 6px;
- width: 30px;
- height: 22px;
- font-size: 10px;
-`;
-
-const NavCenter = styled.div`
- display: flex;
- align-items: center;
- flex: 0 1 560px;
-`;
-
-const SearchBox = styled.div`
- display: flex;
- align-items: center;
- flex: 1;
- height: 38px;
- border: 1px solid #d4d4d4;
- border-radius: 10px;
- overflow: hidden;
- background-color: #f0f0f0;
- transition: border-color 0.2s;
- &:focus-within {
- border-color: #1a1a1a;
- }
-`;
-
-const SearchInput = styled.input`
- flex: 1;
- height: 100%;
- padding: 0 14px;
- background: transparent;
- border: none;
- outline: none;
- color: #1a1a1a;
- font-size: 14px;
- &::placeholder {
- color: #909090;
- }
-`;
-
-const SearchButton = styled.button`
- width: 52px;
- height: 100%;
- background-color: #e8e8e8;
- border: none;
- border-left: 1px solid #d4d4d4;
- color: #606060;
- font-size: 14px;
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: center;
- &:hover {
- background-color: #d4d4d4;
- color: #1a1a1a;
- }
-`;
-
-const NavRight = styled.div`
- display: flex;
- align-items: center;
- gap: 6px;
-`;
-
-const NavLink = styled(Link)`
- font-size: 13px;
- font-weight: 500;
- color: #606060;
- text-decoration: none;
- padding: 6px 10px;
- border-radius: 8px;
- transition: background-color 0.15s, color 0.15s;
- &:hover {
- background-color: #f0f0f0;
- color: #1a1a1a;
- }
-`;
-
-const Avatar = styled.div`
- font-size: 28px;
- color: #909090;
- display: flex;
- align-items: center;
- cursor: pointer;
- padding: 4px;
- border-radius: 50%;
- &:hover {
- color: #606060;
- }
-`;
-
-const ChipsBar = styled.div`
- display: flex;
- align-items: center;
- gap: 10px;
- padding: 14px 24px;
- overflow-x: auto;
- background-color: #f9f9f9;
- &::-webkit-scrollbar {
- display: none;
- }
-`;
-
-const Chip = styled.button<{ $active?: boolean }>`
- white-space: nowrap;
- padding: 7px 16px;
- border-radius: 10px;
- border: 1px solid ${(p) => (p.$active ? "transparent" : "#d4d4d4")};
- font-size: 13px;
- font-weight: 500;
- cursor: pointer;
- transition: all 0.15s;
- background-color: ${(p) => (p.$active ? "#1a1a1a" : "transparent")};
- color: ${(p) => (p.$active ? "#fff" : "#606060")};
- &:hover {
- background-color: ${(p) => (p.$active ? "#333" : "#f0f0f0")};
- color: ${(p) => (p.$active ? "#fff" : "#1a1a1a")};
- }
-`;
-
-const GridContainer = styled.div`
- padding: 8px 24px 24px;
-`;
-
-const CardGrid = styled.div`
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
- gap: 20px;
-`;
-
-const Card = styled(Link)`
- cursor: pointer;
- border-radius: 14px;
- text-decoration: none;
- color: inherit;
- display: block;
- transition: transform 0.15s, box-shadow 0.15s;
- &:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
- }
-`;
-
-const ThumbnailWrapper = styled.div`
- width: 100%;
- aspect-ratio: 16 / 9;
- background-color: #e4e4e4;
- border-radius: 12px;
- display: flex;
- align-items: center;
- justify-content: center;
- color: #c0c0c0;
- font-size: 36px;
- overflow: hidden;
- position: relative;
-`;
-
-const Thumbnail = styled.img`
- width: 100%;
- height: 100%;
- object-fit: cover;
-`;
-
-const PlayOverlay = styled.div`
- position: absolute;
- inset: 0;
- display: flex;
- align-items: center;
- justify-content: center;
- background: rgba(0, 0, 0, 0);
- border-radius: 12px;
- transition: background 0.2s;
- ${Card}:hover & {
- background: rgba(0, 0, 0, 0.25);
- }
-`;
-
-const PlayCircle = styled.div`
- width: 48px;
- height: 48px;
- border-radius: 50%;
- background: rgba(0, 0, 0, 0.7);
- color: #fff;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 16px;
- opacity: 0;
- transform: scale(0.8);
- transition: opacity 0.2s, transform 0.2s;
- ${Card}:hover & {
- opacity: 1;
- transform: scale(1);
- }
-`;
-
-const BadgeRow = styled.div`
- position: absolute;
- bottom: 8px;
- left: 8px;
- display: flex;
- gap: 4px;
-`;
-
-const Badge = styled.span<{ $color: string }>`
- font-size: 10px;
- font-weight: 700;
- letter-spacing: 0.4px;
- padding: 2px 6px;
- border-radius: 4px;
- background-color: ${(p) => p.$color};
- color: #fff;
- text-transform: uppercase;
-`;
-
-const CardMeta = styled.div`
- display: flex;
- gap: 12px;
- margin-top: 12px;
- padding: 0 4px 12px;
-`;
-
-const CardInfo = styled.div`
- display: flex;
- flex-direction: column;
- gap: 3px;
- min-width: 0;
-`;
-
-const CardTitle = styled.span`
- font-size: 14px;
- font-weight: 600;
- color: #1a1a1a;
- line-height: 1.35;
- display: -webkit-box;
- -webkit-line-clamp: 2;
- -webkit-box-orient: vertical;
- overflow: hidden;
-`;
-
-const CardSub = styled.span`
- font-size: 12px;
- color: #909090;
- line-height: 1.3;
-`;
-
-const EmptyState = styled.div`
- grid-column: 1 / -1;
- padding: 48px 0;
- text-align: center;
- font-size: 14px;
- color: #909090;
-`;
-
-const CtaSection = styled.div`
- padding: 32px 24px;
- border-top: 1px solid #e5e5e5;
- margin-top: 8px;
-`;
-
-const SectionHeading = styled.h2`
- font-size: 17px;
- font-weight: 700;
- color: #1a1a1a;
- margin: 0 0 14px;
-`;
-
-const OpenPlayerLink = styled(Link)`
- display: inline-flex;
- align-items: center;
- gap: 8px;
- padding: 10px 22px;
- border-radius: 10px;
- background-color: #1a1a1a;
- color: #fff;
- font-size: 14px;
- font-weight: 600;
- text-decoration: none;
- transition: background-color 0.15s;
- &:hover {
- background-color: #333;
- }
-`;
-
-const PlayerDescription = styled.p`
- font-size: 13px;
- color: #909090;
- margin: 14px 0 0;
- line-height: 1.6;
- max-width: 480px;
-`;
-
function capitalize(s: string) {
return s.charAt(0).toUpperCase() + s.slice(1);
}
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage