diff --git a/CHANGELOG.md b/CHANGELOG.md index a366f42..4ab1dc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,27 @@ All notable changes to this project are documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## [2.1.0] - 2026-07-13 + +### Added + +- The `JayButton Classic` and `JayButton Studio` names for the two maintained designs. +- Descriptive `.jay-button-classic`, `.jay-button-studio`, and `.jay-button-studio__cap` class names. + +### Changed + +- The live demo and documentation now present Classic and Studio together. +- The project preview now shows both distinct button designs. + +### Fixed + +- Restored the original glossy brown face, copper highlight, deep edge, ground shadow, and press depth for `.JayBrown`. +- Removed unrelated page-wide rules from the original stylesheet while preserving the button itself. + +### Compatibility + +- `.JayBrown`, `.jay-button`, and `.jay-button__cap` remain supported without markup changes. + ## [2.0.0] - 2026-07-12 ### Added @@ -30,3 +51,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - The original `.JayBrown` single-element class remains available for existing markup. [2.0.0]: https://github.com/JaydenART/JaydenART_Realistic_3D_CSS_Button/releases/tag/v2.0.0 +[2.1.0]: https://github.com/JaydenART/JaydenART_Realistic_3D_CSS_Button/compare/v2.0.0...v2.1.0 diff --git a/JayButton.css b/JayButton.css index 176a0ad..7ab3c9f 100644 --- a/JayButton.css +++ b/JayButton.css @@ -1,6 +1,7 @@ -/* JaydenART Realistic 3D CSS Button v2.0.0 */ +/* JaydenART Realistic 3D CSS Button v2.1.0 */ -.jay-button { +.jay-button, +.jay-button-studio { --jay-cap: #abcf37; --jay-cap-hover: #b9dc49; --jay-edge: #718a23; @@ -25,7 +26,8 @@ appearance: none; } -.jay-button::before { +.jay-button::before, +.jay-button-studio::before { content: ""; position: absolute; z-index: -1; @@ -35,7 +37,8 @@ box-shadow: inset 0 -1px 0 rgb(0 0 0 / 0.32); } -.jay-button::after { +.jay-button::after, +.jay-button-studio::after { content: ""; position: absolute; z-index: -2; @@ -46,7 +49,8 @@ filter: blur(7px); } -.jay-button__cap { +.jay-button__cap, +.jay-button-studio__cap { position: relative; display: block; padding: 1rem 1.55rem; @@ -62,7 +66,8 @@ } @media (hover: hover) and (pointer: fine) { - .jay-button:hover .jay-button__cap { + .jay-button:hover .jay-button__cap, + .jay-button-studio:hover .jay-button-studio__cap { background: var(--jay-cap-hover); transform: translateY(-1px); box-shadow: @@ -72,105 +77,133 @@ } } -.jay-button:active .jay-button__cap { +.jay-button:active .jay-button__cap, +.jay-button-studio:active .jay-button-studio__cap { transform: translateY(var(--jay-travel)); box-shadow: inset 0 2px 3px rgb(0 0 0 / 0.16), inset 0 -1px 0 rgb(255 255 255 / 0.28); } -.jay-button:focus-visible { +.jay-button:focus-visible, +.jay-button-studio:focus-visible { outline: 3px solid var(--jay-focus); outline-offset: 5px; } -.jay-button:disabled { +.jay-button:disabled, +.jay-button-studio:disabled { cursor: not-allowed; opacity: 0.48; } -.jay-button:disabled .jay-button__cap { +.jay-button:disabled .jay-button__cap, +.jay-button-studio:disabled .jay-button-studio__cap { transform: none; } -.jay-button[data-tone="brown"] { +.jay-button[data-tone="brown"], +.jay-button-studio[data-tone="brown"] { --jay-cap: #6c5b54; --jay-cap-hover: #7b6961; --jay-edge: #382f2b; --jay-ink: #ffffff; } -/* Backward-compatible single-element class from the original release. */ -.JayBrown { +/* JayButton Classic preserves the original JaydenART signature button. */ +.JayBrown, +.jay-button-classic { display: inline-block; - min-inline-size: 10rem; - padding: 1rem 1.55rem; - border: 1px solid #3b312d; - border-radius: 14px; - color: #ffffff; - background: #6c5b54; + box-sizing: content-box; + margin: 0 0 15px; + padding: 8px 20px 10px; + border: 1px solid rgb(127 70 34); + border-radius: 10px; + color: rgb(255 255 255); + background: + linear-gradient(0deg, rgb(255 255 255 / 0) 0, rgb(255 255 255 / 0) 1%, rgb(206 133 88 / 0.99) 100%), + rgb(114 71 42); box-shadow: - inset 0 1px 0 rgb(255 255 255 / 0.22), - inset 0 -2px 0 rgb(0 0 0 / 0.2), - 0 6px 0 #382f2b, - 0 11px 14px rgb(0 0 0 / 0.28); - font: 700 1rem/1 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + inset 0 0 5px 1px rgb(239 159 105 / 0.6), + inset 0 1.5px 0 rgb(229 151 98), + 0 6px 0 rgb(89 50 24), + 0 8px 3px 1px rgb(0 0 0 / 0.99); + font: 700 14px/1 "Coda", Helvetica, sans-serif; + text-align: center; + text-shadow: 0 -1px 1px rgb(45 22 7); cursor: pointer; - transform: translateY(0); - transition: transform 130ms ease, background-color 130ms ease, box-shadow 130ms ease; touch-action: manipulation; -webkit-tap-highlight-color: transparent; appearance: none; } @media (hover: hover) and (pointer: fine) { - .JayBrown:hover { - background: #7b6961; - transform: translateY(-1px); + .JayBrown:hover, + .jay-button-classic:hover { + background: + linear-gradient(180deg, rgb(255 255 255 / 0) 0, rgb(211 140 99 / 0.7) 100%), + rgb(137 89 57); + box-shadow: + inset 0 0 5px 1px rgb(239 159 105 / 0.6), + inset 0 1.5px 0 rgb(234 161 112 / 0.96), + 0 6px 0 rgb(89 50 24), + 0 8px 3px 1px rgb(0 0 0 / 0.99); + text-shadow: 0 -1px 1px rgb(30 45 77); } } -.JayBrown:active { - transform: translateY(4px); +.JayBrown:active, +.jay-button-classic:active { + margin: 5px 0 10px; + background: + linear-gradient(0deg, rgb(255 255 255 / 0) 0, rgb(255 255 255 / 0) 1%, rgb(206 133 88 / 0.99) 100%), + rgb(114 71 42); box-shadow: - inset 0 2px 3px rgb(0 0 0 / 0.18), - 0 2px 0 #382f2b, - 0 6px 9px rgb(0 0 0 / 0.26); + inset 0 1px 10px 1px rgb(239 159 105 / 0.6), + inset 0 1.5px 0 rgb(234 171 129), + 0 2px 0 rgb(89 50 24), + 0 3px 3px 1px rgb(0 0 0 / 0.99); } -.JayBrown:focus-visible { +.JayBrown:focus-visible, +.jay-button-classic:focus-visible { outline: 3px solid #abcf37; outline-offset: 5px; } @media (prefers-reduced-motion: reduce) { .jay-button__cap, - .JayBrown { + .jay-button-studio__cap { transition-duration: 0.01ms; } .jay-button:hover .jay-button__cap, .jay-button:active .jay-button__cap, - .JayBrown:hover, - .JayBrown:active { + .jay-button-studio:hover .jay-button-studio__cap, + .jay-button-studio:active .jay-button-studio__cap { transform: none; } } @media (forced-colors: active) { .jay-button, - .JayBrown { + .jay-button-studio, + .JayBrown, + .jay-button-classic { forced-color-adjust: none; } .jay-button__cap, - .JayBrown { + .jay-button-studio__cap, + .JayBrown, + .jay-button-classic { border-color: ButtonText; color: ButtonText; background: ButtonFace; } - .jay-button::before { + .jay-button::before, + .jay-button-studio::before { background: ButtonText; } } diff --git a/README.md b/README.md index 9af8908..88b368f 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # JaydenART® Realistic 3D CSS Button -

A button that actually presses. Pure CSS, no JavaScript, no images, and no dependencies.

+

Two button styles, one small stylesheet. Pure CSS, no JavaScript, no images, and no dependencies.

- JaydenART realistic CSS button shown at rest and pressed, with the cap moving down while the base stays anchored + JayButton Classic in glossy brown beside JayButton Studio in JaydenART green, each shown with dimensional press styling

@@ -12,36 +12,49 @@ MIT License

-## Why It Feels Real +## Choose a style -Many CSS buttons move the whole element, including the shadow that is supposed to anchor it to the page. This component separates the moving cap from the fixed edge and ground shadow: +### JayButton Classic -- The outer button owns the edge and shadow. -- The inner cap lifts on hover and travels down on press. -- The component keeps stable dimensions through every state. -- Touch, keyboard, reduced-motion, disabled, and forced-color states are included. +Classic is the original JaydenART signature button. Its warm copper highlight, glossy brown face, deep edge, and compact press motion are preserved from the first release. Use it when you want the distinctive original look in a single HTML element. -## Use It +```html + + + +``` -Add [`JayButton.css`](JayButton.css) to your project: +The original `.JayBrown` class is still supported: ```html - + +``` - ``` -For the brown JaydenART variant: +The original Studio class names from version 2.0 remain supported: ```html - ``` -## Customize It +For the brown Studio tone, add `data-tone="brown"` to the outer button. + +## Why the names + +Classic and Studio are two maintained styles, not old and new releases of the same design. The names make that distinction clear while repository versions continue to describe changes to the complete package. + +## Customize Studio Override the component variables on the button or in your own class: @@ -69,17 +82,7 @@ Override the component variables on the button or in your own class: ## Accessibility -The demo uses native ` -``` - -New work should use `.jay-button` with `.jay-button__cap` because that structure keeps the cap and base physically independent. +Both examples use native ` +

JayButton Classic

+
-

JaydenART brown

-
diff --git a/package.json b/package.json index 11bce06..bdc278d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "jaydenart-realistic-3d-css-button", - "version": "2.0.0", - "description": "A dependency-free CSS button with an anchored edge, stable layout, and accessible interaction states.", + "version": "2.1.0", + "description": "Two dependency-free CSS buttons: the original glossy JayButton Classic and the accessible layered JayButton Studio.", "private": true, "scripts": { "check": "node --check test/button.test.mjs", diff --git a/test/button.test.mjs b/test/button.test.mjs index 1b2d12f..a14b693 100644 --- a/test/button.test.mjs +++ b/test/button.test.mjs @@ -17,8 +17,9 @@ test("page has a complete, secure document shell", () => { }); test("demo uses valid native button markup", () => { - assert.equal((html.match(/class="jay-button"/g) || []).length, 2); - assert.equal((html.match(/class="jay-button__cap"/g) || []).length, 2); + assert.equal((html.match(/class="jay-button-classic"/g) || []).length, 1); + assert.equal((html.match(/class="jay-button-studio"/g) || []).length, 1); + assert.equal((html.match(/class="jay-button-studio__cap"/g) || []).length, 1); assert.doesNotMatch(html, /]+type="button"/i); assert.doesNotMatch(html, /]*>\s*<(button|input)\b/is); }); @@ -30,6 +31,21 @@ test("component keeps the base separate from the moving cap", () => { assert.match(component, /transform: translateY\(var\(--jay-travel\)\)/); }); +test("Classic preserves the original signature visual contract", () => { + assert.match(component, /\.JayBrown,\s*\.jay-button-classic/); + assert.match(component, /linear-gradient\(0deg,[\s\S]*rgb\(206 133 88 \/ 0\.99\)/); + assert.match(component, /0 6px 0 rgb\(89 50 24\)/); + assert.match(component, /0 8px 3px 1px rgb\(0 0 0 \/ 0\.99\)/); + assert.match(component, /\.jay-button-classic:active/); + assert.match(component, /margin: 5px 0 10px/); +}); + +test("Studio supports descriptive and version 2.0 class names", () => { + assert.match(component, /\.jay-button,\s*\.jay-button-studio/); + assert.match(component, /\.jay-button__cap,\s*\.jay-button-studio__cap/); + assert.match(component, /\.jay-button-studio:active \.jay-button-studio__cap/); +}); + test("component covers keyboard and user preference states", () => { assert.match(component, /:focus-visible/); assert.match(component, /prefers-reduced-motion: reduce/);