With React-Select, how can I make the dropdown accessible through a React-Bootstrap-Glyphicon? - reactjs

I wanted to create a dropdown using React-Select, but instead of the UI looking like this:
I wanted it to look like this:
This is my current code:
dropDown = R.createElement(Select, {
options: options,
valueKey: 'value',
labelKey: 'name',
clearable: false,
placeholder: "Action",
searchable: false,
autosize: false,
onChange: function (opt) {
if (opt.callback === undefined && opt.callback !== "function") { return; }
opt.callback({
importable: importable,
scheduledImportable: sImportable
}, index);
},
optionRenderer: function (ele) {
return R.createElement(
'span',
{ style: { color: ele.color} },
R.createElement('span', { className: ele.icon},null, " "),
ele.name
);
}
});
Any help would be greatly appreciated.

Is it ok to use another element to help?
<div className="select-wrapper">
<span className="glyphicon glyphicon-align-left" aria-hidden="true"></span>
<Select .... />
</div>
Then css
.select-wrapper {
position:relative;
}
.select-wrapper .glyphicon {
position: absolute;
z-index: 5;
display: block;
top: 7px;
left: 10px;
color: #ccc;
pointer-events: none;
}

Related

React-codemirror2 (json editor)

I'm using the lib "react-codemirror2" to make a JSON editor. But I can't set the styles as I need. This is what I want to get
This is how I'm trying to implement, I've tried setting styles for various modifiers, but nothing helps, and the default styles don't change.:
export const CodeMirrorStyled = styled(CodeMirror)`
& .CodeMirror {
background: ${palette(EPaletteTheme.light_grey, 0)};
font-family: "Roboto", monospace;
font-size: 16px;
height: 198px;
}
& .cm-variable {
color: ${palette(EPaletteTheme.brand_blue, 0)};
}
/* stylelint-disable declaration-no-important */
& div {
&::-webkit-scrollbar {
width: 4px !important;
}
&::-webkit-scrollbar-track {
background: ${palette(EPaletteTheme.light_grey, 0)} !important;
}
&::-webkit-scrollbar-thumb {
background-color: ${palette(EPaletteTheme.grey, 0)} !important;
border-radius: 4px !important;
}
}
/* stylelint-enable declaration-no-important */
& .CodeMirror-gutters {
background: ${palette(EPaletteTheme.light_grey, 0)};
}
`;
<CodeMirrorStyled
value={httpBody}
options={{
theme: "default",
height: "auto",
viewportMargin: Infinity,
mode: {
name: "javascript",
json: true,
statementIndent: 2,
},
lineNumbers: true,
lineWrapping: true,
indentWithTabs: false,
tabSize: 2,
}}
onBeforeChange={(
editor: any,
data: any,
value: string
) => {
onChangeCodeEditor(value);
}}
/>

How to display a span based on a invalid input SASS

im using SASS and i would like to display an error span when the input is invalid, can this be done using just SASS?
this is the input div:
const FormInput = (props) => {
const [focused, setFocused] = useState(false);
const { label, errorMessage, onChange, id, ...inputProps } = props;
const handleFocus = (e) => {
setFocused(true);
};
return (
<div className="formInput">
<span>{errorMessage}</span>
<input
{...inputProps}
onChange={onChange}
onBlur={handleFocus}
onFocus={() =>
inputProps.name === "confirmPassword" && setFocused(true)
}
focused={focused.toString()}
className="Input"
/>
</div>
);
};
and this is the SASS file i can change the border color of the input field it self but idk how to change the display of the span from none to block when the input is invalid
.formInput {
display: flex;
flex-direction: column;
width: 90%;
height: max-content;
span {
color: red;
font-size: 13px;
display: none;
padding: 0.5rem 0;
}
.Input {
border: none;
outline: none;
background-color: var(--inputColor);
border-radius: 8px;
padding: 20px;
&:invalid[focused="true"] {
border: 1px solid red;
}
}
}
the inputs are validated using html pattern with regex and required attribute
like this:
const inputs = [
{
id: 1,
name: "email",
type: "email",
placeholder: "Email",
errorMessage: "It should be a valid email address!",
label: "Email",
required: true,
},
{
id: 2,
name: "password",
type: "password",
placeholder: "Password",
errorMessage:
"Password should be 8-20 characters and include at least 1 letter, 1 number and 1 special character!",
label: "Password",
pattern: `/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/`,
required: true,
},
]
I found a way to do this, first you have to make sure that the span is placed after the input like this
<div className="formInput">
<input
{...inputProps}
onChange={onChange}
onBlur={handleFocus}
onFocus={() =>
inputProps.name === "confirmPassword" && setFocused(true)
}
focused={focused.toString()}
className="Input"
/>
<span>{errorMessage}</span>
</div>
and then add this to the SCSS file:
.Input {
border: none;
outline: none;
background-color: var(--inputColor);
border-radius: 8px;
padding: 20px;
&:invalid[focused="true"] {
border: 1px solid red;
}
&:invalid[focused="true"] {
display: block;
**~ {
span {
display: block;
}**
}
}
}
Yeah, you can do it with pseudo class like the following example, you need to put the span tag just next to the input tag, here I'm using a text input element but you can change it as you require:
HTML
<input name="question1" type="text" value="prefixed value" required> <span></span>
CSS
input[type="text"]:invalid + span:after {
content: '✖';
}
input[type="text"]:valid + span:after {
content: '✓';
}
Here the content will change if the person leave this input field empty.

React ag-grid row auto height doesn't work

I was trying to implement the row auto height feature described in the docs here:
https://www.ag-grid.com/javascript-grid-row-height/#auto-row-height
However it seems to not be working in my case. What happens for me is that the text doesn't wrap at all and it just creates a single long line for each row.
I've tried adapting the code as best as I could to my own app, but maybe I missed something? I'll be thankful if you could take a look at my code and tell me if something is missing:
const defaultColDefProperties = {
flex: 1,
editable: true,
resizable: true,
floatingFilter: true,
filter: true,
wrapText: true,
autoHeight: true,
};
const columnDefinition = [{headerName: "Key", field: "Key"},
{headerName: "Value", field: "Value"}];
const ConfigurationDataGrid = (props) =>
{
const [gridRowData, setGridRowData] = useState([]);
const gridApi = useRef(null);
useEffect(async () =>
{
const getRowData = async () =>
{
let rowData = await WebApi.getRowData();
setGridRowData(rowData);
}
await getRowData();
},[]);
const onGridReady = params =>
{
gridApi.current = params.api;
}
const onColumnResized = (params) =>
{
params.api.resetRowHeights();
}
const onColumnVisible = (params) =>
{
params.api.resetRowHeights();
}
return (
<div style={{ width: '100%', height: '100%' }}>
<UxDataGrid
id='datagrid'
className='custom-datagrid'
onGridReady={onGridReady}
columnDefs={columnDefinition}
rowData={gridRowData}
defaultColDef={defaultColDefProperties}
onColumnResized={onColumnResized}
onColumnVisible={onColumnVisible}/>
</div>
);
}
The css class:
.custom-datagrid {
height: 100%;
border: 0px;
margin-top: 0px !important;
margin-right: 0px !important;
margin-left: 0px !important;
}
What am I missing?
In my case I have ra-ui-grid it is the same as your component - UxDataGrid
Inside ra-ui-grid I have next definitions:
.html:
<ag-grid-angular
class="ag-theme-balham grid"
...
></ag-grid-angular>
.ts:
defaultColDef: {
flex: 1,
...
},
.scss:
ra-ui-grid {
height: 100%;
display: flex;
flex-flow: column nowrap;
.grid {
height: 100%;
}
}
Then in some component, I am using ra-ui-grid with 2 wrappers
.html
<div class="io">
<div class="io__table">
<ra-ui-grid
[data]="data"
[config]="gridConfig"
[columns]="columnDefs"
(onPaginationChanged)="paginationChanged.next($event)"
></ra-ui-grid>
</div>
</div>
.scss:
.io {
height: calc(100% - 36px);
display: flex;
flex-direction: column;
&__table {
flex: 1;
min-height: 254px;
}
}

How do I dynamically adjust the size of the React chart 2 pie chart

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;
}

How can I change the styles of the react-toastify popup message?

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

Resources