I'm using Mui V5 and want to change TreeView so it doesnt include collapse/extand icons since I need them to be a part of the TreeItem label component and appear on the left, not right. Also, I want to cancel the indentation of the TreeItems. how can I do that?
I think that what you are trying to do with indentation cannot be directly done through TreeView or TreeItem props. You can remove icons just avoiding defaultCollapseIcon and defaultExpandIcon props.
You can always add some custom styling to achieve what you want. Here's an example to just get a TreeView without icons nor indentation.
const StyledTreeView = styled(TreeView)`
.MuiTreeItem-group {
margin-left: 0;
}
`;
const StyledTreeItem = styled(TreeItem)`
.MuiTreeItem-iconContainer {
display: none;
}
`;
export default function App() {
return (
<StyledTreeView aria-label="tree">
<StyledTreeItem nodeId="1" label="Item 1">
<StyledTreeItem nodeId="2" label="Subitem 1-1" />
</StyledTreeItem>
<StyledTreeItem nodeId="5" label="Item 2">
<StyledTreeItem nodeId="10" label="Subitem 2-1" />
<StyledTreeItem nodeId="6" label="Subitem 2-2">
<StyledTreeItem nodeId="8" label="Subitem 2-2-1" />
</StyledTreeItem>
</StyledTreeItem>
</StyledTreeView>
);
}
The custom style applied to TreeView removes the indentation, and the one applied to StyledTreeItem removes the space assigned to an icon.
Here's a sandbox with an unintended TreeView
Related
I am making a drag n drop sort of game where you match the logos with their corresponding name.
If user matches the logo with the name correctly than the field which you could drop the logo gets additional classes.
Like this:
if (isCorrectMatching) {
event.target.classList.add("dropped");
draggableElement.classList.add("dragged");
event.target.classList.add("dragged");
event.target.setAttribute("draggable", "false");
draggableElement.setAttribute("draggable", "false");
event.target.innerHTML = `<i class="fab fa-${draggableElementBrand}" style="color: ${draggableElement.style.color};"></i>`;
}
If every match is found user can go to next level , my problem is that these additional classes are staying there , how do I remove them ?
I am mapping them out like this:
<div className="containerItems">
{draggableItems.map((x, i) => {
return (
<div className="draggable-items">
<i
onDragStart={(e) => dragStart(e)}
className={`draggable fab fa-${x}`}
id={x}
draggable="true"
ref={draggableOnes.current[i]}
></i>
</div>
);
})}
</div>;
{
matchingPairs.map((x, i) => {
return (
<section className="matching-pairs">
<div className="matching-pair">
<span className="label">{x}</span>
<span
className="droppable"
// ref={droppableOnes.current[i]}
onDragEnter={(e) => dragEnter(e)}
onDragOver={(e) => dragOver(e)}
onDragLeave={(e) => dragLeave(e)}
onDrop={(e) => drop(e)}
data-brand={x}
></span>
</div>
</section>
);
});
}
I can not seem to solve this one, like how do I remove all the classes that I've added when there was a correct matching.
I would like to remove basically everything that I've added in my if (isCorrectMatching) .
I've tried to use refs but it did not work. What is the way to go for this?
In React, you don't directly manipulate DOM elements (well, almost never), including their the class lists. Instead, you keep your state information in the component and use that state information to render the elements that make up your component (including their classes). React will then compare the rendered elements you return with the DOM and make any necessary changes (such as updating the classList). So in your code, when you see that you have a correct matching, you wouldn't directly modify those DOM elements' classList lists, you'd update your state to remember the match, and use that state information in the next render to put the appropriate classes on the elements being rendered.
Here's a simpler example with a tickbox, but it's the same general concept:
const {useState} = React;
const Example = () => {
const [isChecked, setIsChecked] = useState(false);
return <div>
<label>
<input
type="checkbox"
checked={isChecked}
onChange={() => setIsChecked(flag => !flag)}
/>
Ticked
</label>
<div className={isChecked ? "yes" : "no"}>
Example
</div>
</div>;
};
ReactDOM.render(<Example />, document.getElementById("root"));
.yes {
color: green;
}
.no {
color: #d00;
}
label {
user-select: none;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
Note how the state member isChecked determines what classes the div has, and is updated by ticking/unticking the checkbox.
I'm new to javascript, react, and Material-UI so my question (and code sample) may be naive.
I have the following code in a Material-UI TableCell (not a form):
<input type="color" name="backgroundColor" list="categoryColours" id="categoryColour"/>
<datalist id="categoryColours">
{colourOptions.map((val) =>`<option value=${val.value}>${val.value}</option>`)}
</datalist>
I like the colour picker it produces (it renders the 25 colour swabs in a nice grid), but I would like to replace this with the appropriate Material-UI component. Is there such a thing?
I'm going to use material-ui-color. It's not part of the Material-UI library, but it is a compatible module that can do both colour picker and colour swabs.
The current URL is https://www.npmjs.com/package/material-ui-color.
The provided example is:
<div>
<ColorPicker defaultValue="black" palette={paletteObj} />
</div>
There is also a package for Material UI v5 (or MUI) called Mui color input and it's working with React 17 and 18 !
Simply way to use. Color validation available too.
Check the doc here : https://github.com/viclafouch/mui-color-input
import React from 'react'
import { MuiColorInput } from 'mui-color-input'
const MyComponent = () => {
const [value, setValue] = React.useState('#ffffff')
const handleChange = (newValue) => {
setValue(newValue)
}
return <MuiColorInput value={value} onChange={handleChange} />
}
I am calling a component "MyRadioButton" with following props:
<MyRadioButton
label="Radio Group"
theme="custom-red" //this line
error="Field is required "
radioBtns={options}
id="radioBtns"
name="radioBtns"
getValue={this.getValue}
/>
I have created a react component "MyRadioButton" that will accept color name(theme) as props.
export const MyRadioButton = props => {
const {theme} = props;
return (
<div className="my-radio-buttons"> // need to use theme here
<input
onChange={onChange}
type="radio"
/>
</div>
)}
Based on this prop i want to assign the variable in my components scss file, which will take the color code from my custom defined color pallet.
my-radio-button.scss
/* custom color pallet */
$custom-orange: #F060D6;
$custom-red: #BB532E;
$custom-blue: #4C9FEB;
.my-radio-buttons {
.input{
border: 2px solid $custom-red; // i want to assign the color variable based on input prop value to this property
}
}
I have already tried setting variable at css root with javascript and accessing it with variable function var(), it works fine.
But because of some limitations i dont want to use that approach.
also because the color pallet list is huge, i dont want to use separate classes for all of them.
I am looking for some other solution or different approach.
So you can use a combination of custom css variables and your passed theme property. In you css, you would define the basecolor of the border for example:
.my-radio-buttons {
--theme-color: red;
input {
border: 2px solid var(--theme-color);
}
}
This can be updated by your components via componentDidMount or useEffect with the passed theme:
const MyRadioButton = props => {
const { theme } = props;
React.useEffect(() => {
const input = document.querySelector(".my-radio-buttons input");
input.style.setProperty("--theme-color", props.theme);
}, []);
return (
<div className="my-radio-buttons">
<input />
</div>
);
};
Depending on your code style, you can replace the querySelector with a ref.
I have a list that I want to style with Microsoft fabrics react "list" component as seen here:
https://developer.microsoft.com/en-us/fabric#/components/list
(the one with the "Rendering ghost items while the list is scrolling" header).
I try to follow the examples and do the folowing:
import { List } from 'office-ui-fabric-react/lib/List';
import { Image, ImageFit } from 'office-ui-fabric-react/lib/Image';
return (
<div>
{ listItems.length > 0 && listItems.map((item: Project) => {
return (
<div>
<div data-is-focusable={true} className="ms-ListGhostingExample-
itemCell">
<Image
className="ms-ListGhostingExample-itemImage"
src={item.ListUrl.substring(0, item.ListUrl.indexOf("/Lists")) + "/_api/GroupService/GetGroupImage?id" }
width={50}
height={50}
imageFit={ImageFit.cover}
/>
<div className="ms-ListGhostingExample-itemContent">
<div className="ms-ListGhostingExample-itemName"> <a href={item.ListUrl.substring(0, item.ListUrl.indexOf("/Lists"))}>{item.Title}</a></div>
</div></div>
</div>
);
})}
</div>
While I don't get any (syntax) errors, no styling is applied at all. Why does it not work?
In Rendering ghost items while the list is scrolling example via the following reference:
imports import './List.Ghosting.Example.scss';
the expected styling is applied per a List component. In your case those styles could be applied like this:
import 'office-ui-fabric-react/lib/components/List/examples/List.Ghosting.Example.scss';
I want to make a dynamic component. (the dynamic TAG will be a styled component -> emotion)
const Dynamic = ({ tag: Tag, children, ...rest }) =>
<Tag {...rest}>
{ children }
</Tag>
The component will be a styled component like:
const Column = styled(div)({ color: 'red' })
const Row = styled(span)({ color: 'yellow' })
This looks all nice, and working properly, BUUUUUT:
When I try use a DynamicComponent inside another DynamicComponent:
<DynamicComponent tag={Row}>
{
mapOver.map(item=>
<DynamicComponent tag={Column}/>
)
}
</DynamicComponent>
then for some reason the Dynamic children will use the Dynamic Parent's style.
Is there anything I missing?
P.S.:
If instead of using dynamic styles, I do something like this:
<Row>
<Column/>
</Row>
then the styles, classNames, styled tags, are applied properly.
To make it a little more clear:
As you can see the DynamicComponent's will use the parent's styles, classNames, styled tags... (NOT THE BEHAVIOUR I WOULD EXPECT)
Below example creating a dynamic tag name for a styled-component:
// All headings use the same styled-component "Heading" function
const StyledHeading = styled.div`
font-size: ${({level}) => 4/level }em; // <- dynamic font size
font-weight: 300;
margin: 0;
`
// the trick here is the "as={...}" to create dynamic tag name
const Heading = ({level = 1, children}) =>
<StyledHeading as={`h${level}`} level={level}>
{children}
</StyledHeading>
ReactDOM.render([
<Heading>Hello, world!</Heading>,
<Heading level={2}>Title 2</Heading>,
<Heading level={3}>Title 3</Heading>
] ,document.body
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/styled-components#4.4.1/dist/styled-components.min.js"></script>
Reference:
"as" prop documentation
There is a misunderstanding in the usage of styled-components as a tag is intended as HTML tag (input, div and so on). The best way is to define a StyledRow and a StyledColumn separately and use them with appropriate names. This will help also to make your code more readable.