Skip to content

Commit

Permalink
Merge branch 'master' into pladaria/WEB-1581_fix-ScreenReaderOnly-styles
Browse files Browse the repository at this point in the history
  • Loading branch information
pladaria authored Nov 16, 2023
2 parents 7c33e71 + dea744d commit ec771ca
Show file tree
Hide file tree
Showing 19 changed files with 197 additions and 33 deletions.
Binary file not shown.
Binary file not shown.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
## [14.31.1](https://github.com/Telefonica/mistica-web/compare/v14.31.0...v14.31.1) (2023-11-16)


### Bug Fixes

* **Carousel:** avoid immediate style reflow on component mount ([#945](https://github.com/Telefonica/mistica-web/issues/945)) ([c46206e](https://github.com/Telefonica/mistica-web/commit/c46206eff42c6e76cbbe5b0ed6859967de636281))

# [14.31.0](https://github.com/Telefonica/mistica-web/compare/v14.30.0...v14.31.0) (2023-11-16)


### Bug Fixes

* **FixedFooterLayout:** consider bottom inset area for calculations ([#943](https://github.com/Telefonica/mistica-web/issues/943)) ([23c7544](https://github.com/Telefonica/mistica-web/commit/23c75444a8e2234b6685d2d51b10f68565df6819))


### Features

* **createNestableContext:** allow custom valuesReducer ([#941](https://github.com/Telefonica/mistica-web/issues/941)) ([ec5b2a1](https://github.com/Telefonica/mistica-web/commit/ec5b2a104ad8c84b96a1d5862f576b7886df96c9))
* **skin:** update design tokens ([#938](https://github.com/Telefonica/mistica-web/issues/938)) ([605c517](https://github.com/Telefonica/mistica-web/commit/605c51712e11a341d4320af44ede06c7055ab125))

# [14.30.0](https://github.com/Telefonica/mistica-web/compare/v14.29.0...v14.30.0) (2023-11-13)


Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@telefonica/mistica",
"version": "14.30.0",
"version": "14.31.1",
"license": "MIT",
"repository": {
"type": "git",
Expand Down Expand Up @@ -82,7 +82,7 @@
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.61",
"@swc/jest": "^0.2.26",
"@telefonica/acceptance-testing": "2.13.0",
"@telefonica/acceptance-testing": "2.21.1",
"@telefonica/eslint-config": "^1.7.0",
"@telefonica/prettier-config": "^1.1.0",
"@testing-library/jest-dom": "^5.16.5",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions src/__screenshot_tests__/fixed-footer-screenshot-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,34 @@ test('Fixed footer with static position when height is smaller than the footer i
const imageOverflowScrolled = await page.screenshot({fullPage: false});
expect(imageOverflowScrolled).toMatchImageSnapshot();
});

test('Fixed footer with safe inset at the bottom', async () => {
const page = await openStoryPage({
id: 'layout-fixed-footer-layout--more-complex-footer',
device: 'MOBILE_IOS_INSET',
});

const image = await page.screenshot();
expect(image).toMatchImageSnapshot();

await (await screen.findByRole('button', {name: 'Load more text'})).click();
await (await screen.findByRole('button', {name: 'Load more text'})).click();
await (await screen.findByRole('button', {name: 'Load more text'})).click();
await (await screen.findByTestId('line-15')).evaluate((el) => el.scrollIntoView());

const imageOverflowLinesInset = await page.screenshot({fullPage: false});
expect(imageOverflowLinesInset).toMatchImageSnapshot();

await page.setViewport({
width: 564,
height: 150,
deviceScaleFactor: 1,
isMobile: true,
isLandscape: false,
hasTouch: true,
});

await (await screen.findByRole('button', {name: 'Load more text'})).evaluate((el) => el.scrollIntoView());
const imageOverflowLinesInsetHorizontal = await page.screenshot({fullPage: false});
expect(imageOverflowLinesInsetHorizontal).toMatchImageSnapshot();
});
2 changes: 1 addition & 1 deletion src/__stories__/fixed-footer-layout-story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export const MoreComplexFooter: StoryComponent = () => {
FixedFooterLayout instead of ButtonFixedFooterLayout
</Text2>
{textLines.map((line, idx) => (
<Text2 regular key={idx}>
<Text2 regular key={idx} dataAttributes={{testid: `line-${idx}`}}>
{line}
</Text2>
))}
Expand Down
83 changes: 77 additions & 6 deletions src/__tests__/nestable-context-test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as React from 'react';
import createContext from '../nestable-context';
import {createNestableContext} from '../nestable-context';
import {render, fireEvent, screen} from '@testing-library/react';

test('happy case', () => {
const {Provider, Getter, Setter} = createContext<string>('nothing');
const {Provider, Getter, Setter} = createNestableContext<string>('nothing');

render(
<Provider>
Expand All @@ -16,7 +16,7 @@ test('happy case', () => {
});

test('When unmount, the default value is restored', async () => {
const {Provider, Getter, Setter} = createContext<string>('nothing');
const {Provider, Getter, Setter} = createNestableContext<string>('nothing');

const A = () => {
const [isVisible, setIsVisible] = React.useState(true);
Expand All @@ -42,7 +42,7 @@ test('When unmount, the default value is restored', async () => {
});

test('When unmount, the previous value is restored', async () => {
const {Provider, Getter, Setter} = createContext<string>('nothing');
const {Provider, Getter, Setter} = createNestableContext<string>('nothing');

const A = () => {
const [isVisible, setIsVisible] = React.useState(true);
Expand Down Expand Up @@ -70,7 +70,7 @@ test('When unmount, the previous value is restored', async () => {
});

test('when nesting, the innermost component wins', () => {
const {Provider, Getter, Setter} = createContext<string>('nothing');
const {Provider, Getter, Setter} = createNestableContext<string>('nothing');

const C = () => <Setter value="c" />;

Expand Down Expand Up @@ -121,7 +121,7 @@ const Transition = ({a, b}: {a: React.ReactNode; b: React.ReactNode}) => {
};

test('works as expected with transitions', async () => {
const {Provider, Getter, Setter} = createContext<string>('nothing');
const {Provider, Getter, Setter} = createNestableContext<string>('nothing');

render(
<Provider>
Expand All @@ -132,3 +132,74 @@ test('works as expected with transitions', async () => {

expect(await screen.findByText('The value is: b')).toBeInTheDocument();
});

test('when value is an object, nested values are merged', () => {
type Value = {foo?: string; bar?: string};

const {Provider, Getter, Setter} = createNestableContext<Value>({});

const C = () => <Setter value={{bar: 'c'}} />;

const B = () => (
<>
<Setter value={{bar: 'b'}} />
<C />
</>
);

const A = () => (
<>
<Setter value={{foo: 'a'}} />
<B />
</>
);

render(
<Provider>
<Getter>{({foo, bar}) => `foo is ${foo} and bar is ${bar}`}</Getter>
<A />
</Provider>
);

expect(screen.getByText('foo is a and bar is c')).toBeInTheDocument();
});

test('can use a custom valuesReducer', () => {
type Value = {foo?: string; bar?: string; reset?: boolean};

const valuesReducer = (values: Array<Value>): Value => {
return values.reduce((acc, value) => {
if (value.reset) {
return value;
}
return {...acc, ...value};
}, {});
};

const {Provider, Getter, Setter} = createNestableContext<Value>({}, valuesReducer);

const C = () => <Setter value={{bar: 'c'}} />;

const B = () => (
<>
<Setter value={{bar: 'b', reset: true}} />
<C />
</>
);

const A = () => (
<>
<Setter value={{foo: 'a'}} />
<B />
</>
);

render(
<Provider>
<Getter>{({foo, bar}) => `foo is ${foo} and bar is ${bar}`}</Getter>
<A />
</Provider>
);

expect(screen.getByText('foo is undefined and bar is c')).toBeInTheDocument();
});
4 changes: 2 additions & 2 deletions src/carousel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import IconChevronLeftRegular from './generated/mistica-icons/icon-chevron-left-regular';
import IconChevronRightRegular from './generated/mistica-icons/icon-chevron-right-regular';
import {useIsInViewport, useIsomorphicLayoutEffect, useScreenSize, useTheme} from './hooks';
import {useIsInViewport, useScreenSize, useTheme} from './hooks';
import Inline from './inline';
import Stack from './stack';
import {BaseTouchable} from './touchable';
Expand Down Expand Up @@ -226,7 +226,7 @@ const BaseCarousel: React.FC<BaseCarouselProps> = ({
const showNextArrow = scrollRight !== 0;
const showPrevArrow = scrollLeft !== 0;

useIsomorphicLayoutEffect(() => {
React.useEffect(() => {
if (carouselRef.current) {
const carouselEl = carouselRef.current;

Expand Down
16 changes: 9 additions & 7 deletions src/fixed-footer-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
} from './utils/dom';
import * as styles from './fixed-footer-layout.css';
import {assignInlineVars} from '@vanilla-extract/dynamic';
import {safeAreaInsetBottom} from './utils/css';

const FOOTER_CANVAS_RATIO = 2;
const getScrollEventTarget = (el: HTMLElement) => (el === document.documentElement ? window : el);
Expand Down Expand Up @@ -54,17 +55,16 @@ const FixedFooterLayout: React.FC<Props> = ({
const containerRef = React.useRef<HTMLDivElement>(null);
const {isTabletOrSmaller} = useScreenSize();
const {platformOverrides} = useTheme();
const {height: realFooterHeight, ref} = useElementDimensions();
const {height: domFooterHeight, ref} = useElementDimensions();
const isWithinIFrame = useIsWithinIFrame();
const windowHeight = useWindowHeight();
const screenHeight = useScreenHeight();
const hasContentEnoughVSpace =
windowHeight - realFooterHeight >
(isWithinIFrame ? windowHeight : screenHeight) / FOOTER_CANVAS_RATIO;
windowHeight - domFooterHeight > (isWithinIFrame ? windowHeight : screenHeight) / FOOTER_CANVAS_RATIO;

useIsomorphicLayoutEffect(() => {
onChangeFooterHeight?.(realFooterHeight);
}, [onChangeFooterHeight, realFooterHeight]);
onChangeFooterHeight?.(domFooterHeight);
}, [onChangeFooterHeight, domFooterHeight]);

React.useEffect(() => {
const scrollable = getScrollableParentElement(containerRef.current);
Expand Down Expand Up @@ -116,7 +116,9 @@ const FixedFooterLayout: React.FC<Props> = ({
...(containerBgColor && {
[styles.vars.backgroundColor]: containerBgColor,
}),
[styles.vars.footerHeight]: isFixedFooter ? `${realFooterHeight}px` : '0px',
[styles.vars.footerHeight]: isFixedFooter
? `calc(${safeAreaInsetBottom} + ${domFooterHeight}px)`
: '0px',
})}
>
{children}
Expand Down Expand Up @@ -148,7 +150,7 @@ const FixedFooterLayout: React.FC<Props> = ({
data-component-name="FixedFooter"
style={{
height: footerHeight,
marginBottom: 'env(safe-area-inset-bottom)',
marginBottom: safeAreaInsetBottom,
}}
>
{footer}
Expand Down
2 changes: 1 addition & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export {default as Snackbar} from './snackbar';
export {Portal} from './portal';
export {default as LoadingBar} from './loading-bar';
export {default as FixedToTop, TopDistanceContext} from './fixed-to-top';
export {default as createNestableContext} from './nestable-context';
export {createNestableContext} from './nestable-context';
export type {NestableContext} from './nestable-context';
export {default as OverscrollColor, OverscrollColorProvider} from './overscroll-color-context';
export {
Expand Down
13 changes: 9 additions & 4 deletions src/nestable-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ export type NestableContext<Value> = {
useSetValue: (value: Value) => void;
};

const createNestableContext = <Value,>(defaultValue: Value): NestableContext<Value> => {
export const createNestableContext = <Value,>(
defaultValue: Value,
valuesReducer?: (values: Array<Value>) => Value
): NestableContext<Value> => {
const DispatchContext = React.createContext<Dispatch<Value>>(() => {});
const ValueContext = React.createContext<Value>(defaultValue);

Expand Down Expand Up @@ -94,7 +97,11 @@ const createNestableContext = <Value,>(defaultValue: Value): NestableContext<Val
let computedValue: Value = defaultValue;
if (values.length) {
if (isObject(values[0])) {
computedValue = Object.assign({}, defaultValue, ...values);
if (valuesReducer) {
computedValue = valuesReducer(values);
} else {
computedValue = Object.assign({}, defaultValue, ...values);
}
} else {
computedValue = values[values.length - 1];
}
Expand Down Expand Up @@ -131,5 +138,3 @@ const createNestableContext = <Value,>(defaultValue: Value): NestableContext<Val

return {Setter, Provider, Getter, useSetValue, useValue};
};

export default createNestableContext;
2 changes: 1 addition & 1 deletion src/overscroll-color-context.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import {useThemeVariant} from './theme-variant-context';
import {useTheme, useScreenSize} from './hooks';
import createNestableContext from './nestable-context';
import {createNestableContext} from './nestable-context';
import {isInsideNovumNativeApp, getPlatform} from './utils/platform';
import {vars} from './skins/skin-contract.css';

Expand Down
2 changes: 1 addition & 1 deletion src/package-version.tsx
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// DO NOT EDIT THIS FILE. It's autogenerated by set-version.js
export const PACKAGE_VERSION = '14.30.0' as string;
export const PACKAGE_VERSION = '14.31.1' as string;
26 changes: 23 additions & 3 deletions src/test-utils/index.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import {openPage, serverHostName, screen, getGlobalPage, PageApi} from '@telefonica/acceptance-testing';
import {MOVISTAR_SKIN} from '../skins/constants';

import type {Viewport} from '@telefonica/acceptance-testing';
import type {TestViewport} from '@telefonica/acceptance-testing';

export type {ElementHandle} from '@telefonica/acceptance-testing';

export {screen, PageApi};

export type StoryArgs = {[key: string]: string | number | boolean};

const MOBILE_DEVICE_IOS_SMALL = 'MOBILE_IOS_SMALL';
const MOBILE_DEVICE_IOS_INSET = 'MOBILE_IOS_INSET';
const MOBILE_DEVICE_IOS = 'MOBILE_IOS';
const MOBILE_DEVICE_ANDROID = 'MOBILE_ANDROID';
const TABLET_DEVICE = 'TABLET';
const DESKTOP_DEVICE = 'DESKTOP';

export type Device =
| typeof MOBILE_DEVICE_IOS_SMALL
| typeof MOBILE_DEVICE_IOS_INSET
| typeof MOBILE_DEVICE_IOS
| typeof MOBILE_DEVICE_ANDROID
| typeof TABLET_DEVICE
Expand All @@ -26,7 +29,7 @@ type DeviceCollection = Record<
{
platform?: string;
userAgent?: string;
viewport: Viewport;
viewport: TestViewport;
}
>;

Expand Down Expand Up @@ -57,6 +60,23 @@ const DEVICES: DeviceCollection = {
isLandscape: false,
},
},
[MOBILE_DEVICE_IOS_INSET]: {
userAgent:
'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
platform: 'ios',
viewport: {
width: 375,
height: 667,
deviceScaleFactor: 2,
isMobile: true,
hasTouch: true,
isLandscape: false,
safeAreaInset: {
// smallest iPhone's bottom inset height on vertical position (iPhone 13 mini)
bottom: '34px',
},
},
},
[MOBILE_DEVICE_ANDROID]: {
userAgent:
'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Mobile Safari/537.36',
Expand Down Expand Up @@ -134,7 +154,7 @@ export const openStoryPage = ({
}: {
id: string;
device?: Device;
viewport?: Viewport;
viewport?: TestViewport;
skin?: 'Movistar' | 'Vivo' | 'Vivo-new' | 'O2' | 'Telefonica' | 'Blau';
args?: StoryArgs;
isDarkMode?: boolean;
Expand Down
Loading

0 comments on commit ec771ca

Please sign in to comment.