diff --git a/README.md b/README.md
index c33ea6f..7ee02b5 100644
--- a/README.md
+++ b/README.md
@@ -32,33 +32,54 @@
```sh
volt/
-├── package.json
-├── tsconfig.json
-├── vite.config.ts
-├── README.md
-├── src/
-│ ├── index.ts # entry point
-│ ├── core/
-│ │ ├── signal.ts # reactive primitives
-│ │ ├── dom.ts # DOM helpers
-│ │ ├── patch.ts # JSON patch engine
-│ │ ├── stream.ts # SSE / WebSocket layer
-│ │ ├── plugin.ts # plugin registration API
-│ │ └── binder.ts # mounts and binds data-volt-* attributes
-│ └── plugins/
-│ ├── persist.ts
-│ ├── scroll.ts
-│ ├── animate.ts
-│ └── url.ts
-└── test/
- ├── setupTests.ts
- ├── core/
- │ ├── signal.test.ts
- │ ├── dom.test.ts
- │ └── patch.test.ts
- └── integration/
- ├── mount.test.ts
- └── plugin.persist.test.ts
+├── dev/
+├── docs/
+├── examples/
+├── lib
+│ ├── index.html
+│ ├── public
+│ ├── src
+│ │ ├── core
+│ │ │ ├── asyncEffect.ts
+│ │ │ ├── binder.ts
+│ │ │ ├── charge.ts
+│ │ │ ├── dom.ts
+│ │ │ ├── evaluator.ts
+│ │ │ ├── http.ts
+│ │ │ ├── lifecycle.ts
+│ │ │ ├── plugin.ts
+│ │ │ ├── reactive.ts
+│ │ │ ├── shared.ts
+│ │ │ ├── signal.ts
+│ │ │ ├── ssr.ts
+│ │ │ └── tracker.ts
+│ │ ├── debug
+│ │ │ ├── graph.ts
+│ │ │ ├── logger.ts
+│ │ │ └── registry.ts
+│ │ ├── debug.ts
+│ │ ├── demo/
+│ │ ├── index.ts
+│ │ ├── main.ts
+│ │ ├── plugins
+│ │ │ ├── persist.ts
+│ │ │ ├── scroll.ts
+│ │ │ └── url.ts
+│ │ ├── styles
+│ │ │ ├── index.css
+│ │ │ ├── variables.css
+│ │ │ ├── typography.css
+│ │ │ ├── forms.css
+│ │ │ ├── components.css
+│ │ │ ├── collections.css
+│ │ │ ├── media.css
+│ │ │ └── base.css
+│ │ └── types
+│ │ ├── helpers.ts
+│ │ └── volt.d.ts
+│ └── test/
+└── README.md
+
```
## License
diff --git a/docs/css/volt-css.md b/docs/css/volt-css.md
index b974340..a8c41c6 100644
--- a/docs/css/volt-css.md
+++ b/docs/css/volt-css.md
@@ -92,7 +92,7 @@ Include the stylesheet in your HTML `
`:
-
+
My Document
@@ -101,6 +101,12 @@ Include the stylesheet in your HTML ``:
```
+Or import in JavaScript/TypeScript:
+
+```js
+import 'volt/styles';
+```
+
### Example Document Structure
```html
@@ -180,9 +186,14 @@ Forms get styling with focus states, required field indicators, and spacing betw
### CSS Custom Properties
-All design tokens are defined as CSS custom properties (CSS variables) in the `:root` selector. Override them to customize the appearance:
+All design tokens are defined as CSS custom properties (CSS variables) in `variables.css`.
+Override them in your own stylesheet to customize the appearance:
```css
+/* Load Volt CSS first */
+@import 'volt.css';
+
+/* Then override variables */
:root {
/* Change the accent color */
--color-accent: #d63384;
@@ -199,7 +210,9 @@ All design tokens are defined as CSS custom properties (CSS variables) in the `:
}
```
-### Properties
+See `variables.css` for the complete list of available tokens.
+
+### Available Properties
**Typography**:
diff --git a/lib/package.json b/lib/package.json
index 6087856..f1c991b 100644
--- a/lib/package.json
+++ b/lib/package.json
@@ -5,8 +5,10 @@
"type": "module",
"scripts": {
"dev": "vite",
- "build": "tsc && vite build",
+ "build": "pnpm build:lib && pnpm build:css",
"build:lib": "tsc && vite build --mode lib",
+ "build:css": "postcss src/styles/index.css -o dist/volt.css",
+ "build:css:min": "postcss src/styles/index.css -o dist/volt.min.css --env production",
"preview": "vite preview",
"test": "vitest",
"test:run": "vitest run",
@@ -16,8 +18,12 @@
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@vitest/coverage-v8": "3.2.4",
+ "cssnano": "^7.1.1",
"dprint": "^0.50.2",
"jsdom": "^27.0.0",
+ "postcss": "^8.5.6",
+ "postcss-cli": "^11.0.1",
+ "postcss-import": "^16.1.1",
"vite": "npm:rolldown-vite@7.1.14"
}
}
diff --git a/lib/postcss.config.js b/lib/postcss.config.js
new file mode 100644
index 0000000..01604b9
--- /dev/null
+++ b/lib/postcss.config.js
@@ -0,0 +1 @@
+export default { plugins: { "postcss-import": {}, "cssnano": {} } };
diff --git a/lib/src/styles/base.css b/lib/src/styles/base.css
index 5c692ba..ac9bc26 100644
--- a/lib/src/styles/base.css
+++ b/lib/src/styles/base.css
@@ -1,123 +1,6 @@
-/*
- 8b d8 88
- `8b d8' 88 ,d
- `8b d8' 88 88
- `8b d8' ,adPPYba, 88 MM88MMM ,adPPYba, ,adPPYba, ,adPPYba,
- `8b d8' a8" "8a 88 88 a8" "" I8[ "" I8[ ""
- `8b d8' 8b d8 88 88 8b `"Y8ba, `"Y8ba,
- `888' "8a, ,a8" 88 88, 888 "8a, ,aa aa ]8I aa ]8I
- `8' `"YbbdP"' 88 "Y888 888 `"Ybbd8"' `"YbbdP"' `"YbbdP"'
-*/
-
-/**
- * Volt CSS - Classless stylesheet for elegant, readable web documents
- *
- * Design Philosophy:
- * - Classless: Style semantic HTML5 elements directly
- * - Dual theme: Automatic light/dark mode via prefers-color-scheme
- * - Typography-first: Optimized for reading and information density
- * - Accessible: WCAG AA contrast ratios, keyboard navigation support
- * - Responsive: Mobile-first, adapts gracefully to all screen sizes
- *
- * Inspired by: magick.css, latex-css, sakura, matcha, mvp.css
- */
-
-@import url('https://fonts.googleapis.com/css2?family=Google+Sans+Code:ital,wght@0,300..800;1,300..800&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Libre+Baskerville:ital,wght@0,400;0,700;1,400&display=swap');
-
-/**
- * Root-level CSS variables define the design system.
- *
- * Light theme is default, dark theme overrides via media query.
- */
-:root {
- /* Typography Scale - Modular scale based on 1.25 ratio */
- --font-size-base: 18px;
- --font-size-sm: 0.889rem;
- --font-size-lg: 1.125rem;
- --font-size-xl: 1.266rem;
- --font-size-2xl: 1.424rem;
- --font-size-3xl: 1.802rem;
- --font-size-4xl: 2.027rem;
- --font-size-5xl: 2.566rem;
-
- --font-sans: "Inter", sans-serif;
- --font-serif: "Libre Baskerville", serif;
- --font-mono: "Google Sans Code", monospace;
-
- /* Spacing Scale - Based on 0.5rem increments */
- --space-xs: 0.25rem;
- --space-sm: 0.5rem;
- --space-md: 1rem;
- --space-lg: 1.5rem;
- --space-xl: 2rem;
- --space-2xl: 3rem;
- --space-3xl: 4rem;
-
- --line-height-tight: 1.25;
- --line-height-base: 1.6;
- --line-height-relaxed: 1.8;
-
- --content-width: 79ch;
- /* Width of margin notes */
- --sidenote-width: 18rem;
- /* Space between content and sidenotes */
- --sidenote-gap: 2rem;
-
- --color-bg: #fefefe;
- /* For code blocks, tables */
- --color-bg-alt: #f5f5f5;
- --color-text: #1a1a1a;
- --color-text-muted: #666666;
- /* Links, primary actions */
- --color-accent: #0066cc;
- --color-accent-hover: #0052a3;
- --color-border: #d4d4d4;
- --color-code-bg: #f8f8f8;
- /* Highlighted text */
- --color-mark: #fff3cd;
- --color-success: #22863a;
- --color-warning: #bf8700;
- --color-error: #cb2431;
-
- --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
- --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
- --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
-
- /* Border Radius */
- --radius-xs: 1px;
- --radius-sm: 3px;
- --radius-md: 6px;
- --radius-lg: 8px;
-
- --transition-fast: 150ms ease-in-out;
- --transition-base: 250ms ease-in-out;
-}
-
-/**
- * Dark Theme Overrides
- *
- * Automatically applied when user prefers dark color scheme
- */
-@media (prefers-color-scheme: dark) {
- :root {
- --color-bg: #1a1a1a;
- --color-bg-alt: #2a2a2a;
- --color-text: #e6e6e6;
- --color-text-muted: #a0a0a0;
- --color-accent: #4da6ff;
- --color-accent-hover: #66b3ff;
- --color-border: #404040;
- --color-code-bg: #2a2a2a;
- --color-mark: #4a4a00;
- --color-success: #34d058;
- --color-warning: #ffdf5d;
- --color-error: #f97583;
-
- --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
- --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
- --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.5);
- }
-}
+/* ========================================================================== */
+/* Base Rules & Reset */
+/* ========================================================================== */
*, *::before, *::after {
box-sizing: border-box;
@@ -157,182 +40,6 @@ body {
padding: var(--space-2xl) var(--space-lg);
}
-/**
- * Headings hierarchy
- * - Uses modular scale for harmonious sizing
- * - Tighter line-height for larger text improves readability
- */
-h1, h2, h3, h4, h5, h6 {
- font-weight: 700;
- line-height: var(--line-height-tight);
- color: var(--color-text);
- margin-top: var(--space-2xl);
- margin-bottom: var(--space-md);
- letter-spacing: -0.02em;
-}
-
-h1 {
- font-size: var(--font-size-5xl);
- margin-top: 0;
-}
-
-h2 {
- font-size: var(--font-size-4xl);
-}
-
-h3 {
- font-size: var(--font-size-3xl);
-}
-
-h4 {
- font-size: var(--font-size-2xl);
-}
-
-h5 {
- font-size: var(--font-size-xl);
-}
-
-h6 {
- font-size: var(--font-size-lg);
- color: var(--color-text-muted);
- text-transform: uppercase;
- letter-spacing: 0.05em;
-}
-
-/**
- * Paragraph spacing
- *
- * Generous spacing between paragraphs aids scanning
- */
-p {
- margin-bottom: var(--space-lg);
- max-width: var(--content-width);
-}
-
-/**
- * First paragraph after headings - No top margin
- *
- * Inspired by tufte.css
- */
-h1 + p, h2 + p, h3 + p, h4 + p, h5 + p, h6 + p {
- margin-top: 0;
-}
-
-/**
- * Links
- *
- * Uses accent color with underline for clarity
- */
-a {
- color: var(--color-accent);
- text-decoration: underline;
- text-decoration-thickness: 1px;
- text-underline-offset: 2px;
- transition: color var(--transition-fast);
-}
-
-a:hover {
- color: var(--color-accent-hover);
-}
-
-a:focus-visible {
- outline: 2px solid var(--color-accent);
- outline-offset: 2px;
- border-radius: var(--radius-sm);
-}
-
-em {
- font-style: italic;
-}
-
-strong {
- font-weight: 700;
-}
-
-mark {
- background-color: var(--color-mark);
- padding: 0.1em 0.2em;
- border-radius: var(--radius-sm);
-}
-
-/**
- * Subscript and superscript
- *
- * Prevents them from affecting line height
- */
-sub, sup {
- font-size: 0.75em;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-
-sup {
- top: -0.5em;
-}
-
-sub {
- bottom: -0.25em;
-}
-
-/**
- * Small text
- * Also used for Tufte-style sidenotes (see sidenotes section)
- */
-small {
- font-size: var(--font-size-sm);
- color: var(--color-text-muted);
-}
-
-/**
- * List spacing and indentation
- *
- * Nested lists inherit spacing
- */
-ul, ol {
- margin-bottom: var(--space-lg);
- padding-left: var(--space-xl);
- max-width: var(--content-width);
-}
-
-/**
- * List items
- */
-li {
- margin-bottom: var(--space-sm);
-}
-
-li::marker {
- color: var(--color-accent);
-}
-
-/**
- * Nested lists - Reduced spacing
- */
-li > ul, li > ol {
- margin-top: var(--space-sm);
- margin-bottom: var(--space-sm);
-}
-
-/**
- * Description lists - For key-value pairs
- */
-dl {
- margin-bottom: var(--space-lg);
- max-width: var(--content-width);
-}
-
-dt {
- font-weight: 700;
- margin-top: var(--space-md);
- margin-bottom: var(--space-xs);
-}
-
-dd {
- margin-left: var(--space-xl);
- margin-bottom: var(--space-sm);
- color: var(--color-text-muted);
-}
/**
* Sidenotes using elements
@@ -384,347 +91,6 @@ dd {
}
}
-/**
- * Blockquote styling
- * Left border for visual distinction, italic for emphasis
- */
-blockquote {
- margin: var(--space-xl) 0;
- padding: var(--space-md) var(--space-lg);
- border-left: 4px solid var(--color-accent);
- background-color: var(--color-bg-alt);
- font-style: italic;
- color: var(--color-text-muted);
- max-width: var(--content-width);
- border-radius: var(--radius-sm);
-}
-
-blockquote p:last-child {
- margin-bottom: 0;
-}
-
-/**
- * Citation element
- */
-cite {
- font-style: normal;
- font-size: var(--font-size-sm);
- color: var(--color-text-muted);
-}
-
-blockquote cite::before {
- /* em dash */
- content: "— ";
-}
-
-/**
- * Inline code
- *
- * Monospace font with subtle background
- */
-code {
- font-family: var(--font-mono);
- font-size: 0.9em;
- padding: 0.15em 0.4em;
- color: var(--color-text);
- background-color: var(--color-code-bg);
- border: 1px solid var(--color-border);
- border-radius: var(--radius-sm);
-}
-
-/**
- * Keyboard input
- *
- * Styled like keys on a keyboard
- */
-kbd {
- font-family: var(--font-mono);
- font-size: 0.9em;
- padding: 0.15em 0.4em;
- background-color: var(--color-bg-alt);
- border: 1px solid var(--color-border);
- border-radius: var(--radius-sm);
- box-shadow: 0 1px 0 var(--color-border), 0 0 0 2px var(--color-bg) inset;
-}
-
-samp {
- font-family: var(--font-mono);
- font-size: 0.9em;
-}
-
-var {
- font-family: var(--font-mono);
- font-style: normal;
- font-weight: 600;
-}
-
-/**
- * Preformatted code blocks
- *
- * Horizontal scrolling for overflow, no word wrap
- */
-pre {
- margin: var(--space-xl) 0;
- padding: var(--space-lg);
- color: var(--color-text);
- background-color: var(--color-code-bg);
- border: 1px solid var(--color-border);
- border-radius: var(--radius-md);
- overflow-x: auto;
- max-width: var(--content-width);
- line-height: var(--line-height-base);
-}
-
-pre code {
- padding: 0;
- color: inherit;
- background: none;
- border: none;
- font-size: 0.875rem;
-}
-
-
-hr {
- margin: var(--space-3xl) auto;
- border: none;
- border-top: 1px solid var(--color-border);
- max-width: 50%;
-}
-
-table {
- width: 100%;
- max-width: var(--content-width);
- margin: var(--space-xl) 0;
- border-collapse: collapse;
- overflow-x: auto;
- display: block;
-}
-
-thead {
- background-color: var(--color-bg-alt);
- border-bottom: 2px solid var(--color-border);
-}
-
-th {
- padding: var(--space-sm) var(--space-md);
- text-align: left;
- font-weight: 700;
- color: var(--color-text);
-}
-
-td {
- padding: var(--space-sm) var(--space-md);
- border-bottom: 1px solid var(--color-border);
-}
-
-tbody tr:nth-child(even) {
- background-color: var(--color-bg-alt);
-}
-
-tbody tr:hover {
- background-color: var(--color-border);
- transition: background-color var(--transition-fast);
-}
-
-form {
- margin: var(--space-xl) 0;
- max-width: var(--content-width);
-}
-
-fieldset {
- border: 1px solid var(--color-border);
- border-radius: var(--radius-md);
- padding: var(--space-lg);
- margin-bottom: var(--space-lg);
-}
-
-legend {
- font-weight: 700;
- padding: 0 var(--space-sm);
- color: var(--color-text);
-}
-
-label {
- display: block;
- margin-bottom: var(--space-xs);
- font-weight: 600;
- color: var(--color-text);
-}
-
-label:has(+ input[required])::after,
-label:has(+ textarea[required])::after,
-label:has(+ select[required])::after {
- content: " *";
- color: var(--color-error);
-}
-
-input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]),
-select,
-textarea {
- width: 100%;
- padding: var(--space-sm) var(--space-md);
- font-family: inherit;
- font-size: 1rem;
- line-height: var(--line-height-base);
- color: var(--color-text);
- background-color: var(--color-bg);
- border: 1px solid var(--color-border);
- border-radius: var(--radius-sm);
- transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
- margin-bottom: var(--space-md);
-}
-
-input:focus,
-select:focus,
-textarea:focus {
- outline: none;
- border-color: var(--color-accent);
- box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);
-}
-
-input:disabled,
-select:disabled,
-textarea:disabled {
- opacity: 0.6;
- cursor: not-allowed;
- background-color: var(--color-bg-alt);
-}
-
-textarea {
- resize: vertical;
- min-height: 8rem;
-}
-
-input[type="checkbox"],
-input[type="radio"] {
- margin-right: var(--space-xs);
- accent-color: var(--color-accent);
-}
-
-input[type="file"] {
- padding: var(--space-sm);
- border: 1px dashed var(--color-border);
- border-radius: var(--radius-sm);
- cursor: pointer;
- margin-bottom: var(--space-md);
-}
-
-input[type="range"] {
- width: 100%;
- margin: var(--space-md) 0;
- accent-color: var(--color-accent);
-}
-
-progress, meter {
- width: 100%;
- height: 1.5rem;
- margin: var(--space-md) 0;
- border-radius: var(--radius-sm);
- overflow: hidden;
-}
-
-button,
-input[type="submit"],
-input[type="button"],
-input[type="reset"] {
- display: inline-block;
- padding: var(--space-sm) var(--space-lg);
- font-family: inherit;
- font-size: 1rem;
- font-weight: 600;
- line-height: 1;
- color: white;
- background-color: var(--color-accent);
- border: none;
- border-radius: var(--radius-md);
- cursor: pointer;
- text-decoration: none;
- transition: background-color var(--transition-fast), transform var(--transition-fast);
- margin-right: var(--space-sm);
- margin-bottom: var(--space-sm);
-}
-
-button:hover,
-input[type="submit"]:hover,
-input[type="button"]:hover {
- background-color: var(--color-accent-hover);
-}
-
-button:active,
-input[type="submit"]:active,
-input[type="button"]:active {
- transform: translateY(1px);
-}
-
-input[type="reset"] {
- background-color: var(--color-bg-alt);
- color: var(--color-text);
- border: 1px solid var(--color-border);
-}
-
-input[type="reset"]:hover {
- background-color: var(--color-border);
-}
-
-button:disabled,
-input[type="submit"]:disabled,
-input[type="button"]:disabled {
- opacity: 0.6;
- cursor: not-allowed;
- transform: none;
-}
-
-button:focus-visible,
-input[type="submit"]:focus-visible,
-input[type="button"]:focus-visible {
- outline: 2px solid var(--color-accent);
- outline-offset: 2px;
-}
-
-/**
- * Images are responsive by default, maintains aspect ratio
- */
-img {
- max-width: 100%;
- height: auto;
- display: block;
- border-radius: var(--radius-sm);
-}
-
-/**
- * Figures with captions
- * Common in academic and technical writing
- */
-figure {
- margin: var(--space-xl) 0;
- max-width: var(--content-width);
-}
-
-figcaption {
- margin-top: var(--space-sm);
- font-size: var(--font-size-sm);
- color: var(--color-text-muted);
- font-style: italic;
- text-align: center;
-}
-
-video, audio {
- max-width: 100%;
- margin: var(--space-xl) 0;
-}
-
-canvas, svg {
- max-width: 100%;
- height: auto;
-}
-
-iframe {
- max-width: 100%;
- border: 1px solid var(--color-border);
- border-radius: var(--radius-md);
- margin: var(--space-xl) 0;
-}
-
article, section {
margin-bottom: var(--space-3xl);
}
@@ -768,37 +134,6 @@ nav li {
margin: 0;
}
-/**
- * Details and Summary
- *
- * Disclosure widget for expandable content
- */
-details {
- margin: var(--space-lg) 0;
- padding: var(--space-md);
- border: 1px solid var(--color-border);
- border-radius: var(--radius-md);
- max-width: var(--content-width);
-}
-
-summary {
- font-weight: 700;
- cursor: pointer;
- user-select: none;
- padding: var(--space-sm);
- margin: calc(-1 * var(--space-sm));
- transition: background-color var(--transition-fast);
-}
-
-summary:hover {
- background-color: var(--color-bg-alt);
-}
-
-details[open] summary {
- margin-bottom: var(--space-md);
- border-bottom: 1px solid var(--color-border);
-}
-
/**
* Screen reader only
*
@@ -903,3 +238,4 @@ details[open] summary {
font-size: var(--font-size-sm);
}
}
+
diff --git a/lib/src/styles/collections.css b/lib/src/styles/collections.css
new file mode 100644
index 0000000..b183a68
--- /dev/null
+++ b/lib/src/styles/collections.css
@@ -0,0 +1,85 @@
+/**
+ * List spacing and indentation
+ *
+ * Nested lists inherit spacing
+ */
+ul, ol {
+ margin-bottom: var(--space-lg);
+ padding-left: var(--space-xl);
+ max-width: var(--content-width);
+}
+
+/**
+ * List items
+ */
+li {
+ margin-bottom: var(--space-sm);
+}
+
+li::marker {
+ color: var(--color-accent);
+}
+
+/**
+ * Nested lists - Reduced spacing
+ */
+li > ul, li > ol {
+ margin-top: var(--space-sm);
+ margin-bottom: var(--space-sm);
+}
+
+/**
+ * Description lists - For key-value pairs
+ */
+dl {
+ margin-bottom: var(--space-lg);
+ max-width: var(--content-width);
+}
+
+dt {
+ font-weight: 700;
+ margin-top: var(--space-md);
+ margin-bottom: var(--space-xs);
+}
+
+dd {
+ margin-left: var(--space-xl);
+ margin-bottom: var(--space-sm);
+ color: var(--color-text-muted);
+}
+
+
+table {
+ width: 100%;
+ max-width: var(--content-width);
+ margin: var(--space-xl) 0;
+ border-collapse: collapse;
+ overflow-x: auto;
+ display: block;
+}
+
+thead {
+ background-color: var(--color-bg-alt);
+ border-bottom: 2px solid var(--color-border);
+}
+
+th {
+ padding: var(--space-sm) var(--space-md);
+ text-align: left;
+ font-weight: 700;
+ color: var(--color-text);
+}
+
+td {
+ padding: var(--space-sm) var(--space-md);
+ border-bottom: 1px solid var(--color-border);
+}
+
+tbody tr:nth-child(even) {
+ background-color: var(--color-bg-alt);
+}
+
+tbody tr:hover {
+ background-color: var(--color-border);
+ transition: background-color var(--transition-fast);
+}
diff --git a/lib/src/styles/components.css b/lib/src/styles/components.css
new file mode 100644
index 0000000..5007855
--- /dev/null
+++ b/lib/src/styles/components.css
@@ -0,0 +1,158 @@
+/* ========================================================================== */
+/* Components */
+/* ========================================================================== */
+
+/**
+ * Dialog (Modal)
+ *
+ * Native