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
2 changes: 1 addition & 1 deletion LAST_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.9
1.0.9-dev1
126 changes: 126 additions & 0 deletions docs/nav/development/component-showcase.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Component Showcase

This page exercises every themed component using real content about the
[Dracula theme](https://github.com/dracula) project, so visual regressions
are easy to spot during development.

## What is Dracula?

Dracula is a dark theme for code editors, terminals, and hundreds of other
applications, created by [Zeno Rocha](https://github.com/zenorocha). It
started as a single Sublime Text theme and has since grown into one of the
most widely ported color schemes in open source.

### Design goals

# A single color scheme, everywhere
## Consistency across every tool you use
### From the editor to the terminal
#### From the terminal to the browser
##### From the browser to your IDE plugins
###### Down to the smallest utility script

## The philosophy

Dracula follows a few simple rules, explained in **bold**, *italics*,
***bold italics***, and even ~~occasionally~~ always with a bit of
`inline code` for terms like `background`, `foreground`, and `selection`.

Read the [official spec](https://draculatheme.com/contribute) before
porting the theme to a new [application](https://draculatheme.com).

## Why people port it

- It looks good on every screen, day or night
- It is consistent across dozens of tools
- Editors: VS Code, Vim, Sublime Text
- Terminals: iTerm2, Alacritty, Windows Terminal
- Browsers, IDEs, and even Slack

1. Pick a base application to port
2. Follow the official color specification
3. Submit the port for review
1. Maintainers check contrast and accuracy
2. Once approved, it ships on draculatheme.com

## In the maintainers' words

> Dracula is not just a theme, it's a community. Every port follows the
> same spec so that switching tools never means switching colors.

## The official palette

```python
palette = {
"background": "#282A36",
"current_line": "#44475A",
"foreground": "#F8F8F2",
"comment": "#6272A4",
"cyan": "#8BE9FD",
"green": "#50FA7B",
"orange": "#FFB86C",
"pink": "#FF79C6",
"purple": "#BD93F9",
"red": "#FF5555",
"yellow": "#F1FA8C",
}
```

## Palette reference

| Name | Hex | Usage |
| ------------ | --------- | ----------------------- |
| Background | `#282A36` | Editor background |
| Current Line | `#44475A` | Selection / active line |
| Foreground | `#F8F8F2` | Default text |
| Comment | `#6272A4` | Comments, muted text |
| Purple | `#BD93F9` | Keywords |
| Pink | `#FF79C6` | Operators |
| Green | `#50FA7B` | Strings |

## Notes for contributors

!!! note
Every port must follow the [official spec](https://draculatheme.com/contribute) exactly — no custom colors.

!!! abstract
tl;dr: fork the [contributing guide repo](https://github.com/dracula/contributing-guide), copy the closest existing port, swap the palette.

!!! info
Dracula has 400+ official ports, from editors to hardware keyboards.

!!! tip
Test your port against real code with syntax highlighting before submitting — flat colors alone can hide contrast issues.

!!! success
Once merged, your port is listed on [draculatheme.com](https://draculatheme.com) and this `mkdocs` theme is one of them.

!!! question
Not sure which repo to fork? Check the [ports list](https://draculatheme.com) for a project similar to yours.

!!! warning
Don't rename the official color variables (`--purple`, `--cyan`, etc.) — themes and tooling depend on those names staying stable.

!!! failure
A port that changes background/foreground contrast ratios below WCAG AA will be rejected in review.

!!! danger
Never hardcode hex values in component CSS — always reference the palette variables, or the port breaks when the palette updates.

!!! bug
Found a color mismatch against the spec? Open an issue on the [ports repo](https://github.com/dracula).

!!! example
This very page is an example: it's built with `mkdocs-dracula-theme`, itself a Dracula port for MkDocs sites.

!!! quote
"The most famous theme ever created and available everywhere." — [draculatheme.com](https://draculatheme.com)

!!! warning "Before you open a PR"
Read `CONTRIBUTING.md` in the target repo — most ports have screenshot and structure requirements beyond just the colors.

## Footer

This page's footer is controlled by `theme.show_footer` in `mkdocs.yml`,
linking back to the [dracula/mkdocs](https://github.com/dracula/mkdocs)
repository unless disabled.
5 changes: 5 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ nav:
- nav/settings/show-footer.md
- Development:
- nav/development/development-guide.md
- nav/development/component-showcase.md
- nav/development/release-notes.md

markdown_extensions:
- admonition
- tables

theme:
name: dracula
logo: assets/img/dracula.png
Expand Down
2 changes: 1 addition & 1 deletion mkdocs_dracula_theme/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "1.0.9"
__version__ = "1.0.9-dev1"

__author__ = "Fernando Celmer <email@fernandocelmer.com>"
__copyright__ = """MIT License
Expand Down
3 changes: 2 additions & 1 deletion mkdocs_dracula_theme/assets/css/mkdocs.min.css

Large diffs are not rendered by default.

93 changes: 92 additions & 1 deletion template/assets/css/mkdocs.css
Original file line number Diff line number Diff line change
Expand Up @@ -476,4 +476,95 @@ img, svg {
.drac-input-search {
margin-top: 2px;
width: 170px;
}
}

/* =============================================================
Admonitions
============================================================= */

.admonition {
border-left: 4px solid var(--purple);
border-radius: 0.5rem;
background: var(--purple-transparent);
padding: 0.75rem 1rem;
margin: 1.25rem 0;
overflow: hidden;
}

.admonition p:last-child {
margin-bottom: 0;
}

.admonition-title {
font-weight: 700;
margin: -0.75rem -1rem 0.75rem -1rem;
padding: 0.5rem 1rem;
display: flex;
align-items: center;
}

.admonition-title::before {
font-family: FontAwesome;
margin-right: 0.5rem;
content: "\f040";
}

/* note */
.admonition.note { border-color: var(--purple); background: var(--purple-transparent); }
.admonition.note .admonition-title { background: rgba(149,128,255,.15); color: var(--purple); }
.admonition.note .admonition-title::before { content: "\f040"; }

/* abstract / summary / tldr */
.admonition.abstract,.admonition.summary,.admonition.tldr { border-color: var(--cyan); background: var(--cyan-transparent); }
.admonition.abstract .admonition-title,.admonition.summary .admonition-title,.admonition.tldr .admonition-title { background: rgba(128,255,234,.15); color: var(--cyan); }
.admonition.abstract .admonition-title::before,.admonition.summary .admonition-title::before,.admonition.tldr .admonition-title::before { content: "\f0ea"; }

/* info */
.admonition.info { border-color: var(--cyan); background: var(--cyan-transparent); }
.admonition.info .admonition-title { background: rgba(128,255,234,.15); color: var(--cyan); }
.admonition.info .admonition-title::before { content: "\f05a"; }

/* tip / hint / important */
.admonition.tip,.admonition.hint,.admonition.important { border-color: var(--green); background: var(--green-transparent); }
.admonition.tip .admonition-title,.admonition.hint .admonition-title,.admonition.important .admonition-title { background: rgba(138,255,128,.15); color: var(--green); }
.admonition.tip .admonition-title::before,.admonition.hint .admonition-title::before,.admonition.important .admonition-title::before { content: "\f0eb"; }

/* success / check / done */
.admonition.success,.admonition.check,.admonition.done { border-color: var(--green); background: var(--green-transparent); }
.admonition.success .admonition-title,.admonition.check .admonition-title,.admonition.done .admonition-title { background: rgba(138,255,128,.15); color: var(--green); }
.admonition.success .admonition-title::before,.admonition.check .admonition-title::before,.admonition.done .admonition-title::before { content: "\f058"; }

/* question / help / faq */
.admonition.question,.admonition.help,.admonition.faq { border-color: var(--yellow); background: var(--yellow-transparent); }
.admonition.question .admonition-title,.admonition.help .admonition-title,.admonition.faq .admonition-title { background: rgba(255,255,128,.15); color: var(--yellow); }
.admonition.question .admonition-title::before,.admonition.help .admonition-title::before,.admonition.faq .admonition-title::before { content: "\f059"; }

/* warning / caution / attention */
.admonition.warning,.admonition.caution,.admonition.attention { border-color: var(--orange); background: var(--orange-transparent); }
.admonition.warning .admonition-title,.admonition.caution .admonition-title,.admonition.attention .admonition-title { background: rgba(255,202,128,.15); color: var(--orange); }
.admonition.warning .admonition-title::before,.admonition.caution .admonition-title::before,.admonition.attention .admonition-title::before { content: "\f071"; }

/* failure / fail / missing */
.admonition.failure,.admonition.fail,.admonition.missing { border-color: var(--pink); background: var(--pink-transparent); }
.admonition.failure .admonition-title,.admonition.fail .admonition-title,.admonition.missing .admonition-title { background: rgba(255,128,191,.15); color: var(--pink); }
.admonition.failure .admonition-title::before,.admonition.fail .admonition-title::before,.admonition.missing .admonition-title::before { content: "\f057"; }

/* danger / error */
.admonition.danger,.admonition.error { border-color: var(--red); background: var(--red-transparent); }
.admonition.danger .admonition-title,.admonition.error .admonition-title { background: rgba(255,149,128,.15); color: var(--red); }
.admonition.danger .admonition-title::before,.admonition.error .admonition-title::before { content: "\f0e7"; }

/* bug */
.admonition.bug { border-color: var(--red); background: var(--red-transparent); }
.admonition.bug .admonition-title { background: rgba(255,149,128,.15); color: var(--red); }
.admonition.bug .admonition-title::before { content: "\f188"; }

/* example */
.admonition.example { border-color: var(--purple); background: var(--purple-transparent); }
.admonition.example .admonition-title { background: rgba(149,128,255,.15); color: var(--purple); }
.admonition.example .admonition-title::before { content: "\f03a"; }

/* quote / cite */
.admonition.quote,.admonition.cite { border-color: var(--grey); background: rgba(65,69,88,.2); }
.admonition.quote .admonition-title,.admonition.cite .admonition-title { background: rgba(65,69,88,.3); color: var(--white); }
.admonition.quote .admonition-title::before,.admonition.cite .admonition-title::before { content: "\f10d"; }
16 changes: 16 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@ def theme_dir():
return Path(mkdocs_dracula_theme.__file__).parent


@pytest.fixture(scope="session")
def css_source():
return (
Path(__file__).parent.parent
/ "template"
/ "assets"
/ "css"
/ "mkdocs.css"
)


@pytest.fixture(scope="session")
def css_min(theme_dir):
return theme_dir / "assets" / "css" / "mkdocs.min.css"


@pytest.fixture()
def docs_dir(tmp_path):
d = tmp_path / "docs"
Expand Down
62 changes: 62 additions & 0 deletions tests/test_admonition_colors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import re
import unittest

import pytest

EXPECTED_COLORS = {
"note": "--purple",
"example": "--purple",
"abstract": "--cyan",
"summary": "--cyan",
"tldr": "--cyan",
"info": "--cyan",
"tip": "--green",
"hint": "--green",
"important": "--green",
"success": "--green",
"check": "--green",
"done": "--green",
"question": "--yellow",
"help": "--yellow",
"faq": "--yellow",
"warning": "--orange",
"caution": "--orange",
"attention": "--orange",
"failure": "--pink",
"fail": "--pink",
"missing": "--pink",
"danger": "--red",
"error": "--red",
"bug": "--red",
"quote": "--grey",
"cite": "--grey",
}


class TestAdmonitionColors(unittest.TestCase):
@pytest.fixture(autouse=True)
def _inject_css(self, css_source):
self.css_source = css_source

def test_source_css_uses_dracula_variables(self):
"""Admonition styles must use CSS variables, not hardcoded hex values."""
content = self.css_source.read_text()
start = content.find(".admonition {")

self.assertNotEqual(start, -1, "Admonition base rule not found")

admonition_section = content[start:]

self.assertIsNone(
re.search(r":\s*#[0-9a-fA-F]{3,6}", admonition_section),
"Admonition styles must use CSS variables (var(--color)), not hardcoded hex values",
)

def test_expected_color_variables_present(self):
"""Each admonition type must reference its expected Dracula color variable."""
content = self.css_source.read_text()

for admonition_type, color_var in EXPECTED_COLORS.items():
pattern = rf"\.admonition\.{admonition_type}[^{{]*\{{[^}}]*{re.escape(color_var)}"
with self.subTest(admonition_type=admonition_type):
self.assertIsNotNone(re.search(pattern, content))
Loading
Loading