Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chromium workaround for CSS mask-image bug #7855

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/eui/changelogs/upcoming/7855.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**Bug fixes**

- Fixed a Chrome/Edge CSS `mask-image` bug that was affecting scroll overflow shadow utilties
193 changes: 147 additions & 46 deletions packages/eui/src-docs/src/views/modal/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,164 @@ import {
EuiButton,
EuiModal,
EuiModalBody,
EuiModalFooter,
EuiModalHeader,
EuiModalHeaderTitle,
EuiCodeBlock,
EuiSpacer,
useGeneratedHtmlId,
} from '../../../../src';
EuiHealth,
EuiLink,
EuiInMemoryTable,
} from '../../../../src/components';

export default () => {
const [isModalVisible, setIsModalVisible] = useState(false);
import _times from 'lodash/times';

const closeModal = () => setIsModalVisible(false);
const showModal = () => setIsModalVisible(true);
const firstNames = [
'Very long first name that will wrap or be truncated',
'Another very long first name which will wrap or be truncated',
'Clinton',
'Igor',
undefined,
'Drew',
null,
'Rashid',
undefined,
'John',
];

const lastNames = [
'Very long last name that will wrap or be truncated',
'Another very long last name which will wrap or be truncated',
'Gormley',
'Motov',
'Minarik',
'Raines',
'Král',
'Khan',
'Sissel',
'Dorlus',
];

const modalTitleId = useGeneratedHtmlId();
const github = [
'martijnvg',
'elissaw',
'clintongormley',
'imotov',
'karmi',
'drewr',
'HonzaKral',
'rashidkpc',
'jordansissel',
'silne30',
];

const createUsers = () => {
return _times(20, (index) => {
return {
id: index,
firstName: index < 10 ? firstNames[index] : firstNames[index - 10],
lastName: index < 10 ? lastNames[index] : lastNames[index - 10],
github: index < 10 ? github[index] : github[index - 10],
dateOfBirth: new Date(
1980,
Math.floor(Math.random() * 12),
Math.floor(Math.random() * 27) + 1
),
nationality: 'nationality',
online: index % 2 === 0,
};
});
};

export const Table = () => {
const columns = [
{
field: 'firstName',
name: 'First Name',
sortable: true,
truncateText: true,
},
{
field: 'lastName',
name: 'Last Name',
truncateText: true,
},
{
field: 'github',
name: 'Github',
render: (username: string) => (
<EuiLink href={`https://github.com/${username}`} target="_blank">
{username}
</EuiLink>
),
},
{
field: 'dateOfBirth',
name: 'Date of Birth',
dataType: 'string',
render: () => `hello`,
sortable: true,
},
{
field: 'nationality',
name: 'Nationality',
},
{
field: 'online',
name: 'Online',
dataType: 'boolean',
render: (online: boolean) => {
const color = online ? 'success' : 'danger';
const label = online ? 'Online' : 'Offline';
return <EuiHealth color={color}>{label}</EuiHealth>;
},
sortable: true,
},
];

const sorting = {
sort: {
field: 'dateOfBirth',
direction: 'desc',
},
} as const;

return (
<>
<EuiButton onClick={showModal}>Show modal</EuiButton>
<EuiInMemoryTable
tableCaption="Demo of EuiInMemoryTable"
items={createUsers()}
columns={columns as any}
pagination={true}
sorting={sorting}
/>
);
};

{isModalVisible && (
<EuiModal aria-labelledby={modalTitleId} onClose={closeModal}>
<EuiModalHeader>
<EuiModalHeaderTitle id={modalTitleId}>
Modal title
</EuiModalHeaderTitle>
</EuiModalHeader>
export default () => {
const [isModalVisible, setIsModalVisible] = useState(false);

<EuiModalBody>
This modal has the following setup:
<EuiSpacer />
<EuiCodeBlock language="html" isCopyable>
{`<EuiModal aria-labelledby={titleId} onClose={closeModal}>
<EuiModalHeader>
<EuiModalHeaderTitle title={titleId}><!-- Modal title --></EuiModalHeaderTitle>
</EuiModalHeader>
const closeModal = () => setIsModalVisible(false);
const showModal = () => setIsModalVisible(true);

let modal;

<EuiModalBody>
<!-- Modal body -->
</EuiModalBody>
if (isModalVisible) {
modal = (
<EuiModal onClose={closeModal}>
<EuiModalHeader>
<EuiModalHeaderTitle>
<h1>title</h1>
</EuiModalHeaderTitle>
</EuiModalHeader>

<EuiModalFooter>
<EuiButton onClick={closeModal} fill>
Close
</EuiButton>
</EuiModalFooter>
</EuiModal>`}
</EuiCodeBlock>
</EuiModalBody>
<EuiModalBody>
<Table />
</EuiModalBody>
</EuiModal>
);
}

<EuiModalFooter>
<EuiButton onClick={closeModal} fill>
Close
</EuiButton>
</EuiModalFooter>
</EuiModal>
)}
</>
return (
<div>
<EuiButton onClick={showModal}>Show modal</EuiButton>
{modal}
</div>
);
};
3 changes: 1 addition & 2 deletions packages/eui/src/components/modal/modal.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ export const euiModalStyles = (euiThemeContext: UseEuiTheme) => {
z-index: ${euiTheme.levels.modal};
min-inline-size: ${euiFormVariables(euiThemeContext).maxWidth};
max-inline-size: calc(100vw - ${euiTheme.size.base});
/* TODO: Consider restoring this once https://bugs.chromium.org/p/chromium/issues/detail?id=1229700 is resolved */
/* overflow: hidden; Ensure long, non-breaking text doesn't expand beyond the modal bounds */
overflow: hidden; /* Ensure long, non-breaking text doesn't expand beyond the modal bounds */

${euiCanAnimate} {
animation: ${euiAnimSlideInUp(euiTheme.size.xxl)}
Expand Down
12 changes: 10 additions & 2 deletions packages/eui/src/global_styling/mixins/_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,18 @@ const euiOverflowShadowStyles = (
}
}

// Chrome+Edge has a very bizarre edge case bug where `mask-image` stops working
// This workaround forces a stacking context on the scrolling container, which
// hopefully addresses the bug. @see:
// - https://issues.chromium.org/issues/40778541
// - https://github.com/elastic/kibana/issues/180828
// - https://github.com/elastic/eui/pull/6343#issuecomment-1302732021
const chromiumMaskWorkaround = 'transform: translateZ(0);';

if (direction === 'y') {
return `mask-image: linear-gradient(to bottom, ${gradient});`;
return `mask-image: linear-gradient(to bottom, ${gradient}); ${chromiumMaskWorkaround}`;
} else {
return `mask-image: linear-gradient(to right, ${gradient});`;
return `mask-image: linear-gradient(to right, ${gradient}); ${chromiumMaskWorkaround}`;
}
};

Expand Down
5 changes: 5 additions & 0 deletions packages/eui/src/global_styling/mixins/_shadow.scss
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,9 @@
} @else {
@warn "euiOverflowShadow() expects direction to be 'y' or 'x' but got '#{$direction}'";
}

// Chrome+Edge has a very bizarre edge case bug where `mask-image` stops working
// This workaround forces a stacking context on the scrolling container, which
// hopefully addresses the bug. @see https://github.com/elastic/eui/pull/7855
transform: translateZ(0);
}
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ exports[`global utility styles generates static global styles 1`] = `
,
rgb(255,0,0) calc(100% - 8px),
rgba(255,0,0,0.1) 100%
);
); transform: translateZ(0);
;}
.eui-xScrollWithShadows{

Expand Down Expand Up @@ -221,7 +221,7 @@ exports[`global utility styles generates static global styles 1`] = `
,
rgb(255,0,0) calc(100% - 8px),
rgba(255,0,0,0.1) 100%
);
); transform: translateZ(0);
;}[class*='eui-showFor']{display:none!important;}
.eui-hideFor--xl {
@media only screen and (min-width: 1200px) {
Expand Down
Loading