Is there a way to stack sticky headers in react native? - reactjs

I'm having a table (two directional scroll) with a sticky header showing the title of columns. If it wouldn't support two directional scroll, I could just place the header outside of the scroll view, but it's not the case.
I want to implement grouping of rows (basically SectionList with stickySectionHeadersEnabled). There an upcoming section header replaces the previous section header, which is the expected behaviour for my case. However, I want to have two sticky headers stay in place (the table header, and the current section header). I couldn't find a way to set the top value for the sticky headers as in html:
.container {
width: 200px;
height: 200px;
position: relative;
overflow: scroll;
}
.tableHeader, .sectionHeader {
position: sticky;
}
.tableHeader {
top: 0;
}
.sectionHeader {
top: 20px;
}
.section {
height: 500px;
width: 500px;
}
.section:last-of-type {
background: wheat;
}
<div class='container'>
<div class='tableHeader'>Table header</div>
<div class='section'>
<div class='sectionHeader'>Section header 1</div>
</div>
<div class='section'>
<div class='sectionHeader'>Section header 2</div>
</div>
</div
Any way to earn the above in react native?
I was thinking about the implementation of nesting two ScrollViews, where the outer could be horizontal, and it could have the first child as the table header, and the second is the SectionList. It could work, but not being able to scroll diagonally is very annoying for me, had a hard time to implement it on ios, and wasn't even able to do it on android, so it would be a last case.

You can use a FlatList with stickyHeaderIndices where the indices are the indices of the headers in your array.
const renderItem = ({ item }) => <Item title={item.title} />;
<FlatList
data={DATA}
stickyHeaderIndices={[0, 6]}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
For the diagonal scroll, it should work on iOS with directionalLockEnabled set to false according to the docs but it doesn't.
For both ScrollViews to work on android the nestedScrollEnabled property should be set to true.
Here's a snack with an implementation, it doesn't seem to work on the web but it works on the iOS and android emulators:
https://snack.expo.dev/yyz6ro3Hi

Related

React: Absolute Position In Child Components

Introduction: I have a React component structure that looks like this.
-- ParentComponent.tsx --
<div>Some Content Here</div>
<ChildComponent/>
<div style={{ position: "relative", zIndex: "1" }}>
Some Other Content -- should be covered when the absolutely positioned content
inside of ChildComponent renders on the screen!
</div>
-- ChildComponent.tsx --
/* at the top of my render method */
const [booleanCondition, setBooleanCondition] = useState(false);
const toggleBooleanCondition = () => { setBooleanCondition(!booleanCondition); };
...
/* much later, in the return value of render method */
<div style={{ position: "relative", zIndex: "2" }}>
Some Content Here, capable of calling toggleBooleanCondition()
{ booleanCondition ?
<div style={{ position: "absolute", width: "400px", height: "400px" }}>
Some Content Here. Should definitely cover the bottom <div> in parent!
</div>
: <></>
</div>
The toggle logic definitely works. The problem is, I would expect the div in ChildComponent.tsx to sit cleanly on top of the div in ParentComponent.tsx, which has a smaller z-index. However, this is not the case: the screenshot below shows that elements are being rendered in a random sort of order.
I feel like the issue may be due to different components assigning different meanings to their own z-indexes. No matter how I played with position: relative, and z-index: , nothing seemed to change. Does anybody know of a reliable solution to this problem??

Different colour for react-table headers

Having trouble with styling table created by react-table library.
Please find the design below.
Table is created the way it is shown in documentation. Is it possible to colour headers as shown in design?
Thank you in advance
P.S.
Here is the code snippet from documentation
To create headers I need to create an array. So i cant change style for a specific header (actually I can provide element to render, but it will be rendered inside the element)
Check this, there are class names added to the data where the data should be styled differently. I think that's what you need.
You can use any react component or JSX to display content in column headers, cells and footers.
const columns = [
{
Header: () => (
<span>
<i className="fa-tasks" /> Progress
</span>
)
}
]
kindly check on this link for further details
https://github.com/tannerlinsley/react-table/tree/v6#custom-cell-header-and-footer-rendering
Had to use a workaround.
As Taha Jamil mentioned you can any JSX to render inside of the Header. By adjusting some styles you will get something like this:
{
Header: () => {
return(
<div
style={{
backgroundColor: "red",
position: "absolute",
width: "100%",
height: "100%",
top: "0px",
left: "0px",
padding: "12px 20px",
}}
>
Title
</div>
);
}
}
Not the best solution, but works

Unable to set Nuka Carousel slide content height

I can't get the content of my nuka-carousel slides to be the same height. Setting heightMode="max" on the carousel sets the slide heights equal, but trying to expand the slide content isn't working right.
I've tried setting height on the slides to 100%, inherit, 100vh but no matter what, the slides expand to maybe 2-20x what they should be (depending on the div with the most content).
I've also tried using flexbox with flex:1 and I've tried with css-grid. Nothing seems to help
const Item = ({ children }) => (
<div
style={{
boxShadow: "rgb(153, 153, 153) 2px 2px 4px 2px"
// height: "100%"
// height: "100vh"
/// height: 'inherit'
}}
>
{children}
</div>
);
<Carousel
wrapAround
heightMode="max"
slidesToShow={1.25}
cellAlign="center">
{/* Item components with varying content */}
</Carousel>
Here's a codesandbox, If anyone has any suggestions I'd appreciate it.
https://codesandbox.io/s/brave-khorana-bowrz?file=/src/index.js

Autosizer making a div of height and width 0

My configuration goes as follows:
// Calling it
<div style={{ width: 1000, height: 800 }}>
<MyComponent />
</div>
// MyComponent.js
<InfiniteLoader { ...itsProps }>
{({ onRowsRendered }) => (
<AutoSizer>
{({ width, height }) => (
<Table
width={ width }
width={ height }
...
The problem is that this is what is being rendered:
<div style="overflow: visible; height: 0px; width: 0px;">
<div class="ReactVirtualized__Table" role="grid">
...
So nothing is seen in the screen.
Maybe I misunderstood Autosizer usage, so I set it up to adjust itself to the parent's width/height.
What am I missing?
The height: 0 style in the snippet of HTML you shared isn't actually a problem, because of the overflow: visible style. This is the way AutoSizer is meant to work.
I suggest you read the "Using AutoSizer" docs page. I suspect your problem is similar to one of the common issues mentioned there:
AutoSizer expands to fill its parent but it will not stretch the parent. This is done to prevent problems with flexbox layouts. If AutoSizer is reporting a height (or width) of 0- then it's likely that the parent element (or one of its parents) has a height of 0. One easy way to test this is to add a style property (eg background-color: red;) to the parent to ensure that it is the correct size. (eg You may need to add height: 100% or flex: 1 to the parent.)

How to disable click events for props.children in React?

How can any click events be disabled for props.children?
const Example = props => (
<div>
<div>This can be clicked</div>
{props.children} /* These can't be clicked */
</div>
)
I am rendering a PDF page using react-pdf and want the user to be able to drag a custom selection marquee (like in Photoshop...). As it is, the PDF page under or inside the marquee element still registers mouse events upon dragging, like text selection.
There is an easy, but not robust way to do this:
const Example = props => (
<div style={{pointerEvents:'none'}}>
<div style={{pointerEvents:'auto'}}>This can be clicked</div>
{props.children}
</div>
)
It is not robust, because if any of the children have pointer-events set to auto, they will be clickable too. See if it fits your needs. Also, it will kill hover and other mouse events.
Use CSS Grid to put a div on top!
A transparent div rendered on top of another div will intercept click events.
CSS Grid can be used (abused?) to make a single grid area (using grid-template-areas) and assign multiple elements to it (using grid-area).
JSX
const ClickGuard = ({allow, block}) => (
<div className='click-guard-area'>
<div className='click-guard-allowed'>{props.allow}</div>
<div className='click-guard-block' />
<div className='click-guard-blocked'>{props.block}</div>
</div>
)
CSS
.click-guard-area {
display: grid;
grid-template-areas: 'click-guard';
height: 100%;
width: 100%;
}
.click-guard-allowed {
grid-area: click-guard;
height: 100%;
width: 100%;
z-index: 2;
}
.click-guard-block {
grid-area: click-guard;
height: 100%;
width: 100%;
z-index: 1;
}
.click-guard-blocked {
grid-area: click-guard;
height: 100%;
width: 100%;
}
Note that ClickGuard expects two props: allow and block. These should be JSX. The React docs explain passing React elements here.
<ClickGuard
allow={<div>I can be clicked!</div>}
block={<div>No clicks for me. 😞</div>}
/>
You cannot change the props within an element thus its children props.
An alternative solution may be possible with React.cloneElement,
Here is a simple peace of code for you:
const Example = props => (
<div>
<div>This can be clicked</div>
{props.children.map((child)=>
React.cloneElement(child, {
disabled: true
})
)}
</div>
)

Resources