I want to create a slider in react js but don't know how to implement this without using any third-party plugins.
Something similar to this https://mui.com/components/slider/
You can try Something like this:
class Slider extends React.Component {
constructor() {
super();
this.state = { value: 0 };
this.changeValue = this.changeValue.bind(this);
}
changeValue() {
this.setState({ value: this.refs.input.value * this.props.max });
}
render() {
const sliderStyle = {
position: "relative",
width: "284px",
height: "28px"
};
const rangeStyle = {
webkitAppearance: "none",
appearance: "none",
touchAction: "pan-y",
position: "absolute",
margin: "0",
padding: "0",
width: "284px",
backgroundColor: "transparent"
};
const progressBarStyle = {
webkitAppearance: "none",
appearance: "none",
position: "absolute",
display: "block",
margin: "0",
top: "13px",
left: "13px",
width: "256px",
height: "3px",
zIndex: "-1",
backgroundColor: "#D7D7D7"
};
return (
<div
style={sliderStyle}
aria-valuemin={this.props.min}
aria-valuemax={this.props.max}
aria-valuenow={this.state.value}
aria-valuetext={this.state.value}
>
<input
ref="input"
type="range"
onChange={this.changeValue}
defaultValue={this.props.min}
min={this.props.min}
max={this.props.max}
step={this.props.max / 100}
style={rangeStyle}
/>
<progress
value={this.state.value}
min={this.props.min}
max={this.props.max}
style={progressBarStyle}
></progress>
</div>
);
}
}
ReactDOM.render(<Slider min={0} max={1} />, document.querySelector("#root"));
:root {
--thumb-shadow:
0 3px 8px rgba(0, 0, 0, .15),
0 1px 1px rgba(0, 0, 0, .16),
0 3px 1px rgba(0, 0, 0, .10)
}
body {
margin: 0;
width: 100vw;
height: 100vh;
display: -webkit-flex;
display: flex;
justify-content: center;
align-items: center;
background-color: #EFEFF4
}
* { outline: none }
progress::-webkit-progress-value { background-color: #007AFF }
progress::-webkit-progress-bar {
background-color: #B6B6B6;
border-radius: 1.5px;
overflow: hidden
}
input::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
height: 28px;
width: 28px;
border: none;
border-radius: 50%;
background-color: white;
z-index: 2;
box-shadow: var(--thumb-shadow)
}
<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>
<div id=root>
</div>
titles come dynamically. The number is not clear. That's why I can't give a fixed height. The graphic is getting smaller. How can I make the chart size dynamic ?
const options = {
legend: {
"position": "bottom",
align:'start',
display:true,
itemWrap: true,
},
responsive: true,
maintainAspectRatio: false,
animation: false,
};
<div className={styles['department-charts__card__altCard']}>
<Doughnut
data={doughnutData}
options={options}
/>
</div>
If the Legend is too much, the graphic gets smaller. With Legend, the chart does not appear in a separate container. When I check it looks like this
<canvas height="600" width="542" class="chartjs-render-monitor" style="display: block; height: 300px; width: 271px;"></canvas>
I want the cake to be at least 300 pixels. With Legend it will be more comfortable to check whether the pie is in a different container. How can I make this show dynamic? Pie does not appear at all on small screens. If there are 3 or 4 in some values, it is not a problem. If it's too much, it doesn't fit. I don't want to hide the legend
Amme hizmeti,
Ben bu şekilde çözdüm. Özel bir efsane yarattım
import { Doughnut } from 'react-chartjs-2';
const options = {
legend: {
"position": "bottom",
display:false,
},
responsive: true,
maintainAspectRatio: false,
animation: false,
offset:true
};
let chartInstance = null;
const DepartmentCharts = ({
t, departmentDistribution
}) => {
const keys = departmentDistribution.map(it => {
const key = it.key
return t(key)
}) || [t('salesAndMarketing'), t('ik'), t('management')]
const values = departmentDistribution.map(it => it.value) || [0, 0, 0]
const doughnutData = {
labels: keys,
datasets: [{
data: values,
backgroundColor: [
'#FF6384',
'#36A2EB',
'#FFCE56',
'#8bc34a',
'#6c429b',
'#00a860',
'#0154a3',
'#f78f1e',
"#CCCC99",
"#666666",
"#FFCC66",
"#6699CC",
"#663366",
"#9999CC",
"#CCCCCC",
"#669999",
"#CCCC66",
"#CC6600",
"#9999FF",
"#0066CC",
"#99CCCC",
"#999999",
"#FFCC00",
"#009999",
"#99CC33",
"#FF9900",
"#999966",
"#66CCCC",
"#339966",
"#CCCC33",
"#003f5c",
"#665191",
"#a05195",
"#d45087",
"#2f4b7c",
"#f95d6a",
"#ff7c43",
"#ffa600",
"#EF6F6C",
"#465775",
"#56E39F",
"#59C9A5",
"#5B6C5D",
"#0A2342",
"#2CA58D",
"#84BC9C",
"#CBA328",
"#F46197",
"#DBCFB0",
"#545775"
],
hoverBackgroundColor: [
'#FF6384',
'#36A2EB',
'#FFCE56',
'#8bc34a',
'#6c429b',
'#00a860',
'#0154a3',
'#f78f1e',
"#CCCC99",
"#666666",
"#FFCC66",
"#6699CC",
"#663366",
"#9999CC",
"#CCCCCC",
"#669999",
"#CCCC66",
"#CC6600",
"#9999FF",
"#0066CC",
"#99CCCC",
"#999999",
"#FFCC00",
"#009999",
"#99CC33",
"#FF9900",
"#999966",
"#66CCCC",
"#339966",
"#CCCC33",
"#003f5c",
"#665191",
"#a05195",
"#d45087",
"#2f4b7c",
"#f95d6a",
"#ff7c43",
"#ffa600",
"#EF6F6C",
"#465775",
"#56E39F",
"#59C9A5",
"#5B6C5D",
"#0A2342",
"#2CA58D",
"#84BC9C",
"#CBA328",
"#F46197",
"#DBCFB0",
"#545775"
]
}]
};
const handleClick = (e, index) => {
const ctx = chartInstance.chartInstance;
const meta = ctx.getDatasetMeta(0);
// See controller.isDatasetVisible comment
meta.data[index].hidden = !meta.data[index].hidden;
// Toggle strikethrough class
if (e.currentTarget.classList.contains("disable-legend")) {
//console.log("çizgiyi kaldır")
e.currentTarget.classList.remove("disable-legend");
e.currentTarget.style.textDecoration = "inherit";
} else {
//console.log("çizgi çiz")
e.currentTarget.classList.add("disable-legend");
e.currentTarget.style.textDecoration = "line-through";
}
chartInstance.chartInstance.update();
};
useEffect(() => {
const legend = chartInstance.chartInstance.generateLegend();
document.getElementById("legend").innerHTML = legend;
document.querySelectorAll("#legend li").forEach((item, index) => {
item.addEventListener("click", (e) => handleClick(e, index));
});
}, [doughnutData]);
return (
<div className={styles['department-charts']}>
<Card className={styles['department-charts__card']}>
<CardHeader
title={`${t('departmentTitle')}`}
align='center'
/>
<CardContent>
<div className={styles['department-charts__card__altCard']}>
<Doughnut
data={doughnutData}
options={options}
ref={input => {
chartInstance = input;
}}
/>
</div>
<div id="legend" className={styles['department-charts__card__altCard__legend']}/>
</CardContent>
</Card>
</div>
);
};
style.css - efsane kısmı sizin için yeterli olabilir
.department-charts {
height: 100%;
&__card {
height: 100%;
padding: 16px;
&__altCard{
min-height: 235px;
&__legend{
color: #666666;
ul{
list-style: none;
font: 12px Verdana;
white-space: nowrap;
display: inline-block;
padding-top: 20px;
font-family: "Helvetica Neue";
}
li{
cursor: pointer;
float: left;
padding-left: 7px;
span{
width: 36px;
height: 12px;
display: inline-block;
margin: 0 5px 8px 0;
vertical-align: -9.4px;
}
}
}
}
}
}
.disable-legend {
text-decoration: line-through;
}
I'm trying to set up a React project where I want to use some of the tools provided by the ol-ext. I looked around and found some Codesandbox projects from the creator of the library but I was unable to make them work properly because of the way the library is imported in the projects causes an error.
Is there a problem with the syntax or incompatibility with ol-ext and the other Open Layers versions?
For anyone coming to the same problem I managed to make it work and I implemented the Interaction Transform Features example. Here is the code below:
JS:
// Import stylesheets
import './style.css';
import "ol/ol.css";
import "ol-ext/dist/ol-ext.css";
import Transform from "ol-ext/interaction/Transform";
import Stamen from 'ol/source/Stamen';
import { Map, View } from "ol";
import { defaults } from "ol/control";
import * as olEvents from 'ol/events';
import TileLayer from 'ol/layer/Tile';
import { Style, Fill, Text, Icon, Stroke, RegularShape } from "ol/style";
import {Polygon, LineString, Point, Circle} from 'ol/geom';
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import Feature from "ol/Feature";
var interaction = new Transform ({
enableRotatedTransform: false,
/* Limit interaction inside bbox * /
condition: function(e, features) {
return ol.extent.containsXY([-465960, 5536486, 1001630, 6514880], e.coordinate[0], e.coordinate[1]);
},
/* */
addCondition: olEvents.condition,
// filter: function(f,l) { return f.getGeometry().getType()==='Polygon'; },
// layers: [vector],
hitTolerance: 2,
translateFeature: false,
scale: true,
rotate: true,
translate: true,
stretch: true
});
var circle = new RegularShape({
fill: new Fill({color:[255,255,255,0.01]}),
stroke: new Stroke({width:1, color:[0,0,0,0.01]}),
radius: 8,
points: 10
});
interaction.setStyle ('rotate',
new Style({
text: new Text ({
text:'\uf0e2',
font:"16px Fontawesome",
textAlign: "left",
fill:new Fill({color:'red'})
}),
image: circle
}));
// Center of rotation
interaction.setStyle ('rotate0',
new Style({
text: new Text ({
text:'\uf0e2',
font:"20px Fontawesome",
fill: new Fill({ color:[255,255,255,0.8] }),
stroke: new Stroke({ width:2, color:'red' })
}),
}));
// Style the move handle
interaction.setStyle('translate',
new Style({
text: new Text ({
text:'\uf047',
font:"20px Fontawesome",
fill: new Fill({ color:[255,255,255,0.8] }),
stroke: new Stroke({ width:2, color:'red' })
})
}));
// Layers
var layers = [
new TileLayer({
title:'terrain-background',
source: new Stamen({ layer: 'terrain' })
})
]
// The map
var map = new Map({
target: null,
view: new View({
zoom: 5,
center: [261720, 5951081]
}),
controls: defaults({ "attribution": false }),
layers: layers
});
// Style
function getStyle(feature) {
return [ new Style({
image: new RegularShape({
fill: new Fill({ color: [0,0,255,0.4]}),
stroke: new Stroke({color: [0,0,255,1],width: 1}),
radius: 10,
points: 3,
angle: feature.get('angle')||0
}),
fill: new Fill({color: [0,0,255,0.4]}),
stroke: new Stroke({color: [0,0,255,1],width: 1})
})];
}
// New vector layer
var vector = new VectorLayer({
name: 'Vecteur',
source: new VectorSource({ wrapX: false }),
style: getStyle
})
map.addLayer(vector);
vector.getSource().addFeature(new Feature(new Polygon([[[34243, 6305749], [-288626, 5757848], [210354, 5576845], [300000, 6000000], [34243, 6305749]]])));
vector.getSource().addFeature(new Feature(new LineString([[406033, 5664901], [689767, 5718712], [699551, 6149206], [425601, 6183449]])));
vector.getSource().addFeature(new Feature(new Point( [269914, 6248592])));
vector.getSource().addFeature(new Feature(new Circle( [500000, 6400000], 100000 )));
// Set cursor style
Transform.prototype.Cursors['rotate'] = 'url(\'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAXAgMAAACdRDwzAAAAAXNSR0IArs4c6QAAAAlQTFRF////////AAAAjvTD7AAAAAF0Uk5TAEDm2GYAAAABYktHRACIBR1IAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH2wwSEgUFmXJDjQAAAEZJREFUCNdjYMAOuCCk6goQpbp0GpRSAFKcqdNmQKgIILUoNAxIMUWFhoKosNDQBKDgVAilCqcaQBogFFNoGNjsqSgUTgAAM3ES8k912EAAAAAASUVORK5CYII=\') 5 5, auto';
Transform.prototype.Cursors['rotate0'] = 'url(\'data:image/png;base64,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\') 5 5, auto';
map.addInteraction(interaction);
class App extends Component {
state = {
name: 'React',
styles: false,
scale: true,
stretch: true,
disableStretch: false,
rotate: true,
translate: true,
translateFeature: false,
forceMatching: false,
info: "Hello there"
};
setHandleStyleInput = (event) => {
this.setState({styles: event.target.checked})
if (!interaction instanceof Transform) return;
if (event.target.checked) {
// Style the rotate handle
var circle = new RegularShape({
fill: new Fill({color:[255,255,255,0.01]}),
stroke: new Stroke({width:1, color:[0,0,0,0.01]}),
radius: 8,
points: 10
});
interaction.setStyle ('rotate',
new Style({
text: new Text ({
text:'\uf0e2',
font:"16px Fontawesome",
textAlign: "left",
fill:new Fill({color:'yellow'})
}),
image: circle
}));
// Center of rotation
interaction.setStyle ('rotate0',
new Style({
text: new Text ({
text:'\uf0e2',
font:"20px Fontawesome",
fill: new Fill({ color:[255,255,255,0.8] }),
stroke: new Stroke({ width:2, color:'yellow' })
}),
}));
// Style the move handle
interaction.setStyle('translate',
new Style({
text: new Text ({
text:'\uf047',
font:"20px Fontawesome",
fill: new Fill({ color:[255,255,255,0.8] }),
stroke: new Stroke({ width:2, color:'yellow' })
})
}));
interaction.setStyle ('scaleh1',
new Style({
text: new Text ({
text:'\uf07d',
font:"bold 20px Fontawesome",
fill: new Fill({ color:[255,255,255,0.8] }),
stroke: new Stroke({ width:2, color:'yellow' })
})
}));
interaction.style.scaleh3 = interaction.style.scaleh1;
interaction.setStyle('scalev',
new Style({
text: new Text ({
text:'\uf07e',
font:"bold 20px Fontawesome",
fill: new Fill({ color:[255,255,255,0.8] }),
stroke: new Stroke({ width:2, color:'yellow' })
})
}));
interaction.style.scalev2 = interaction.style.scalev;
} else {
interaction.setDefaultStyle();
}
// Refresh
interaction.set('translate', interaction.get('translate'));
}
setPropertieScale = (p) =>{
this.setState({scale: p.target.checked})
if (p.target.checked) this.setState({ disableStretch: false});
else this.setState({ disableStretch: true});
}
setPropertieStretch = (p) =>{
this.setState({stretch: p.target.checked})
}
setPropertieRotate = (p) =>{
this.setState({rotate: p.target.checked})
}
setPropertieTranslate = (p) =>{
this.setState({translate: p.target.checked})
}
setPropertieTranslateFeature = (p) =>{
this.setState({translateFeature: p.target.checked})
}
componentDidMount() {
map.setTarget("map");
}
componentDidUpdate(prevState) {
/** Style the transform handles for the current interaction
*/
if(this.state.scale !== prevState.scale || this.state.stretch !== prevState.stretch || this.state.rotate !== prevState.rotate || this.state.translate !== prevState.translate || this.state.styles !== prevState.styles){
var interaction = new Transform ({
enableRotatedTransform: false,
/* Limit interaction inside bbox * /
condition: function(e, features) {
return ol.extent.containsXY([-465960, 5536486, 1001630, 6514880], e.coordinate[0], e.coordinate[1]);
},
/* */
addCondition: olEvents.condition,
// filter: function(f,l) { return f.getGeometry().getType()==='Polygon'; },
// layers: [vector],
hitTolerance: 2,
translateFeature: this.state.translateFeature,
scale: this.state.scale,
rotate: this.state.rotate,
translate: this.state.translate,
stretch: this.state.stretch
});
interaction.set('translate', interaction.get('translate'));
// Style handles
}
}
render() {
var info = "Heyyou"
// Events handlers
var startangle = 0;
var d=[0,0];
// Handle rotate on first point
var firstPoint = false;
interaction.on (['select'], function(e) {
if (firstPoint && e.features && e.features.getLength()) {
interaction.setCenter(e.features.getArray()[0].getGeometry().getFirstCoordinate());
}
});
interaction.on (['rotatestart','translatestart'], function(e){
// Rotation
startangle = e.feature.get('angle')||0;
// Translation
d=[0,0];
});
interaction.on('rotating', (e)=>{
info= "rotate: "+((e.angle*180/Math.PI -180)%360+180).toFixed(2)
// Set angle attribute to be used on style !
e.feature.set('angle', startangle - e.angle);
});
interaction.on('translating', (e) =>{
d[0]+=e.delta[0];
d[1]+=e.delta[1];
info= "translate: "+d[0].toFixed(2)+","+d[1].toFixed(2)
if (firstPoint) {
interaction.setCenter(e.features.getArray()[0].getGeometry().getFirstCoordinate());
}
});
interaction.on('scaling', (e) => {
info= "scale: "+e.scale[0].toFixed(2)+","+e.scale[1].toFixed(2)
if (firstPoint) {
interaction.setCenter(e.features.getArray()[0].getGeometry().getFirstCoordinate());
}
});
interaction.on(['rotateend', 'translateend', 'scaleend'], (e) =>{
this.setState({info: info})
info= ""
});
return (
<div>
<div id="map" style={{width:"500px", height:"400px"}}></div>
<div className="options" >
<h2>Options:</h2>
<ul><li>
<input
className="style"
type="checkbox"
checked={this.state.styles}
onChange={this.setHandleStyleInput} />
<label> styles transform handles (using fontawesome)</label>
</li><li>
<input
className="scale"
type="checkbox"
checked={this.state.scale}
onChange={this.setPropertieScale} /><label> enable scale</label>
</li><li>
<input
className="stretch"
type="checkbox"
checked={this.state.stretch}
onChange={this.setPropertieStretch} disabled={this.state.disableStretch} />
<label> enable stretch</label>
</li><li>
<input
className="rotate"
type="checkbox"
checked={this.state.rotate}
onChange={this.setPropertieRotate} />
<label> enable rotate</label>
</li><li>
<input
className="translate"
type="checkbox"
checked={this.state.translate}
onChange={this.setPropertieTranslate} />
<label> enable translate</label>
</li><li>
<input
className="translateFeature"
type="checkbox"
checked={this.state.translateFeature}
onChange={this.setPropertieTranslateFeature} />
<label> translate when click on feature</label>
</li><li>
SetRotateCenter:
<button onClick={()=>{firstPoint=false; interaction.setCenter()}}>objects</button>
<button onClick={()=>{firstPoint=false; interaction.setCenter(map.getView().getCenter())}}>view center</button>
<button onClick={()=>{firstPoint=true;}}>first point</button>
</li><li>
<hr/>
Use <i>Shift</i> to add object to tranform
<hr/>
Use <i>Shift</i> key to preserve proportions when scaling (see keepAspectRatio).
<br />
Use <i>Ctrl</i> key to modify the center when scaling.
</li></ul>
<div style={{background:"white", padding:"0 0.45em"}}><span id="info"></span>{this.state.info}</div>
</div>
</div>
);
}
}
HTML:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<div id="root"></div>
CSS:
h1, p {
font-family: Lato;
}
a.icss-github-corner,
a.icss-github-corner-left {
font-size: 2.5em;
position: fixed;
top:0;
right: 0;
z-index: 1000;
color: #fff;
background-color: #333;
padding: .5em 2em 0;
text-align: center;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
-webkit-transform-origin: 3.9em 3em;
-ms-transform-origin: 3.9em 3em;
transform-origin: 3.9em 3em;
overflow: hidden;
}
a.icss-github-corner-left {
left: 0;
right: auto;
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
-webkit-transform-origin: 1em 3.1em;
-ms-transform-origin: 1em 3.1em;
transform-origin: 1em 3.1em;
}
a.icss-github-corner:hover i,
a.icss-github-corner-left:hover i{
-webkit-animation: vertical 2s ease;
animation: vertical 2s ease;
}
a.icss-github-corner i,
a.icss-github-corner-left i,
i.icss-github-corner {
color: #fff;
position: relative;
display:inline-block;
font-style: normal;
background-color:currentColor;
-webkit-box-sizing: border-box;
box-sizing: border-box;
vertical-align: middle;
width: .8em;
height: .6em;
-webkit-border-radius: 45% 45% 45% 45% / 50%;
border-radius: 45% 45% 45% 45% / 50%;
background-color: currentColor;
-webkit-box-shadow: 0 .35em 0 -.2em,
0 .38em 0 -.2em,
0 .41em 0 -.2em,
0 .44em 0 -.2em,
0 .47em 0 -.2em;
box-shadow: 0 .35em 0 -.2em,
0 .38em 0 -.2em,
0 .41em 0 -.2em,
0 .44em 0 -.2em,
0 .47em 0 -.2em;
margin: .12em .1em .23em;
}
a.icss-github-corner i:before,
a.icss-github-corner-left i:before,
i.icss-github-corner:before {
content: "";
border-width: 0;
position: absolute;
-webkit-box-sizing: border-box;
box-sizing: border-box;
border-width: .15em .15em;
border-style: solid;
-webkit-border-radius: 0.02em 60% 100% 80%;
border-radius: 0.02em 60% 100% 80%;
left: 0;
top: -.07em;
-webkit-transform: rotate(20deg);
-ms-transform: rotate(20deg);
transform: rotate(20deg);
}
a.icss-github-corner i:after,
a.icss-github-corner-left i:after,
i.icss-github-corner:after {
content: "";
border-width: 0;
position: absolute;
-webkit-box-sizing: border-box;
box-sizing: border-box;
border-width: .15em .15em;
border-style: solid;
-webkit-border-radius: 0.02em 80% 100% 60%;
border-radius: 0.02em 80% 100% 60%;
left: .5em;
top: -.07em;
-webkit-transform: rotate(65deg);
-ms-transform: rotate(65deg);
transform: rotate(65deg);
}
#-webkit-keyframes vertical {
0%{-webkit-transform:translate(0,-3px);transform:translate(0,-3px)}
4%{-webkit-transform:translate(0,3px);transform:translate(0,3px)}
8%{-webkit-transform:translate(0,-3px);transform:translate(0,-3px)}
12%{-webkit-transform:translate(0,3px);transform:translate(0,3px)}
16%{-webkit-transform:translate(0,-3px);transform:translate(0,-3px)}
20%{-webkit-transform:translate(0,3px);transform:translate(0,3px)}
22%,100%{-webkit-transform:translate(0,0);transform:translate(0,0)}
}
#keyframes vertical {
0%{-webkit-transform:translate(0,-3px);transform:translate(0,-3px)}
4%{-webkit-transform:translate(0,3px);transform:translate(0,3px)}
8%{-webkit-transform:translate(0,-3px);transform:translate(0,-3px)}
12%{-webkit-transform:translate(0,3px);transform:translate(0,3px)}
16%{-webkit-transform:translate(0,-3px);transform:translate(0,-3px)}
20%{-webkit-transform:translate(0,3px);transform:translate(0,3px)}
22%,100%{-webkit-transform:translate(0,0);transform:translate(0,0)}
}
/**/
body {
font-family: 'Lucida Grande',Verdana,Geneva,Lucida,Arial,Helvetica,sans-serif;
font-size: 16px;
}
a, i, b {
color: #337ab7;
text-decoration: none;
}
button i {
color: #fff;
}
.ol-control.ol-bar .ol-control button i {
color: #fff;
}
a:hover {
text-decoration: underline;
}
a.title {
text-decoration: none;
}
h1 {
background: #1f6b75 url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACE1BMVEX///8A//8AgICA//8AVVVAQID///8rVVVJtttgv98nTmJ2xNgkW1ttyNsmWWZmzNZYxM4gWGgeU2JmzNNr0N1Rwc0eU2VXxdEhV2JqytQeVmMhVmNoydUfVGUgVGQfVGQfVmVqy9hqy9dWw9AfVWRpydVry9YhVmMgVGNUw9BrytchVWRexdGw294gVWQgVmUhVWPd4N6HoaZsy9cfVmQgVGRrytZsy9cgVWQgVWMgVWRsy9YfVWNsy9YgVWVty9YgVWVry9UgVWRsy9Zsy9UfVWRsy9YgVWVty9YgVWRty9Vsy9aM09sgVWRTws/AzM0gVWRtzNYgVWRuy9Zsy9cgVWRGcHxty9bb5ORbxdEgVWRty9bn6OZTws9mydRfxtLX3Nva5eRix9NFcXxOd4JPeINQeIMiVmVUws9Vws9Vw9BXw9BYxNBaxNBbxNBcxdJexdElWWgmWmhjyNRlx9IqXGtoipNpytVqytVryNNrytZsjZUuX210k5t1y9R2zNR3y9V4lp57zth9zdaAnKOGoaeK0NiNpquV09mesrag1tuitbmj1tuj19uktrqr2d2svcCu2d2xwMO63N+7x8nA3uDC3uDFz9DK4eHL4eLN4eIyYnDX5OM5Z3Tb397e4uDf4uHf5uXi5ePi5+Xj5+Xk5+Xm5+Xm6OY6aHXQ19fT4+NfhI1Ww89gx9Nhx9Nsy9ZWw9Dpj2abAAAAWnRSTlMAAQICAwQEBgcIDQ0ODhQZGiAiIyYpKywvNTs+QklPUlNUWWJjaGt0dnd+hIWFh4mNjZCSm6CpsbW2t7nDzNDT1dje5efr7PHy9PT29/j4+Pn5+vr8/f39/f6DPtKwAAABTklEQVR4Xr3QVWPbMBSAUTVFZmZmhhSXMjNvkhwqMzMzMzPDeD+xASvObKePPa+ffHVl8PlsnE0+qPpBuQjVJjno6pZpSKXYl7/bZyFaQxhf98hHDKEppwdWIW1frFnrxSOWHFfWesSEWC6R/P4zOFrix3TzDFLlXRTR8c0fEEJ1/itpo7SVO9Jdr1DVxZ0USyjZsEY5vZfiiAC0UoTGOrm9PZLuRl8X+Dq1HQtoFbJZbv61i+Poblh/97TC7n0neCcK0ETNUrz1/xPHf+DNAW9Ac6t8O8WH3Vp98f5lCaYKAOFZMLyHL4Y0fe319idMNgMMp+zWVSybUed/+/h7I4wRAG1W6XDy4XmjR9HnzvDRZXUAYDFOhC1S/Hh+fIXxen+eO+AKqbs+wAo30zDTDvDxKoJN88sjUzDFAvBzEUGFsnADoIvAJzoh2BZ8sner+Ke/vwECuQAAAABJRU5ErkJggg==") no-repeat scroll 10px center;
color: #fff;
font-size: 1.5em;
padding: 0.5em 50px;
margin:0;
}
h2 {
color: #337ab7;
font-size:1.1em;
margin: 0.5em 0;
}
.info {
background:#f5f5f5;
padding:0.5em;
margin: 1em 0;
}
.info ul {
margin:0;
}
#map {
float:left;
margin-right:1em;
background:#ddd;
}
.ol-attribution img {
vertical-align:middle;
}
.layerSwitcher {
display:inline-block;
background:#cdf;
padding:0.5em;
}
.btn {
color:#fff;
background:#369;
padding:0.5em;
text-decoration:none;
cursor:pointer;
display:inline-block;
margin-right:0.5em;
}
.block,
.options {
display: table;
margin: 0.5em;
position: relative;
z-index: 1;
margin:1em;
}
.options {
background: #def;
padding: 0.5em;
}
.options ul {
list-style: none;
padding-left: 0.5em;
}
i[class*="icss-"] {
position: relative;
display:inline-block;
font-style: normal;
background-color:currentColor;
box-sizing: border-box;
vertical-align: middle;
font-size: 1.5em;
}
i[class*="icss-"]:before,
i[class*="icss-"]:after {
content: "";
border-width: 0;
position: absolute;
}
i.icss-book {
width:1em;
height:.8em;
background-color: transparent;
margin: 0 .03em .08em 0;
}
i.icss-book:before {
height: .8em;
width: 0.7em;
box-shadow: inset 0 0 0 0.15em,
inset 0 -.48em,
.07em .07em;
border: 0.07em solid transparent;
border-width: 0 0.07em .07em 0;
border-radius: .05em .15em .1em .1em / .05em .05em .1em .05em;
transform: skewX(-20deg);
left: 0.15em;
}
i.icss-book:after {
width: .2em;
height: .2em;
background-color: transparent;
border: 0.05em solid currentColor;
border-color: currentColor transparent transparent currentColor;
border-radius: 50%;
transform: rotate(-45deg);
top: 0.67em;
left: .018em;
box-shadow: .13em -.15em 0 -.05em,
.51em -.33em 0 -.05em;
}
.experimental {
color:#fff;
background: #f91;
padding:.2em .5em;
display: inline-block;
-webkit-transform: rotate(-5deg);
transform: rotate(-5deg);
margin: -1em 0;
}
.ol-attribution ul {
font-size: .8em;
}
Also here is a working example: StackBlitz
I want to add my own custom style to the react-toastify message popup, depending on whether its success or error. So far I tried the following approach:
toastify.js
import { toast, Slide } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { css } from "glamor";
toast.configure({
position: toast.POSITION.BOTTOM_RIGHT,
autoClose: 3000,
transition: Slide,
pauseOnFocusLoss: false,
className: css({
backgroundColor: 'red',
}),
bodyClassName: css({
backgroundColor: 'blue',
height: '100%',
width: '100%',
})
});
export default function (message, type, styles = {}) {
switch (type) {
case type === 'success':
toast.success(message);
break;
case type === 'error':
toast.error(message);
break;
case type === 'info':
toast.info(message);
break;
case type === 'warn':
toast.warn(message);
break;
default:
toast(message);
break;
}
}
This is a function in which I define what type of message style toastify shows based on the type param. Then I call this function like this:
export default function ({params}) {
...
async function deleteTodo (id) {
try {
const res = await axios.delete(http://localhost:8000/api/delete-task/${id});
toastifyMessage(res.data, 'success');
} catch (error) {
errorInfo(toastifyMessage(error, 'error'));
}
}
return (
<li className="menu-item">
<i
className="fas fa-trash"
onClick={() => deleteTask(task._id)}
></i>
</li>
);
}
And this is what I get:
I still get that white background. All I want is to remove the default styles and add my own for success and error.
for custom style react-toastify
css
.Toastify__toast--error {
border: 1px solid #EB5757;
border-radius: 50px !important;
background: #FAE1E2 !important;
}
.Toastify__toast--error::after {
content : url('../assets/images/svg/closeToast.svg'); // Your svg Path
position: absolute;
color: #333333;
font-size: 15px;
font-weight: 700;
left:265px;
padding-top: 14px !important;
}
.Toastify__toast--error::before {
content: url("../assets/images/svg/errorToast.svg");// Your svg Path
position:relative;
z-index:100000;
left:12px;
top:6px;
}
.Toastify__toast--success {
border: 1px solid #3A9EA5 !important;
border-radius: 50px !important;
background: #F0F9FA !important;
}
.Toastify__toast--success::before {
content: url("../assets/images/svg/successToast.svg");// Your svg Path
position:relative;
z-index:100000;
left:12px;
top:6px;
}
.Toastify__toast--success::after {
content : url('../assets/images/svg/closeToast.svg');// Your svg Path
position: absolute;
color: #333333;
font-size: 15px;
font-weight: 700;
left:265px;
padding-top: 14px !important;
}
.Toastify__toast--warning {
border: 1px solid #E78326 !important;
border-radius: 50px !important;
background: #FADFC5 !important;
}
.Toastify__toast--warning::before {
content: url("../assets/images/svg/warnToast.svg");// Your svg Path
position:relative;
z-index:100000;
left:12px;
top:6px;
}
.Toastify__toast--warning::after {
content : url('../assets/images/svg/closeToast.svg'); // Your svg Path
position: absolute;
color: #E78326;
font-size: 15px;
font-weight: 700;
left:265px;
padding-top: 14px !important;
}
.Toastify__toast-body {
color: #444C63 ;
font-size: 16px;
padding-left: 20px;
line-height: 20px;
padding: 0px;
padding-top: 25px;
width: 100%;
font-weight: 400;
margin-left: 25px !important;
}
.Toastify__toast > button> svg {
display: none;
}
In my case (also a React app) I only needed to change:
background color of warning and error
progress bar color
font
I found this to be the easiest & quickest solution. In my app's CSS file I overwrite the background-property in the default classes. I also define my own classes for toast body and the progress bar:
/* https://fkhadra.github.io/react-toastify/how-to-style/ */
.Toastify__toast--warning {
background: #FFE8BC !important;
}
.Toastify__toast--error {
background: #FCA7A9 !important;
}
.toastBody {
font-family: "Atlas Grotesk Web", Arial, Helvetica, sans-serif;
color: #10171D; /* #10171D */
font-size: 0.875rem !important;
}
.toastProgress {
background: #333F48 !important;
}
To use my classes:
<ToastContainer
progressClassName="toastProgress"
bodyClassName="toastBody"
/>
Easest way to define a custom method, which can take the type of notification, content, and toast options. With the type of notification, you can pass different classNames to your custom content and override root toast component styles. Typescript example:
export enum NOTIFICATIONS_TYPES {
SUCCESS = 'success',
ERROR = 'error',
}
const NotificationStringContent: React.FunctionComponent<{
content: string;
}> = ({ content }) => (
<Typography component="p" variant="text-200">
{content}
</Typography>
);
export const showNotification = (
type: NOTIFICATIONS_TYPES,
content: string | React.ReactElement,
options: ToastOptions = {}
) => {
const toastContent = typeof content === 'string' ? (
<NotificationStringContent content={content} />
) : (
content
);
toast(toastContent, {
className: classnames(styles.toast, {
[styles.toastSuccess]: type === NOTIFICATIONS_TYPES.SUCCESS,
[styles.toastError]: type === NOTIFICATIONS_TYPES.ERROR,
}),
...options,
});
};
const NotificationContainer: React.FunctionComponent<{}> = () => (
<ToastContainer
position="bottom-left"
hideProgressBar
closeButton={<NotificationCloseButton />}
closeOnClick={false}
pauseOnHover
/>
);
export default NotificationContainer;
import { toast } from "react-toastify";
// promise is a function that returns a promise
export const withToast = (promise) => {
toast.promise(
promise,
{
pending: {
render() {
return (
<div className="p-6 py-2 bg-green-400">
<p className="mb-2">Your transaction is being processed.</p>
<p>Hang tight... Just few more moments.</p>
</div>
);
},
icon: false,
},
success: {
render({ data }) {
return (
<div>
<p className="font-bold">
Tx: {data.transactionHash.slice(0, 20)}...
</p>
<p>Has been succesfuly processed.</p>
</div>
);
},
// other options
icon: "🟢",
},
error: {
render({ data }) {
// When the promise reject, data will contains the error
return <div>{data.message ?? "Transaction has failed"}</div>;
},
},
},
// configuration
{
closeButton: true,
}
);
};
When you need to use it:
withToast(_purchase({ Id, value }));
Depending on _purchase, your app will show different messages with different styles