Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,24 @@ on:
jobs:
ci:
runs-on: ubuntu-latest
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}

steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with: {version: 9}
with: { version: 9 }
- uses: actions/setup-node@v4
with:
with:
node-version: 20
cache: pnpm

- run: pnpm install --frozen-lockfile

- run: pnpm build:content

- run: pnpm typecheck
- run: pnpm lint

- run: pnpm build

- run: pnpm build
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface Props {
pageSize: number;
}

export default function SeriesPostList({
export default async function SeriesPostList({
category,
series,
sort,
Expand All @@ -19,7 +19,7 @@ export default function SeriesPostList({
}: Props) {
const appliedSort: PostSort = sort === "popular" ? "popular" : "latest";

const result = queryPosts({
const result = await queryPosts({
category,
series,
sort: appliedSort,
Expand All @@ -32,7 +32,7 @@ export default function SeriesPostList({
const seriesMeta = series ? getSeriesMeta(series) : null;

return (
<section id="series-post-section" className="mt-10 scroll-mt-24">
<section id="series-post-section" className="mt-20 scroll-mt-24">
<div>
<h2 className="text-3xl font-bold">{seriesMeta?.name ?? "모아보기"}</h2>

Expand Down
43 changes: 22 additions & 21 deletions src/app/(layout)/(shell)/_components/layout/SiteHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,28 +83,29 @@ export default function SiteHeader() {
</div>
</div>

<motion.button
type="button"
className="mr-2 md:hidden"
onClick={handleSearchClick}
aria-label="검색 열기"
whileTap={{ scale: 0.9, opacity: 0.8 }}
transition={{ duration: 0.08 }}
>
<Search size={22} />
</motion.button>

<motion.button
type="button"
className="md:hidden"
onClick={toggleMobileMenu}
aria-label="모바일 메뉴 열기"
whileTap={{ scale: 0.9, opacity: 0.8 }}
transition={{ duration: 0.08 }}
>
{isMobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
</motion.button>
</div>
<section className="flex grow justify-between items-center py-1 md:hidden">
<motion.button
type="button"
className="md:hidden"
onClick={toggleMobileMenu}
aria-label="모바일 메뉴 열기"
whileTap={{ scale: 0.9, opacity: 0.8 }}
transition={{ duration: 0.08 }}
>
{isMobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
</motion.button>
Comment on lines +88 to +97
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

접근성 개선: 메뉴 상태에 따라 aria-label 동적 변경 권장

현재 aria-label이 "모바일 메뉴 열기"로 고정되어 있습니다. 메뉴가 열린 상태에서는 "모바일 메뉴 닫기"로 변경되어야 스크린 리더 사용자에게 정확한 정보를 전달할 수 있습니다.

♿ 제안 수정
            <motion.button
              type="button"
-              className="md:hidden"
              onClick={toggleMobileMenu}
-              aria-label="모바일 메뉴 열기"
+              aria-label={isMobileMenuOpen ? "모바일 메뉴 닫기" : "모바일 메뉴 열기"}
+              aria-expanded={isMobileMenuOpen}
              whileTap={{ scale: 0.9, opacity: 0.8 }}
              transition={{ duration: 0.08 }}
            >
              {isMobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
            </motion.button>

aria-expanded 속성을 추가하면 메뉴의 열림/닫힘 상태를 보조 기술에 더 명확하게 전달할 수 있습니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<motion.button
type="button"
className="md:hidden"
onClick={toggleMobileMenu}
aria-label="모바일 메뉴 열기"
whileTap={{ scale: 0.9, opacity: 0.8 }}
transition={{ duration: 0.08 }}
>
{isMobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
</motion.button>
<motion.button
type="button"
className="md:hidden"
onClick={toggleMobileMenu}
aria-label={isMobileMenuOpen ? "모바일 메뉴 닫기" : "모바일 메뉴 열기"}
aria-expanded={isMobileMenuOpen}
whileTap={{ scale: 0.9, opacity: 0.8 }}
transition={{ duration: 0.08 }}
>
{isMobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
</motion.button>
🤖 Prompt for AI Agents
In `@src/app/`(layout)/(shell)/_components/layout/SiteHeader.tsx around lines 88 -
97, Update the mobile menu button in the SiteHeader component so its
accessibility state reflects whether the menu is open: make the aria-label
dynamic (use "모바일 메뉴 닫기" when isMobileMenuOpen is true, otherwise "모바일 메뉴 열기")
and add an aria-expanded attribute bound to isMobileMenuOpen; modify the
motion.button that calls toggleMobileMenu (and renders X/Menu based on
isMobileMenuOpen) to include these dynamic attributes so screen readers receive
correct state.

<motion.button
type="button"
className="md:hidden "
onClick={handleSearchClick}
aria-label="검색 열기"
whileTap={{ scale: 0.9, opacity: 0.8 }}
transition={{ duration: 0.08 }}
>
<Search size={22} />
</motion.button>
</section>
Comment on lines +87 to +108
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

중복된 md:hidden 클래스 제거 권장

부모 <section>에 이미 md:hidden이 적용되어 있으므로, 내부 버튼들(lines 90, 100)의 md:hidden은 불필요합니다. 제거해도 동작은 동일하며 코드가 더 간결해집니다.

♻️ 제안 수정
          <section className="flex grow justify-between items-center py-1 md:hidden">
            <motion.button
              type="button"
-              className="md:hidden"
              onClick={toggleMobileMenu}
              aria-label="모바일 메뉴 열기"
              whileTap={{ scale: 0.9, opacity: 0.8 }}
              transition={{ duration: 0.08 }}
            >
              {isMobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
            </motion.button>
            <motion.button
              type="button"
-              className="md:hidden "
              onClick={handleSearchClick}
              aria-label="검색 열기"
              whileTap={{ scale: 0.9, opacity: 0.8 }}
              transition={{ duration: 0.08 }}
            >
              <Search size={22} />
            </motion.button>
          </section>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<section className="flex grow justify-between items-center py-1 md:hidden">
<motion.button
type="button"
className="md:hidden"
onClick={toggleMobileMenu}
aria-label="모바일 메뉴 열기"
whileTap={{ scale: 0.9, opacity: 0.8 }}
transition={{ duration: 0.08 }}
>
{isMobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
</motion.button>
<motion.button
type="button"
className="md:hidden "
onClick={handleSearchClick}
aria-label="검색 열기"
whileTap={{ scale: 0.9, opacity: 0.8 }}
transition={{ duration: 0.08 }}
>
<Search size={22} />
</motion.button>
</section>
<section className="flex grow justify-between items-center py-1 md:hidden">
<motion.button
type="button"
onClick={toggleMobileMenu}
aria-label="모바일 메뉴 열기"
whileTap={{ scale: 0.9, opacity: 0.8 }}
transition={{ duration: 0.08 }}
>
{isMobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
</motion.button>
<motion.button
type="button"
onClick={handleSearchClick}
aria-label="검색 열기"
whileTap={{ scale: 0.9, opacity: 0.8 }}
transition={{ duration: 0.08 }}
>
<Search size={22} />
</motion.button>
</section>
🤖 Prompt for AI Agents
In `@src/app/`(layout)/(shell)/_components/layout/SiteHeader.tsx around lines 87 -
108, The two child motion.button elements inside the section already covered by
the parent section's md:hidden class have redundant className="md:hidden"
attributes; remove the md:hidden (and any trailing space) from the motion.button
elements that render the menu/search buttons (the buttons using
toggleMobileMenu, handleSearchClick, and rendering {isMobileMenuOpen ? <X /> :
<Menu />} and <Search />) so the visibility is controlled only by the parent and
the markup is cleaner.

</div>

<AnimatePresence initial={false}>
Expand Down
2 changes: 1 addition & 1 deletion src/app/(layout)/(shell)/_components/posts/PostCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface PostCardProps {
category: string;
date: string;
title: string;
excerpt: string;
excerpt?: string;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

excerpt가 optional로 변경되었지만 렌더링 시 처리가 없습니다.

excerptundefined인 경우에도 빈 <p> 태그가 렌더링됩니다. 의도된 동작이라면 괜찮지만, 빈 공간이 UI에 표시될 수 있습니다.

excerpt가 없을 때 해당 영역을 숨기거나 플레이스홀더를 표시하는 것이 UX상 더 나을 수 있습니다.

🔧 제안된 수정 (excerpt가 없을 때 숨기기)
-            <p
-              className={clsx(
-                "text-gray-800 dark:text-gray-200/80",
-                isSmall
-                  ? "mt-1.5 line-clamp-2 text-[10px] leading-tight"
-                  : "mt-2 line-clamp-2 text-xs"
-              )}
-            >
-              {excerpt}
-            </p>
+            {excerpt && (
+              <p
+                className={clsx(
+                  "text-gray-800 dark:text-gray-200/80",
+                  isSmall
+                    ? "mt-1.5 line-clamp-2 text-[10px] leading-tight"
+                    : "mt-2 line-clamp-2 text-xs"
+                )}
+              >
+                {excerpt}
+              </p>
+            )}

Also applies to: 119-128

🤖 Prompt for AI Agents
In `@src/app/`(layout)/(shell)/_components/posts/PostCard.tsx at line 12, The
PostCard component's excerpt prop is now optional but the JSX always renders an
empty paragraph when excerpt is undefined; update the PostCard render to
conditionally render the excerpt block (or a placeholder) only when
props.excerpt exists to avoid empty <p> elements — locate the PostCard
function/Component and the JSX that renders the <p> for excerpt (also the
similar rendering around lines 119-128) and wrap it with a conditional (e.g.,
render the paragraph only if excerpt is truthy, or render a small placeholder
string/UI when you want a visible fallback).

className?: string;
size?: "md" | "sm";
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/(layout)/(shell)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default async function HomePage({

const tags = getAllTags(false);

const { posts, pagination, pageRange, applied } = queryPosts(params);
const { posts, pagination, pageRange, applied } = await queryPosts(params);

return (
<main className="px-5 sm:px-12 lg:px-40 space-y-12 ">
Expand Down
2 changes: 1 addition & 1 deletion src/app/(layout)/posts/[slug]/_components/PostToc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function PostToc({ items }: { items: TocItem[] }) {
"group relative block rounded-md py-1.5 pr-2 text-sm transition-colors",
"pl-4",
isActive
? "text-gray-900 dark:text-blue-300"
? "text-gray-900 dark:text-blue-300 font-semibold"
: "text-neutral-400 hover:text-gray-800 dark:text-neutral-400 dark:hover:text-blue-300"
)}
>
Expand Down
32 changes: 11 additions & 21 deletions src/app/(layout)/posts/[slug]/_components/RecommendedPosts.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
import RecommendedPostCard, {
RecommendedPost,
} from "@/app/(layout)/posts/[slug]/_components/post-recommended/RecommendedPostCard";
import { getRecommendedPostsForPost, VelitePost } from "@/lib/posts";

export default function RecommendedPosts() {
const items: RecommendedPost[] = [
{
title: "React 상태 관리, 왜 어려울까?",
overview:
"state, props, context가 섞일 때 복잡도가 급증하는 이유와 단순화 전략을 정리합니다.",
href: "#",
},
{
title: "useEffect를 덜 쓰는 패턴",
overview:
"불필요한 effect를 줄이고 서버/쿼리/파생 상태로 대체하는 실전 패턴을 소개합니다.",
href: "#",
},
{
title: "컴포넌트 분해 기준 5가지",
overview:
"재사용성과 응집도를 동시에 챙기는 컴포넌트 분해 체크리스트를 제공합니다.",
href: "#",
},
];
export default async function RecommendedPosts({ post }: { post: VelitePost }) {
const recommended = await getRecommendedPostsForPost(post, 3);
if (!recommended.length) return null;

const items: RecommendedPost[] = recommended.map((p) => ({
title: p.title,
overview: p.summary ?? "",
href: `/posts/${p.slug}`,
thumbnail: p.thumbnail,
}));

return (
<section className="space-y-3">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,30 @@ export default function RecommendedPostCard({
<a
href={post.href}
Comment on lines 16 to 17
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Next.js <Link> 컴포넌트 사용 권장

현재 <a> 태그를 직접 사용하고 있어 클릭 시 전체 페이지 새로고침이 발생합니다. Next.js의 <Link> 컴포넌트를 사용하면 클라이언트 사이드 네비게이션으로 더 빠른 페이지 전환이 가능합니다.

♻️ 제안된 수정
 import clsx from "clsx";
 import Image from "next/image";
+import Link from "next/link";

 // ...

-    <a
-      href={post.href}
+    <Link
+      href={post.href}
       className={clsx(
         // ...
       )}
     >
       {/* content */}
-    </a>
+    </Link>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<a
href={post.href}
import clsx from "clsx";
import Image from "next/image";
import Link from "next/link";
// ... other code ...
<Link
href={post.href}
className={clsx(
// className values
)}
>
{/* content */}
</Link>
🤖 Prompt for AI Agents
In
`@src/app/`(layout)/posts/[slug]/_components/post-recommended/RecommendedPostCard.tsx
around lines 16 - 17, The anchor tag using post.href in the RecommendedPostCard
component is causing full page reloads; replace the raw <a href={post.href}>
with Next.js's Link component: import Link from 'next/link', wrap the card
content with <Link href={post.href}> (move any className/children into the Link
or an inner <a> as appropriate), and remove the direct plain <a> usage so
navigation uses client-side routing. Ensure the change is made inside the
RecommendedPostCard component and preserves existing attributes/styling.

className={clsx(
"group relative block overflow-hidden rounded-xl bg-[#f2f3f6] transition-transform duration-200",
"group relative block overflow-hidden rounded-xl bg-[#f2f3f6] transition-transform duration-200",
"min-w-55",
"border border-gray-300",
"hover:scale-[1.02]",
"dark:bg-[#050a2a] dark:border-white/20"
)}
>
<div className="flex gap-3 py-4 px-3.5">
<div className="h-16 w-16 shrink-0 overflow-hidden rounded-lg bg-muted/20">
{post.thumbnail ? (
<Image
src={post.thumbnail}
alt=""
className="h-full w-full object-cover"
/>
) : (
<div className="h-full w-full bg-gray-300 dark:bg-background/50" />
)}
<div className="flex gap-2.5 p-3">
<div className="shrink-0 overflow-hidden rounded-lg bg-muted/20">
<Image
src={post.thumbnail ?? "/post-fallback.png"}
alt={post.title}
width={64}
height={64}
className="h-16 w-16 object-cover object-center"
/>
</div>

<div className="min-w-0 flex-1">
<div
className={clsx(
"text-sm font-semibold text-neutral-900 transition-colors",
"group-hover:text-neutral-950",
"dark:text-foreground/70",
"dark:text-foreground/90",
"line-clamp-1"
)}
>
Expand All @@ -52,9 +51,6 @@ export default function RecommendedPostCard({
</p>
</div>
</div>

<div className="pointer-events-none absolute -top-24 -right-24 hidden h-48 w-48 rounded-full bg-cyan-500/15 blur-3xl dark:block" />
<div className="pointer-events-none absolute -bottom-24 -left-24 hidden h-48 w-48 rounded-full bg-emerald-500/15 blur-3xl dark:block" />
</a>
);
}
10 changes: 5 additions & 5 deletions src/app/(layout)/posts/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import RecommendedPosts from "@/app/(layout)/posts/[slug]/_components/Recommende
import { adaptVeliteToc } from "@/lib/mdx/toc";
import { Metadata } from "next";
import { notFound } from "next/navigation";
import { posts } from "../../../../../.velite";
import { velitePosts } from "@/lib/posts";

type PageProps = {
params: Promise<{ slug: string }>;
Expand All @@ -18,7 +18,7 @@ export async function generateMetadata({
params,
}: PageProps): Promise<Metadata> {
const { slug } = await params;
const post = posts.find((p) => p.slug === slug);
const post = velitePosts.find((p) => p.slug === slug);
if (!post) return {};

const baseUrl = process.env.NEXT_PUBLIC_SITE_URL ?? "https://b0o0a.com";
Expand Down Expand Up @@ -56,7 +56,7 @@ export async function generateMetadata({
export default async function PostPage({ params }: PageProps) {
const { slug } = await params;

const post = posts.find((p) => p.slug === slug);
const post = velitePosts.find((p) => p.slug === slug);
if (!post) return notFound();

return (
Expand Down Expand Up @@ -90,13 +90,13 @@ export default async function PostPage({ params }: PageProps) {
</div>

<div className="pt-10 max-w-55 ml-auto">
<RecommendedPosts />
<RecommendedPosts post={post} />
</div>
</aside>
</div>

<div className="mt-10 xl:hidden">
<RecommendedPosts />
<RecommendedPosts post={post}/>
Comment on lines +93 to +99
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

코드 포맷팅 일관성 확인 필요

Line 93과 Line 99에서 RecommendedPosts 컴포넌트 사용 시 닫는 태그 앞 공백이 일관되지 않습니다:

  • Line 93: post={post} /> (공백 있음)
  • Line 99: post={post}/> (공백 없음)

사소한 부분이지만, 코드 일관성을 위해 통일하면 좋겠습니다.

🔧 제안된 수정
       <div className="mt-10 xl:hidden">
-        <RecommendedPosts post={post}/>
+        <RecommendedPosts post={post} />
       </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<RecommendedPosts post={post} />
</div>
</aside>
</div>
<div className="mt-10 xl:hidden">
<RecommendedPosts />
<RecommendedPosts post={post}/>
<RecommendedPosts post={post} />
</div>
</aside>
</div>
<div className="mt-10 xl:hidden">
<RecommendedPosts post={post} />
🤖 Prompt for AI Agents
In `@src/app/`(layout)/posts/[slug]/page.tsx around lines 93 - 99, The
RecommendedPosts component is self-closed inconsistently; standardize the JSX
self-closing tag spacing for the prop post by making both usages of
<RecommendedPosts post={post} .../> follow the same style (either "post={post}
/>" or "post={post}/>" )—update the instance inside the mt-10 xl:hidden div to
match the other occurrence so both <RecommendedPosts post={post} /> forms are
consistent.

</div>
</main>
);
Expand Down
18 changes: 13 additions & 5 deletions src/components/common/CommandPalette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,25 +60,33 @@ export function CommandPaletteProvider({
<Dialog.Root open={open} onOpenChange={handleOpenChange}>
<Dialog.Portal>
<Dialog.Overlay className="fixed inset-0 z-60 bg-black/40 backdrop-blur-sm" />
<Dialog.Content className="fixed left-1/2 top-50 z-70 w-full max-w-xl -translate-x-1/2 rounded-2xl border border-white/10 bg-foreground/70 dark:bg-foreground shadow-2xl">

<Dialog.Content
className={[
"fixed inset-x-3 top-[18%] z-70 w-auto rounded-2xl border border-white/10",
"bg-foreground/80 text-background shadow-2xl dark:bg-foreground",
"max-h-[70vh]",
"sm:left-1/2 sm:top-50 sm:w-full sm:max-w-xl sm:-translate-x-1/2 sm:inset-x-auto",
].join(" ")}
>
Comment on lines +64 to +71
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

반응형 레이아웃 개선이 잘 되었습니다.

모바일에서는 inset-x-3으로 좌우 여백을 주고, sm 이상에서는 sm:inset-x-autosm:left-1/2 sm:-translate-x-1/2로 중앙 정렬하는 패턴이 적절합니다.

다만 한 가지 확인 사항: Line 68의 max-h-[70vh]가 Line 74의 Command 컴포넌트에서도 동일하게 적용되어 있어 중복됩니다. 의도적인 방어 코드라면 괜찮지만, 불필요하다면 한 곳에서만 관리하는 것이 유지보수에 유리할 수 있습니다.

🤖 Prompt for AI Agents
In `@src/components/common/CommandPalette.tsx` around lines 64 - 71,
Dialog.Content and the nested Command component both apply the same
max-h-[70vh], causing duplicated styling; remove the redundant max-h-[70vh] from
one place (preferably the inner Command component) so the max height is
controlled in a single location, locate the class array on Dialog.Content and
the Command component that also sets max-h-[70vh], keep the max-h on the
higher-level Dialog.Content (or document the intentional duplication if
required) and update any tests/styles referencing the removed class.

<Dialog.Title className="sr-only">사이트 검색</Dialog.Title>

<Command className="overflow-hidden rounded-2xl bg-transparent text-sm text-background">
<Command className="flex max-h-[70vh] flex-col overflow-hidden rounded-2xl bg-transparent text-sm text-background">
<div className="flex items-center gap-2 border-b border-white/10 px-3">
<Search className="h-4 w-4 text-background " />
<Search className="h-4 w-4 text-background" />
<Command.Input
autoFocus
value={query}
onValueChange={setQuery}
placeholder="무엇을 찾고 계신가요?"
className="flex-1 bg-transparent py-3 text-sm outline-none placeholder:text-background/70"
/>
<span className="rounded bg-foreground/70 dark:bg-background/30 px-1.5 py-0.5 text-[10px] text-white ">
<span className="hidden rounded bg-foreground/70 px-1.5 py-0.5 text-[10px] text-white sm:inline-block dark:bg-background/30">
ESC
</span>
</div>

<Command.List className="max-h-80 overflow-y-auto py-2">
<Command.List className="max-h-[60vh] overflow-y-auto py-2">
<Command.Empty className="px-4 py-3 text-xs text-background/70">
검색 결과가 없습니다.
</Command.Empty>
Expand Down
2 changes: 1 addition & 1 deletion src/components/common/fallback/BrowseFallback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default function BrowseFallback({
description = "조금만 기다리면 더 맛있게 정리될 거예요.",
}: BrowseFallbackProps) {
return (
<section className="flex flex-col items-center justify-center gap-4 mt-10 py-14 text-center">
<section className="flex flex-col items-center justify-center gap-4 mt-30 py-14 text-center">
<BoabamIcon className="w-50 text-foreground/25 dark:text-white/70" />

{/* 텍스트 */}
Expand Down
2 changes: 1 addition & 1 deletion src/components/mdx/Quote.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default function Quote({
)}
/>

<div className="pl-6 pr-5 py-1 leading-0">
<div className="pl-6 pr-5 leading-snug wrap-break-word">
{children}
</div>
</div>
Expand Down
Loading
Loading