Skip to content

Commit dfab46f

Browse files
authored
Sync branch [skip ci]
2 parents a2d206f + 76e79f8 commit dfab46f

12 files changed

Lines changed: 173 additions & 33 deletions

File tree

assets/apps/customizer-controls/src/responsive-range/ResponsiveRangeComponent.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const ResponsiveRangeComponent = ({ control }) => {
3636
}, []);
3737

3838
const { label } = control.params;
39-
const { hideResponsive, units, defaultVal, min, max } =
39+
const { hideResponsive, units, defaultVal, min, max, unitsMax } =
4040
control.params.input_attrs;
4141

4242
const suffixValue = () => {
@@ -58,6 +58,16 @@ const ResponsiveRangeComponent = ({ control }) => {
5858

5959
const isRelativeUnit = () => ['em', 'rem'].includes(suffixValue());
6060

61+
// Allow a different max per unit (e.g. 1200 for px but 100 for %).
62+
const maxForUnit = (unit) => {
63+
if (unitsMax && unit && unitsMax[unit] !== undefined) {
64+
return unitsMax[unit];
65+
}
66+
return max || 100;
67+
};
68+
69+
const currentMax = () => maxForUnit(suffixValue());
70+
6171
const unitButtons = () => {
6272
if (!units) {
6373
return null;
@@ -90,6 +100,12 @@ const ResponsiveRangeComponent = ({ control }) => {
90100
nextValue[currentDevice]
91101
);
92102
}
103+
// Clamp the value to the new unit's max (e.g. when
104+
// switching from px to %, 600 becomes 100).
105+
const unitMax = maxForUnit(unit);
106+
if (nextValue[currentDevice] > unitMax) {
107+
nextValue[currentDevice] = unitMax;
108+
}
93109
setValue(nextValue);
94110
control.setting.set(JSON.stringify(nextValue));
95111
}}
@@ -134,7 +150,7 @@ const ResponsiveRangeComponent = ({ control }) => {
134150
<RangeControl
135151
value={displayValue}
136152
min={min || 0}
137-
max={max || 100}
153+
max={currentMax()}
138154
step={isRelativeUnit() ? 0.1 : 1}
139155
allowReset
140156
onChange={(nextValue) => {

assets/js/src/frontend/navigation.js

Lines changed: 84 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export const initNavigation = () => {
1919
handleMobileDropdowns();
2020
handleSearch();
2121
handleMiniCartPosition();
22+
handleMiniCartMobileToggle();
2223
window.HFG.initSearch = function () {
2324
handleSearch();
2425
handleMobileDropdowns();
@@ -224,20 +225,96 @@ function handleSearch() {
224225
* Handle the mini cart position in nav.
225226
*/
226227
function handleMiniCartPosition() {
227-
const item = document.querySelector('.header--row .menu-item-nav-cart');
228-
if (item === null) {
228+
const items = document.querySelectorAll('.header--row .menu-item-nav-cart');
229+
if (items.length === 0) {
229230
return;
230231
}
231-
const miniCart = item.querySelector('.nv-nav-cart:not(.cart-off-canvas)');
232232

233-
if (miniCart !== null) {
234-
miniCart.style.left =
235-
item.getBoundingClientRect().left < 350 ? 0 : null;
236-
}
233+
const isMobile = window.matchMedia('(max-width: 959px)').matches;
234+
const sideSpacing = 2 * 16;
235+
236+
items.forEach((item) => {
237+
const miniCart = item.querySelector(
238+
'.nv-nav-cart:not(.cart-off-canvas)'
239+
);
240+
241+
if (miniCart === null) {
242+
return;
243+
}
244+
245+
miniCart.style.left = '';
246+
miniCart.style.right = '';
247+
248+
if (isMobile) {
249+
const cartWidth = Math.min(360, window.innerWidth - sideSpacing);
250+
const itemOffset = item.getBoundingClientRect().left;
251+
252+
miniCart.style.width = `${cartWidth}px`;
253+
miniCart.style.maxWidth = `calc(100vw - ${sideSpacing}px)`;
254+
miniCart.style.left = `${
255+
(window.innerWidth - cartWidth) / 2 - itemOffset
256+
}px`;
257+
miniCart.style.right = 'auto';
258+
return;
259+
}
260+
261+
miniCart.style.width = '';
262+
miniCart.style.maxWidth = '';
263+
miniCart.style.left = item.getBoundingClientRect().left < 350 ? 0 : '';
264+
});
237265
}
238266

239267
window.addEventListener('resize', handleMiniCartPosition);
240268

269+
/**
270+
* Toggle the dropdown mini cart on tap for mobile.
271+
*
272+
* On desktop the dropdown mini cart opens on hover. Touch devices have no
273+
* hover, so without this the cart icon would just follow its link to the cart
274+
* page. Below the laptop breakpoint we toggle a `cart-dropdown-open` class on
275+
* tap instead; the dropdown's appearance is reused from the desktop styles
276+
* (see the woocommerce nav-cart styles), so customers can preview the cart and
277+
* keep shopping. It closes on a second tap or when tapping outside of it.
278+
*/
279+
function handleMiniCartMobileToggle() {
280+
const carts = document.querySelectorAll('.responsive-nav-cart.dropdown');
281+
if (carts.length === 0) {
282+
return;
283+
}
284+
285+
// Mirrors the $laptop (960px) breakpoint where the hover dropdown applies.
286+
const isMobile = () => window.matchMedia('(max-width: 959px)').matches;
287+
288+
carts.forEach((cart) => {
289+
const openButton = cart.querySelector('.cart-icon-wrapper');
290+
if (openButton === null) {
291+
return;
292+
}
293+
openButton.addEventListener('click', function (e) {
294+
if (!isMobile() || cart.classList.contains('cart-is-empty')) {
295+
return;
296+
}
297+
e.preventDefault();
298+
cart.classList.toggle('cart-dropdown-open');
299+
});
300+
});
301+
302+
// Close an open dropdown when tapping outside of it.
303+
document.addEventListener('click', function (e) {
304+
if (!isMobile()) {
305+
return;
306+
}
307+
carts.forEach((cart) => {
308+
if (
309+
cart.classList.contains('cart-dropdown-open') &&
310+
!cart.contains(e.target)
311+
) {
312+
cart.classList.remove('cart-dropdown-open');
313+
}
314+
});
315+
});
316+
}
317+
241318
/**
242319
* Create an overlay to allow closing.
243320
*

assets/scss/components/compat/woocommerce/_nav-cart.scss

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,23 @@ $cart-width: 360px;
165165
}
166166
}
167167

168+
// Mobile: tapping the cart icon toggles `cart-dropdown-open` (see
169+
// navigation.js). The dropdown appearance is already defined above, so we only
170+
// need to reveal it here — reusing the same element and styles as the desktop.
171+
@media (max-width: 959px) {
172+
173+
.responsive-nav-cart.dropdown .nv-nav-cart:not(.cart-off-canvas) {
174+
width: min(#{$cart-width}, calc(100vw - #{2 * $spacing-md}));
175+
max-width: calc(100vw - #{2 * $spacing-md});
176+
}
177+
178+
.responsive-nav-cart.dropdown.cart-dropdown-open .nv-nav-cart {
179+
display: block;
180+
opacity: 1;
181+
visibility: visible;
182+
}
183+
}
184+
168185
@mixin nav-cart--laptop() {
169186

170187
.nv-nav-cart {

assets/scss/components/editor/_typography.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ ul,
9090
ol {
9191
padding-left: $spacing-md;
9292
margin: $spacing-lg 0;
93+
font-family: var(--bodyfontfamily);
9394

9495
li {
9596
margin-top: $spacing-xs;
@@ -172,6 +173,7 @@ ol {
172173
th,
173174
td {
174175
border: 0;
176+
font-family: var(--bodyfontfamily);
175177

176178
// Allow align inside editor but make sure cells are left-aligned default
177179
&:not([class*="has-text-align"]) {

assets/scss/components/main/_gutenberg.scss

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@
4646
}
4747

4848
.nv-sidebar-left,
49-
.nv-sidebar-right {
49+
.nv-sidebar-right,
50+
[class*="wp-block-"]:has(> [class*="wp-block-"]):not(.alignfull):not(.alignwide) {
5051

51-
.alignfull,
52-
.alignwide {
52+
:is(.alignfull, .alignwide) {
53+
width: 100%;
5354
max-width: 100%;
5455
margin-left: auto;
5556
margin-right: auto;

assets/scss/gutenberg-editor-style.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
.editor-styles-wrapper {
55
-webkit-font-smoothing: antialiased;
66
-moz-osx-font-smoothing: grayscale;
7+
font-family: var(--bodyfontfamily);
78

89
&, > *:not(.block-canvas-cover) {
910
background-color: var(--nv-site-bg);

assets/scss/main/_gutenberg.scss

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,25 @@
1616
body {
1717
&.nv-sidebar-left,
1818
&.nv-sidebar-right {
19-
.alignfull, .alignwide {
20-
max-width: 100%;
21-
margin-left: auto;
22-
margin-right: auto;
23-
}
19+
.alignfull,
20+
.alignwide {
21+
width: 100%;
22+
max-width: 100%;
23+
margin-left: auto;
24+
margin-right: auto;
25+
}
26+
}
27+
}
28+
29+
.wp-block-column,
30+
.is-layout-constrained:not(.alignfull):not(.alignwide),
31+
[class*="wp-block-"]:has(> [class*="wp-block-"]):not(.alignfull):not(.alignwide) {
32+
.alignfull,
33+
.alignwide {
34+
width: 100%;
35+
max-width: 100%;
36+
margin-left: auto;
37+
margin-right: auto;
2438
}
2539
}
2640

composer.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e-tests/specs/admin/tpc-notice-install.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ test.describe('Dashboard Notice', () => {
2626

2727
// Welcome screen
2828
await expect(page.locator('h1')).toContainText(
29-
'What type of website are you creating?'
29+
'Choose a design'
3030
);
3131

3232
const categories = await page.locator('.ob-cat-wrap .cat');

inc/views/header.php

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -283,14 +283,26 @@ public function track_mm_settings( $menu_id ) {
283283
}
284284
}
285285

286-
Tracker::track(
287-
array(
286+
// Cache the active state and only send when it changes or the refresh window has elapsed.
287+
// `wp_update_nav_menu` fires multiple times per save and the value is near-static per site,
288+
// so sending unconditionally floods the tracking pipeline with duplicate readings.
289+
$last = get_option( 'neve_mm_active_state', null );
290+
$now = $has_mm ? 'yes' : 'no';
291+
$stale = ! get_transient( 'neve_mm_tracked' );
292+
293+
if ( $now !== $last || $stale ) {
294+
update_option( 'neve_mm_active_state', $now );
295+
set_transient( 'neve_mm_tracked', 1, MONTH_IN_SECONDS );
296+
297+
Tracker::track(
288298
array(
289-
'feature' => 'mega-menu-free',
290-
'featureComponent' => 'is-active',
291-
'featureValue' => $has_mm,
292-
),
293-
)
294-
);
299+
array(
300+
'feature' => 'mega-menu-free',
301+
'featureComponent' => 'is-active',
302+
'featureValue' => $has_mm,
303+
),
304+
)
305+
);
306+
}
295307
}
296308
}

0 commit comments

Comments
 (0)