Introduction of React Native zIndex
This is an outline on React Native zIndex. To specify the stack order of an element, zIndex is used. The element which has a greater stack order is positioned in front of the element which has a low stack order. Z-index always works on the elements which are positioned as absolute, sticky, fixed and relative. The default value of zIndex is always auto. It has an additional feature that the zIndex can also be nested. zIndexes are generally quite complex to manage, the dropdown is needed to have a greater zIndex and the same goes with tooltips and popovers. This article explains the use of zIndexes with examples.
Syntax:
import ZIndex from 'react-z-index'
ZIndex.setVars({
Modal: 30,
Overlay: 20,
Dropdown: 10
})
Working of React Native zIndex with Examples
The syntax mentioned above is used for applying zIndex it is used to structure the elements in a systematic manner. Higher stack ordered elements are placed ahead of the lower stack ordered elements. In the example below, four elements are structured according to their stack values. The element Rahul has the highest stack value and it follows with Anmol, Aadarsh, and Ankush. While hovering over the elements, an arrow is displayed from different directions on different elements.
To implement the code below, the files used are:
1. App.tsx
/** @jsxjsx */
import { jsx } from '@emotion/core'
import styled from '@emotion/styled';
import Partition, {
} from './Partition';
import {
TooltipPointingDirection,
} from './Tooltip';
import usePromotableZIndex from './usePromotableZIndex';
export enumGridArea {
Rahul = 'Rahul',
Anmol = 'Anmol',
Ankush = 'Ankush',
Aadarsh = 'Aadarsh',
}
const Root = styled.div`
width: 94vw;
height: 97vh;
display: grid;
grid-template-rows: repeat(2, 1fr);
grid-template-columns: repeat(3, 1fr);
grid-gap: 3vmin;
grid-template-areas:
"${GridArea.Rahul} ${GridArea.Rahul} ${GridArea.Aadarsh}"
"${GridArea.Anmol} ${GridArea.Anmol} ${GridArea.Ankush}";
`;
const App = () => {
constzIndices = {
Rahul: 10,
Anmol: 20,
Ankush: 30,
Aadarsh: 40,
}
const {getZIndex
, promoteZIndex
, restoreZIndex} = usePromotableZIndex({
normalZIndices: zIndices,
promotedZIndex: 100,
})
return (
<Root>
<Partition
color='#5df0eb'
label='Rahul'
tooltipContent={'D.S.'}
gridArea={GridArea.Rahul}
tooltipPointingDirection={TooltipPointingDirection.Up}
getZIndex={() =>getZIndex('Rahul')}
promoteZIndex={() =>promoteZIndex('Rahul')}
restoreZIndex={restoreZIndex}
/>
<Partition
color='#bbe854'
label='Anmol'
tooltipContent={'D.A.'}
gridArea={GridArea.Anmol}
tooltipPointingDirection={TooltipPointingDirection.Up}
getZIndex={() =>getZIndex('Anmol')}
promoteZIndex={() =>promoteZIndex('Anmol')}
restoreZIndex={restoreZIndex}
/>
<Partition
color='#9464d9'
label='Ankush'
tooltipContent={'B.A.'}
gridArea={GridArea.Ankush}
tooltipPointingDirection={TooltipPointingDirection.Right}
getZIndex={() =>getZIndex('Ankush')}
promoteZIndex={() =>promoteZIndex('Ankush')}
restoreZIndex={restoreZIndex}
/>
<Partition
color='#f25a76'
label='Aadarsh'
tooltipContent={'R.A.'}
gridArea={GridArea.Aadarsh}
tooltipPointingDirection={TooltipPointingDirection.Down}
getZIndex={() =>getZIndex('Aadarsh')}
promoteZIndex={() =>promoteZIndex('Aadarsh')}
restoreZIndex={restoreZIndex}
/>
</Root>
);
}
export default App;
2. Partition.tsx
/** @jsxjsx */
import { jsx
, css } from '@emotion/core'
import styled from '@emotion/styled';
import {
GridArea,
} from './App';
import { useState } from 'react';
import Tooltip
, {
TooltipPointingDirection,
} from './Tooltip';
const Root = styled.div`
position: relative;
color: black;
font-size: 4rem;
display: flex;
justify-content: center;
align-items: center;
opacity: 0.7;
&:hover {
opacity: 2;
}
interface Props {
color: string
label: string
tooltipContent: string
tooltipPointingDirection: TooltipPointingDirection
gridArea: GridArea
getZIndex: () => number
promoteZIndex: () => void
restoreZIndex: () => void
}
const Partition = (props: Props) => {
const {
color
, gridArea
, label
, promoteZIndex
, restoreZIndex
, getZIndex
, tooltipContent
, tooltipPointingDirection,
} = props;
const [isTooltipShown, setIsTooltipShown] = useState<boolean>(false);
constonMouseEnter = () => {
promoteZIndex();
setIsTooltipShown(true);
}
constonMouseLeave = () => {
setIsTooltipShown(false);
restoreZIndex();
}
let tooltip: React.ReactElement<any> | null;
if (isTooltipShown === true) {
tooltip = (
<Tooltip
content={tooltipContent}
direction={tooltipPointingDirection}
color={color}
/>
);
} else {
tooltip = null;
}
return (
<Root
css={css`
background-color: ${color};
grid-area: ${gridArea};
z-index: ${getZIndex()};
`}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
{tooltip}
{label}
</Root>
)
}
export default Partition;
3. Tooltip.tsx
/** @jsxjsx */
import { jsx
, css
,Interpolation } from '@emotion/core'
import styled from '@emotion/styled';
export enumTooltipPointingDirection{ Up
, Down
, Right,
}
const Root = styled.div`
position: absolute;
width: 25vw;
height: 25vh;
background-color: black;
display: flex;
justify-content: center;
align-items: center;
&::after {
position: absolute;
content: '';
background-color: inherit;
width: 50vmin;
height: 10vmin;
}
`
interface Props {
direction: TooltipPointingDirection
content: string;
color: string;
}
const Tooltip = (props: Props) => {
const {direction
, color
, content} = props;
let positionStyle: Interpolation;
if (direction === TooltipPointingDirection.Up) {
positionStyle = css`
color: ${color};
top: 70%;
left: 40%;
transform: translateX(-40%);
&::after {
bottom: calc(100% - 1px);
left: 49%;
transform: translateX(-49%);
clip-path: polygon(49% 0, 0 99%, 99% 99%);
}
`
} else if (direction === TooltipPointingDirection.Down) {
positionStyle = css`
color: ${color};
bottom: 70%;
left: 40%;
transform: translateX(-40%);
&::after {
top: calc(100% - 1px);
left: 49%;
transform: translateX(-49%);
clip-path: polygon(99% 0, 0 0, 49% 99%);
}
`
} else {
positionStyle = css`
color: ${color};
top: 49%;
right: 79%;
transform: translateY(-49%);
&::after {
top: 49%;
left: calc(100% - 1px);
transform: translateY(-49%);
clip-path: polygon(0 0, 0 99%, 99% 49%);
}
`
}
return (
<Root css={positionStyle}>
{content}
</Root>
)
}
export default Tooltip;
4. index.tsx
/** @jsxjsx */
import {
jsx
} from '@emotion/core';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();
5. react-app-env.d.ts
/// <reference types="react-scripts" />
6. serviceWorker.ts
constisLocalhost = Boolean(
window.location.hostname === 'localhost' ||
window.location.hostname === '[::1]' ||
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
type Config = {
onSuccess?: (registration: ServiceWorkerRegistration) => void;
onUpdate?: (registration: ServiceWorkerRegistration) => void;
};
export function register(config?: Config) {
if (process.env.NODE_ENV === 'production'
&&
'serviceWorker'
in navigator) {
constpublicUrl = new URL(
(process as {
env: {
[
key: string
]: string
}
}).env.PUBLIC_URL,
window.location.href
);
if (publicUrl.origin !== window.location.origin) {
return;
}
window.addEventListener('load', () => {
constswUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
checkValidServiceWorker(swUrl
, config);
navigator.serviceWorker.ready.then(() => {
console.log(
'x ' +
'y'
);
});
} else {
registerValidSW(swUrl, config);
}
});
}
}
function registerValidSW(swUrl: string
, config?:Config) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
constinstallingWorker = registration.installing;
if (installingWorker == null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
console.log(
'x' +
'y'
);
if (config&&config.onUpdate) {
config.onUpdate(registration);
}
} else {
console.log('cached content');
if (config&&config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
})
.catch(error => {
console.error('Error'
, error);
});
}
function checkValidServiceWorker(swUrl: string
, config?:Config) {
fetch(swUrl)
.then(response => {
constcontentType = response.headers.get('content-type');
if (
response.status === 404 ||
(contentType != null &&contentType.indexOf('javascript') === -1)
) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
registerValidSW(swUrl
, config);
}
})
.catch(() => {
console.log(
'No network'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}
7. usePromotableZIndex.ts
import {
useState,
} from 'react';
constretrieveKey = <T
, K extends keyof T>(obj: T
, key: K): T[K] =>obj[key];
interface Input<K extends string | number | symbol> {
normalZIndices: Record<K
, number>
promotedZIndex: number
}
constusePromotableZIndex = <K extends string | number | symbol>(input: Input<K>) => {
const {normalZIndices
, promotedZIndex} = input;
type SiblingName = keyoftypeofnormalZIndices
const [promotedElementName
, setPromotedElementName] = useState<SiblingName | undefined>(undefined);
constgetZIndex = (siblingName: SiblingName) =>
(promotedElementName === siblingName) ?
promotedZIndex :retrieveKey(normalZIndices
, siblingName);
constpromoteZIndex = (siblingName: SiblingName) =>setPromotedElementName(siblingName);
constrestoreZIndex = () =>setPromotedElementName(undefined);
return {
getZIndex
, promoteZIndex
, restoreZIndex,
}
}
export default usePromotableZIndex;
Output:
Conclusion
On the basis of above discussion, we understood zindex, its syntax, and using zIndex function with an example. The example will help in understanding the application of zIndex in React native. This article will help the coders in understanding and using zIndexes according to their requirements.
Recommended Articles
This is a guide to React Native zIndex. Here we also discuss the introduction and working of zindex along with different examples and its code implementation. You may also have a look at the following articles to learn more –