ply-css 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CLAUDE.md CHANGED
@@ -28,7 +28,7 @@ ply automatically styles semantic HTML elements — `<nav>`, `<table>`, `<code>`
28
28
  8. **Use semantic HTML first** — ply auto-styles `<code>`, `<pre>`, `<kbd>`, `<blockquote>`, `<mark>`, `<table>`, `<details>`, `<dialog>`, `<nav>`, etc. Use native elements before creating custom classes.
29
29
  9. **Only use documented ply classes** — Do NOT invent class names. Search `ply-classes.json` to find the right class. See PLY.md for the full prose reference.
30
30
  10. **Dark mode is automatic** — Auto dark mode activates only when no `data-theme` attribute is set on `<html>`. Use `data-theme="dark"` for explicit dark mode, `data-theme="light"` for explicit light mode, or any custom value (e.g., `data-theme="warm"`) for a custom theme without dark-mode interference. Use `var(--ply-*)` custom properties for colors (see `customProperties` in the JSON), never hard-code values that break dark mode.
31
- 11. **Icons** — Use [Feather Icons](https://feathericons.com) as the preferred icon library. Any icon library works, but Feather pairs well with ply's aesthetic.
31
+ 11. **Icons** — Use [Lucide](https://lucide.dev) as the preferred icon library. Any icon library works, but Lucide pairs well with ply's aesthetic. For icon + text buttons, place the icon before or after the label — the button's built-in `inline-flex` layout with `gap: 0.5em` handles alignment automatically. Use `btn-icon` only for icon-only buttons (no visible text).
32
32
  12. **Container queries** — Use `container-query` on a parent element and `container-tablet-unit-*`, `container-phone-unit-*`, etc. for component-level responsive behavior (responds to parent width, not viewport). See PLY.md for details.
33
33
 
34
34
  ## Custom Themes
@@ -50,6 +50,8 @@ Create a custom theme by defining a `data-theme` value and overriding `--ply-*`
50
50
  --ply-btn-default-bg-active: #7c2d12;
51
51
  --ply-btn-secondary-bg: #78350f;
52
52
  --ply-btn-border-radius: 0.5rem;
53
+ --ply-btn-font-size: 0.875rem; /* button text size */
54
+ --ply-btn-gap: 0.375rem; /* icon-to-text gap */
53
55
  --ply-nav-bg: #fef3c7;
54
56
  --ply-nav-border: #f59e0b;
55
57
 
package/PLY.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # PLY — AI-Ready CSS Framework
2
2
 
3
- ply is a ratio-based, flexbox CSS framework with dark mode, accessibility defaults, and a small footprint (~21KB gzip full, ~17KB core). 457 utility classes, 120+ CSS custom properties, 13 auto-styled semantic elements.
3
+ ply is a ratio-based, flexbox CSS framework with dark mode, accessibility defaults, and a small footprint (~21KB gzip full, ~17KB core). 458 utility classes, 120+ CSS custom properties, 13 auto-styled semantic elements.
4
4
 
5
5
  **Differentiators:** Small bundle, AI-parseable class system, accessible out of the box, dark mode built-in.
6
6
 
@@ -8,7 +8,7 @@ ply is a ratio-based, flexbox CSS framework with dark mode, accessibility defaul
8
8
 
9
9
  **`ply-classes.json`** is the complete searchable reference. Before writing any custom CSS, search it first:
10
10
 
11
- - **`classes`** — Every ply class (457) with category, description, and usage examples. Search here before inventing a class name or writing a custom style.
11
+ - **`classes`** — Every ply class (458) with category, description, and usage examples. Search here before inventing a class name or writing a custom style.
12
12
  - **`customProperties`** — All `--ply-*` CSS variables organized by category (background, text, borders, interactive, forms, code, tables, buttons, navigation, elevation, brand, palette, colorSurfaces, spacing). Each entry includes light and dark mode values. Use these instead of hardcoding colors.
13
13
  - **`semanticElements`** — Every HTML element ply auto-styles (`<dialog>`, `<details>`, `<table>`, `<code>`, `<kbd>`, `<mark>`, `<progress>`, `<meter>`, headings, form controls) with styling details and usage tips. Check here before building a custom component.
14
14
 
@@ -33,6 +33,8 @@ Create a custom theme by defining a `data-theme` value and overriding `--ply-*`
33
33
  --ply-btn-default-bg-active: #7c2d12;
34
34
  --ply-btn-secondary-bg: #78350f;
35
35
  --ply-btn-border-radius: 0.5rem;
36
+ --ply-btn-font-size: 0.875rem; /* button text size — default 1em inherits from context */
37
+ --ply-btn-gap: 0.375rem; /* icon-to-text gap — default 0.5em */
36
38
  --ply-nav-bg: #fef3c7;
37
39
  --ply-nav-border: #f59e0b;
38
40
 
@@ -144,15 +146,16 @@ Note: The CDN approach gives you ply's classes and dark mode, but you won't have
144
146
 
145
147
  ## Icons
146
148
 
147
- ply does not include icons. [Feather Icons](https://feathericons.com) is the recommended icon library — it's lightweight, clean, and pairs well with ply's aesthetic. Any icon library works.
149
+ ply does not include icons. [Lucide](https://lucide.dev) is the recommended icon library — it's lightweight, clean, and pairs well with ply's aesthetic. Any icon library works.
148
150
 
149
151
  ```html
150
- <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
151
- <script>feather.replace();</script>
152
+ <!-- CDN -->
153
+ <script src="https://cdn.jsdelivr.net/npm/lucide@latest/dist/umd/lucide.min.js"></script>
154
+ <script>lucide.createIcons();</script>
152
155
 
153
156
  <!-- Usage -->
154
- <i data-feather="check"></i> Saved
155
- <button class="btn btn-blue"><i data-feather="send"></i> Send</button>
157
+ <i data-lucide="check"></i> Saved
158
+ <button class="btn btn-primary"><i data-lucide="send"></i> Send</button>
156
159
  ```
157
160
 
158
161
  ## Dark Mode
@@ -246,7 +249,61 @@ All classes, CSS custom properties, and semantic element styles are documented i
246
249
 
247
250
  - **`btn-icon`** — Icon-only button modifier. Equal padding for a square aspect ratio. Always add `aria-label` (no visible text).
248
251
  - Combine with `btn-ghost` for toolbar-style icon buttons. Combine with size modifiers (`btn-sm`, `btn-xs`) for smaller icons.
249
- - For icon + text buttons, use a regular `btn` with an inline SVG no `btn-icon` needed.
252
+ - **Icon + text buttons** Place the icon before or after the label text inside a regular `btn`. The button automatically uses `inline-flex` with `align-items: center` and `gap: 0.5em`, so icon and text are vertically centered with consistent spacing. No extra classes needed.
253
+
254
+ ```html
255
+ <!-- Icon left -->
256
+ <button class="btn btn-primary">
257
+ <i data-lucide="save"></i> Save
258
+ </button>
259
+
260
+ <!-- Icon right -->
261
+ <button class="btn btn-secondary">
262
+ Next <i data-lucide="arrow-right"></i>
263
+ </button>
264
+
265
+ <!-- Icon-only (always include aria-label) -->
266
+ <button class="btn btn-ghost btn-icon" aria-label="Delete">
267
+ <i data-lucide="trash-2"></i>
268
+ </button>
269
+
270
+ <!-- Size variants work the same way -->
271
+ <button class="btn btn-primary btn-sm">
272
+ <i data-lucide="download"></i> Export
273
+ </button>
274
+ ```
275
+
276
+ ### Button Groups
277
+
278
+ Wrap buttons in `.btn-group` for a flex row with consistent gap and connected border-radius on the outer edges.
279
+
280
+ - **`btn-group`** — Default: buttons with `0.5rem` gap between them.
281
+ - **`btn-group joined`** — No gap; buttons connect as a single unit with a 1px divider between them. Use for segmented controls, toolbars, and pagination-style groups.
282
+ - **`align-right`** / **`align-left`** / **`align-center`** — Justify the group within its container.
283
+ - **`fill-width`** — Stretch all buttons to share equal width.
284
+ - **`rounded`** — Larger border-radius on the outer edges.
285
+
286
+ ```html
287
+ <!-- Default: gapped -->
288
+ <div class="btn-group">
289
+ <button class="btn btn-primary">Save</button>
290
+ <button class="btn">Cancel</button>
291
+ </div>
292
+
293
+ <!-- Joined: connected, no gap -->
294
+ <div class="btn-group joined">
295
+ <button class="btn">Week</button>
296
+ <button class="btn btn-primary">Month</button>
297
+ <button class="btn">Year</button>
298
+ </div>
299
+
300
+ <!-- Joined icon toolbar -->
301
+ <div class="btn-group joined">
302
+ <button class="btn btn-ghost btn-icon" aria-label="Bold"><i data-lucide="bold"></i></button>
303
+ <button class="btn btn-ghost btn-icon" aria-label="Italic"><i data-lucide="italic"></i></button>
304
+ <button class="btn btn-ghost btn-icon" aria-label="Underline"><i data-lucide="underline"></i></button>
305
+ </div>
306
+ ```
250
307
 
251
308
  ## Common Patterns
252
309
 
package/README.md CHANGED
@@ -114,11 +114,11 @@ See `snippets/custom-theme.html` for a full working example.
114
114
 
115
115
  ## Icons
116
116
 
117
- ply doesn't include icons. [Feather Icons](https://feathericons.com) is recommended — lightweight, clean, and pairs well with ply. Any icon library works.
117
+ ply doesn't include icons. [Lucide](https://lucide.dev) is recommended — lightweight, clean, and pairs well with ply. Any icon library works.
118
118
 
119
119
  ```html
120
- <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
121
- <script>feather.replace();</script>
120
+ <script src="https://cdn.jsdelivr.net/npm/lucide@latest/dist/umd/lucide.min.js"></script>
121
+ <script>lucide.createIcons();</script>
122
122
  ```
123
123
 
124
124
  ## AI Integration
@@ -151,7 +151,7 @@ ply targets ADA Title II (28 CFR Part 35) / WCAG 2.1 AA compliance at the framew
151
151
 
152
152
  ## Documentation
153
153
 
154
- Full interactive docs at [plyCSS.com](https://plycss.com) — browse every class with live examples, search the entire framework, and copy-paste code snippets.
154
+ Full interactive docs at [plycss.com](https://plycss.com) — browse every class with live examples, search the entire framework, and copy-paste code snippets.
155
155
 
156
156
  ## Roadmap
157
157
 
@@ -145,9 +145,9 @@
145
145
  --ply-color-text-inverse: #161616;
146
146
  --ply-border-color: #393939;
147
147
  --ply-border-strong: #6f6f6f;
148
- --ply-color-link: var(--ply-btn-default-bg);
148
+ --ply-color-link: #4589ff;
149
149
  --ply-color-link-hover: #619bff;
150
- --ply-color-link-hover: color-mix(in oklch, var(--ply-btn-default-bg), white 15%);
150
+ --ply-color-link-hover: color-mix(in oklch, #4589ff, white 15%);
151
151
  --ply-color-focus: #0f62fe;
152
152
  --ply-color-field-bg: #262626;
153
153
  --ply-color-input-border: #6f6f6f;
@@ -261,9 +261,9 @@
261
261
  --ply-color-text-inverse: #161616;
262
262
  --ply-border-color: #393939;
263
263
  --ply-border-strong: #6f6f6f;
264
- --ply-color-link: var(--ply-btn-default-bg);
264
+ --ply-color-link: #4589ff;
265
265
  --ply-color-link-hover: #619bff;
266
- --ply-color-link-hover: color-mix(in oklch, var(--ply-btn-default-bg), white 15%);
266
+ --ply-color-link-hover: color-mix(in oklch, #4589ff, white 15%);
267
267
  --ply-color-focus: #0f62fe;
268
268
  --ply-color-field-bg: #262626;
269
269
  --ply-color-input-border: #6f6f6f;
@@ -1913,7 +1913,7 @@ table tfoot td {
1913
1913
  .units-row.reverse-direction, .units-row.right-to-left {
1914
1914
  flex-direction: row-reverse;
1915
1915
  }
1916
- .units-row.split {
1916
+ .units-row.joined, .units-row.split {
1917
1917
  --units-gap: 0px;
1918
1918
  gap: 0;
1919
1919
  }
@@ -4449,13 +4449,15 @@ input[type=button].btn,
4449
4449
  input[type=reset].btn,
4450
4450
  button.btn {
4451
4451
  transition: all 150ms ease-in-out, transform 50ms ease, background 150ms ease-in-out;
4452
- display: inline-block;
4452
+ display: inline-flex;
4453
4453
  vertical-align: top;
4454
+ align-items: center;
4455
+ justify-content: center;
4456
+ gap: var(--ply-btn-gap, 0.5em);
4454
4457
  font-family: var(--ply-font-body, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji);
4455
- font-size: 1em;
4458
+ font-size: var(--ply-btn-font-size, 1em);
4456
4459
  font-weight: 400;
4457
4460
  line-height: 1.5rem;
4458
- text-align: center;
4459
4461
  text-decoration: none;
4460
4462
  color: var(--ply-btn-secondary-color, var(--ply-color-text-inverse, #fff));
4461
4463
  -webkit-appearance: none;
@@ -5402,6 +5404,10 @@ button.btn-white.btn-outline.btn-active {
5402
5404
  .btn-group .btn:last-child {
5403
5405
  border-radius: 0 0.125rem 0.125rem 0;
5404
5406
  }
5407
+ .btn-single.joined,
5408
+ .btn-group.joined {
5409
+ gap: 0;
5410
+ }
5405
5411
  .btn-single.rounded .btn:first-child,
5406
5412
  .btn-single.rounded .input-search:first-child,
5407
5413
  .btn-group.rounded .btn:first-child,