How to modify table row borders (antd)? - reactjs

I am working on displaying a report using a tree table component from ant design.
I would like to make the bottom border of the collapsed parent or of the last expanded child in order to split the report into it's sections.
Current Situation Vs. Desired Effect
Ideally I need a way to set the css class name through an attribute in the table data source.

All border attributes will not work at the level. They must be on the level. So, just giving a class name that modifies the border to a row won't work.
A workaround would be to set a class name using the Antd "rowClassName" prop (this can be set to a function that dynamically returns the class names).
Then, assign the following classes:
.highlight-bottom-border > td {
border-bottom: solid 1px black !important
}
.highlight-top-border > td {
border-top: solid 2px black !important;
border-bottom: solid 2px #6d9eff !important
}
By doing so, the level is modified resulting in a more defined border.

you can customize the className in JSX tags and add css property
You can find the target className in the inspection
.customizeClassName { :global {
.targetAntdClassName {
border: none
} } }

Related

Adding single or multiple className on styledComponent not showing the style on the server

As mentioned in the question title I am trying to style, with ClassName, a component by adding a class to my StyledComponents but despite I believe I added the classes in the right way the style wont show, so I am not sure what I am doing wrong. any clues? I am
talking about the classes:
"sunday" in the styledComponent Date
"active-month" in the styledComponent Date
"active" in the styledComponent text
This is the code:
You still need to use the ampersand (&) to refer back to the parent components, Date and Text.
Pseudoelements, pseudoselectors, and nesting
The ampersand (&) can be used to refer back to the main component.
If you put selectors in without the ampersand, they will refer to
children of the component.
Example:
const Date = styled.div`
....
&.sunday {
background-color: #f5f5f5;
}
&.active-month {
transition: color 0.3s ease-in;
color: black;
}
`;

Prevent DOM element re-render in virtualized tree component using react-window

I want to re implement a tree component to improve its performance. I used the FixedSizeList from react-window. Its working relatively well. It can handle even 100,000 tree node.
My problem is, that I want to animate the little opening triangle of the tree node. The following css responsible for the animation:
.tree-branch::after {
content: '';
display: block;
width: 0;
height: 0;
margin-top: 1px;
margin-left: 23px;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-left: 6px solid rgba(0, 0, 0, 0.7);
opacity: 0.7;
position: absolute;
top: 0;
left: -36px;
transform: rotate(90deg);
animation-duration: 0.3s;
}
.tree-item-closed::after {
transform: rotate(0deg);
}
The animation does not works. Because at each open and close all of the list element divs re-rendering. Then I tried to add itemKey property for the list to help React reusing the divs.
<List
className="List"
height={height}
itemCount={flattenedData.length}
itemSize={32}
width={width}
itemKey={index => flattenedData[index].id} // key defined
>
{Row}
</List>
It does not work either. The divs are not updated instead the whole divs are re-rendered. Is there a proper solution for this problem? How can I prevent the re-rendering?
Here is the whole example: https://codesandbox.io/s/a-quick-react-tree-component-based-on-react-window-tyxnm
To prevent react-window from re-rendering every item in the list, you need to:
Memoize your row-rendering function
Move that function outside the scope of the parent function
Use the itemData prop to communicate between the parent component and per-row render function.
This is the strategy used in the react-window example sandbox here: https://codesandbox.io/s/github/bvaughn/react-window/tree/master/website/sandboxes/memoized-list-items
Here's an example using your code:
https://codesandbox.io/s/a-quick-react-tree-component-based-on-react-window-8psp0
There may be a simpler way to do it using useMemo but I couldn't figure that out.
If you examine the DOM nodes using Chrome dev tools, you'll see that DOM nodes are no longer being re-created for the entire tree when one node is expanded. This removes the flicker that you'd see before (in Chrome, but not in Firefox) when selecting a new node.
But there's also something else that's preventing your rotation animations from working properly. In the CodeSandbox example I linked above, I added some animations on the border properties to show how animation of some CSS properties is working, but animation of the transform CSS properties is not working. I suspect this problem has nothing to do with react-window, so you'll probably want to debug it separately to figure out why your transforms aren't animating but other properties are animating OK.

Why might a react app perform poorly in the layout rendering stage?

In here we have boxes which can have children. If you click on a box, it will add a child for it.
https://codesandbox.io/s/suspicious-fire-e2jes
What I struggle to understand is why does it take increasingly long to create a child as the max depth increases?
According to performance audit, the problem is not in the data structure format where you define parent for a node, rather than defining all children for a node.
So the issue is layout. From what I could find, one anti-pattern is where you read-write-read-write styles over and over which forces browser to calculate layout before each read. I don't see anything of this sort in my code.
The issue is definitely layout. But not your layout.
I tried your code without loading your style.css file.
And it works as expected.
I created a similar use case without react. Pure css here with same dom structure:
const node = (id, children) => `
<div class='node'>${id}</div>
<div class='children'>
<div class='nodeAndChildren'>
${children}
</div>
</div>
`
document.getElementById("app").innerHTML = `
<div class='nodeAndChildren'>
${node(0, node(1, node(2, node(3, node(4, node(5, node(6, node(7, 'end'))))))))}
</div>
`;
.App {
font-family: sans-serif;
text-align: center;
}
.nodeAndChildren {
display: grid;
grid-auto-flow: column;
}
.node {
width: 100px;
border: 1px solid black;
}
.children {
display: grid;
}
<div id='app'/>
You can see how slow this is, even here.
This seems like a weird pattern matching issue for css or grid layout.
So, i tried it only with inline styling, was still slow
https://codesandbox.io/embed/displaygrid-bug-bcgsm
My suggestion is to use css columns instead of grid. Or just flex boxes with wrap.

How to use material-ui (alpha) with styeld-components properly?

I've been trying to use styled-components with the alpha version of material-ui
According to the documentation, this should work out of the box.
This code:
const StyledButton = styled(Button)`
color: red;
text-transform: uppercase;
`;
return <StyledButton>Button</StyledButton>;
will generate something like this:
<button tabindex="0" class="MuiButtonBase-root-3177716317 sc-bdVaJa sxRGN" type="button" role="button">
...
</button>
It looks good.
However, the only problem I have is the order of the injected CSS styles (pic). Styles from styled-components are injected before MUI's styles which make their priority lower.
Is there any way to solve this without using !important?
In the current release (i.e. non-alpha) version, what you've asked would indeed require !important basis:
"Note that CSS properties defined inline are given priority over those defined in a CSS class. You need to use !important to take precedence over the inline style."
Ref: http://www.material-ui.com/#/customization/styles
Perhaps the alpha hasn't quite moved away from this inline requirement yet or it is still a work-in-progress.
What I've done to overcome this sort of thing myself is to (unfortunately) recreate the entire CSS on a standard <button> element when I need such a solution. Here's an example of how I'm doing that with a react-photonkit "theme"
// #flow
import styled from 'styled-components';
const PhotonStyledButton = styled.button`
font-family: Arial, Roboto, Helvetica, sans-serif;
height: 30px;
display: inline-block;
padding: 6px 12px;
margin-bottom: 0;
font-size: 12px !important;
line-height: 1.4;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: default;
background-image: none;
border: 1px solid transparent;
border-radius: $default-border-radius;
box-shadow: 0 1px 1px rgba(0,0,0,.06);
-webkit-app-region: no-drag;
&:focus {
outline: none;
box-shadow: none;
}
color: #333;
border-top-color: #c2c0c2;
border-right-color: #c2c0c2;
border-bottom-color: #a19fa1;
border-left-color: #c2c0c2;
background-color: #fcfcfc;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fcfcfc), color-stop(100%,#f1f1f1));
background-image: -webkit-linear-gradient(top, #fcfcfc 0%, #f1f1f1 100%);
background-image: linear-gradient(to bottom, #fcfcfc 0%, #f1f1f1 100%);
&:active {
background-color: #ddd;
background-image: none;
}
`;
export default PhotonStyledButton;
styled-components in general is compatible with any component library. When you write styled(AnotherComponent) we take that component and inject an automatically generated class name. This means essentially it's the same thing as writing <AnotherComponent className="sc-asdf123" />!
The current version of material-ui specifically is a bit difficult to custom style because it uses inline styles. From the MaterialUI documentation:
Note that CSS properties defined inline are given priority over those defined in a CSS class. You need to use !important to take precedence over the inline style.
This means simply using styled(MaterialButton) won't work as the passed-in styles will mostly just be ignored. You need to bump the specificity of your styles to override the inline styles that material-ui ships with. (this article is a great primer on specificity if you're not familiar with the details)
Answer for the alpha version of material-ui
The current alpha version of material-ui has switched to using JSS under the hood. (which is CSS in JS not inline styles, like styled-components) This means the issue is likely to be that the styled-components styles are injected after the default material-ui styles. (which are injected by JSS)
JSS supports custom injection points so you might be able to add a <!-- jss --> comment to the HEAD of your HTML to make sure JSS injects its CSS before the styled-components injected CSS?
Answer for the current version of material-ui
There are two ways to bump the specificity of the styled-components injected styles, one more tedious and one a bit more "hacky". The first one is adding !important at the end of all of your styles:
const Button = styled(MaterialButton)`
color: blue!important;
`
While this works in most cases it gets tedious very fast when you have lots of custom styling in a component. The better way is to use the class name hack:
const Button = styled(MaterialButton)`
&&& {
color: blue;
}
`
These ampersands get replaced with the automatically generated class name meaning the outputted CSS looks something like this:
.sc-asdf123.sc-asdf123.sc-asdf123 {
color: blue;
}
This bumps specificity by a big margin, thusly overriding the defined inline styles, and is less annoying than having to put !important after each rule.
Now we can use <!-- material-ui --> to make sure the styles are injected after it.
By default, Material-UI will look for a html comment named to inject styles after. By adjusting the placement of this comment within your HTML body you can control the order that CSS rules are applied to your components. (ref)

How to change label background color dynamically?

For instance, there is a label (without textfield!):
Ext.create('Ext.form.Label', {
id: "lb1",
height: 20,
html: "Title"
cls: 'cls1'
})
How can I change the background color dynamically without a CSS?
There are couple of ways to achieve that, but all of them use manipulate CSS.
1. Change css class on label
CSS classes
.cls1 {
background-color: #fff;
}
.cls2 {
background-color: #ccc;
}
ExtJS
label.removeCls('cls1');
label.addCls('cls2');
2. Change style on DOM Element
label.getEl().setStyle('background', '#CCC');
Good Luck!

Resources