I am using npm to show develop a widget.
I want to use material-ui Ratin component and I have integrate it. But when I place the widget in a webpage, it has a html font-size: 62.5%, so the component is too small because in the icon style, there are a 1em unit in height and in width.
screenshot.
This is my code:
import React from 'react';
import Rating from '#material-ui/lab/Rating';
import Typography from '#material-ui/core/Typography';
import Box from '#material-ui/core/Box';
import { withStyles } from '#material-ui/core/styles';
import StarOutlineIcon from '#material-ui/icons/StarOutline';
const styles = theme => ({
iconFilled:{
color:theme.palette.primary.main,
},
iconEmpty:{
color:theme.palette.primary.main
}
})
class SimpleRating extends React.Component{
state = {
disabled: false,
rating: 0,
opinion: "",
};
changeRating(event, newRating) {
this.setState({
rating: newRating,
disabled: true
});
this.props.send_rating(newRating)
}
defaultLabelText(value) {
let text="sin calificación"
if (value===1){
text = "una estrella"
}
else if (value>1 && value<=5) {
text = ""+ value + " estrellas"
}
return(text)
}
render() {
const { classes } = this.props;
return (
<div>
<Box component="fieldset" mb={3} borderColor="transparent">
<Typography component="legend"></Typography>
<Rating
classes={{
iconFilled: classes.iconFilled,
iconEmpty: classes.iconEmpty
}}
emptyIcon = {<StarOutlineIcon></StarOutlineIcon>}
name={"rating_"+this.props.number}
disabled={this.state.disabled}
getLabelText={this.defaultLabelText.bind(this)}
onChange={this.changeRating.bind(this)}
value={this.state.rating}
/>
</Box>
</div>
);
}
}
export default withStyles(styles)(SimpleRating);
Althougth I have been able to change the color with the styles, I cannot modify that down.
How can I change that properties of the icon?
EDIT:
If i use the class icon in css i change the parent of the star icons while they continue with 1em x 1em size.
screenshot with changes in icon
To increase the size of the rating icons, we can use font-size. Using height and width will not work as it increases the size of the container they're in.
For example:
<Rating
name="rating"
value={starValue}
precision={0.1}
size="large"
readOnly
sx={{
fontSize: "4rem"
}}
/>
will increase the size of the icon further than just .MuiRating-sizeLarge which is their size if you set size="large". For reference, that size is about 1.8rem.
Have you tried to set the icon class of the rating component to a class which defines a new width and height?
const styles = theme => ({
iconFilled:{
color:theme.palette.primary.main,
},
iconEmpty:{
color:theme.palette.primary.main
},
//just some sample values
icon: {
width: 64,
height: 64
})
and then:
<Rating
classes={{
iconFilled: classes.iconFilled,
iconEmpty: classes.iconEmpty,
icon: classes.icon
}}
emptyIcon = {<StarOutlineIcon></StarOutlineIcon>}
name={"rating_"+this.props.number}
disabled={this.state.disabled}
getLabelText={this.defaultLabelText.bind(this)}
onChange={this.changeRating.bind(this)}
value={this.state.rating}
/>
Finally I solve it with this code because I was no able to enter to the icon itself:
icon = {<StarIcon style={{width:"32px",height:"32px"}}></StarIcon>}
emptyIcon = {<StarOutlineIcon style={{width:"32px",height:"32px"}}></StarOutlineIcon>}
Related
I have an app that gets data of employees and displays their attendance inside the company building.
Each employee is assigned a card and all employees are displayed inside a grid.
I would like to do 2 things:
give a background to the whole grid, so that if there's not enough employees to fill the grid, it would be gray
give each card a white line in between, by either a gap between the cards or a border
How do I do that?
If I apply a background color to the grid, the spacing of the cards doesn't apply (since there are no cards).
If I try to add another card by an after element, only a small, single "card-like" element appears, which is not enough to fill the whole space.
//CardGrid.tsx
import React from "react";
import Card from "./Card";
import { CardGridType } from "../types/componentTypes";
import { UserDataType } from "../types/general";
const CardGrid: React.FC<CardGridType> = ({ data }) => {
return (
<div className="m-4 grid grid-cols-2 overflow-hidden rounded shadow-lg sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8 2xl:grid-cols-8">
{data.map((d: UserDataType) => (
<Card data={d} key={d.cas} />
))}
</div>
);
};
export default CardGrid;
//Card.tsx
import React from "react";
import { UserDataType } from "../types/general";
const Card: React.FC<{ data: UserDataType }> = ({ data }) => {
const { jmeno, prijmeni, pritomny } = data;
const cardClass =
"py-8 px-8 text-center text-xl text-white " +
(pritomny ? "bg-emerald-600" : "bg-gray-400");
return (
<div className={cardClass}>
<p className="card-text">
{jmeno} {prijmeni}
</p>
</div>
);
};
export default Card;
Please share your advice if you have any idea on how to tackle the problem.
For problem 1, you can add a background color to the CardGrid component itself and set the width and height to 100%.
For problem 2, you can add a border to the Card component with the desired width and color. To add space between the cards, you can add some padding to the CardGrid component.
Here's an updated code for CardGrid.tsx and Card.tsx:
// CardGrid.tsx
import React from "react";
import Card from "./Card";
import { CardGridType } from "../types/componentTypes";
import { UserDataType } from "../types/General";
const CardGrid: React.FC<CardGridType> = ({ data }) => {
return (
<div className="m-4 grid grid-cols-2 overflow-hidden rounded shadow-lg sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8 2xl:grid-cols-8 bg-gray-200" style={{ width: "100%", height: "100%" }}>
{data.map((d: UserDataType) => (
<Card data={d} key={d.cas} />
))}
</div>
);
};
export default CardGrid;
// Card.tsx
import React from "react";
import { UserDataType } from "../types/General";
const Card: React.FC<{ data: UserDataType }> = ({ data }) => {
const { jmeno, prijmeni, pritomny } = data;
const cardClass =
"py-8 px-8 text-center text-xl text-white " +
(pritomny ? "bg-emerald-600" : "bg-gray-400");
return (
<div className={cardClass} style={{ border: "1px solid white" }}>
<p className="card-text">
{jmeno} {prijmeni}
</p>
</div>
);
};
export default Card;
I'm trying to modify a button depending on every page where is imported. Let's take a look at my button component.
import React from "react";
import "./Button.css";
export interface Props {
marginLeft?: string;
name?: string;
backgroundColor?: string;
color?: string;
width?: string;
onClick?: () => void;
border?: string;
fontWeight?: number;
fontSize?: string;
lineHeight?: string;
marginBottom?: string;
height?: string;
display?: string;
alignItems?: string;
}
export const Button: React.FC<Props> = ({
name,
backgroundColor,
onClick,
color,
border,
width,
height,
marginLeft,
fontWeight,
fontSize,
lineHeight,
marginBottom,
display,
alignItems,
}) => {
return (
<button
className="myButton"
style={{
background: backgroundColor,
color: color,
border: border,
width: width,
marginLeft: marginLeft,
fontWeight: fontWeight,
fontSize: fontSize,
lineHeight: lineHeight,
marginBottom: marginBottom,
height: height,
alignItems: alignItems,
display: display,
}}
onClick={onClick}
>
{name}
</button>
);
};
export default Button;
The problem is coming from my mentor. He said that I should not do this like sending through props my css... and he suggested me to change it and to use a className on every specific place where I import my button and I wanted to change something.
Here is how I did it until he suggested me to change it.
<Button
backgroundColor="white"
border="1px solid #595959"
width="100%"
name="Add a team member + "
color="#595959"
fontWeight={200}
height="52px"
marginBottom="25px"
/>
<Button
width="13%"
name="Submit Project"
border="none"
color="#FFFFFF"
/>
and I don't know exactly how I can write className on a component. I mean I get every time when I'm trying to do something a error that is suggesting me it can not be possible to do it. Can you guide me on how I should do it?
I would asked my mentor if he was not that scary ... he doesn't smile that much ... you know he's a programming for over 8 yaers.
You could just create a css class for every variation of the button you want, and then write your button component like this:
const Button = ({class, name}) => {
return (
<button className={class}>{name}<button/>
)
}
and when you want to use the Button
<Button class='class1' name="Button with class 1"/>
We are creating button like common components to reuse the component and reduce the code repetition, if you are passing all the style values and props from all parent components(where Button is used) then there is no advantage of the common component or code reuse because you are duplicating everything in all the parent components. what should I suggest is create some CSS classes for similar style buttons,
Let say you have 3 types of buttons
primary (will have a blue background and fixed sizes)
secondary (Will have a grey background and fixed sizes)
danger (Will have a red background and fixed sizes)
So for these cases create 3 CSS in your CSS file
.btn {
//common styles for button
width="100px"
fontWeight={200}
height="52px"
marginBottom="25px"
}
.primary {
backgroundColor="blue"
border="1px solid #595959"
color="white"
}
.secondary {
backgroundColor="grey"
color="red"
}
.danger {
backgroundColor="red"
color="green"
}
after this
change your button component like
import React from "react";
import "./Button.css";
export interface Props {
name?: string;
onClick?: () => void;
className?:string;
}
export const Button: React.FC<Props> = ({
name,
onClick,
className
}) => {
return (
<button
className={`btn ${className}`}
onClick={onClick}
>
{name}
</button>
);
};
export default Button;
And from your any parent component
<Button
className="primary"
name="Add a team member + "
/>
<Button
className="secondary"
name="Submit Project"
/>
Note: This is just a sample code and classNames, you can use the class names and styles as you needed
import React from "react";
import "./styles.css";
import Input from "#material-ui/core/Input";
import MenuItem from "#material-ui/core/MenuItem";
import FormControl from "#material-ui/core/FormControl";
import Select from "#material-ui/core/Select";
const names = [
"Oliver Hansen",
"Van Henry",
"April Tucker",
"Ralph Hubbard",
"Omar Alexander",
"Carlos Abbott",
"Miriam Wagner",
"Bradley Wilkerson",
"Virginia Andrews",
"Kelly Snyder"
];
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250
}
},
disableScrollLock: true
};
export default function App() {
const [personName, setPersonName] = React.useState([]);
const handleChange = event => {
setPersonName(event.target.value);
};
return (
<div className="App" style={{ height: "1000px" }}>
<FormControl>
<Select
labelId="demo-mutiple-name-label"
id="demo-mutiple-name"
multiple
value={personName}
onChange={handleChange}
input={<Input />}
MenuProps={MenuProps}
>
{names.map(name => (
<MenuItem key={name} value={name}>
{name}
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
The codes can be found here as well https://codesandbox.io/s/awesome-leaf-ooko1
I am using React 16, latest Material UI core, Material UI Select Component
What I am trying to do here is when I open the drop down menu (with disableScrollLock=true), when I scroll the window, the drop down menu will be relative to the anchor element not fixed on window. How can I achieve that?
I'm not acquainted with React but I've managed to find a working example with a different component.
See this answer: https://stackoverflow.com/a/54011607/152016
Coder used a ReportComboBox instead of a Select, but he tackled another problem of your snippet: growing selection size.
When in your snippet you select a lot of items, there is a UI problem.
Enough digressing, I've changed the answers' snippet to enable scrolling (by setting body { height: 3000px; } for instance, and you can see that the scrolling keeps the select box in its place: https://codesandbox.io/s/react-select-ellipsis-one-row-example-k62hy
Hope this is enough for solving the problem or at least a clue to it.
Now, I have component like this:
code of it:
import React from "react";
import {withStyles} from "material-ui/styles";
import Settings from "material-ui-icons/Settings";
import Button from "material-ui/Button";
const styles = {
button: {
color: "primary",
height: 95,
width: 95,
disableRipple: "true",
focusRipple: "true",
},
icon: {
height: 35,
width: 35,
display: "block",
float: "none",
},
text: {
height: 35,
width: 35,
display: "block",
float: "none",
marginTop: 10,
},
};
/* eslint-disable react/prop-types */
const IconedLabel = ({classes}) => (
<section>
<Button className={classes.iconButton} variant="raised" color="primary">
<Settings className={classes.icon}/>
<div className={classes.text}>Message</div>
</Button>
</section>
);
export default withStyles(styles)(IconedLabel);
But need to button, that in top part contains icon and text message in bottom.
I use reactjs and material-ui lib from here https://material-ui-next.com/demos/buttons/
The Button component uses flexbox to control the layout/alignment of content. To align the content vertically (so the icon is above the text), you can simply change the flex-direction to column.
This style needs to be applied to an element inside the button component, not to the root element. You can use the classes property to override all of the styles in a component.
In this case, you want to add flexDirection: column to the label class.
Documentation on class overrides in material ui v1
Here's a working example. Hope it helps.
const [React, ReactDOM, Button, Settings, withStyles] = [window.React, window.ReactDOM, window['material-ui'].Button, ({className}) => <i className={`material-icons ${className}`}>settings</i>, window['material-ui'].withStyles]
// Ignore code above this line
const styles = theme => ({
button: {
height: 95, // setting height/width is optional
},
label: {
// Aligns the content of the button vertically.
flexDirection: 'column'
},
icon: {
fontSize: '32px !important',
marginBottom: theme.spacing.unit
}
})
const CustomButton = ({ classes }) => (
<Button
/* Use classes property to inject custom styles */
classes={{ root: classes.button, label: classes.label }}
variant="raised"
color="primary"
disableRipple={true}
>
<Settings className={classes.icon} />
Message
</Button>
)
const WrappedCustomButton = withStyles(styles)(CustomButton)
ReactDOM.render(<WrappedCustomButton />, document.querySelector('#root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script><script src="https://unpkg.com/material-ui#1.0.0-beta.40/umd/material-ui.production.min.js"></script><link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"><div id="root" />
A (potentially bad) solution would simply be:
.MuiIconButton-label {
flex-direction: column
}
I say bad, because you might want to use it in it's standard format elsewhere.
What I opted to do was add a class name nav-bar-icon-wrapper to the IconButton & set the flex direction in it's parent:
.nav-bar-icon-wrapper {
flex-direction: column
}
.MuiIconButton-label {
flex-direction: inherit
}
If I run into instance later where I want the icon/label button to be standard, I'll just add a new class default-icon-wrapper and css that handles that:
.default-icon-wrapper {
flex-direction: row
}
FWIW:
I preach the BEM http://getbem.com/introduction/ convention AND that whenever you make a component, you add an optional modifier prop.
I have functions in a shared dir that looks these:
export function BEMifyThis(modifier) {
return (klass) => BEMify(klass, modifier)
}
export function BEMify(klass, modifier=false) {
if (modifier) {
klass += ` ${klass}-${modifier}`
}
return klass
}
Then I use that everywhere in my component so the user can access the component elements as a group or individually using their modifiers.
import {BEMifyThis} from '../shared/bem'
const BEMify = BEMifyThis(this.props.modifier)
className={"navbar__menu_item")}
becomes
className={BEMify("navbar__menu_item")}
so something like navbar__menu_item becomes navbar__menu_item navbar__menu_item-logout
So I put my Toggle button in my AppBar, which created an issue because they are the same color when the Toggle is selected.
I've tried many different things (as shown below), but have been unable to change it's color.
import React from 'react';
import Toggle from 'material-ui/Toggle'
import Drawer from 'material-ui/Drawer';
import AppBar from 'material-ui/AppBar';
import MenuItem from 'material-ui/MenuItem';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
var Style =
{
palette:
{
primary1Color: '#ffffff',
},
};
class AppBarComp extends React.Component {
constructor() {
super();
this.state = {
open: false
};
}
getChildContext() {
return {muiTheme: getMuiTheme(Style)};
}
handleToggle = () => this.setState({open: !this.state.open});
handleClose = () => this.setState({open: false});
render() {
return <MuiThemeProvider muiTheme={getMuiTheme()}>
<div>
<AppBar
onLeftIconButtonTouchTap={this.handleToggle}
title="Time Visualizer"
iconElementRight={
<Toggle
labelStyle={{color:'white'}}
style={{marginTop:'.75em'}}
label="Toggle Compare"
/>
}/>
<Drawer
docked={false}
width={250}
open={this.state.open}
onRequestChange={(open) => this.setState({open})}
>
<MenuItem onTouchTap={this.handleClose}>Settings</MenuItem>
<MenuItem onTouchTap={this.handleClose}>About</MenuItem>
</Drawer>
</div>
</MuiThemeProvider>
}
}
AppBarComp.childContextTypes ={
muiTheme: React.PropTypes.object,
};
export default AppBarComp;
I'm not really sure how I can get to that element to change it's color. using Chrome, I was able to inspect the element and change it's color that way, but have been unable to repeat that with code.
I've also been unable to center the Toggle programmatically, but have been able to do it in chrome which makes be believe I'm not high enough in the object?
If that makes sense.
Thanks!
If you want change toggle color in 'on mode', you need to update colors in the theme:
const muiTheme = getMuiTheme({
toggle: {
thumbOnColor: 'yellow',
trackOnColor: 'red'
}
});
and then use it :)
<MuiThemeProvider muiTheme={muiTheme}>
You can check here what other theme stuff is used by toggle:
https://github.com/callemall/material-ui/blob/master/src/Toggle/Toggle.js
I don't know if that is the only way to do this but it seems to work :)
There might be problem though if some other control uses that color path :/
Changing color of toggle in 'off mode' is easier:
<Toggle
thumbStyle={{ backgroundColor: 'red' }}
trackStyle={{ backgroundColor: 'green' }} />
Hope it helps :)
import {Switch,makeStyles} from "material-ui/core"
const useStyles = makeStyles((theme) => ({
toggle: {
width:50,
'& .Mui-checked': {
color: '#109125',
transform:'translateX(25px) !important'
},
'& .MuiSwitch-track': {
backgroundColor:'#008000e0'
}
},
})
const Index= (props) => {
const classes = useStyles();
return(
<Switch color="primary" size="small" className={classes.toggle} checked: {true} />)
}
Refer to this code and you will get what you need.
Click on this link for more information Material-Ui/Switch
All you need to do
thumbSwitchedStyle={{ backgroundColor: 'grey' }}
Example
<Toggle
thumbSwitchedStyle={{ backgroundColor: 'grey' }}
labelStyle={{color:'white'}}
style={{marginTop:'.75em'}}
label="Toggle Compare"
Thus, if selected the color becomes grey :)
image
const toggleStyles = makeStyles({
root: { /* … */ },
label: { /* … */ },
outlined: {
/* … */
'&$disabled': { /* … */ },
},
outlinedPrimary: {
/* … */
'&:hover': { /* … */ },
},
disabled: {},
}, { name: 'MuiButton' });
generates the following class names that you can override:
.MuiButton-root { /* … */ }
.MuiButton-label { /* … */ }
.MuiButton-outlined { /* … */ }
.MuiButton-outlined.Mui-disabled { /* … */ }
.MuiButton-outlinedPrimary: { /* … */ }
.MuiButton-outlinedPrimary:hover { /* … */ }
To use the code:
function FunctionalComponent(props){
const toggleClass = toggleStyles();
return (
<ToggleButtonGroup value={toggleValue} onChange ={handleToggleValueChange}>
<ToggleButton value="toggleValue1" className={toggleClass.root}>VALUE 1</ToggleButton>
<ToggleButton value="toggleValue2" className={toggleClass.outlined}>VALUE 2</ToggleButton>
</ToggleButtonGroup>
)
}
For more details: https://material-ui.com/styles/advanced/#with-material-ui-core
The color of the Material-UI toggle is set to primary1Color, which you can over-ride by making a custom theme.
http://www.material-ui.com/#/customization/themes
You'd want to make a styles object somewhere (a separate file is probably best) that contains an object like this:
{
palette: {
primary1Color: '#YOURCOLOR',
},
}
Assuming you import that into your React class as Styles, you'd want to set it as the theme like this:
getChildContext() {
return {
muiTheme: getMuiTheme(Styles),
};
}
And
YOUR_CLASS.childContextTypes = {
muiTheme: React.PropTypes.object,
};