fix: ck editor in darkmode

This commit is contained in:
Sabda Yagra 2026-02-05 18:02:24 +07:00
parent 27fbb39396
commit 587e0568fc
13 changed files with 266 additions and 116 deletions

View File

@ -6,7 +6,7 @@ const page = () => {
return (
<div className="">
<SiteBreadcrumb />
<div className="bg-slate-100">
<div className="bg-slate-100 dark:bg-default-50">
<CategoriesUpdateForm />
</div>
</div>

View File

@ -150,10 +150,10 @@ export default function UserDetailPage() {
<p className="text-lg font-mono">{user.statusId}</p>
</div>
<div>
{/* <div>
<label className="text-sm font-medium text-gray-600">Keycloak ID</label>
<p className="text-xs font-mono break-all bg-gray-100 p-2 rounded">{user.keycloakId}</p>
</div>
<p className="text-xs font-mono break-all p-2 rounded">{user.keycloakId}</p>
</div> */}
<div>
<label className="text-sm font-medium text-gray-600">Dibuat Oleh</label>
@ -185,10 +185,10 @@ export default function UserDetailPage() {
<p className="text-lg">{formatDateToIndonesian(user.updatedAt)}</p>
</div>
<div>
{/* <div>
<label className="text-sm font-medium text-gray-600">Foto Profil</label>
<p className="text-lg">{user.profilePicturePath ? "Tersedia" : "Tidak ada"}</p>
</div>
</div> */}
</div>
{/* Additional Information (only show if data exists) */}

View File

@ -133,25 +133,6 @@
}
}
@layer base {
/* CKEditor force light mode even in dark */
.ck-viewer .ck.ck-editor__main > .ck-editor__editable {
@apply bg-white text-black;
}
.ck-viewer .ck-content {
@apply text-black;
}
.ck-viewer .ck-content h1,
.ck-viewer .ck-content h2,
.ck-viewer .ck-content h3,
.ck-viewer .ck-content p,
.ck-viewer .ck-content li {
@apply text-black;
}
}
/* @import "tailwindcss";
@import "tw-animate-css";

View File

@ -7,7 +7,7 @@ import Navbar from "@/components/landing-page/navbar";
export default function Home() {
return (
<div className="relative min-h-screen font-[family-name:var(--font-geist-sans)]">
<div className="relative z-10 bg-white w-full mx-auto">
<div className="relative z-10 bg-white dark:bg-default-50 w-full mx-auto">
<Navbar />
<div className="flex-1">
<Header />

View File

@ -2,40 +2,213 @@
import React from "react";
import { CKEditor } from "@ckeditor/ckeditor5-react";
import Editor from "@/vendor/ckeditor5/build/ckeditor";
import Editor from "ckeditor5-custom-build";
function CustomEditor(props) {
const maxHeight = props.maxHeight || 600;
return (
<CKEditor
editor={Editor}
data={props.initialData}
onChange={(event, editor) => {
const data = editor.getData();
console.log({ event, editor, data });
props.onChange(data);
}}
config={{
toolbar: [
"heading",
"fontsize",
"bold",
"italic",
"link",
"numberedList",
"bulletedList",
"undo",
"redo",
"alignment",
"outdent",
"indent",
"blockQuote",
"insertTable",
"codeBlock",
"sourceEditing",
],
}}
/>
<div className="ckeditor-wrapper">
<CKEditor
editor={Editor}
data={props.initialData}
onChange={(event, editor) => {
const data = editor.getData();
console.log({ event, editor, data });
props.onChange(data);
}}
config={{
toolbar: [
"heading",
"fontsize",
"bold",
"italic",
"link",
"numberedList",
"bulletedList",
"undo",
"redo",
"alignment",
"outdent",
"indent",
"blockQuote",
"insertTable",
"codeBlock",
"sourceEditing",
],
content_style: `
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-size: 14px;
line-height: 1.6;
color: #111 !important;
background: #fff !important;
margin: 0;
padding: 1rem;
}
p {
margin: 0.5em 0;
}
h1, h2, h3, h4, h5, h6 {
margin: 1em 0 0.5em 0;
color: inherit !important;
}
ul, ol {
margin: 0.5em 0;
padding-left: 2em;
}
blockquote {
margin: 1em 0;
padding: 0.5em 1em;
border-left: 4px solid #d1d5db;
background-color: #f9fafb;
color: inherit !important;
}
`,
height: props.height || 400,
removePlugins: ["Title"],
mobile: {
theme: "silver",
},
}}
/>
<style jsx>{`
.ckeditor-wrapper {
border-radius: 6px;
overflow: hidden;
box-shadow:
0 1px 3px 0 rgba(0, 0, 0, 0.1),
0 1px 2px 0 rgba(0, 0, 0, 0.06);
}
.ckeditor-wrapper :global(.ck.ck-editor__main) {
min-height: ${props.height || 400}px;
max-height: ${maxHeight}px;
}
.ckeditor-wrapper :global(.ck.ck-editor__editable) {
min-height: ${(props.height || 400) - 50}px;
max-height: ${maxHeight - 50}px;
overflow-y: auto !important;
scrollbar-width: thin;
scrollbar-color: #cbd5e1 #f1f5f9;
background: #fff !important;
color: #111 !important;
}
/* Dark mode support */
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable) {
background: #111 !important;
color: #f9fafb !important;
}
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable h1),
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable h2),
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable h3),
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable h4),
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable h5),
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable h6) {
color: #f9fafb !important;
}
:global(.dark)
.ckeditor-wrapper
:global(.ck.ck-editor__editable blockquote) {
background-color: #1f2937 !important;
border-left-color: #374151 !important;
color: #f3f4f6 !important;
}
/* Custom scrollbar styling for webkit browsers */
.ckeditor-wrapper :global(.ck.ck-editor__editable::-webkit-scrollbar) {
width: 8px;
}
.ckeditor-wrapper
:global(.ck.ck-editor__editable::-webkit-scrollbar-track) {
background: #f1f5f9;
border-radius: 4px;
}
.ckeditor-wrapper
:global(.ck.ck-editor__editable::-webkit-scrollbar-thumb) {
background: #cbd5e1;
border-radius: 4px;
}
.ckeditor-wrapper
:global(.ck.ck-editor__editable::-webkit-scrollbar-thumb:hover) {
background: #94a3b8;
}
/* Dark mode scrollbar */
:global(.dark)
.ckeditor-wrapper
:global(.ck.ck-editor__editable::-webkit-scrollbar-track) {
background: #1f2937;
}
:global(.dark)
.ckeditor-wrapper
:global(.ck.ck-editor__editable::-webkit-scrollbar-thumb) {
background: #4b5563;
}
:global(.dark)
.ckeditor-wrapper
:global(.ck.ck-editor__editable::-webkit-scrollbar-thumb:hover) {
background: #6b7280;
}
/* Ensure content doesn't overflow */
.ckeditor-wrapper :global(.ck.ck-editor__editable .ck-content) {
overflow: hidden;
}
`}</style>
</div>
);
}
export default CustomEditor;
// // components/custom-editor.js
// import React from "react";
// import { CKEditor } from "@ckeditor/ckeditor5-react";
// import Editor from "@/vendor/ckeditor5/build/ckeditor";
// function CustomEditor(props) {
// return (
// <CKEditor
// editor={Editor}
// data={props.initialData}
// onChange={(event, editor) => {
// const data = editor.getData();
// console.log({ event, editor, data });
// props.onChange(data);
// }}
// config={{
// toolbar: [
// "heading",
// "fontsize",
// "bold",
// "italic",
// "link",
// "numberedList",
// "bulletedList",
// "undo",
// "redo",
// "alignment",
// "outdent",
// "indent",
// "blockQuote",
// "insertTable",
// "codeBlock",
// "sourceEditing",
// ],
// }}
// />
// );
// }
// export default CustomEditor;

View File

@ -1,39 +1,18 @@
// import React from "react";
// import { CKEditor } from "@ckeditor/ckeditor5-react";
// import Editor from "@/vendor/ckeditor5/build/ckeditor";
// function ViewEditor(props) {
// return (
// <CKEditor
// editor={Editor}
// data={props.initialData}
// disabled={true}
// config={{
// // toolbar: [],
// isReadOnly: true,
// }}
// />
// );
// }
// export default ViewEditor;
import React from "react";
import { CKEditor } from "@ckeditor/ckeditor5-react";
import Editor from "@/vendor/ckeditor5/build/ckeditor";
function ViewEditor({ initialData }) {
function ViewEditor(props) {
return (
<div className="ck-viewer">
<CKEditor
editor={Editor}
data={initialData}
disabled
config={{
isReadOnly: true,
}}
/>
</div>
<CKEditor
editor={Editor}
data={props.initialData}
disabled={true}
config={{
// toolbar: [],
isReadOnly: true,
}}
/>
);
}

View File

@ -122,11 +122,28 @@ export default function CategoriesUpdateForm() {
// 🔹 hanya kirim data mandatory
const payload = {
id: formData.id,
description: formData.description || "",
statusId: formData.statusId || 1,
title: formData.title || "",
title: formData.title,
description: formData.description,
statusId: formData.statusId,
// ⬇️ FIELD KRUSIAL (WAJIB)
isActive: true,
is_active: true,
isPublish: formData.isPublish,
publishedAt: formData.publishedAt,
parentId: formData.parentId,
slug: formData.slug,
createdById: formData.createdById,
};
// const payload = {
// id: formData.id,
// description: formData.description || "",
// statusId: formData.statusId || 1,
// title: formData.title || "",
// };
console.log("UPDATE PAYLOAD:", payload);
const res = await updateArticleCategory(Number(id), payload);
if (!res?.error) {

View File

@ -56,7 +56,7 @@ export default function Category() {
return (
<section className="px-4 py-10">
<div className="max-w-[1350px] mx-auto bg-white rounded-xl shadow-md p-6">
<div className="max-w-[1350px] mx-auto bg-white dark:bg-default-50 dark:border dark:border-slate-50 rounded-xl shadow-md p-6">
<h2 className="text-xl font-semibold mb-5">
{loading
? t("loadCategory")
@ -89,7 +89,7 @@ export default function Category() {
return (
<button
key={index}
className="px-4 py-2 rounded border border-gray-300 text-gray-700 text-sm font-medium hover:bg-gray-100 hover:border-gray-400 transition-all duration-200"
className="px-4 py-2 rounded border border-gray-300 text-gray-700 dark:text-white text-sm font-medium hover:bg-gray-100 hover:border-gray-400 transition-all duration-200"
onClick={() => {
// Navigate to category page or search by category
console.log(

View File

@ -100,7 +100,7 @@ export default function Footer() {
}, []);
return (
<footer className="border-t bg-white text-center">
<footer className="border-t bg-white dark:bg-default-50 text-center">
<style jsx>{swiperStyles}</style>
<div className="max-w-[1350px] mx-auto">
<div className="py-6">
@ -195,7 +195,7 @@ export default function Footer() {
<div className="border-t my-6 w-full max-w-6xl mx-auto" />
<div className="flex flex-col md:flex-row items-center justify-between gap-4 px-4 pb-6 max-w-6xl mx-auto text-sm text-gray-600">
<div className="flex flex-col md:flex-row items-center justify-between gap-4 px-4 pb-6 max-w-6xl mx-auto text-sm text-gray-600 dark:text-white">
<div className="flex items-center gap-2">
<span>ver 1.0.0 @2025 - {t("netidhub")}</span>
<Image
@ -208,7 +208,7 @@ export default function Footer() {
</div>
{/* Social Media */}
<div className="flex gap-3 text-gray-800">
<div className="flex gap-3 text-gray-800 dark:text-white">
<Instagram className="hover:text-black" />
<svg
xmlns="http://www.w3.org/2000/svg"

View File

@ -294,7 +294,7 @@ function Card({
return (
<div>
<div
className={`rounded-xl overflow-hidden shadow hover:shadow-lg transition-all bg-white ${
className={`rounded-xl overflow-hidden shadow hover:shadow-lg transition-all bg-white dark:bg-black dark:border dark:border-slate-50 ${
isBig
? "w-full lg:max-w-[670px] lg:min-h-[680px]"
: "w-full h-[350px] md:h-[330px]"

View File

@ -358,15 +358,15 @@ export default function MediaUpdate() {
}
return (
<section className="bg-white px-4 py-10 border max-w-[1350px] mx-auto rounded-md border-[#CDD5DF] my-10">
<section className="bg-white dark:bg-default-50 px-4 py-10 border max-w-[1350px] mx-auto rounded-md border-[#CDD5DF] my-10">
<div className="max-w-screen-xl mx-auto">
<h2 className="text-2xl font-semibold text-center mb-6">
{t("title")}
</h2>
{/* Main Tab */}
<div className="flex justify-center mb-6 bg-white">
<Card className="bg-[#FFFFFF] rounded-xl flex flex-row p-3 gap-2 shadow-md border border-gray-200">
<div className="flex justify-center mb-6 bg-white dark:bg-default-50">
<Card className="bg-[#FFFFFF] dark:bg-default-50 rounded-xl flex flex-row p-3 gap-2 shadow-md border border-gray-200">
<button
onClick={() => setTab("latest")}
className={`px-6 py-3 rounded-lg text-sm font-semibold transition-all duration-200 ${
@ -392,7 +392,7 @@ export default function MediaUpdate() {
{/* Content Type Filter */}
<div className="flex justify-center mb-8">
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 rounded-2xl p-4 border-2 border-blue-100 shadow-lg">
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 rounded-2xl p-4 border-2 border-blue-100 shadow-lg dark:bg-default-50">
<div className="flex flex-wrap justify-center gap-2">
{/* <button
onClick={() => setContentType("all")}
@ -465,7 +465,7 @@ export default function MediaUpdate() {
>
{filteredData.map((item) => (
<SwiperSlide key={item.id}>
<div className="rounded-xl shadow-md overflow-hidden bg-white">
<div className="rounded-xl shadow-md overflow-hidden bg-white dark:bg-default-50 dark:border dark:border-slate-50">
{/* ✅ Kondisi: jika typeId = 3 (text) atau 4 (audio) tampilkan ikon, lainnya tampilkan thumbnail */}
{item.typeId === 3 ? (
// 📝 TEXT

View File

@ -122,7 +122,7 @@ export default function Navbar() {
<button
onClick={() => setDropdownOpen(!isDropdownOpen)}
className={cn(
"relative text-gray-500 hover:text-black transition-colors",
"relative text-gray-500 dark:text-white dark:hover:text-slate-300 hover:text-black transition-colors",
isDropdownOpen ||
pathname.startsWith("/public/publication")
? "text-black"
@ -147,7 +147,7 @@ export default function Navbar() {
<Link
key={sub.label}
href={sub.href}
className="block px-4 py-2 text-sm hover:bg-gray-100 text-gray-700"
className="block px-4 py-2 text-sm hover:bg-gray-100 text-gray-700 dark:text-white"
>
{sub.label}
</Link>
@ -160,7 +160,7 @@ export default function Navbar() {
href={item.href}
onClick={handleClick}
className={cn(
"relative text-gray-500 hover:text-black transition-colors",
"relative text-gray-500 dark:text-white dark:hover:text-slate-300 hover:text-black transition-colors",
isActive && "text-black",
)}
>
@ -194,7 +194,7 @@ export default function Navbar() {
<div className="relative">
<button
onClick={() => setShowProfileMenu((prev) => !prev)}
className="flex items-center gap-2 border-2 py-1 px-3 rounded-lg hover:bg-gray-50 cursor-pointer"
className="flex items-center gap-2 border-2 py-1 px-3 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-700 cursor-pointer"
>
<div className="w-9 h-9 rounded-full overflow-hidden border">
<Image
@ -205,17 +205,17 @@ export default function Navbar() {
className="object-cover"
/>
</div>
<span className="text-sm font-medium text-gray-800">
<span className="text-sm font-medium text-gray-800 dark:text-white">
{fullname}
</span>
<ChevronDown className="w-4 h-4 text-gray-600" />
</button>
{showProfileMenu && (
<div className="absolute right-0 mt-2 w-40 bg-white border rounded shadow z-50 ">
<div className="absolute right-0 mt-2 w-40 bg-white dark:bg-black border rounded shadow z-50 ">
<Link
href="/admin/dashboard"
className="flex flex-row items-center text-left px-4 py-2 hover:bg-gray-100 text-gray-700"
className="flex flex-row items-center text-left px-4 py-2 hover:bg-gray-300 dark:hover:bg-gray-700 text-gray-700 dark:text-white"
>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -233,7 +233,7 @@ export default function Navbar() {
<button
onClick={handleLogout}
className="w-full flex flex-row text-left px-4 py-2 hover:bg-gray-100 text-gray-700 cursor-pointer"
className="w-full flex flex-row text-left px-4 py-2 hover:bg-gray-300 text-gray-700 dark:text-white cursor-pointer"
>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -312,7 +312,7 @@ export default function Navbar() {
</div>
<div>
<h3 className="text-[16px] font-bold text-gray-700 mb-2">
<h3 className="text-[16px] font-bold text-gray-700 dark:text-white mb-2">
{t("features")}
</h3>
<div className="space-y-5 ml-3">
@ -331,7 +331,7 @@ export default function Navbar() {
}
setIsSidebarOpen(false);
}}
className="block text-[15px] text-gray-800 text-left w-full"
className="block text-[15px] text-gray-800 dark:text-white text-left w-full"
>
{item.label}
</button>
@ -340,19 +340,19 @@ export default function Navbar() {
</div>
<div className="space-y-5 text-[16px] font-bold">
<Link href="/about" className="block text-black">
<Link href="/about" className="block text-black dark:text-white">
{t("about")}
</Link>
<Link href="/advertising" className="block text-black">
<Link href="/advertising" className="block text-black dark:text-white">
{t("advertising")}
</Link>
<Link href="/contact" className="block text-black">
<Link href="/contact" className="block text-black dark:text-white">
{t("contact")}
</Link>
{!isLoggedIn ? (
<>
<Link href="/auth" className="block text-lg text-gray-800">
<Link href="/auth" className="block text-lg text-gray-800 dark:text-white">
{t("login")}
</Link>
<Link

View File

@ -1,7 +1,7 @@
import type { Config } from "tailwindcss";
const config = {
darkMode: ["class", "html"],
darkMode: ["class"],
content: [
"./pages/**/*.{ts,tsx}",
"./components/**/*.{js,ts,tsx}",