'use client';
import { useDarkMode } from '@/state/darkModeStore';
import { themeTokens, getResponsiveFz } from '@/utils/themeTokens';
import { Text, Title, Box, BoxProps } from '@mantine/core';
import React from 'react';
type TextTruncate = 'end' | 'start' | boolean;
/**
* Unified Typography Components
*
* Komponen text dengan styling konsisten di seluruh aplikasi
* Mendukung dark mode sesuai spesifikasi darkMode.md
*
* Usage:
* import { UnifiedText, UnifiedTitle } from '@/components/admin/UnifiedTypography';
*
* Judul Halaman
* Konten teks
*/
// ============================================================================
// Unified Title Component
// ============================================================================
interface UnifiedTitleProps {
order?: 1 | 2 | 3 | 4 | 5 | 6;
children: React.ReactNode;
align?: 'left' | 'center' | 'right';
color?: 'primary' | 'secondary' | 'brand' | string;
mb?: string;
mt?: string;
ml?: string;
mr?: string;
mx?: string;
my?: string;
style?: React.CSSProperties;
}
export function UnifiedTitle({
order = 1,
children,
align = 'left',
color = 'primary',
mb,
mt,
ml,
mr,
mx,
my,
style,
}: UnifiedTitleProps) {
const { isDark } = useDarkMode();
const tokens = themeTokens(isDark);
const responsiveFz = getResponsiveFz(isDark);
const getTypography = () => {
switch (order) {
case 1:
return tokens.typography.h1;
case 2:
return tokens.typography.h2;
case 3:
return tokens.typography.h3;
case 4:
return tokens.typography.h4;
default:
return tokens.typography.body;
}
};
const typo = getTypography();
const getColor = () => {
if (color === 'primary') return tokens.colors.text.primary;
if (color === 'secondary') return tokens.colors.text.secondary;
if (color === 'brand') return tokens.colors.text.brand;
return color;
};
return (
{children}
);
}
// ============================================================================
// Unified Text Component
// ============================================================================
interface UnifiedTextProps {
size?: 'small' | 'body' | 'label';
weight?: 'normal' | 'medium' | 'bold';
children: React.ReactNode;
align?: 'left' | 'center' | 'right';
color?: 'primary' | 'secondary' | 'tertiary' | 'muted' | 'brand' | 'link' | string;
lineClamp?: number;
truncate?: TextTruncate;
span?: boolean;
mt?: string;
mb?: string;
ml?: string;
mr?: string;
mx?: string;
my?: string;
style?: React.CSSProperties;
}
export function UnifiedText({
size = 'body',
weight = 'normal',
children,
align = 'left',
color = 'primary',
lineClamp,
truncate,
span = false,
mt,
mb,
ml,
mr,
mx,
my,
style,
}: UnifiedTextProps) {
const { isDark } = useDarkMode();
const tokens = themeTokens(isDark);
const getTypography = () => {
switch (size) {
case 'small':
return tokens.typography.small;
case 'label':
return tokens.typography.label;
default:
return tokens.typography.body;
}
};
const getWeight = () => {
switch (weight) {
case 'normal':
return 400;
case 'medium':
return 500;
case 'bold':
return 700;
default:
return 400;
}
};
const getColor = () => {
switch (color) {
case 'primary':
return tokens.colors.text.primary;
case 'secondary':
return tokens.colors.text.secondary;
case 'tertiary':
return tokens.colors.text.tertiary;
case 'muted':
return tokens.colors.text.muted;
case 'brand':
return tokens.colors.text.brand;
case 'link':
return tokens.colors.text.link;
default:
return color;
}
};
const typo = getTypography();
const fw = getWeight();
const textColor = getColor();
if (span) {
return (
{children}
);
}
return (
{children}
);
}
// ============================================================================
// Unified Page Header Component
//
// Header standar untuk setiap halaman admin
// Sesuai spesifikasi: Section Header dengan font weight lebih besar
// ============================================================================
interface UnifiedPageHeaderProps extends BoxProps {
title: string;
subtitle?: string;
action?: React.ReactNode;
showBorder?: boolean;
}
export function UnifiedPageHeader({
title,
subtitle,
action,
showBorder = true,
style,
...props
}: UnifiedPageHeaderProps) {
const { isDark } = useDarkMode();
const tokens = themeTokens(isDark);
return (
{title}
{subtitle && (
{subtitle}
)}
{action &&
{action}
}
);
}
export default UnifiedText;