refactor: enhance layout and styling for improved responsiveness and usability across components
Gitea Auto Deploy / Deploy-Container (push) Successful in 33s

This commit is contained in:
2026-08-28 19:24:25 +07:00
parent 87e34933fb
commit bbe4c92872
11 changed files with 81 additions and 60 deletions
+7 -4
View File
@@ -11,10 +11,13 @@
nocompatible: true; nocompatible: true;
} }
:root { html, body {
--size-big: 4vw; height: 100%;
--size-medium: 3vw; height: 100dvh;
--size-small: 2vw; width: 100%;
overflow: hidden;
overscroll-behavior: none;
-webkit-overflow-scrolling: touch;
} }
/* Smooth Modern Ultra-Sleek Scrollbars */ /* Smooth Modern Ultra-Sleek Scrollbars */
+4 -4
View File
@@ -64,9 +64,9 @@ export default async function RootLayout({
const locale = await getLocale() const locale = await getLocale()
return ( return (
<html lang={locale} suppressHydrationWarning className="h-full overflow-hidden"> <html lang={locale} suppressHydrationWarning className="h-full w-full overflow-hidden overscroll-none fixed inset-0">
<body <body
className={`${geistSans.variable} ${geistMono.variable} antialiased h-full overflow-hidden max-w-full`} className={`${geistSans.variable} ${geistMono.variable} antialiased h-full w-full overflow-hidden overscroll-none fixed inset-0 max-w-full`}
suppressHydrationWarning suppressHydrationWarning
> >
<NextIntlClientProvider messages={messages}> <NextIntlClientProvider messages={messages}>
@@ -74,7 +74,7 @@ export default async function RootLayout({
<ThemeProvider> <ThemeProvider>
<ClientThemeWrapper> <ClientThemeWrapper>
<ClientDataFetcher > <ClientDataFetcher >
<div className="h-screen w-full flex flex-col overflow-hidden bg-ambient-mesh selection:bg-primary/20 selection:text-primary"> <div className="h-dvh w-full flex flex-col overflow-hidden bg-ambient-mesh selection:bg-primary/20 selection:text-primary">
<Header /> <Header />
<main className="grid grid-cols-12 w-full flex-1 min-h-0 overflow-hidden"> <main className="grid grid-cols-12 w-full flex-1 min-h-0 overflow-hidden">
<aside className="hidden sm:block sm:col-span-4 md:col-span-4 lg:col-span-3 h-full overflow-hidden border-r border-base-content/10 bg-base-100/30 backdrop-blur-sm"> <aside className="hidden sm:block sm:col-span-4 md:col-span-4 lg:col-span-3 h-full overflow-hidden border-r border-base-content/10 bg-base-100/30 backdrop-blur-sm">
@@ -84,7 +84,7 @@ export default async function RootLayout({
<div className="shrink-0"> <div className="shrink-0">
<ActionBar /> <ActionBar />
</div> </div>
<div className="flex-1 overflow-y-auto min-h-0 p-2 sm:p-3 sm:pt-1 flex flex-col justify-between"> <div className="flex-1 overflow-y-auto min-h-0 px-3 sm:px-4 pt-1 pb-3 flex flex-col justify-between">
<div> <div>
{children} {children}
</div> </div>
+16 -6
View File
@@ -122,8 +122,18 @@ export default function ActionBar() {
}; };
const actionMove = (path: string) => { const actionMove = (path: string) => {
router.push(`/${path}`) if (typeof document !== "undefined" && document.activeElement instanceof HTMLElement) {
} document.activeElement.blur();
}
if (typeof window !== "undefined") {
window.scrollTo(0, 0);
const scrollContainer = document.querySelector('section > div.flex-1.overflow-y-auto');
if (scrollContainer) {
scrollContainer.scrollTo({ top: 0, behavior: 'instant' });
}
}
router.push(`/${path}`, { scroll: false });
};
const handleProfileSelect = (profileId: number) => { const handleProfileSelect = (profileId: number) => {
if (!avatarSelected || !avatars[avatarSelected.ID]) return; if (!avatarSelected || !avatars[avatarSelected.ID]) return;
@@ -267,7 +277,7 @@ export default function ActionBar() {
const currentActivePath = pathname?.replace(/^\//, '') || ""; const currentActivePath = pathname?.replace(/^\//, '') || "";
return ( return (
<div className="w-full bg-transparent px-3 sm:px-4 py-2 space-y-2"> <div className="w-full bg-transparent px-3 sm:px-4 pt-2.5 sm:pt-3 pb-1 space-y-2">
{/* Top Row: Character Identity + Profile Selector + Connect PS */} {/* Top Row: Character Identity + Profile Selector + Connect PS */}
<div className="flex flex-wrap items-center justify-between gap-2.5"> <div className="flex flex-wrap items-center justify-between gap-2.5">
{/* Character Identity */} {/* Character Identity */}
@@ -436,9 +446,9 @@ export default function ActionBar() {
</button> </button>
<div className="dropdown dropdown-end w-full"> <div className="dropdown dropdown-end w-full">
<label tabIndex={0} className="btn btn-info btn-sm w-full font-bold shadow-xs"> <div tabIndex={0} role="button" className="btn btn-info btn-sm w-full font-bold shadow-xs">
{transI18n("actions")} {transI18n("actions")}
</label> </div>
<ul <ul
tabIndex={0} tabIndex={0}
className="dropdown-content z-50 menu p-2 shadow-2xl bg-base-100 rounded-2xl w-56 mt-2 border border-base-300 space-y-1" className="dropdown-content z-50 menu p-2 shadow-2xl bg-base-100 rounded-2xl w-56 mt-2 border border-base-300 space-y-1"
@@ -554,7 +564,7 @@ export default function ActionBar() {
<button <button
type="button" type="button"
onClick={handleConfirmDeleteProfile} onClick={handleConfirmDeleteProfile}
className="flex-1 h-10 px-4 rounded-xl font-bold text-xs sm:text-sm bg-gradient-to-r from-rose-500 to-red-600 hover:from-rose-400 hover:to-red-500 text-white shadow-md shadow-rose-500/25 hover:shadow-rose-500/40 transition-all flex items-center justify-center gap-1.5 cursor-pointer" className="flex-1 h-10 px-4 rounded-xl font-bold text-xs sm:text-sm bg-linear-to-r from-rose-500 to-red-600 hover:from-rose-400 hover:to-red-500 text-white shadow-md shadow-rose-500/25 hover:shadow-rose-500/40 transition-all flex items-center justify-center gap-1.5 cursor-pointer"
> >
<Trash2 className="w-4 h-4" /> <Trash2 className="w-4 h-4" />
<span>{transI18n("confirmDelete")}</span> <span>{transI18n("confirmDelete")}</span>
+1 -1
View File
@@ -456,7 +456,7 @@ export default function AvatarInfo() {
<dialog id="action_detail_modal" className="modal"> <dialog id="action_detail_modal" className="modal">
<div className="modal-box w-11/12 max-w-[92vw] sm:max-w-[88vw] max-h-[90vh] flex flex-col bg-base-100 text-base-content border border-white/10 shadow-2xl rounded-2xl p-0 overflow-hidden"> <div className="modal-box w-11/12 max-w-[92vw] sm:max-w-[88vw] max-h-[90vh] flex flex-col bg-base-100 text-base-content border border-white/10 shadow-2xl rounded-2xl p-0 overflow-hidden">
<div className="sticky top-0 z-20 flex items-center justify-between px-6 py-4 border-b border-base-content/10 bg-base-100 shrink-0"> <div className="sticky top-0 z-20 flex items-center justify-between px-6 py-4 border-b border-base-content/10 bg-base-100 shrink-0">
<h3 className="font-bold text-xl tracking-tight bg-clip-text text-transparent bg-linear-to-r from-primary via-accent to-secondary"> <h3 className="font-bold text-xl tracking-tight text-base-content">
{transI18n("lightconeEquipment")} {transI18n("lightconeEquipment")}
</h3> </h3>
<button <button
+4 -4
View File
@@ -19,7 +19,7 @@ export default function LightconeCard({ data }: LightconeCardProps) {
const is4Star = data.Rarity === "CombatPowerLightconeRarity4"; const is4Star = data.Rarity === "CombatPowerLightconeRarity4";
return ( return (
<li className="group relative flex flex-col items-center rounded-xl overflow-hidden bg-base-100 border border-base-content/10 shadow-sm hover:shadow-md cursor-pointer select-none h-full"> <li className="group relative flex flex-col items-center rounded-xl overflow-hidden bg-base-100 border border-base-content/10 shadow-xs hover:shadow-md hover:border-primary/50 transition-all duration-200 cursor-pointer select-none w-full list-none">
{/* Artwork container with vibrant rarity background */} {/* Artwork container with vibrant rarity background */}
<div <div
className={`w-full relative aspect-3/4 flex items-center justify-center overflow-hidden bg-linear-to-b ${ className={`w-full relative aspect-3/4 flex items-center justify-center overflow-hidden bg-linear-to-b ${
@@ -42,12 +42,12 @@ export default function LightconeCard({ data }: LightconeCardProps) {
/> />
</div> </div>
{/* Name Label - Uniform Fixed-Height Footer */} {/* Name Label - Uniform Fixed-Height Footer with larger text */}
<div className="w-full h-11 px-1 py-0.5 text-center flex items-center justify-center bg-base-100"> <div className="w-full min-h-12 px-1.5 py-1 text-center flex items-center justify-center bg-base-100 shrink-0">
<ParseText <ParseText
locale={locale} locale={locale}
text={text} text={text}
className="font-bold text-xs leading-tight line-clamp-2 text-base-content group-hover:text-primary transition-colors text-center" className="font-bold text-xs sm:text-[13px] leading-snug line-clamp-2 text-base-content group-hover:text-primary transition-colors text-center"
/> />
</div> </div>
</li> </li>
+1 -1
View File
@@ -27,7 +27,7 @@ const getRarityColor = (rarity: string) => {
} }
}; };
const slotIconMap: Record<string, { icon: string; key: string }> = { export const slotIconMap: Record<string, { icon: string; key: string }> = {
'1': { icon: '/relics/HEAD.png', key: 'HEAD' }, '1': { icon: '/relics/HEAD.png', key: 'HEAD' },
'2': { icon: '/relics/HAND.png', key: 'HAND' }, '2': { icon: '/relics/HAND.png', key: 'HAND' },
'3': { icon: '/relics/BODY.png', key: 'BODY' }, '3': { icon: '/relics/BODY.png', key: 'BODY' },
+2 -2
View File
@@ -280,7 +280,7 @@ export default function Header() {
}; };
return ( return (
<header className="sticky top-0 z-40 w-full bg-base-100 border-b border-base-300 shadow-xs"> <header className="sticky top-0 z-40 w-full shrink-0 bg-base-100 border-b border-base-300 shadow-xs">
<div className="navbar max-w-[1920px] mx-auto px-2 sm:px-4 py-1.5 min-h-14"> <div className="navbar max-w-[1920px] mx-auto px-2 sm:px-4 py-1.5 min-h-14">
<div className="navbar-start gap-2"> <div className="navbar-start gap-2">
{/* Mobile menu dropdown */} {/* Mobile menu dropdown */}
@@ -638,7 +638,7 @@ export default function Header() {
<dialog key={id} id={id} className="modal"> <dialog key={id} id={id} className="modal">
<div className={`modal-box w-11/12 ${ <div className={`modal-box w-11/12 ${
id === 'monster_modal' || id === 'import_modal' || id === 'extra_modal' id === 'monster_modal' || id === 'import_modal' || id === 'extra_modal'
? 'max-w-[95vw] sm:max-w-[90vw] lg:max-w-[85vw] 2xl:max-w-[1500px] h-[88vh]' ? 'max-w-[95vw] sm:max-w-[90vw] lg:max-w-[85vw] 2xl:max-w-375 h-[88vh]'
: id === 'connect_modal' : id === 'connect_modal'
? 'max-w-[95vw] sm:max-w-2xl md:max-w-3xl lg:max-w-4xl max-h-[88vh]' ? 'max-w-[95vw] sm:max-w-2xl md:max-w-3xl lg:max-w-4xl max-h-[88vh]'
: id === 'changelog_modal' : id === 'changelog_modal'
+3 -3
View File
@@ -170,12 +170,12 @@ export default function LightconeBar() {
</div> </div>
</div> </div>
{/* Results Grid */} {/* Results Grid - Compact multi-column layout */}
<div className="grid grid-cols-2 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 xl:grid-cols-7 gap-3 auto-rows-fr max-h-[58vh] overflow-y-auto pr-1"> <div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 xl:grid-cols-7 2xl:grid-cols-8 gap-2.5 sm:gap-3 pr-1">
{listLightcone.map((item) => ( {listLightcone.map((item) => (
<div <div
key={item.ID} key={item.ID}
className="h-full flex flex-col" className="flex flex-col"
onClick={() => { onClick={() => {
if (avatarSelected) { if (avatarSelected) {
const avatar = avatars[avatarSelected.ID.toString()] const avatar = avatars[avatarSelected.ID.toString()]
+31 -23
View File
@@ -16,7 +16,7 @@ import useDetailDataStore from "@/stores/detailDataStore";
import { getLocaleName } from '@/helper'; import { getLocaleName } from '@/helper';
import useLocaleStore from "@/stores/localeStore"; import useLocaleStore from "@/stores/localeStore";
import { useShallow } from 'zustand/react/shallow'; import { useShallow } from 'zustand/react/shallow';
import { Trash2 } from "lucide-react"; import { Trash2, SlidersHorizontal } from "lucide-react";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
export default function RelicsInfo() { export default function RelicsInfo() {
@@ -249,6 +249,15 @@ export default function RelicsInfo() {
return () => window.removeEventListener('keydown', handleEscKey); return () => window.removeEventListener('keydown', handleEscKey);
}, [isOpenRelic]); }, [isOpenRelic]);
useEffect(() => {
if (!selectedRelicSlot) {
setSelectedRelicSlot("1");
}
}, [selectedRelicSlot, setSelectedRelicSlot]);
const selectedRelic = selectedRelicSlot ? getRelic(selectedRelicSlot) : null;
const isSelectedRelicEquipped = Boolean(selectedRelic);
return ( return (
<div className="w-full space-y-4"> <div className="w-full space-y-4">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 sm:gap-6"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-4 sm:gap-6">
@@ -274,7 +283,7 @@ export default function RelicsInfo() {
</button> </button>
</div> </div>
{/* 6-Slot Grid completely free of box-in-box */} {/* 6-Slot Grid */}
<div className="grid grid-cols-2 sm:grid-cols-3 gap-3 sm:gap-4"> <div className="grid grid-cols-2 sm:grid-cols-3 gap-3 sm:gap-4">
{["1", "2", "3", "4", "5", "6"].map((item, index) => ( {["1", "2", "3", "4", "5", "6"].map((item, index) => (
<div <div
@@ -291,34 +300,30 @@ export default function RelicsInfo() {
/> />
{/* Micro Actions */} {/* Micro Actions */}
<div className="absolute top-0 right-0 opacity-0 group-hover:opacity-100 transition-opacity duration-200 flex gap-1"> <div className="absolute top-1.5 right-1.5 opacity-0 group-hover:opacity-100 transition-all duration-200 flex gap-1 z-20">
<button <button
type="button" type="button"
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation();
handlerChangeRelic(item) handlerChangeRelic(item);
}} }}
className="btn btn-xs btn-circle btn-primary shadow-xs" className="w-6 h-6 rounded-lg bg-primary text-primary-content shadow-xs hover:scale-110 active:scale-95 transition-all flex items-center justify-center border border-white/20 cursor-pointer"
title={transI18n("changeRelic")} title={transI18n("changeRelic")}
> >
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <SlidersHorizontal className="w-3 h-3 stroke-[2.2]" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15.232 5.232l3.536 3.536M4 20h4l10.293-10.293a1 1 0 000-1.414l-2.586-2.586a1 1 0 00-1.414 0L4 16v4z" />
</svg>
</button> </button>
{getRelic(item) && ( {getRelic(item) && (
<button <button
type="button" type="button"
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation();
requestDeleteRelic(item) requestDeleteRelic(item);
}} }}
className="btn btn-xs btn-circle btn-error shadow-xs" className="w-6 h-6 rounded-lg bg-rose-500 text-white shadow-xs hover:scale-110 active:scale-95 transition-all flex items-center justify-center border border-white/20 cursor-pointer"
title={transI18n("deleteRelic")} title={transI18n("deleteRelic")}
> >
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <Trash2 className="w-3 h-3 stroke-[2.2]" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6M9 7V4h6v3m5 0H4" />
</svg>
</button> </button>
)} )}
</div> </div>
@@ -332,22 +337,25 @@ export default function RelicsInfo() {
type="button" type="button"
disabled={!selectedRelicSlot} disabled={!selectedRelicSlot}
onClick={() => handlerChangeRelic(selectedRelicSlot)} onClick={() => handlerChangeRelic(selectedRelicSlot)}
className="btn btn-primary btn-sm rounded-xl font-bold shadow-xs" className="btn btn-primary btn-sm rounded-xl font-bold gap-2 shadow-xs transition-all active:scale-[0.98] cursor-pointer"
> >
{transI18n("changeRelic")} <SlidersHorizontal className="w-4 h-4" />
<span>{transI18n("changeRelic")}</span>
</button> </button>
<button <button
type="button" type="button"
disabled={!selectedRelicSlot || !getRelic(selectedRelicSlot)} disabled={!selectedRelicSlot || !isSelectedRelicEquipped}
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation();
if (selectedRelicSlot) { if (selectedRelicSlot) {
requestDeleteRelic(selectedRelicSlot) requestDeleteRelic(selectedRelicSlot);
} }
}} }}
className="btn btn-ghost btn-sm text-error hover:bg-error/20 rounded-xl disabled:opacity-40 disabled:pointer-events-none" className="btn btn-outline btn-error hover:btn-error btn-sm rounded-xl font-bold gap-2 transition-all active:scale-[0.98] cursor-pointer disabled:opacity-40 disabled:pointer-events-none"
> >
{transI18n("deleteRelic")} <Trash2 className="w-4 h-4" />
<span>{transI18n("deleteRelic")}</span>
</button> </button>
</div> </div>
</div> </div>
@@ -513,7 +521,7 @@ export default function RelicsInfo() {
<button <button
type="button" type="button"
onClick={handleConfirmDelete} onClick={handleConfirmDelete}
className="flex-1 h-10 px-4 rounded-xl font-bold text-xs sm:text-sm bg-gradient-to-r from-rose-500 to-red-600 hover:from-rose-400 hover:to-red-500 text-white shadow-md shadow-rose-500/25 hover:shadow-rose-500/40 transition-all flex items-center justify-center gap-1.5 cursor-pointer" className="flex-1 h-10 px-4 rounded-xl font-bold text-xs sm:text-sm bg-linear-to-r from-rose-500 to-red-600 hover:from-rose-400 hover:to-red-500 text-white shadow-md shadow-rose-500/25 hover:shadow-rose-500/40 transition-all flex items-center justify-center gap-1.5 cursor-pointer"
> >
<Trash2 className="w-4 h-4" /> <Trash2 className="w-4 h-4" />
<span>{transI18n("confirmDelete")}</span> <span>{transI18n("confirmDelete")}</span>
+3 -3
View File
@@ -702,9 +702,9 @@ export default function ShowCaseInfo() {
<div className="bg-base-100 rounded-2xl p-4 sm:p-6 border border-base-300 shadow-sm space-y-6"> <div className="bg-base-100 rounded-2xl p-4 sm:p-6 border border-base-300 shadow-sm space-y-6">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between pb-3 border-b border-base-content/10 flex-wrap gap-3"> <div className="flex items-center justify-between pb-3 border-b border-base-content/10 flex-wrap gap-3">
<h2 className="text-xl sm:text-2xl font-extrabold flex items-center gap-2.5"> <h2 className="text-lg sm:text-xl font-bold flex items-center gap-2.5">
<div className="w-2 h-6 bg-linear-to-b from-primary to-accent rounded-full"></div> <div className="w-1.5 h-5 bg-linear-to-b from-primary to-accent rounded-full"></div>
<span className="bg-clip-text text-transparent bg-linear-to-r from-primary to-accent"> <span className="bg-clip-text text-transparent bg-linear-to-r from-primary to-accent font-bold tracking-tight">
{transI18n("showcaseCard")} {transI18n("showcaseCard")}
</span> </span>
</h2> </h2>
+9 -9
View File
@@ -152,7 +152,7 @@ export default function SkillsInfo() {
{/* Visual Skill Tree Container */} {/* Visual Skill Tree Container */}
<div className="flex justify-center items-center py-2"> <div className="flex justify-center items-center py-2">
{traceButtons && avatarSelected && ( {traceButtons && avatarSelected && (
<div className="relative w-full max-w-md aspect-square"> <div className="relative w-full max-w-155 aspect-square select-none">
<Image <Image
unoptimized unoptimized
crossOrigin="anonymous" crossOrigin="anonymous"
@@ -164,7 +164,7 @@ export default function SkillsInfo() {
style={{ style={{
filter: (theme === "winter" || theme === "cupcake") ? "invert(1)" : "none" filter: (theme === "winter" || theme === "cupcake") ? "invert(1)" : "none"
}} }}
className="w-full h-full object-cover" className="w-full h-full object-contain pointer-events-none"
/> />
{traceButtons.map((btn, index) => { {traceButtons.map((btn, index) => {
if (!avatarSelected?.SkillTrees?.[btn.id]) { if (!avatarSelected?.SkillTrees?.[btn.id]) {
@@ -181,12 +181,12 @@ export default function SkillsInfo() {
id={btn.id} id={btn.id}
className={` className={`
absolute rounded-full border border-black/70 cursor-pointer transition-all duration-150 ease-out flex justify-center items-center select-none overflow-visible absolute rounded-full border border-black/70 cursor-pointer transition-all duration-150 ease-out flex justify-center items-center select-none overflow-visible
${btn.size === "small" ? "w-[6.5vw] h-[6.5vw] md:w-[2.2vw] md:h-[2.2vw] bg-white" : ""} ${btn.size === "small" ? "w-[7%] h-[7%] bg-white" : ""}
${btn.size === "medium" ? "w-[8.5vw] h-[8.5vw] md:w-[3vw] md:h-[3vw] bg-white" : ""} ${btn.size === "medium" ? "w-[9.6%] h-[9.6%] bg-white" : ""}
${btn.size === "big" ? "w-[9.5vw] h-[9.5vw] md:w-[3.5vw] md:h-[3.5vw] bg-black" : ""} ${btn.size === "big" ? "w-[10%] h-[10%] bg-black" : ""}
${btn.size === "special" ? "w-[9.5vw] h-[9.5vw] md:w-[3.5vw] md:h-[3.5vw] bg-white" : ""} ${btn.size === "special" ? "w-[10%] h-[10%] bg-white" : ""}
${btn.size === "memory" ? "w-[9.5vw] h-[9.5vw] md:w-[3.5vw] md:h-[3.5vw] bg-black" : ""} ${btn.size === "memory" ? "w-[10%] h-[10%] bg-black" : ""}
${btn.size === "elation" ? "w-[9.5vw] h-[9.5vw] md:w-[3.5vw] md:h-[3.5vw] bg-black" : ""} ${btn.size === "elation" ? "w-[10%] h-[10%] bg-black" : ""}
${isSelected ? "ring-3 ring-cyan-400 ring-offset-2 ring-offset-base-100 shadow-[0_0_12px_rgba(34,211,238,0.8)] z-20" : "hover:ring-2 hover:ring-primary/40 z-10"} ${isSelected ? "ring-3 ring-cyan-400 ring-offset-2 ring-offset-base-100 shadow-[0_0_12px_rgba(34,211,238,0.8)] z-20" : "hover:ring-2 hover:ring-primary/40 z-10"}
${!isLearned ? "opacity-40 grayscale" : "shadow-[0_0_6px_rgba(255,255,255,0.4)]"} ${!isLearned ? "opacity-40 grayscale" : "shadow-[0_0_6px_rgba(255,255,255,0.4)]"}
`} `}
@@ -257,7 +257,7 @@ export default function SkillsInfo() {
)} )}
{isMajor && ( {isMajor && (
<p className="z-12 text-[10px] sm:text-xs font-mono font-bold text-center rounded-full absolute translate-y-full mt-0.5 bg-black/80 text-white px-1.5 py-0.2 border border-white/20 left-1/2 -translate-x-1/2 shadow-xs whitespace-nowrap"> <p className="z-12 text-[9px] sm:text-[10px] md:text-xs font-mono font-bold text-center rounded-full absolute -bottom-1.5 bg-black/85 text-white px-1.5 py-0.2 border border-white/20 left-1/2 -translate-x-1/2 shadow-xs whitespace-nowrap pointer-events-none">
{`${avatarData?.data.skills?.[avatarSkillTree?.[btn.id]?.["1"]?.PointID] || 0}/${avatarSkillTree?.[btn.id]?.["1"]?.MaxLevel}`} {`${avatarData?.data.skills?.[avatarSkillTree?.[btn.id]?.["1"]?.PointID] || 0}/${avatarSkillTree?.[btn.id]?.["1"]?.MaxLevel}`}
</p> </p>
)} )}