feat(dimentorin): audit FE samakan dgn Figma design system
- FIX KRITIS: apps/dimentorin/src/index.css @theme nyimpang dari Figma (67 token beda: primary-500 #1a8ce6 vs #23a1eb, semua warna success/info/warning/danger + skala typography). Disamakan dgn libs/ui (source of truth Figma). - Hapus hardcoded warna non-token di apps: blue-400, gray-5/6/700, amber/emerald/red-100, green-200/500 -> token primary/neutral/warning/success/danger - libs/ui: gray-* -> neutral-*, blue-* -> primary-*, #1a8ce6 -> #23a1eb, bg-[#F0F8FF] -> primary-50, SVG fill hex -> fill-* token classes - Typography: text-[27/26/22/11px] menyimpang dari skala Figma -> text-[29/23/19/12px] - Radius: rounded-4xl (32px, tidak ada di Figma) -> rounded-3xl (24px)
This commit is contained in:
@@ -26,10 +26,10 @@ type TButtonProps = DetailedHTMLProps<
|
||||
const variantClasses: Record<TButtonVariant, string> = {
|
||||
primary: 'bg-primary-500 hover:bg-primary-600 text-white shadow-md',
|
||||
secondary:
|
||||
'bg-white hover:text-primary-600 hover:bg-gray-50 text-primary-500 shadow-md',
|
||||
text: 'bg-transparent hover:text-primary-600 hover:bg-gray-50 text-primary-500',
|
||||
'bg-white hover:text-primary-600 hover:bg-neutral-50 text-primary-500 shadow-md',
|
||||
text: 'bg-transparent hover:text-primary-600 hover:bg-neutral-50 text-primary-500',
|
||||
bordered:
|
||||
'border border-primary-500 hover:border-primary-600 bg-transparent hover:text-primary-600 hover:bg-gray-50 text-primary-500',
|
||||
'border border-primary-500 hover:border-primary-600 bg-transparent hover:text-primary-600 hover:bg-neutral-50 text-primary-500',
|
||||
success: 'bg-success-500 hover:bg-success-600 text-white shadow-md',
|
||||
danger: 'bg-danger-100 hover:bg-danger-200 text-danger-500 shadow-md',
|
||||
};
|
||||
|
||||
@@ -49,7 +49,7 @@ export const Input: FC<TInputProps> = ({
|
||||
};
|
||||
|
||||
const mergedClassName = cn(
|
||||
`px-[12px] py-[8px] text-neutral-800 bg-white placeholder:text-neutral-300 border border-neutral-200 hover:border-blue-300 focus:outline-1 focus:outline-blue-500 rounded-md font-bai-jamjuree ${widthform === "standard" ? "min-w-70" : ""}`,
|
||||
`px-[12px] py-[8px] text-neutral-800 bg-white placeholder:text-neutral-300 border border-neutral-200 hover:border-primary-300 focus:outline-1 focus:outline-primary-500 rounded-md font-bai-jamjuree ${widthform === "standard" ? "min-w-70" : ""}`,
|
||||
sizeClasses[size].textSize,
|
||||
disabled && disabledClass,
|
||||
className
|
||||
|
||||
@@ -35,7 +35,7 @@ export const Select: FC<TSelectProps> = ({
|
||||
...rest
|
||||
}): ReactElement => {
|
||||
const mergedClassName = cn(
|
||||
`appearance-none px-[12px] py-[8px] text-neutral-800 bg-white placeholder:text-neutral-300 border border-neutral-200 hover:border-blue-300 focus:outline-1 focus:outline-blue-500 rounded-md`,
|
||||
`appearance-none px-[12px] py-[8px] text-neutral-800 bg-white placeholder:text-neutral-300 border border-neutral-200 hover:border-primary-300 focus:outline-1 focus:outline-primary-500 rounded-md`,
|
||||
sizeClasses[size],
|
||||
widthform === 'standard' && 'min-w-70',
|
||||
disabled && disabledClass,
|
||||
|
||||
@@ -38,7 +38,7 @@ export const Textarea: FC<TTextareaProps> = ({
|
||||
...rest
|
||||
}): ReactElement => {
|
||||
const mergedClassName = cn(
|
||||
'rounded-md border border-neutral-200 hover:border-blue-300 focus:outline-1 focus:outline-blue-500 px-[12px] py-[8px] invalid:border-danger-500 invalid:text-danger-500',
|
||||
'rounded-md border border-neutral-200 hover:border-primary-300 focus:outline-1 focus:outline-primary-500 px-[12px] py-[8px] invalid:border-danger-500 invalid:text-danger-500',
|
||||
sizeClasses[size],
|
||||
disabled && disabledClass,
|
||||
error && errorClass,
|
||||
|
||||
@@ -15,15 +15,15 @@ export const ForgotStep: FC<TForgotStepProps> = ({
|
||||
<div className="w-full grid grid-cols-3 gap-3">
|
||||
<div className="flex flex-col items-center justify-center gap-2">
|
||||
<div className={`${step === 1 ? "bg-primary-500" : "bg-primary-200"} px-5 py-2 rounded-md w-full`}></div>
|
||||
<h4 className={`${step === 1 ? "text-primary-500" : "text-gray-500"} text-xs`}>Masukkan Email</h4>
|
||||
<h4 className={`${step === 1 ? "text-primary-500" : "text-neutral-500"} text-xs`}>Masukkan Email</h4>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center gap-2">
|
||||
<div className={`${step === 2 ? "bg-primary-500" : "bg-primary-200"} px-5 py-2 rounded-md w-full`}></div>
|
||||
<h4 className={`${step === 2 ? "text-primary-500" : "text-gray-500"} text-xs`}>Verifikasi OTP</h4>
|
||||
<h4 className={`${step === 2 ? "text-primary-500" : "text-neutral-500"} text-xs`}>Verifikasi OTP</h4>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center gap-2">
|
||||
<div className={`${step === 3 ? "bg-primary-500" : "bg-primary-200"} px-5 py-2 rounded-md w-full`}></div>
|
||||
<h4 className={`${step === 3 ? "text-primary-500" : "text-gray-500"} text-xs`}>Summon Password ^^</h4>
|
||||
<h4 className={`${step === 3 ? "text-primary-500" : "text-neutral-500"} text-xs`}>Summon Password ^^</h4>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -66,7 +66,7 @@ const Modal = ({
|
||||
<div className="fixed inset-0 z-50">
|
||||
<div
|
||||
className={cn(
|
||||
'fixed inset-0 bg-gray-900/80 transition-opacity duration-200',
|
||||
'fixed inset-0 bg-neutral-900/80 transition-opacity duration-200',
|
||||
isOpen ? 'opacity-100' : 'opacity-0',
|
||||
overlayClassName
|
||||
)}
|
||||
@@ -90,7 +90,7 @@ const Modal = ({
|
||||
<button
|
||||
onClick={onClose}
|
||||
className={cn(
|
||||
'absolute right-4 top-4 rounded-sm p-1 text-gray-500 transition-colors hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-gray-950 focus:ring-offset-2',
|
||||
'absolute right-4 top-4 rounded-sm p-1 text-neutral-500 transition-colors hover:text-neutral-900 focus:outline-none focus:ring-2 focus:ring-neutral-950 focus:ring-offset-2',
|
||||
closeButtonClassName
|
||||
)}
|
||||
aria-label="Close modal"
|
||||
@@ -168,7 +168,7 @@ const ModalDescription = ({
|
||||
children,
|
||||
id,
|
||||
}: ModalDescriptionProps) => (
|
||||
<p id={id} className={cn('text-sm text-gray-500', className)}>
|
||||
<p id={id} className={cn('text-sm text-neutral-500', className)}>
|
||||
{children}
|
||||
</p>
|
||||
);
|
||||
|
||||
@@ -40,7 +40,7 @@ export const Default: Story = {
|
||||
<button className="px-4 py-2 bg-blue-500 text-white rounded">
|
||||
Confirm
|
||||
</button>
|
||||
<button className="px-4 py-2 bg-gray-300 rounded">Cancel</button>
|
||||
<button className="px-4 py-2 bg-neutral-300 rounded">Cancel</button>
|
||||
</Modal.Footer>
|
||||
</>
|
||||
),
|
||||
|
||||
@@ -66,7 +66,7 @@ const Modal = ({
|
||||
<div className="fixed inset-0 z-50">
|
||||
<div
|
||||
className={cn(
|
||||
'fixed inset-0 bg-gray-900/80 transition-opacity duration-200',
|
||||
'fixed inset-0 bg-neutral-900/80 transition-opacity duration-200',
|
||||
isOpen ? 'opacity-100' : 'opacity-0',
|
||||
overlayClassName
|
||||
)}
|
||||
@@ -75,7 +75,7 @@ const Modal = ({
|
||||
/>
|
||||
<div
|
||||
className={cn(
|
||||
'fixed left-[50%] top-[50%] z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 bg-[#F0F8FF] rounded-lg p-6 shadow-xl transition-all duration-200',
|
||||
'fixed left-[50%] top-[50%] z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 bg-primary-50 rounded-lg p-6 shadow-xl transition-all duration-200',
|
||||
'sm:rounded-lg sm:max-w-md',
|
||||
isOpen ? 'opacity-100 scale-100' : 'opacity-0 scale-95',
|
||||
className
|
||||
@@ -90,7 +90,7 @@ const Modal = ({
|
||||
<button
|
||||
onClick={onClose}
|
||||
className={cn(
|
||||
'absolute right-4 top-4 rounded-sm p-1 text-gray-500 transition-colors hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-gray-950 focus:ring-offset-2',
|
||||
'absolute right-4 top-4 rounded-sm p-1 text-neutral-500 transition-colors hover:text-neutral-900 focus:outline-none focus:ring-2 focus:ring-neutral-950 focus:ring-offset-2',
|
||||
closeButtonClassName
|
||||
)}
|
||||
aria-label="Close modal"
|
||||
@@ -168,7 +168,7 @@ const ModalDescription = ({
|
||||
children,
|
||||
id,
|
||||
}: ModalDescriptionProps) => (
|
||||
<p id={id} className={cn('text-sm text-gray-500', className)}>
|
||||
<p id={id} className={cn('text-sm text-neutral-500', className)}>
|
||||
{children}
|
||||
</p>
|
||||
);
|
||||
|
||||
@@ -17,7 +17,7 @@ export const RegisterMentorStep: FC<TRegisterMentorStep> = ({ step }): ReactElem
|
||||
return (
|
||||
<div className="relative w-full px-8">
|
||||
{/* Garis dasar (abu/biru muda) */}
|
||||
<div className="absolute top-5 left-8 right-8 h-0.5 bg-blue-100 z-0" />
|
||||
<div className="absolute top-5 left-8 right-8 h-0.5 bg-primary-100 z-0" />
|
||||
|
||||
{/* Garis progress biru (dinamis) */}
|
||||
<div
|
||||
@@ -37,7 +37,7 @@ export const RegisterMentorStep: FC<TRegisterMentorStep> = ({ step }): ReactElem
|
||||
className={`w-10 h-10 rounded-full flex items-center justify-center border-2 ${
|
||||
isActive
|
||||
? "bg-gradient-to-b from-purple-600 to-blue-500 text-white border-transparent"
|
||||
: "bg-white text-gray-700 border-blue-400"
|
||||
: "bg-white text-neutral-700 border-blue-400"
|
||||
}`}
|
||||
>
|
||||
<span className="font-bold">{currentStep}</span>
|
||||
|
||||
@@ -29,7 +29,7 @@ export const BackofficeSidebar: FC = (): ReactElement => {
|
||||
className={`flex items-center justify-items-start gap-3 px-[8px] py-[10px] ${
|
||||
isActive('/dashboard')
|
||||
? 'bg-primary-500 text-white rounded-md'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
: 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<AppstoreOutlined className="text-[20px]" />
|
||||
@@ -41,7 +41,7 @@ export const BackofficeSidebar: FC = (): ReactElement => {
|
||||
className={`flex items-center justify-items-start gap-3 px-[8px] py-[10px] ${
|
||||
isActive('/gacha-roll')
|
||||
? 'bg-primary-500 text-white rounded-md'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
: 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<ReloadOutlined className="text-[20px]" />
|
||||
@@ -53,7 +53,7 @@ export const BackofficeSidebar: FC = (): ReactElement => {
|
||||
className={`flex items-center justify-items-start gap-3 px-[8px] py-[10px] ${
|
||||
isActive('/permissions')
|
||||
? 'bg-primary-500 text-white rounded-md'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
: 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<UserSwitchOutlined className="text-[20px]" />
|
||||
@@ -65,7 +65,7 @@ export const BackofficeSidebar: FC = (): ReactElement => {
|
||||
className={`flex items-center justify-items-start gap-3 px-[8px] py-[10px] ${
|
||||
isActive('/roles')
|
||||
? 'bg-primary-500 text-white rounded-md'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
: 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<UsergroupAddOutlined className="text-[20px]" />
|
||||
@@ -77,7 +77,7 @@ export const BackofficeSidebar: FC = (): ReactElement => {
|
||||
className={`flex items-center justify-items-start gap-3 px-[8px] py-[10px] ${
|
||||
isActive('/accounts')
|
||||
? 'bg-primary-500 text-white rounded-md'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
: 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<UserOutlined className="text-[20px]" />
|
||||
@@ -89,7 +89,7 @@ export const BackofficeSidebar: FC = (): ReactElement => {
|
||||
className={`flex items-center justify-items-start gap-3 px-[8px] py-[10px] ${
|
||||
isActive('/transactions')
|
||||
? 'bg-primary-500 text-white rounded-md'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
: 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<AuditOutlined className="text-[20px]" />
|
||||
@@ -101,7 +101,7 @@ export const BackofficeSidebar: FC = (): ReactElement => {
|
||||
className={`flex items-center justify-items-start gap-3 px-[8px] py-[10px] ${
|
||||
isActive('/prizes')
|
||||
? 'bg-primary-500 text-white rounded-md'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
: 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<InboxOutlined className="text-[20px]" />
|
||||
@@ -115,7 +115,7 @@ export const BackofficeSidebar: FC = (): ReactElement => {
|
||||
<Button
|
||||
onClick={signOut}
|
||||
variant="text"
|
||||
className="items-start justify-start gap-3 px-[8px] py-[10px] text-gray-700 hover:text-red-500 transition-colors w-full"
|
||||
className="items-start justify-start gap-3 px-[8px] py-[10px] text-neutral-700 hover:text-danger-500 transition-colors w-full"
|
||||
>
|
||||
<LogoutOutlined className="text-[20px]" />
|
||||
<span className="text-p3 font-medium">Log Out</span>
|
||||
|
||||
@@ -30,9 +30,9 @@ const Radio = ({
|
||||
checked={checked}
|
||||
onChange={onChange}
|
||||
disabled={disabled}
|
||||
className="peer col-start-1 row-start-1 appearance-none shrink-0 size-[10px] bg-primary-100 rounded-full disabled:border-gray-400"
|
||||
className="peer col-start-1 row-start-1 appearance-none shrink-0 size-[10px] bg-primary-100 rounded-full disabled:border-neutral-400"
|
||||
/>
|
||||
<div className="pointer-events-none col-start-1 row-start-1 size-[6px] rounded-full peer-checked:bg-primary-500 peer-checked:peer-disabled:bg-gray-400" />
|
||||
<div className="pointer-events-none col-start-1 row-start-1 size-[6px] rounded-full peer-checked:bg-primary-500 peer-checked:peer-disabled:bg-neutral-400" />
|
||||
</div>
|
||||
<label htmlFor={id} className="text-start text-neutral-400 text-label2">
|
||||
{label || 'This is the radio label'}
|
||||
|
||||
@@ -9,7 +9,7 @@ const meta: Meta<typeof Navbar> = {
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<BrowserRouter>
|
||||
<div className="min-h-screen bg-gray-100 p-4">
|
||||
<div className="min-h-screen bg-neutral-100 p-4">
|
||||
<Story />
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
|
||||
@@ -38,7 +38,7 @@ export const Navbar: FC = (): ReactElement => {
|
||||
<Button
|
||||
size="md"
|
||||
variant="text"
|
||||
className="lg:text-p2 lg:max-h-[44px] text-gray-600 hover:text-gray-700 transition-colors"
|
||||
className="lg:text-p2 lg:max-h-[44px] text-neutral-600 hover:text-neutral-700 transition-colors"
|
||||
>
|
||||
<Link to="#">Merch Gacha</Link>
|
||||
</Button>
|
||||
@@ -56,7 +56,7 @@ export const Navbar: FC = (): ReactElement => {
|
||||
onClick={signOut}
|
||||
variant="text"
|
||||
size="md"
|
||||
className="lg:text-p2 text-red-500 font-bold hover:text-red-600"
|
||||
className="lg:text-p2 text-danger-500 font-bold hover:text-danger-600"
|
||||
>
|
||||
Logout
|
||||
</Button>
|
||||
@@ -69,12 +69,12 @@ export const Navbar: FC = (): ReactElement => {
|
||||
}`}
|
||||
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
|
||||
>
|
||||
<MenuOutlined style={{ color: '#1a8ce6' }} />
|
||||
<MenuOutlined style={{ color: '#23a1eb' }} />
|
||||
</button>
|
||||
<div className="relative">
|
||||
{isDropdownOpen && (
|
||||
<div className="absolute right-0 top-0 mt-5">
|
||||
<ul className="mt-2 w-48 bg-white shadow-md border rounded-[16px] border-gray-200 px-5 py-3">
|
||||
<ul className="mt-2 w-48 bg-white shadow-md border rounded-2xl border-neutral-200 px-5 py-3">
|
||||
<li>
|
||||
<Link
|
||||
to="#"
|
||||
@@ -86,7 +86,7 @@ export const Navbar: FC = (): ReactElement => {
|
||||
<li>
|
||||
<Link
|
||||
to="#"
|
||||
className="block text-gray-600 transition-colors px-4 py-2 text-center font-semibold"
|
||||
className="block text-neutral-600 transition-colors px-4 py-2 text-center font-semibold"
|
||||
>
|
||||
Merch Gacha
|
||||
</Link>
|
||||
@@ -95,20 +95,20 @@ export const Navbar: FC = (): ReactElement => {
|
||||
<li>
|
||||
<Button
|
||||
onClick={() => setShowModalLogin(true)}
|
||||
className="block w-full text-gray-100 transition-colors px-4 py-2 text-center font-semibold"
|
||||
className="block w-full text-neutral-100 transition-colors px-4 py-2 text-center font-semibold"
|
||||
>
|
||||
Login
|
||||
</Button>
|
||||
</li>
|
||||
) : (
|
||||
<>
|
||||
<li className="px-4 py-2 text-center text-gray-600 font-semibold">
|
||||
<li className="px-4 py-2 text-center text-neutral-600 font-semibold">
|
||||
{session?.user?.fullname}
|
||||
</li>
|
||||
<li>
|
||||
<div
|
||||
onClick={signOut}
|
||||
className="block text-red-500 font-bold transition-colors px-4 py-2 text-center cursor-pointer"
|
||||
className="block text-danger-500 font-bold transition-colors px-4 py-2 text-center cursor-pointer"
|
||||
>
|
||||
Logout
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user