diff --git a/frontend/components/admin/table-type/ColumnDetailPanel.tsx b/frontend/components/admin/table-type/ColumnDetailPanel.tsx
index 5e4e2a07..c462d0ff 100644
--- a/frontend/components/admin/table-type/ColumnDetailPanel.tsx
+++ b/frontend/components/admin/table-type/ColumnDetailPanel.tsx
@@ -76,18 +76,34 @@ export function ColumnDetailPanel({
if (!column) return null;
- const refTableOpts = referenceTableOptions.length
- ? referenceTableOptions
- : [
- { value: "none", label: "선택 안함" },
- ...tables.map((t) => ({
- value: t.tableName,
- label:
- t.displayName && t.displayName !== t.tableName
- ? `${t.displayName} (${t.tableName})`
- : t.tableName,
- })),
- ];
+ const refTableOpts = useMemo(() => {
+ const hasKorean = (s: string) => /[가-힣]/.test(s);
+ const raw = referenceTableOptions.length
+ ? [...referenceTableOptions]
+ : [
+ { value: "none", label: "없음" },
+ ...tables.map((t) => ({
+ value: t.tableName,
+ label:
+ t.displayName && t.displayName !== t.tableName
+ ? `${t.displayName} (${t.tableName})`
+ : t.tableName,
+ })),
+ ];
+
+ const noneOpt = raw.find((o) => o.value === "none");
+ const rest = raw.filter((o) => o.value !== "none");
+
+ rest.sort((a, b) => {
+ const aK = hasKorean(a.label);
+ const bK = hasKorean(b.label);
+ if (aK && !bK) return -1;
+ if (!aK && bK) return 1;
+ return a.label.localeCompare(b.label, "ko");
+ });
+
+ return noneOpt ? [noneOpt, ...rest] : rest;
+ }, [referenceTableOptions, tables]);
return (
@@ -183,23 +199,33 @@ export function ColumnDetailPanel({
테이블을 찾을 수 없습니다.
- {refTableOpts.map((opt) => (
- {
- onColumnChange("referenceTable", opt.value === "none" ? undefined : opt.value);
- if (opt.value !== "none") onLoadReferenceColumns?.(opt.value);
- setEntityTableOpen(false);
- }}
- className="text-xs"
- >
-
- {opt.label}
-
- ))}
+ {refTableOpts.map((opt) => {
+ const hasKorean = opt.value !== "none" && opt.label !== opt.value && !opt.label.startsWith(opt.value);
+ return (
+ {
+ onColumnChange("referenceTable", opt.value === "none" ? undefined : opt.value);
+ if (opt.value !== "none") onLoadReferenceColumns?.(opt.value);
+ setEntityTableOpen(false);
+ }}
+ className="text-xs"
+ >
+
+ {hasKorean ? (
+
+ {opt.label.replace(` (${opt.value})`, "")}
+ {opt.value}
+
+ ) : (
+ opt.label
+ )}
+
+ );
+ })}
@@ -263,13 +289,14 @@ export function ColumnDetailPanel({
column.referenceColumn === refCol.columnName ? "opacity-100" : "opacity-0",
)}
/>
-
-
- {refCol.displayName && refCol.displayName !== refCol.columnName
- ? `${refCol.displayName} (${refCol.columnName})`
- : refCol.columnName}
-
-
+ {refCol.displayName && refCol.displayName !== refCol.columnName ? (
+
+ {refCol.displayName}
+ {refCol.columnName}
+
+ ) : (
+
{refCol.columnName}
+ )}
))}
diff --git a/frontend/components/layout/AppLayout.tsx b/frontend/components/layout/AppLayout.tsx
index d2f13c79..2014d535 100644
--- a/frontend/components/layout/AppLayout.tsx
+++ b/frontend/components/layout/AppLayout.tsx
@@ -568,18 +568,7 @@ function AppLayoutInner({ children }: AppLayoutProps) {
);
}
- if (!user) {
- return (
-
- );
- }
-
- const uiMenus = convertMenuToUI(currentMenus, user as ExtendedUserInfo);
+ const uiMenus = user ? convertMenuToUI(currentMenus, user as ExtendedUserInfo) : [];
// 활성 탭에 해당하는 메뉴가 속한 부모 메뉴 자동 확장
useEffect(() => {
@@ -603,6 +592,17 @@ function AppLayoutInner({ children }: AppLayoutProps) {
}
}, [activeTab, uiMenus, isMenuActive, expandedMenus]);
+ if (!user) {
+ return (
+
+ );
+ }
+
return (
{/* 모바일 헤더 */}
diff --git a/frontend/components/layout/TabBar.tsx b/frontend/components/layout/TabBar.tsx
index e86ada2e..1ac5144e 100644
--- a/frontend/components/layout/TabBar.tsx
+++ b/frontend/components/layout/TabBar.tsx
@@ -493,8 +493,8 @@ export function TabBar() {
className={cn(
"group relative flex h-7 shrink-0 cursor-pointer items-center gap-0.5 rounded-t-md border border-b-0 px-3 select-none",
isActive
- ? "text-foreground z-10 -mb-px h-[30px] bg-white"
- : "bg-muted/50 text-muted-foreground hover:bg-muted hover:text-foreground border-transparent",
+ ? "text-primary z-10 -mb-px h-[30px] bg-primary/15 dark:bg-primary/20 border-primary/40 border-t-[3px] border-t-primary font-semibold"
+ : "bg-transparent text-muted-foreground hover:bg-muted/50 hover:text-foreground border-transparent",
)}
style={{
width: TAB_WIDTH,
diff --git a/frontend/components/v2/config-panels/V2SplitPanelLayoutConfigPanel.tsx b/frontend/components/v2/config-panels/V2SplitPanelLayoutConfigPanel.tsx
index ae5679b6..97ff71a3 100644
--- a/frontend/components/v2/config-panels/V2SplitPanelLayoutConfigPanel.tsx
+++ b/frontend/components/v2/config-panels/V2SplitPanelLayoutConfigPanel.tsx
@@ -1552,16 +1552,22 @@ export const V2SplitPanelLayoutConfigPanel: React.FC<
/>
- updateRightPanel({ showEdit: checked })
+ updateRightPanel({
+ showEdit: checked,
+ editButton: { ...config.rightPanel?.editButton!, enabled: checked },
+ })
}
/>
- updateRightPanel({ showDelete: checked })
+ updateRightPanel({
+ showDelete: checked,
+ deleteButton: { ...config.rightPanel?.deleteButton!, enabled: checked },
+ })
}
/>
diff --git a/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutComponent.tsx b/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutComponent.tsx
index 28acdbe6..0c585587 100644
--- a/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutComponent.tsx
+++ b/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutComponent.tsx
@@ -21,7 +21,7 @@ import {
Move,
FileSpreadsheet,
List,
- LayoutPanelRight,
+ PanelRight,
} from "lucide-react";
import { dataApi } from "@/lib/api/data";
import { entityJoinApi } from "@/lib/api/entityJoin";
@@ -3524,7 +3524,7 @@ export const SplitPanelLayoutComponent: React.FC
{columnsToShow.map((col, idx) => (
))}
{hasGroupedLeftActions && (
-
+
)}
@@ -3621,7 +3621,7 @@ export const SplitPanelLayoutComponent: React.FC
{columnsToShow.map((col, idx) => (
))}
{hasLeftTableActions && (
-
+
)}
@@ -3972,17 +3972,17 @@ export const SplitPanelLayoutComponent: React.FC
>
-
+
{/* 탭이 없으면 제목만, 있으면 탭으로 전환 (2px primary 밑줄 인디케이터) */}
{(componentConfig.rightPanel?.additionalTabs?.length || 0) > 0 ? (
handleTabChange(0)}
className={cn(
- "px-3 py-1 text-sm font-medium transition-colors",
+ "px-3.5 py-2 text-[10px] font-semibold transition-all -mb-px",
activeTabIndex === 0
- ? "text-primary border-b-2 border-primary font-semibold bg-primary/5"
- : "text-foreground/70 hover:text-foreground hover:bg-muted/30"
+ ? "text-primary border-b-2 border-primary"
+ : "text-muted-foreground border-b-2 border-transparent hover:text-foreground"
)}
>
{componentConfig.rightPanel?.title || "기본"}
@@ -3992,10 +3992,10 @@ export const SplitPanelLayoutComponent: React.FC
key={tab.tabId || `tab-${index}`}
onClick={() => handleTabChange(index + 1)}
className={cn(
- "px-3 py-1 text-sm font-medium transition-colors",
+ "px-3.5 py-2 text-[10px] font-semibold transition-all -mb-px",
activeTabIndex === index + 1
- ? "text-primary border-b-2 border-primary font-semibold bg-primary/5"
- : "text-foreground/70 hover:text-foreground hover:bg-muted/30"
+ ? "text-primary border-b-2 border-primary"
+ : "text-muted-foreground border-b-2 border-transparent hover:text-foreground"
)}
>
{tab.label || `탭 ${index + 1}`}
@@ -4120,7 +4120,7 @@ export const SplitPanelLayoutComponent: React.FC
);
})}
{hasTabActions && (
- 작업
+ 작업
)}
@@ -4157,13 +4157,13 @@ export const SplitPanelLayoutComponent: React.FC
toggleRightItemExpansion(`tab_${activeTabIndex}_${tabItemId}`)}
>
{tabSummaryColumns.map((col: any) => (
-
+
{col.type === "progress"
? renderProgressCell(col, item, selectedLeftItem)
: formatCellValue(
@@ -4256,7 +4256,7 @@ export const SplitPanelLayoutComponent: React.FC
);
})}
{hasTabActions && (
- 작업
+ 작업
)}
@@ -4292,13 +4292,13 @@ export const SplitPanelLayoutComponent: React.FC
toggleRightItemExpansion(`tab_${activeTabIndex}_${tabItemId}`)}
>
{listSummaryColumns.map((col: any) => (
-
+
{col.type === "progress"
? renderProgressCell(col, item, selectedLeftItem)
: formatCellValue(
@@ -4670,7 +4670,7 @@ export const SplitPanelLayoutComponent: React.FC
);
})}
- {/* 수정 또는 삭제 버튼이 하나라도 활성화되어 있을 때만 작업 컬럼 표시 */}
- {!isDesignMode &&
- ((componentConfig.rightPanel?.editButton?.enabled ?? true) ||
- (componentConfig.rightPanel?.deleteButton?.enabled ?? true)) && (
-
+ {(() => {
+ const rightEditVisible = (componentConfig.rightPanel?.showEdit ?? componentConfig.rightPanel?.editButton?.enabled) !== false;
+ const rightDeleteVisible = (componentConfig.rightPanel?.showDelete ?? componentConfig.rightPanel?.deleteButton?.enabled) !== false;
+ return !isDesignMode && (rightEditVisible || rightDeleteVisible) ? (
+
작업
- )}
+ ) : null;
+ })()}
{filteredData.map((item, idx) => {
const itemId = item.id || item.ID || idx;
+ const rightEditVisible = (componentConfig.rightPanel?.showEdit ?? componentConfig.rightPanel?.editButton?.enabled) !== false;
+ const rightDeleteVisible = (componentConfig.rightPanel?.showDelete ?? componentConfig.rightPanel?.deleteButton?.enabled) !== false;
return (
-
+
{columnsToShow.map((col, colIdx) => (
{col.type === "progress"
@@ -4722,12 +4725,10 @@ export const SplitPanelLayoutComponent: React.FC
))}
{/* 수정 또는 삭제 버튼이 하나라도 활성화되어 있을 때만 작업 셀 표시 */}
- {!isDesignMode &&
- ((componentConfig.rightPanel?.editButton?.enabled ?? true) ||
- (componentConfig.rightPanel?.deleteButton?.enabled ?? true)) && (
-
+ {!isDesignMode && (rightEditVisible || rightDeleteVisible) && (
+
- {(componentConfig.rightPanel?.editButton?.enabled ?? true) && (
+ {rightEditVisible && (
{componentConfig.rightPanel?.editButton?.buttonLabel || "수정"}
)}
- {(componentConfig.rightPanel?.deleteButton?.enabled ?? true) && (
+ {rightDeleteVisible && (
{
e.stopPropagation();
@@ -4801,8 +4802,8 @@ export const SplitPanelLayoutComponent: React.FC
return sum + w;
}, 0);
- const hasEditButton = !isDesignMode && (componentConfig.rightPanel?.editButton?.enabled ?? true);
- const hasDeleteButton = !isDesignMode && (componentConfig.rightPanel?.deleteButton?.enabled ?? true);
+ const hasEditButton = !isDesignMode && (componentConfig.rightPanel?.showEdit ?? componentConfig.rightPanel?.editButton?.enabled) !== false;
+ const hasDeleteButton = !isDesignMode && (componentConfig.rightPanel?.showDelete ?? componentConfig.rightPanel?.deleteButton?.enabled) !== false;
const hasActions = hasEditButton || hasDeleteButton;
return filteredData.length > 0 ? (
@@ -4814,14 +4815,14 @@ export const SplitPanelLayoutComponent: React.FC
{columnsToDisplay.map((col) => (
{col.label}
))}
{hasActions && (
- 작업
+ 작업
)}
@@ -4849,13 +4850,13 @@ export const SplitPanelLayoutComponent: React.FC
toggleRightItemExpansion(itemId)}
>
{columnsToDisplay.map((col) => (
-
+
{formatCellValue(
col.name,
getEntityJoinValue(item, col.name),
@@ -4865,7 +4866,7 @@ export const SplitPanelLayoutComponent: React.FC
))}
{hasActions && (
-
+
{hasEditButton && (
= ({
}}
>
-
+
{actualColumns.map((column, colIndex) => {
// 왼쪽 고정 컬럼들의 누적 너비 계산
const leftFixedWidth = actualColumns
@@ -132,10 +133,10 @@ export const SingleTableWithSticky: React.FC = ({
key={column.columnName}
className={cn(
column.columnName === "__checkbox__"
- ? "bg-background h-9 border-0 px-3 py-1.5 text-center align-middle sm:px-4 sm:py-2"
- : "text-foreground hover:text-foreground bg-background h-9 cursor-pointer border-0 px-3 py-1.5 text-left align-middle text-xs font-semibold whitespace-nowrap transition-all duration-200 select-none sm:px-4 sm:py-2 sm:text-sm",
+ ? "h-9 border-0 px-3 py-1.5 text-center align-middle sm:px-4 sm:py-2"
+ : "text-muted-foreground hover:text-foreground h-9 cursor-pointer border-0 px-3 py-1.5 text-left align-middle text-[10px] font-bold uppercase tracking-[0.04em] whitespace-nowrap transition-all duration-200 select-none sm:px-4 sm:py-2 sm:text-xs",
`text-${column.align}`,
- column.sortable && "hover:bg-primary/10",
+ column.sortable && "hover:bg-muted/70",
// 고정 컬럼 스타일
column.fixed === "left" && "border-border bg-background sticky z-40 border-r shadow-sm",
column.fixed === "right" && "border-border bg-background sticky z-40 border-l shadow-sm",
@@ -150,7 +151,7 @@ export const SingleTableWithSticky: React.FC = ({
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap", // 텍스트 줄바꿈 방지
- backgroundColor: "hsl(var(--background))",
+ backgroundColor: "hsl(var(--muted) / 0.8)",
// sticky 위치 설정
...(column.fixed === "left" && { left: leftFixedWidth }),
...(column.fixed === "right" && { right: rightFixedWidth }),
@@ -228,8 +229,9 @@ export const SingleTableWithSticky: React.FC = ({
handleRowClick?.(row, index, e)}
>
@@ -273,9 +275,10 @@ export const SingleTableWithSticky: React.FC = ({
highlightArray[currentSearchIndex] === cellKey;
// formatCellValue 결과 (이미지 등 JSX 반환 가능)
- const rawCellValue =
- formatCellValue(row[column.columnName], column.format, column.columnName, row) || "\u00A0";
- // 이미지 등 JSX 반환 여부 확인
+ const formattedValue = formatCellValue(row[column.columnName], column.format, column.columnName, row);
+ const rawCellValue = (formattedValue === null || formattedValue === undefined || formattedValue === "")
+ ? -
+ : formattedValue;
const isReactElement = typeof rawCellValue === "object" && React.isValidElement(rawCellValue);
// 셀 값에서 검색어 하이라이트 렌더링
@@ -324,7 +327,7 @@ export const SingleTableWithSticky: React.FC = ({
key={`cell-${column.columnName}`}
id={isCurrentSearchResult ? "current-search-result" : undefined}
className={cn(
- "text-foreground h-10 px-3 py-1.5 align-middle text-xs transition-colors sm:px-4 sm:py-2 sm:text-sm",
+ "text-foreground h-10 px-3 py-[7px] align-middle text-[11px] transition-colors",
// 이미지 셀은 overflow/ellipsis 제외 (이미지 잘림 방지)
!isReactElement && "whitespace-nowrap",
`text-${column.align}`,
diff --git a/frontend/lib/registry/components/v2-table-list/TableListComponent.tsx b/frontend/lib/registry/components/v2-table-list/TableListComponent.tsx
index 7f4f57fe..f9e39810 100644
--- a/frontend/lib/registry/components/v2-table-list/TableListComponent.tsx
+++ b/frontend/lib/registry/components/v2-table-list/TableListComponent.tsx
@@ -178,6 +178,7 @@ import {
CheckSquare,
Trash2,
Lock,
+ GripVertical,
} from "lucide-react";
import * as XLSX from "xlsx";
import { FileText, ChevronRightIcon } from "lucide-react";
@@ -5676,7 +5677,41 @@ export const TableListComponent: React.FC = ({
)}
- {/* 🆕 배치 편집 툴바 */}
+ {/* 필터 칩 바 */}
+ {filterGroups.length > 0 && filterGroups.some(g => g.conditions.some(c => c.column && c.value)) && (
+
+ {filterGroups.flatMap(group =>
+ group.conditions
+ .filter(c => c.column && c.value)
+ .map(condition => {
+ const label = columnLabels[condition.column] || condition.column;
+ const opLabel = condition.operator === "equals" ? "=" : condition.operator === "contains" ? "⊃" : condition.operator === "notEquals" ? "≠" : condition.operator === "startsWith" ? "^" : condition.operator === "endsWith" ? "$" : condition.operator === "greaterThan" ? ">" : condition.operator === "lessThan" ? "<" : condition.operator;
+ return (
+
+ {label} {opLabel} {condition.value}
+ removeFilterCondition(group.id, condition.id)}
+ className="hover:text-destructive ml-0.5 leading-none transition-colors"
+ >
+
+
+
+ );
+ })
+ )}
+
+ 전체 초기화
+
+
+ )}
+
+ {/* 배치 편집 툴바 */}
{(editMode === "batch" || pendingChanges.size > 0) && (
@@ -5826,9 +5861,9 @@ export const TableListComponent: React.FC
= ({
)}
{visibleColumns.map((column, columnIndex) => {
@@ -5856,11 +5891,12 @@ export const TableListComponent: React.FC = ({
key={column.columnName}
ref={(el) => (columnRefs.current[column.columnName] = el)}
className={cn(
- "text-foreground/90 relative h-8 overflow-hidden text-xs font-bold text-ellipsis whitespace-nowrap select-none sm:h-10 sm:text-sm",
- column.columnName === "__checkbox__" ? "px-0 py-1" : "px-2 py-1 sm:px-4 sm:py-2",
+ "group text-muted-foreground relative h-8 overflow-hidden text-[10px] font-bold uppercase tracking-[0.04em] text-ellipsis whitespace-nowrap select-none sm:h-10 sm:text-xs",
+ column.columnName === "__checkbox__" ? "px-0 py-1" : "px-3 py-2",
column.sortable !== false &&
column.columnName !== "__checkbox__" &&
- "hover:bg-muted/70 cursor-pointer transition-colors",
+ "hover:text-foreground hover:bg-muted/70 cursor-pointer transition-colors",
+ sortColumn === column.columnName && "!text-primary",
isFrozen && "sticky z-40 shadow-[2px_0_4px_rgba(0,0,0,0.1)]",
// 🆕 Column Reordering 스타일
isColumnDragEnabled &&
@@ -5880,7 +5916,7 @@ export const TableListComponent: React.FC = ({
minWidth: column.columnName === "__checkbox__" ? "48px" : undefined,
maxWidth: column.columnName === "__checkbox__" ? "48px" : undefined,
userSelect: "none",
- backgroundColor: "hsl(var(--muted))",
+ backgroundColor: "hsl(var(--muted) / 0.8)",
...(isFrozen && { left: `${leftPosition}px` }),
}}
// 🆕 Column Reordering 이벤트
@@ -5900,9 +5936,12 @@ export const TableListComponent: React.FC = ({
renderCheckboxHeader()
) : (
+ {isColumnDragEnabled && (
+
+ )}
{columnLabels[column.columnName] || column.displayName}
{column.sortable !== false && sortColumn === column.columnName && (
-
{sortDirection === "asc" ? "↑" : "↓"}
+
{sortDirection === "asc" ? "↑" : "↓"}
)}
{/* 🆕 헤더 필터 버튼 */}
{tableConfig.headerFilter !== false &&
@@ -6127,7 +6166,8 @@ export const TableListComponent: React.FC
= ({
handleRowClick(row, index, e)}
>
@@ -6158,13 +6198,14 @@ export const TableListComponent: React.FC = ({
= ({
= ({
data-row={index}
data-col={colIndex}
className={cn(
- "text-foreground text-xs font-normal sm:text-sm",
- // 이미지 컬럼은 overflow/ellipsis 제외 (이미지 잘림 방지)
- inputType !== "image" && "overflow-hidden text-ellipsis whitespace-nowrap",
- column.columnName === "__checkbox__" ? "px-0 py-1" : "px-2 py-1 sm:px-4 sm:py-1.5",
+ "text-foreground text-[11px] font-normal",
+ inputType !== "image" && "overflow-hidden text-ellipsis whitespace-nowrap max-w-[170px]",
+ column.columnName === "__checkbox__" ? "px-0 py-[7px]" : "px-3 py-[7px]",
isFrozen && "sticky z-20 shadow-[2px_0_4px_rgba(0,0,0,0.08)]",
- // 🆕 포커스된 셀 스타일
isCellFocused && !editingCell && "ring-primary bg-primary/5 ring-2 ring-inset",
- // 🆕 편집 중인 셀 스타일
editingCell?.rowIndex === index && editingCell?.colIndex === colIndex && "p-0",
- // 🆕 배치 편집: 수정된 셀 스타일 (노란 배경)
isModified && !cellValidationError && "bg-amber-100 dark:bg-amber-900/40",
- // 🆕 유효성 에러: 빨간 테두리 및 배경
cellValidationError && "bg-red-50 ring-2 ring-red-500 ring-inset dark:bg-red-950/40",
- // 🆕 검색 하이라이트 스타일 (노란 배경)
isSearchHighlighted && !isCellFocused && "bg-yellow-200 dark:bg-yellow-700/50",
- // 🆕 편집 불가 컬럼 스타일 (연한 회색 배경)
column.editable === false && "bg-gray-50 dark:bg-gray-900/30",
+ // 코드 컬럼: mono 폰트 + primary 색상
+ (inputType === "code" || inputType === "category") && "font-mono text-[10px] text-primary font-medium",
+ // 숫자 컬럼: tabular-nums 오른쪽 정렬
+ isNumeric && "tabular-nums",
)}
// 🆕 유효성 에러 툴팁
title={cellValidationError || undefined}
@@ -6465,7 +6504,9 @@ export const TableListComponent: React.FC = ({
})()
: column.columnName === "__checkbox__"
? renderCheckboxCell(row, index)
- : formatCellValue(cellValue, column, row)}
+ : (cellValue === null || cellValue === undefined || cellValue === "")
+ ? -
+ : formatCellValue(cellValue, column, row)}
);
})}
diff --git a/frontend/lib/registry/components/v2-tabs-widget/tabs-component.tsx b/frontend/lib/registry/components/v2-tabs-widget/tabs-component.tsx
index 03de3cc1..039a591c 100644
--- a/frontend/lib/registry/components/v2-tabs-widget/tabs-component.tsx
+++ b/frontend/lib/registry/components/v2-tabs-widget/tabs-component.tsx
@@ -48,8 +48,8 @@ const TabsDesignEditor: React.FC<{
return cn(
"px-4 py-2 text-sm font-medium cursor-pointer transition-colors",
isActive
- ? "bg-primary/10 border-b-2 border-primary text-primary font-semibold"
- : "text-foreground/70 hover:text-foreground hover:bg-muted/50"
+ ? "bg-primary/20 dark:bg-primary/25 border-b-2 border-primary text-primary font-semibold"
+ : "text-muted-foreground hover:text-foreground hover:bg-muted/50"
);
};