diff --git a/CHANGELOG.md b/CHANGELOG.md index c249cf8..58b4b68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.4.0] - 2026-03-30 + +### Added +- Shadow Color and Shadow Opacity controls to BoxShadow +- Shadow Color and Shadow Opacity controls to DropShadow +- Updated `globalEffects` hook to apply box shadow color and opacity classes +- Updated `globalFilters` hook to apply drop shadow color and opacity classes + ## [1.2.1] - 2026-01-09 ### Changed diff --git a/controls/Effects/BoxShadow.js b/controls/Effects/BoxShadow.js index 7cf51fa..c7afded 100644 --- a/controls/Effects/BoxShadow.js +++ b/controls/Effects/BoxShadow.js @@ -10,6 +10,27 @@ const BoxShadow = [ }, }, }, + { + title: "Shadow Color", + id: "globalBoxShadowColor", + format: "shadow-{{value}}", + themeColor: { + default: { + name: "surface", + brightness: 950, + }, + }, + }, + { + title: "Shadow Opacity", + id: "globalBoxShadowColorOpacity", + format: "[{{value}}%]", + slider: { + default: 100, + use: "Slider", + units: "%", + }, + }, ]; export default BoxShadow; diff --git a/controls/Effects/DropShadow.js b/controls/Effects/DropShadow.js index bca8073..fac1ba8 100644 --- a/controls/Effects/DropShadow.js +++ b/controls/Effects/DropShadow.js @@ -1,14 +1,37 @@ -const DropShadow = { - title: "Drop Shadow", - id: "globalFiltersDropShadow", - themeShadow: { - mode: "drop", - default: { - base: { - name: "none", +const DropShadow = [ + { + title: "Drop Shadow", + id: "globalFiltersDropShadow", + themeShadow: { + mode: "drop", + default: { + base: { + name: "none", + }, }, }, }, -}; + { + title: "Shadow Color", + id: "globalFiltersDropShadowColor", + format: "drop-shadow-{{value}}", + themeColor: { + default: { + name: "surface", + brightness: 950, + }, + }, + }, + { + title: "Shadow Opacity", + id: "globalFiltersDropShadowColorOpacity", + format: "[{{value}}%]", + slider: { + default: 100, + use: "Slider", + units: "%", + }, + }, +]; export default DropShadow; diff --git a/package.json b/package.json index 3d7a918..520fbab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rw-elements-tools", - "version": "1.3.8", + "version": "1.4.0", "description": "Build tools for RapidWeaver Elements packs - generates properties.json and hooks.js files", "author": "Elements Platform", "license": "MIT", diff --git a/shared-hooks/effects/globalEffects.js b/shared-hooks/effects/globalEffects.js index ebbfbaa..12a3a58 100644 --- a/shared-hooks/effects/globalEffects.js +++ b/shared-hooks/effects/globalEffects.js @@ -5,8 +5,12 @@ const globalEffects = (app, args = {}) => { globalHoverGroupEffects: hoverGroup, globalHoverGroupCustomIdEffects: customId, globalBoxShadow: boxShadow, + globalBoxShadowColor: boxShadowColor, + globalBoxShadowColorOpacity: boxShadowColorOpacity, globalOpacity: opacity, globalBoxShadowEnd: boxShadowEnd, + globalBoxShadowColorEnd: boxShadowColorEnd, + globalBoxShadowColorOpacityEnd: boxShadowColorOpacityEnd, globalOpacityEnd: opacityEnd, } = app.props; @@ -19,18 +23,44 @@ const globalEffects = (app, args = {}) => { const classes = []; + // Helper to build shadow color classes with opacity + const buildShadowColorClasses = (color, colorOpacity, hoverPrefix) => { + if (!color) return ""; + return color + .split(" ") + .filter(Boolean) + .map((c) => { + const colorClass = hoverPrefix + ? `${hoverPrefix}:${c.trim()}/${colorOpacity}` + : `${c.trim()}/${colorOpacity}`; + return colorClass; + }) + .join(" "); + }; + if (type != "none") { classes.push(boxShadow, opacity); + classes.push(buildShadowColorClasses(boxShadowColor, boxShadowColorOpacity)); } if (type == "hover") { classes.push(`${prefix}:${boxShadowEnd}`, `${prefix}:${opacityEnd}`); + classes.push( + buildShadowColorClasses(boxShadowColorEnd, boxShadowColorOpacityEnd, prefix) + ); if (wantsActive) { classes.push( `data-[active=true]:${boxShadowEnd}`, `data-[active=true]:${opacityEnd}` ); + classes.push( + buildShadowColorClasses( + boxShadowColorEnd, + boxShadowColorOpacityEnd, + "data-[active=true]" + ) + ); } if (wantsFocus) { @@ -38,6 +68,13 @@ const globalEffects = (app, args = {}) => { `${prefix.replace(/hover/g, "focus")}:${boxShadowEnd}`, `${prefix.replace(/hover/g, "focus")}:${opacityEnd}` ); + classes.push( + buildShadowColorClasses( + boxShadowColorEnd, + boxShadowColorOpacityEnd, + prefix.replace(/hover/g, "focus") + ) + ); } } diff --git a/shared-hooks/effects/globalFilters.js b/shared-hooks/effects/globalFilters.js index 9c8646c..154f9b9 100644 --- a/shared-hooks/effects/globalFilters.js +++ b/shared-hooks/effects/globalFilters.js @@ -8,6 +8,8 @@ const globalFilters = (app, args = {}) => { globalFiltersBlur: blur, globalFiltersBrightness: brightness, globalFiltersDropShadow: dropShadow, + globalFiltersDropShadowColor: dropShadowColor, + globalFiltersDropShadowColorOpacity: dropShadowColorOpacity, globalFiltersSaturate: saturate, // backdrop filters @@ -17,6 +19,8 @@ const globalFilters = (app, args = {}) => { globalFiltersBlurEnd: blurEnd, globalFiltersBrightnessEnd: brightnessEnd, globalFiltersDropShadowEnd: dropShadowEnd, + globalFiltersDropShadowColorEnd: dropShadowColorEnd, + globalFiltersDropShadowColorOpacityEnd: dropShadowColorOpacityEnd, globalFiltersSaturateEnd: saturateEnd, // end backdrop filters @@ -38,10 +42,26 @@ const globalFilters = (app, args = {}) => { const wantsBackdropBlur = !backdropBlur.endsWith("[0px]") || !backdropBlurEnd.endsWith("[0px]"); + // Helper to build drop shadow color classes with opacity + const buildDropShadowColorClasses = (color, colorOpacity, hoverPrefix) => { + if (!color) return ""; + return color + .split(" ") + .filter(Boolean) + .map((c) => { + const colorClass = hoverPrefix + ? `${hoverPrefix}:${c.trim()}/${colorOpacity}` + : `${c.trim()}/${colorOpacity}`; + return colorClass; + }) + .join(" "); + }; + const classes = [ wantsBlur ? blur : "", brightness, dropShadow, + buildDropShadowColorClasses(dropShadowColor, dropShadowColorOpacity), saturate, wantsBackdropBlur ? backdropBlur : "", ]; @@ -51,6 +71,11 @@ const globalFilters = (app, args = {}) => { wantsBlur ? `${prefix}:${blurEnd}` : "", `${prefix}:${brightnessEnd}`, `${prefix}:${dropShadowEnd}`, + buildDropShadowColorClasses( + dropShadowColorEnd, + dropShadowColorOpacityEnd, + prefix + ), `${prefix}:${saturateEnd}`, wantsBackdropBlur ? `${prefix}:${backdropBlurEnd}` : "" ); @@ -60,6 +85,11 @@ const globalFilters = (app, args = {}) => { `data-[active=true]:${blurEnd}`, `data-[active=true]:${brightnessEnd}`, `data-[active=true]:${dropShadowEnd}`, + buildDropShadowColorClasses( + dropShadowColorEnd, + dropShadowColorOpacityEnd, + "data-[active=true]" + ), `data-[active=true]:${saturateEnd}`, `data-[active=true]:${backdropBlurEnd}` ); @@ -70,6 +100,11 @@ const globalFilters = (app, args = {}) => { `${prefix.replace(/hover/g, "focus")}:${blurEnd}`, `${prefix.replace(/hover/g, "focus")}:${brightnessEnd}`, `${prefix.replace(/hover/g, "focus")}:${dropShadowEnd}`, + buildDropShadowColorClasses( + dropShadowColorEnd, + dropShadowColorOpacityEnd, + prefix.replace(/hover/g, "focus") + ), `${prefix.replace(/hover/g, "focus")}:${saturateEnd}`, `${prefix.replace(/hover/g, "focus")}:${backdropBlurEnd}` );