PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.6
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.6
1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 All 49 releases
← All changes | app/Services/Theme/FrontendTheme.php +101 -16 1.6.5 → 1.6.6 View file →
@@ -74,10 +74,10 @@
74 74 * A named callback on the public filter rather than a call inside the
75 75 * gateway: the payment module stays unaware of the theme service, and
76 76 * removing or replacing FluentCart's contribution is a *_filter() call.
77 77 *
78 - * A default-filler, not an owner: the palette supplies its theme and its
79 - * three colour variables, and everything else — a customised seed, or
78 + * A default-filler, not an owner: the palette supplies its theme, its
79 + * colour variables and its tab rules, and everything else — a customised seed, or
80 80 * what an earlier listener added (labels, rules, extra variables) —
81 81 * survives. The theme is only taken over from the plain default, since
82 82 * an explicit theme choice is a choice. With no opinion (default source,
83 83 * nothing measurable), the incoming value passes through unchanged.
@@ -104,8 +104,24 @@
104 104 (array)Arr::get($appearance, 'variables', []),
105 105 $palette['variables']
106 106 );
107 107
108 + // Per selector: the palette sets its properties, and every other
109 + // selector and property an earlier listener wrote survives. Selectors
110 + // start with a dot, so they are indexed directly, never via Arr::get().
111 + $rules = (array)Arr::get($appearance, 'rules', []);
112 +
113 + foreach ((array)Arr::get($palette, 'rules', []) as $selector => $properties) {
114 + $rules[$selector] = array_merge(
115 + isset($rules[$selector]) ? (array)$rules[$selector] : [],
116 + $properties
117 + );
118 + }
119 +
120 + if ($rules) {
121 + $appearance['rules'] = $rules;
122 + }
123 +
108 124 return $appearance;
109 125 }
110 126
111 127 /**
@@ -124,9 +140,12 @@
124 140 *
125 141 * Seeds the `fluent_cart/stripe_appearance` filter's default — a listener
126 142 * still overrides everything here.
127 143 *
128 - * @return array Stripe appearance config: ['theme' => ..., 'variables' => ...].
144 + * The button pair reaches Stripe on its own, without the input pair: it
145 + * is the accent, and it fills the selected payment-method tab.
146 + *
147 + * @return array Stripe appearance config: ['theme' => ..., 'variables' => ..., 'rules' => ...].
129 148 */
130 149 public static function stripeAppearance(): array
131 150 {
132 151 $appearance = ['theme' => 'stripe'];
@@ -139,28 +158,51 @@
139 158
140 159 $inputBg = (string)Arr::get($colors, 'input_bg_color', '');
141 160 $inputText = (string)Arr::get($colors, 'input_text_color', '');
142 161
143 - if ($inputBg === '' || $inputText === '') {
144 - return $appearance;
145 - }
146 -
147 - $appearance = [
162 + if ($inputBg !== '' && $inputText !== '') {
148 163 // readableOn() picks white on a dark surface — which is exactly
149 164 // when Stripe should start from night instead of its light theme.
150 - 'theme' => ColorMath::readableOn($inputBg) === '#ffffff' ? 'night' : 'stripe',
151 - 'variables' => [
165 + $appearance['theme'] = ColorMath::readableOn($inputBg) === '#ffffff' ? 'night' : 'stripe';
166 + $appearance['variables'] = [
152 167 'colorBackground' => $inputBg,
153 168 'colorText' => $inputText,
154 - ],
155 - ];
169 + ];
170 + }
156 171
157 - $accent = (string)Arr::get($colors, 'primary_bg_color', '');
172 + // The accent and the selected payment-method tab follow the button,
173 + // not primary_bg_color: that is a pale surface behind active states,
174 + // and as Stripe's accent it washed the selected tab out entirely.
175 + $buttonBg = (string)Arr::get($colors, 'btn_bg_color', '');
158 176
159 - if ($accent !== '') {
160 - $appearance['variables']['colorPrimary'] = $accent;
177 + if ($buttonBg === '') {
178 + return $appearance;
161 179 }
162 180
181 + $buttonText = (string)Arr::get($colors, 'btn_text_color', '');
182 +
183 + if ($buttonText === '') {
184 + $buttonText = ColorMath::readableText($buttonBg);
185 + }
186 +
187 + $appearance['variables']['colorPrimary'] = $buttonBg;
188 +
189 + $selectedTab = [
190 + 'backgroundColor' => $buttonBg,
191 + 'borderColor' => $buttonBg,
192 + 'color' => $buttonText,
193 + ];
194 +
195 + $appearance['rules'] = [
196 + '.Tab:hover' => ['borderColor' => $buttonBg],
197 + '.Tab--selected' => $selectedTab,
198 + '.Tab--selected:hover' => $selectedTab,
199 + '.Tab--selected:focus' => $selectedTab,
200 + '.TabIcon--selected' => ['fill' => $buttonText],
201 + '.TabIcon--selected:hover' => ['fill' => $buttonText],
202 + '.TabLabel--selected' => ['color' => $buttonText],
203 + ];
204 +
163 205 return $appearance;
164 206 }
165 207
166 208 /**
@@ -381,8 +423,51 @@
381 423 return preg_match('/^var\(--[A-Za-z0-9_-]+(?:, #(?:[0-9a-f]{3}|[0-9a-f]{6}))?\)$/', $value) ? $value : '';
382 424 }
383 425
384 426 /**
427 + * Give a customised button what theme inheritance would have given it.
428 + *
429 + * Customize lets the owner leave a button's text unset, and every
430 + * stylesheet then falls back to its own literal text — not always one
431 + * that reads on the background the owner did set (the product carousel's
432 + * hovered arrow fell back to a dark icon). Theme inheritance already
433 + * measures a missing partner; this does the same for the button pair and
434 + * the hover pair.
435 + *
436 + * A button background with no hover background also gets the hover
437 + * inheritance derives — the button moved 12% away from itself — with the
438 + * resting text carried over while it reads; otherwise the button hovered
439 + * in its resting colour, with no visible change. A colour the owner chose
440 + * is worn as given.
441 + *
442 + * @param array $colors Settings key => hex, as the owner set them.
443 + * @return array
444 + */
445 + protected static function withButtonPartners(array $colors): array
446 + {
447 + if (isset($colors['btn_bg_color']) && !isset($colors['btn_text_color'])) {
448 + $colors['btn_text_color'] = ColorMath::readableText($colors['btn_bg_color']);
449 + }
450 +
451 + if (isset($colors['btn_bg_color']) && !isset($colors['btn_hover_bg_color'])) {
452 + $colors['btn_hover_bg_color'] = ColorMath::shiftFromItself($colors['btn_bg_color'], 12);
453 +
454 + if (!isset($colors['btn_hover_text_color'])) {
455 + $colors['btn_hover_text_color'] = ThemePalette::hoverTextFor(
456 + $colors['btn_hover_bg_color'],
457 + $colors['btn_text_color']
458 + );
459 + }
460 + }
461 +
462 + if (isset($colors['btn_hover_bg_color']) && !isset($colors['btn_hover_text_color'])) {
463 + $colors['btn_hover_text_color'] = ColorMath::readableText($colors['btn_hover_bg_color']);
464 + }
465 +
466 + return $colors;
467 + }
468 +
469 + /**
385 470 * Every colour that will actually be written, keyed by settings key.
386 471 *
387 472 * @return array
388 473 */
@@ -390,9 +475,9 @@
390 475 {
391 476 $source = self::getSource();
392 477
393 478 if ($source === ColorPalette::SOURCE_CUSTOM) {
394 - $colors = self::getCustomColors();
479 + $colors = self::withButtonPartners(self::getCustomColors());
395 480 } elseif ($source === ColorPalette::SOURCE_THEME) {
396 481 $colors = self::getThemeColors();
397 482 } else {
398 483 $colors = [];