Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
244 changes: 206 additions & 38 deletions docs/stylesheets/extra.css
Original file line number Diff line number Diff line change
@@ -1,75 +1,243 @@
/* === Light scheme — devslab brand ========================================= */
/* ---------------------------------------------------------------------------
* easy-paging docs — devslab brand theme
*
* Aesthetic: header blends into the body — devslab.kr style.
* - Light mode: white header, white body, dark text/logo
* - Dark mode: zinc-900 header, zinc-900 body, white text/logo
* - Visual separation between header and body is a hairline border only
* - Cyan-electric used as a small accent (links, hovers, active tab)
* - Pretendard typography (same family as devslab.kr)
* - Bilingual "EN / 한" language switcher (no CJK glyph, no generic globe)
*
* Material's default paints the header in primary color. We override the
* primary CSS variables to match the body bg so there's no visible color
* block at the top — just navigation sitting cleanly above content.
* --------------------------------------------------------------------------- */

/* === Typography: Pretendard (same family as devslab.kr) =================== */
@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.css");

:root {
--md-text-font: "Pretendard",
-apple-system,
"Apple SD Gothic Neo",
"Noto Sans KR",
system-ui,
sans-serif;
--md-code-font: "JetBrains Mono", "SFMono-Regular", Menlo,
Consolas, "Liberation Mono", monospace;
}

/* === Palette (light scheme) ==============================================
* Scoped to `[data-md-color-scheme="default"]`, not `:root`. Material's
* own default-scheme stylesheet re-defines these variables inside that
* exact scope, and at equal specificity the later rule wins — meaning
* anything we set in `:root` was getting silently overridden, leaving
* body links the wrong color (and sometimes invisible against the
* white body bg). Same trick already worked for the dark scheme below;
* apply it consistently here.
*
* Header bg = body bg (white). Header text = dark (zinc-900) for contrast.
* Cyan-electric stays as a small accent on links/hovers.
* ========================================================================== */
[data-md-color-scheme="default"] {
--md-primary-fg-color: #18181b; /* zinc-900 */
--md-primary-fg-color--light: #27272a; /* zinc-800 */
--md-primary-fg-color--dark: #09090b; /* zinc-950 */
/* Primary = header surface; match body bg so the header blends in. */
--md-primary-fg-color: #ffffff;
--md-primary-fg-color--light: #fafafa;
--md-primary-fg-color--dark: #f4f4f5; /* zinc-100 — used for elevated states */
--md-primary-bg-color: #18181b; /* zinc-900 — text/logo on the white header */
--md-primary-bg-color--light: rgba(24, 24, 27, 0.75);

--md-accent-fg-color: #0891b2; /* cyan-600 */
--md-accent-fg-color--transparent: rgba(8, 145, 178, 0.12);
/* Accent — small surfaces (links, hovers, selection)
*
* cyan-700 instead of cyan-500: against a white body the brighter
* cyan-500 lands at ~2.4:1 contrast — under WCAG AA's 4.5:1 minimum
* for normal text. cyan-700 (#0e7490) gives ~5.4:1 which passes AA
* while keeping the "electric" feel.
*/
--md-accent-fg-color: #0e7490; /* cyan-700 — AA-readable on white */
--md-accent-fg-color--transparent: rgba(14, 116, 144, 0.10);

/* Body link color — decouple from primary, follow accent. */
--md-typeset-a-color: #0e7490; /* cyan-700 */
}

/* === Dark scheme — header blends into the zinc-900 body =================== */
[data-md-color-scheme="slate"] {
--md-primary-fg-color: #18181b; /* zinc-900 — same as body bg */
--md-primary-fg-color--light: #27272a; /* zinc-800 */
--md-primary-fg-color: #18181b; /* zinc-900 — same as body bg below */
--md-primary-fg-color--light: #27272a; /* zinc-800 — slightly raised */
--md-primary-fg-color--dark: #09090b; /* zinc-950 */
--md-primary-bg-color: #fafafa; /* white text/logo on dark header */
--md-primary-bg-color--light: rgba(250, 250, 250, 0.75);

--md-accent-fg-color: #22d3ee; /* cyan-400 — pops on dark */
--md-accent-fg-color: #22d3ee; /* cyan-400 — pops on dark */
--md-accent-fg-color--transparent: rgba(34, 211, 238, 0.12);

/* Body links on dark — slightly brighter cyan for readability. */
--md-typeset-a-color: #22d3ee; /* cyan-400 */

/* Body bg matches devslab.kr's actual zinc-900. */
--md-default-bg-color: #18181b;
--md-default-bg-color--light: #27272a;
--md-default-bg-color--lighter: #3f3f46;
--md-code-bg-color: #09090b; /* zinc-950 */
--md-code-bg-color: #09090b; /* zinc-950 — code blocks pop */
}

/* === Typeset links ========================================================= */
/* === Link affordance ====================================================
* Always-on subtle underline + cyan color. Color alone wasn't enough in
* sections where a link follows bolded descriptive text (e.g. the
* "Where to go next" list on the landing page) — the visual weight of
* the bold text drowned out the cyan link. The underline restores the
* "this is clickable" affordance without relying purely on color.
*
* Underline is dim at rest and thickens on hover for feedback.
* Offset of 0.18em keeps the underline from clipping descender glyphs
* (g, j, p, q, y).
* ========================================================================== */
.md-typeset a {
font-weight: 500;
text-decoration: underline;
text-decoration-thickness: 0.06em;
text-underline-offset: 0.2em;
transition: text-decoration-thickness 150ms;
text-underline-offset: 0.18em;
}
.md-typeset a:hover,
.md-typeset a:focus {
text-decoration: underline;
text-decoration-thickness: 0.12em;
}

/* Code-styled link text — Material's <code> has its own (dark) color which
* blocks the link's cyan from showing through. Force <code> inside any body
* link to inherit the link color, so [`SomeFile.md`](...) reads as a link. */
.md-typeset a code {
color: inherit;
}
.md-typeset a:hover { text-decoration-thickness: 0.12em; }

/* === Active nav link ======================================================= */
.md-nav__item.md-nav__item--active > .md-nav__link {
/* Sidebar nav: active page should be obviously cyan. Material defaults
* to --md-typeset-a-color which is cyan-700, but the chrome around it
* (subtle background, weight) made it easy to miss in light mode. Bump
* weight and remove any opacity so the active page is unmistakable. */
.md-nav__link--active {
color: var(--md-accent-fg-color);
font-weight: 700;
opacity: 1;
}

/* === Buttons =============================================================== */
.md-button {
border: 1px solid var(--md-accent-fg-color);
/* === Buttons ({ .md-button } / { .md-button--primary }) ===================
* Same root cause as the body links: Material's default button colors
* inherit from primary, which we set to match body bg. Result: outlined
* buttons (.md-button) were transparent-on-transparent until hover, and
* the primary CTA looked muddy. Rewire to the accent (cyan) family so the
* three landing-page buttons (Get Started / GitHub / Maven Central) all
* stay visible at rest.
* ========================================================================== */

/* Outlined: cyan border + cyan text, fills on hover.
* Explicit text-decoration: none — buttons shouldn't inherit the
* always-on underline that body links now have. */
.md-typeset .md-button {
color: var(--md-accent-fg-color);
border-color: var(--md-accent-fg-color);
text-decoration: none;
}
.md-button:hover {
background-color: var(--md-accent-fg-color);
color: var(--md-default-bg-color);
}
.md-button--primary {
.md-typeset .md-button:hover,
.md-typeset .md-button:focus {
background-color: var(--md-accent-fg-color);
color: #ffffff;
border-color: var(--md-accent-fg-color);
color: var(--md-default-bg-color);
text-decoration: none; /* override the global link-hover underline */
}

/* === Header & tabs — hairline border ====================================== */
.md-header,
.md-tabs { box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06); }
[data-md-color-scheme="slate"] .md-header,
[data-md-color-scheme="slate"] .md-tabs { box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06); }
/* Primary CTA: filled cyan, white text. Use cyan-500 (brighter) for the
* fill since white text on it has plenty of contrast — the dim cyan-700
* we use for body text would look muddy here. */
.md-typeset .md-button--primary {
background-color: #06b6d4; /* cyan-500 — vibrant fill */
color: #ffffff;
border-color: #06b6d4;
text-decoration: none;
}
.md-typeset .md-button--primary:hover,
.md-typeset .md-button--primary:focus {
background-color: #0891b2; /* cyan-600 — darker on hover */
border-color: #0891b2;
color: #ffffff;
text-decoration: none;
}

/* === Bilingual language switcher — text instead of a globe glyph ========== */
.md-header__option .md-select__button::before {
content: "EN";
font-size: 0.875rem;
/* Dark-mode hover: use a brighter cyan since the base is already brighter,
* with dark text for contrast. */
[data-md-color-scheme="slate"] .md-typeset .md-button--primary:hover,
[data-md-color-scheme="slate"] .md-typeset .md-button--primary:focus {
background-color: #67e8f9; /* cyan-300 */
border-color: #67e8f9;
color: #18181b;
}
[data-md-color-scheme="slate"] .md-typeset .md-button:hover,
[data-md-color-scheme="slate"] .md-typeset .md-button:focus {
color: #18181b; /* dark text on bright-cyan filled hover */
}

/* === Hairline separation (the only visual cue the header exists) ========== */
.md-header {
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);
}
[data-md-color-scheme="slate"] .md-header {
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06);
}

/* === Tabs bar (sub-nav under header) — same blending treatment ============ */
.md-tabs {
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}
[data-md-color-scheme="slate"] .md-tabs {
border-bottom-color: rgba(255, 255, 255, 0.06);
}
.md-tabs__link--active {
color: var(--md-accent-fg-color);
opacity: 1;
}
.md-tabs__link:hover {
color: var(--md-accent-fg-color) !important;
opacity: 1;
}

/* === Brand logo — invert only in dark mode ================================
* logo-mark.svg ships as #0a0a0a (dark). That's perfect on the white light-
* mode header. In dark mode, force it white with brightness(0)+invert(1).
* ========================================================================== */
[data-md-color-scheme="slate"] .md-header__button.md-logo img,
[data-md-color-scheme="slate"] .md-header__button.md-logo svg {
filter: brightness(0) invert(1);
}

/* === Language switcher: bilingual text label ===============================
* Replace Material's "A + 文" CJK glyph with the current page language as
* a short badge ("EN" or "한"). The 文 reads as "Chinese" to most Korean
* visitors which isn't what we want for a language-switcher affordance.
* ========================================================================== */
.md-header [aria-label="Select language"] > svg,
.md-header [aria-label*="언어"] > svg {
display: none;
}

.md-header [aria-label="Select language"]::before,
.md-header [aria-label*="언어"]::before {
font-weight: 700;
font-size: 0.85rem;
letter-spacing: 0.04em;
line-height: 1;
padding: 0 0.15rem;
display: inline-block;
vertical-align: middle;
}
[data-md-color-scheme="slate"] .md-header__option .md-select__button::before {

html[lang="en"] .md-header [aria-label="Select language"]::before,
html[lang="en"] .md-header [aria-label*="언어"]::before {
content: "EN";
}

html[lang="ko"] .md-header [aria-label="Select language"]::before,
html[lang="ko"] .md-header [aria-label*="언어"]::before {
content: "한";
font-size: 1rem;
font-weight: 700;
}
.md-header__option .md-select__button svg { display: none; }
13 changes: 12 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ docs_dir: docs
theme:
name: material
language: en
logo: assets/logo.svg
favicon: assets/logo.svg
features:
- navigation.tabs
- navigation.sections
Expand Down Expand Up @@ -89,16 +91,25 @@ markdown_extensions:
- footnotes
- tables
- pymdownx.details
- pymdownx.superfences
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.tabbed:
alternate_style: true
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
- pymdownx.snippets:
base_path:
- .
check_paths: true
- pymdownx.emoji:
emoji_index: !!python/name:material.extensions.emoji.twemoji
emoji_generator: !!python/name:material.extensions.emoji.to_svg
- toc:
permalink: true
toc_depth: 3
Expand Down
Loading