feat: Implement Algolia DocSearch, enhance MDX components, and update build configurations.

This commit is contained in:
gitfromwildan
2026-02-08 23:10:20 +07:00
parent 8b3de652bb
commit 099c384d9d
43 changed files with 1617 additions and 1156 deletions

162
styles/algolia.css Normal file
View File

@@ -0,0 +1,162 @@
/*
================================================================================
DocSearch Component Styling (Refactored Version)
================================================================================
*/
/* -- LANGKAH 1: Definisi Variabel Global --
Variabel tema DocSearch sekarang didefinisikan secara global di :root.
Ini menyederhanakan pewarisan tema dan memastikan konsistensi.
Mode gelap secara otomatis menimpa variabel ini karena .dark di globals.css.
*/
:root {
--docsearch-primary-color: hsl(var(--primary));
--docsearch-text-color: hsl(var(--muted-foreground));
--docsearch-spacing: 12px;
--docsearch-icon-stroke-width: 1.4;
--docsearch-highlight-color: var(--docsearch-primary-color);
--docsearch-muted-color: hsl(var(--muted-foreground));
--docsearch-container-background: rgba(0, 0, 0, 0.7);
--docsearch-logo-color: hsl(var(--primary-foreground));
/* Modal */
--docsearch-modal-width: 560px;
--docsearch-modal-height: 600px;
--docsearch-modal-background: hsl(var(--background));
--docsearch-modal-shadow: 0 0 0 1px hsl(var(--border)), 0 8px 20px rgba(0, 0, 0, 0.2);
/* SearchBox */
--docsearch-searchbox-height: 56px;
--docsearch-searchbox-background: hsl(var(--input));
--docsearch-searchbox-focus-background: hsl(var(--card));
--docsearch-searchbox-shadow: none;
/* Hit (Hasil Pencarian) */
--docsearch-hit-height: 56px;
--docsearch-hit-color: hsl(var(--foreground));
--docsearch-hit-active-color: hsl(var(--primary-foreground));
--docsearch-hit-background: hsl(var(--card));
--docsearch-hit-shadow: none;
/* Keys */
--docsearch-key-gradient: none;
--docsearch-key-shadow: none;
--docsearch-key-pressed-shadow: none;
/* Footer */
--docsearch-footer-height: 44px;
--docsearch-footer-background: hsl(var(--background));
--docsearch-footer-shadow: none;
}
/* -- LANGKAH 2: Gaya untuk Tombol Awal --
Gaya ini spesifik untuk tombol yang ada di Navbar,
yang dibungkus oleh <div class="docsearch">.
*/
.docsearch .DocSearch-Button {
background-color: hsl(var(--secondary));
border: 1px solid hsl(var(--border));
border-radius: 9999px;
width: 160px;
height: 40px;
color: hsl(var(--muted-foreground));
transition: width 0.3s ease;
margin: 0;
}
.docsearch .DocSearch-Button:hover {
border-color: var(--docsearch-primary-color);
box-shadow: none;
}
.docsearch .DocSearch-Search-Icon {
color: var(--docsearch-muted-color);
width: 1rem;
height: 1rem;
}
.docsearch .DocSearch-Button-Placeholder {
font-style: normal;
margin-left: 0.25rem;
font-size: 0.875rem;
line-height: 1.25rem;
color: var(--docsearch-muted-color);
}
.docsearch .DocSearch-Button-Key {
background: var(--docsearch-primary-color);
color: var(--docsearch-logo-color); /* Menggunakan variabel yg relevan */
border-radius: 6px;
font-size: 14px;
font-weight: 500;
height: 24px;
padding: 0 6px;
border: none;
box-shadow: none;
top: 0;
}
/* -- LANGKAH 3: Gaya untuk Modal dan Isinya --
Gaya ini menargetkan elemen-elemen modal yang dirender terpisah.
Karena variabel sudah global, kita hanya perlu menata elemennya.
*/
.DocSearch-Container .DocSearch-Modal {
backdrop-filter: blur(8px);
}
.DocSearch-Form {
border: 1px solid hsl(var(--border));
background-color: transparent;
}
.DocSearch-Input {
font-size: 15px !important;
}
.DocSearch-Footer {
border-top: 1px solid hsl(var(--border));
}
/* Gaya untuk tombol keyboard di footer */
.DocSearch-Footer--commands kbd {
background-color: hsl(var(--secondary));
border: 1px solid hsl(var(--border));
border-bottom-width: 2px;
border-radius: 6px;
color: var(--docsearch-muted-color);
padding: 4px 8px;
display: flex;
align-items: center;
justify-content: center;
}
/* Menghilangkan gaya default dari ikon di dalam tombol footer */
.DocSearch-Commands-Key {
background: none;
color: hsl(var(--muted-foreground));
border: 1px solid hsl(var(--border));
box-shadow: none;
padding: 2px 4px;
margin-right: 0.4em;
height: 20px;
width: 32px;
border-radius: 6px;
}
/* -- LANGKAH 4: Gaya Responsif --
Tidak ada perubahan, hanya mempertahankan fungsionalitas mobile.
*/
@media (max-width: 768px) {
.docsearch .DocSearch-Button {
width: 40px;
height: 40px;
padding: 0;
justify-content: center;
background: none;
border: none;
}
.docsearch .DocSearch-Button-Placeholder,
.docsearch .DocSearch-Button-Key {
display: none;
}
}

View File

@@ -1,10 +1,131 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import 'tailwindcss';
@plugin '@tailwindcss/typography';
@import url("../styles/syntax.css");
/* ocean */
@custom-variant dark (&:is(.dark *));
@utility container {
margin-inline: auto;
padding-inline: 2rem;
@media (width >=--theme(--breakpoint-sm)) {
max-width: none;
}
@media (width >=1440px) {
max-width: 1440px;
}
}
@theme {
--color-border: hsl(var(--border));
--color-input: hsl(var(--input));
--color-ring: hsl(var(--ring));
--color-background: hsl(var(--background));
--color-foreground: hsl(var(--foreground));
--color-primary: hsl(var(--primary));
--color-primary-foreground: hsl(var(--primary-foreground));
--color-secondary: hsl(var(--secondary));
--color-secondary-foreground: hsl(var(--secondary-foreground));
--color-destructive: hsl(var(--destructive));
--color-destructive-foreground: hsl(var(--destructive-foreground));
--color-muted: hsl(var(--muted));
--color-muted-foreground: hsl(var(--muted-foreground));
--color-accent: hsl(var(--accent));
--color-accent-foreground: hsl(var(--accent-foreground));
--color-popover: hsl(var(--popover));
--color-popover-foreground: hsl(var(--popover-foreground));
--color-card: hsl(var(--card));
--color-card-foreground: hsl(var(--card-foreground));
--color-sidebar: hsl(var(--sidebar-background));
--color-sidebar-foreground: hsl(var(--sidebar-foreground));
--color-sidebar-primary: hsl(var(--sidebar-primary));
--color-sidebar-primary-foreground: hsl(var(--sidebar-primary-foreground));
--color-sidebar-accent: hsl(var(--sidebar-accent));
--color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));
--color-sidebar-border: hsl(var(--sidebar-border));
--color-sidebar-ring: hsl(var(--sidebar-ring));
--radius-lg: var(--radius);
--radius-md: calc(var(--radius) - 2px);
--radius-sm: calc(var(--radius) - 4px);
--font-code: var(--font-geist-mono);
--font-regular: var(--font-geist-sans);
--animate-accordion-down: accordion-down 0.2s ease-out;
--animate-accordion-up: accordion-up 0.2s ease-out;
--animate-shiny-text: shiny-text 8s infinite;
@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(--radix-accordion-content-height);
}
}
@keyframes accordion-up {
from {
height: var(--radix-accordion-content-height);
}
to {
height: 0;
}
}
@keyframes shiny-text {
0%,
90%,
100% {
background-position: calc(-100% - var(--shiny-width)) 0;
}
30%,
60% {
background-position: calc(100% + var(--shiny-width)) 0;
}
}
}
/*
The default border color has changed to `currentcolor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentcolor);
}
}
@utility animate-shine {
--animate-shine: shine var(--duration) infinite linear;
animation: var(--animate-shine);
background-size: 200% 200%;
}
/* Modern Blue Theme */
@layer base {
:root {
--background: 210 50% 95%;
@@ -21,17 +142,18 @@
--muted-foreground: 220 20% 40%;
--accent: 132 86% 32%;
--accent-foreground: 0 0% 100%;
--destructive: 0 65% 55%;
--destructive-foreground: 220 20% 95%;
--border: 220 15% 90%;
--input: 220 15% 90%;
--ring: 132 86% 42%;
--destructive: 0 85% 60%;
--destructive-foreground: 0 0% 100%;
--border: 210 20% 85%;
--input: 210 20% 85%;
--ring: 210 81% 56%;
--radius: 0.5rem;
--chart-1: 210 60% 50%;
--chart-2: 220 40% 65%;
--chart-3: 132 86% 42%;
--chart-4: 200 60% 55%;
--chart-5: 240 30% 40%;
--chart-1: 210 81% 56%;
--chart-2: 200 100% 40%;
--chart-3: 220 76% 60%;
--chart-4: 190 90% 50%;
--chart-5: 230 86% 45%;
--line-number-color: rgba(0, 0, 0, 0.05);
}
.dark {
@@ -72,82 +194,66 @@
}
}
.prose {
margin: 0 !important;
}
@layer utilities {
.prose {
margin: 0 !important;
}
pre {
padding: 2px 0 !important;
width: inherit !important;
overflow-x: auto;
}
pre {
padding: 2px 0 !important;
width: inherit !important;
overflow-x: auto;
}
pre>code {
display: grid;
max-width: inherit !important;
padding: 14px 0 !important;
}
pre>code {
display: grid;
max-width: inherit !important;
padding: 14px 0 !important;
border: 0 !important;
}
.code-line {
padding: 0.75px 16px;
@apply border-l-2 border-transparent
}
.code-line {
padding: 0.75px 16px;
@apply border-l-2 border-transparent;
}
.line-number::before {
display: inline-block;
width: 1rem;
margin-right: 22px;
margin-left: -2px;
color: rgb(110, 110, 110);
content: attr(line);
font-size: 13.5px;
text-align: right;
}
.line-number::before {
display: inline-block;
width: 1rem;
margin-right: 22px;
margin-left: -2px;
color: rgb(110, 110, 110);
content: attr(line);
font-size: 13.5px;
text-align: right;
}
.highlight-line {
@apply bg-primary/5 border-l-2 border-primary/30;
}
.highlight-line {
@apply bg-primary/5 border-l-2 border-primary/30;
}
.rehype-code-title {
@apply px-2 -mb-8 w-full text-sm pb-5 font-medium mt-5 font-code;
}
.rehype-code-title {
@apply px-2 -mb-8 w-full text-sm pb-5 font-medium mt-5 font-code;
}
.highlight-comp>code {
background-color: transparent !important;
}
.line-clamp-3 {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
.highlight-comp>code {
background-color: transparent !important;
}
}
@layer utilities {
.animate-shine {
--animate-shine: shine var(--duration) infinite linear;
animation: var(--animate-shine);
background-size: 200% 200%;
@keyframes shine {
0% {
background-position: 0% 0%;
}
@keyframes shine {
0% {
background-position: 0% 0%;
}
50% {
background-position: 100% 100%;
}
100% {
background-position: 0% 0%;
}
50% {
background-position: 100% 100%;
}
100% {
background-position: 0% 0%;
}
}
}

View File

@@ -1,23 +1,27 @@
/* ocean with green variant */
/* Light Mode */
.keyword {
color: #1EAB18; /* Slightly darker green */
/* Dark Lime */
color: #1EAB18;
/* Slightly darker green */
/* Dark Lime */
}
.function {
color: #39D833; /* Brighter lime green */
/* Bright Lime */
color: #39D833;
/* Brighter lime green */
/* Bright Lime */
}
.punctuation {
color: #357C30; /* Muted green-gray */
/* Sage Green */
color: #357C30;
/* Muted green-gray */
/* Sage Green */
}
.comment {
color: #5F935B; /* Muted green */
/* Olive Green */
color: #5F935B;
/* Muted green */
/* Olive Green */
}
.string,
@@ -25,34 +29,40 @@
.annotation,
.boolean,
.number {
color: #2E8F2A; /* Darker green */
/* Dark Forest Green */
color: #2E8F2A;
/* Darker green */
/* Dark Forest Green */
}
.tag {
color: #1FC01B; /* Original vibrant green */
/* Vibrant Green */
color: #1FC01B;
/* Original vibrant green */
/* Vibrant Green */
}
.attr-name {
color: #4FE34A; /* Light and bright green */
/* Electric Green */
color: #4FE34A;
/* Light and bright green */
/* Electric Green */
}
.attr-value {
color: #1EAB18; /* Slightly darker green */
/* Dark Lime */
color: #1EAB18;
/* Slightly darker green */
/* Dark Lime */
}
/* Dark Mode */
.dark .keyword {
color: #8CFF7D; /* Soft light green */
/* Soft Mint */
color: #8CFF7D;
/* Soft light green */
/* Soft Mint */
}
.dark .function {
color: #A0FF93; /* Light lime green */
/* Minty Green */
color: #A0FF93;
/* Light lime green */
/* Minty Green */
}
.dark .string,
@@ -60,33 +70,52 @@
.dark .annotation,
.dark .boolean,
.dark .number {
color: #72FF73; /* Light green */
/* Spring Green */
color: #72FF73;
/* Light green */
/* Spring Green */
}
.dark .tag {
color: #7FFF7A; /* Vibrant green */
/* Neon Green */
color: #7FFF7A;
/* Vibrant green */
/* Neon Green */
}
.dark .attr-name {
color: #B2FFA3; /* Soft pastel green */
/* Mint Green */
color: #B2FFA3;
/* Soft pastel green */
/* Mint Green */
}
.dark .attr-value {
color: #8CFF7D; /* Soft light green */
/* Soft Mint */
color: #1EAB18;
/* Slightly darker green */
/* Dark Lime */
}
.dark .comment {
color: #9ca3af;
/* Lighter gray for dark mode */
}
.dark .punctuation {
color: #9ca3af;
/* Lighter gray for dark mode */
}
.youtube {
position: relative;
padding-bottom: 56.25%; /* Rasio aspek 16:9 */
padding-bottom: 56.25%;
/* Rasio aspek 16:9 */
height: 0;
overflow: hidden;
background: #000; /* Latar belakang hitam untuk memadukan player */
border-radius: 8px; /* Sudut melengkung */
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2); /* Bayangan lembut */
background: #000;
/* Latar belakang hitam untuk memadukan player */
border-radius: 8px;
/* Sudut melengkung */
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
/* Bayangan lembut */
margin: 24px 0;
}
.youtube iframe {
@@ -96,5 +125,95 @@
width: 100%;
height: 100%;
border: none;
border-radius: 8px; /* Sudut melengkung pada iframe */
border-radius: 8px;
/* Sudut melengkung pada iframe */
}
/* ======================================================================== */
/* Custom styling for code blocks */
/* ======================================================================== */
.code-block-container {
position: relative;
margin: 1.5rem 0;
border: 1px solid hsl(var(--border));
overflow: hidden;
font-size: 0.875rem;
border-radius: 0.75rem;
}
.code-block-header {
display: flex;
align-items: center;
gap: 0.5rem;
background-color: hsl(var(--muted));
padding: 0.5rem 1rem;
border-bottom: 1px solid hsl(var(--border));
color: hsl(var(--muted-foreground));
font-family: monospace;
font-size: 0.8rem;
}
.code-block-actions {
position: absolute;
top: 0.5rem;
right: 0.75rem;
z-index: 10;
}
.code-block-actions button {
color: hsl(var(--muted-foreground));
transition: color 0.2s ease-in-out;
}
.code-block-actions button:hover {
color: hsl(var(--foreground));
}
.code-block-body pre[class*="language-"] {
margin: 0 !important;
padding: 0 !important;
background: transparent !important;
}
.line-numbers-wrapper {
position: absolute;
top: 0;
left: 0;
width: 3rem;
padding-top: 1rem;
text-align: right;
color: var(--line-number-color);
user-select: none;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
background: hsl(var(--primary) / 0.1);
border-left: 2px solid hsl(var(--primary));
pointer-events: none;
}
.code-block-body pre[data-line-numbers="true"] .line-highlight {
padding-left: 3.5rem;
}
.code-block-body::-webkit-scrollbar {
height: 8px;
}
.code-block-body::-webkit-scrollbar-track {
background: transparent;
}
.code-block-body::-webkit-scrollbar-thumb {
background: hsl(var(--border));
border-radius: 4px;
}
.code-block-body::-webkit-scrollbar-thumb:hover {
background: hsl(var(--muted));
}