Unable to limit the maxlength and minlength for input type number - reactjs

JSX:
const input = (props) => {
return (
<div>
<span className="input-icon">{props.icon}</span>
<input
type={props.type || "number"}
className={props.inputClassName || "main-input"}
{...props.attributes}
/>
</div>
);
};
CSS:
.main-input {
width: 100%;
height: 2rem;
padding: 4px 5px 4px 0;
border: none;
caret-color: hsl(183, 100%, 15%);
outline: none;
color:hsl(183, 100%, 15%);
font-weight: bolder;
font-family: inherit;
font-size: 1.1rem;
}
.main-input:focus {
border-bottom: hsl(184, 14%, 56%) solid 1.5px;
}
.main-input::-webkit-outer-spin-button,
.main-input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
.main-input[type="number"] {
-moz-appearance: textfield;
text-align: right;
}
.input-icon {
position: absolute;
padding: 5px 0 0 10px;
font-weight: bolder;
}
.card-label{
font-size: 10px;
color: hsl(186, 14%, 43%);
}
I have changed the number type input and removed the counter using the appearance CSS property. But now I'm trying to limit(maxlength) to 5 and minlength to 1 and also minus(As shown in the image) values are not allowed. Please comment if anyone knows a solution or please comment with any suggestions.

add onChange callback to input, and prevent adding anything inside input which is not number.

Related

Material UI Hidden Overflow in Material UI Design

In my design with Material UI, the overflowing part of the card is absolute, but it is hidden, what could be the reason. Thanks.
my listbox is below
const Listbox = styled('ul')(
({ theme }) => `
width: 100%;
margin: -1px 0 ;
padding: 0;
position: absolute;
list-style: none;
border: 2px solid ${theme.palette.primary.main};
border-top: 0;
background-color: ${theme.palette.mode === 'dark' ? '#141414' : '#fff'};
overflow: auto;
max-height: 250px;
border-bottom-left-radius: 25px;
border-bottom-right-radius: 25px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
z-index: 1;
& li {
padding: 5px 12px;
display: flex;
& span {
flex-grow: 1;
}
& svg {
color: transparent;
}
}
& li[aria-selected='true'] {
background-color: ${theme.palette.mode === 'dark' ? '#2b2b2b' : '#fafafa'};
font-weight: 600;
& svg {
color: #1890ff;
}
}
& li.${autocompleteClasses.focused} {
background-color: ${theme.palette.mode === 'dark' ? '#003b57' : '#e6f7ff'};
cursor: pointer;
& svg {
color: currentColor;
}
}
`,
);
enter image description here
I created absolute postion element bu proble is persist

How to add animation on container changing its width realtime

I am making a form that expands when the user enters any character/key and gets back to its original width when there is no character left, for the plus point, I want to add animation to that expandable form so it gives a smooth look.
Here is the code and I want this action as follows
Not in React but I made an example in Vanilla JS hope it helps. I used CSS variables for changing width and making it smooth.
Instead of removing svg icons completely try scaling it down to 0 or changing it opacity to 0
const btns = Array.from(document.querySelectorAll('.btn'))
const input = document.querySelector('input')
btns.shift() // for leaving first button
input.addEventListener('input', (event) => {
btns.forEach((btn) => {
if (event.target.value.trim().length > 0) {
btn.classList.add('scale-0')
btn.parentElement.classList.add('width-50')
} else {
btn.classList.remove('scale-0')
if (btn.parentElement.classList.contains('width-50')) {
btn.parentElement.classList.remove('width-50')
}
}
})
})
#import 'https://cdn.jsdelivr.net/gh/KunalTanwar/normalize/css/normalize.inter.min.css';
body {
display: grid;
place-items: center;
}
.row {
--column-gap: 1rem; /* 8px */
width: 100%;
display: flex;
max-width: 525px;
column-gap: var(--column-gap);
}
.row input {
flex-grow: 1;
border-radius: 100vmax;
padding: 0.75rem 1.25rem;
border: 1px solid #c1c1c1;
}
.container {
--column-gap: 0.5rem; /* 16px */
--btn-size: 3.125rem; /* 50px */
flex-shrink: 0;
display: inherit;
column-gap: var(--column-gap);
width: calc(var(--column-gap) * 3 + var(--btn-size) * 4);
transition: width 250ms ease;
}
.container.width-50 {
width: var(--btn-size);
}
.container .btn {
width: var(--btn-size);
border-radius: 50%;
aspect-ratio: 1/1;
border: 1px solid #c1c1c1;
transition: transform 250ms ease;
}
.container .btn.scale-0 {
transform: scale(0);
}
<div class="row">
<div class="container">
<button class="btn">1</button>
<button class="btn">2</button>
<button class="btn">3</button>
<button class="btn">4</button>
</div>
<input type="text" />
</div>

make input label stay up when the input in not focus

I have a style component with input and label. the label goes up when it's focus and moves down when it's unfocused.
how can I make the label stay up when there a value in the input or when I unfocusedthe input?
my code :
import React from "react";
import styled from "styled-components";
const Wrapper = styled.div`
position: relative;
`;
const Input = styled.input`
font-size: 18px;
padding: 10px 10px 10px 5px;
display: block;
width: 300px;
border-bottom: 1px solid #757575;
&:focus {
outline: none;
}
`;
const Label = styled.label`
color: #999;
font-size: 18px;
font-weight: normal;
position: absolute;
pointer-events: none;
left: 5px;
top: 10px;
transition: 0.2s ease all;
input:focus ~ &,
input:not(:placeholder-shown).input:not(:focus) ~ .label {
top: -20px;
font-size: 14px;
color: #5264ae;
}
`;
const FloatingInput = () => (
<Wrapper>
<Input />
<Label>First Name</Label>
</Wrapper>
);
export default FloatingInput;
Add a required attribute to the input and add a input:valid ~ & selector for the label. When the input has some value it will become "valid" and the CSS selector will pick that up and apply the same style as when its focused.
const Input = styled.input.attrs(() => ({
required: true,
}))`
font-size: 18px;
padding: 10px 10px 10px 5px;
display: block;
width: 300px;
border-bottom: 1px solid #757575;
&:focus {
outline: none;
}
`;
const Label = styled.label`
color: #999;
font-size: 18px;
font-weight: normal;
position: absolute;
pointer-events: none;
left: 5px;
top: 10px;
transition: 0.2s ease all;
input:focus ~ &,
input:not(:placeholder-shown).input:not(:focus) ~ .label,
input:valid ~ & {
top: -20px;
font-size: 14px;
color: #5264ae;
}
`;
const FloatingInput = () => (
<Wrapper>
<Input />
<Label>First Name</Label>
</Wrapper>
);
If you are wanting to toggle the "focused" style and make it stick once focused you'll need a bit of React state to hold the triggered state.
const Input = styled.input`
font-size: 18px;
padding: 10px 10px 10px 5px;
display: block;
width: 300px;
border-bottom: 1px solid #757575;
&:focus {
outline: none;
}
`;
const focusCSS = css`
top: -20px;
font-size: 14px;
color: #5264ae;
`;
const Label = styled.label`
color: #999;
font-size: 18px;
font-weight: normal;
position: absolute;
pointer-events: none;
left: 5px;
top: 10px;
transition: 0.2s ease all;
input:focus ~ &,
input:not(:placeholder-shown).input:not(:focus) ~ .label {
${focusCSS}
}
${({ focused }) => focused && focusCSS}
`;
const FloatingInput = () => {
const [focused, setFocused] = React.useState(false);
return (
<Wrapper>
<Input onFocus={() => setFocused(true)} />
<Label focused={focused}>First Name</Label>
</Wrapper>
);
};

Track Color in input type Range in react

I have the next input type range in react:
inputElement = <div className={styles.InputElementRange}>
<input
min={props.min}
max={props.min}
value={props.value}
onChange={props.changed}
></input>
<input
type="text"
value={props.value}
onChange={props.changed}
style={props.stylesElement}
/>
</div>
and I got this:
The input type range works very well but I couldn't change the styles of the track.
How can I change the blue color by default? I want to replace the blue color for orange color.
Thanks in advance.
See this link to see how you can style the HTML slider
I found a solution:
inputElement = <div className={styles.InputElementRange}>
<input
min={props.min}
max={props.min}
value={props.value}
onChange={props.changed}
style={{'background': `linear-gradient(to right, orange ${(parseInt(props.value)-props.min)*100/(props.max-props.min)}%, #ccc 0px`}}
></input>
<input
type="text"
value={props.value}
onChange={props.changed}
style={props.stylesElement}
/>
</div>
and these are the styles:
input[type="range"] {
-webkit-appearance: none;
width: 100%;
height: 10px;
margin-right: 10px;
border-radius: 6px;
outline: 0;
background: #ccc;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 18px;
width: 18px;
border-radius: 3px;
background: orange;
border-radius: 50%;
border: 0;
cursor: pointer;
}
/* All the same stuff for Firefox */
input[type=range]::-moz-range-thumb {
height: 18px;
width: 18px;
border-radius: 3px;
background: orange;
border: 0;
border-radius: 50%;
cursor: pointer;
}
/* All the same stuff for IE */
input[type=range]::-ms-thumb {
height: 18px;
width: 18px;
border-radius: 3px;
background: orange;
border-radius: 50%;
border: 0;
cursor: pointer;
}
I thought my answer based in this answer: Ver link
Here's an easy one pretty straight forward.
Note that I'm using styled components but you can use the same with vanilla css or sass as well
import React, { useState } from 'react'
import styled from 'styled-components'
export const Slider = () => {
const [bgSize, setBgSize] = useState(0)
const handleSlide = (e) => {
setBgSize(e.target.value)
}
return (
<SliderContainer>
<ColorSlider
onChange={(e) => {
handleSlide(e)
}}
bgSize={bgSize}
min={0}
max={100}
type={'range'}
/>
</SliderContainer>
)
}
export const SliderContainer = styled.div``
export const ColorSlider = styled.input`
-webkit-appearance: none; /* Override default CSS styles */
appearance: none;
background-image: linear-gradient(#ff4500, #ff4500);
background-size: ${({ bgSize }) => bgSize}% 100%;
background-repeat: no-repeat;
border: 1px solid;
&::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
margin-top: -0.5em;
// position: relative;
appearance: none;
height: 25px;
width: 25px;
border: 1px solid black;
background: #4d4945;
border-radius: 100%;
cursor: pointer;
border: 1px solid black;
}
&::-webkit-slider-runnable-track {
-webkit-appearance: none;
appearance: none;
width: 100%;
max-width: 500px;
outline: none;
height: 10px;
border-radius: 10px;
background-image: transparent;
}
`

React-Select, Multi Select and Text Overflow

I am using React-Select component with multi select. One of the problems I am facing is that if the user select 3 or 4 options the UI looks pretty bad because the text begins to overflow and that causes the component to grow either horizontally and vertically.
I want to have a behavior where the size of the component remains the same and if the user selects more options then it just shows "..." (ellipsis) rather than try to show the newly selected options.
The behavior I want is more inline with this component
http://instructure-react.github.io/react-select-box/
See how it handles multi-select.
I don't want to swap out components now because we have done lots of testing with React-Select.
Can you give me some guide lines on how to achieve this without removing react-select.
i've managed to achieve both the ellipsis effect and leaving the display at one row,
here is a working example
https://codesandbox.io/s/v638kx67w7
hope this helps
I solved this without losing the Input component like this;
import Select, { components as RSComponents } from "react-select";
const ValueContainer = ({ selectProps, children, ...props }) => {
let [values, input] = children;
if (Array.isArray(values)) {
values = selectProps.value.map((x) => x.label).join(', ');
}
return (
<RSComponents.ValueContainer {...props}>
<div style={{
maxWidth: "80%",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
overflow: "hidden",
}}>
{values}
</div>
{input}
</RSComponents.ValueContainer>
);
};
const customStyles = useMemo(() => ({
valueContainer: (provided, state) => ({
...provided,
whiteSpace: "nowrap",
overflow: "hidden",
flexWrap: 'nowrap',
}),
input: (provided, state) => ({
...provided,
minWidth: '20%'
}),
}), []);
<Select
components={{ ValueContainer }}
isMulti
styles={customStyles}
...
/>
This is the generated Html for given react-select element
. react-select-box-container {
position: relative;
width: 240px;
display: inline-block;
background-color: #fff;
border-radius: 4px;
text-align: left;
box-shadow: 0 0 2px rgba(0, 0, 0, .3);
}
.react-select-box {
padding: 15px 0;
display: inline-block;
cursor: pointer;
border: none;
width: 100%;
text-align: left;
background-color: transparent;
}
.react-select-box:focus {
outline: 0;
box-shadow: 0 0 4px #0493D1;
}
.react-select-box:before {
content: ' ';
z-index: 1;
position: absolute;
height: 20px;
top: 15px;
right: 34px;
border-left: 1px solid #CBD2D7;
}
.react-select-box:after {
content: ' ';
position: absolute;
z-index: 1;
top: 23px;
right: 13px;
border-top: 6px solid #7B8E9B;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
.react-select-box-label,
.react-select-box-option {
line-height: 16px;
font-size: 12px;
font-weight: bold;
color: #7B8E9B;
}
.react-select-box-label {
padding: 0 40px 0 20px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #0493D1;
}
.react-select-box-empty .react-select-box-label {
color: #7B8E9B;
}
.react-select-box-click-outside-layer {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2;
}
.react-select-box-clear {
position: absolute;
top: 15px;
right: 0;
width: 35px;
height: 20px;
background-color: #fff;
text-indent: -9999em;
z-index: 3;
border: none;
}
.react-select-box-clear:before {
content: '×';
position: absolute;
top: 2px;
left: 10px;
z-index: 1;
background-color: #7B8E9B;
border-radius: 100%;
font-size: 13px;
color: #fff;
line-height: 1;
width: 15px;
height: 15px;
text-indent: 0;
text-align: center;
}
.react-select-box-clear:hover,
.react-select-box-clear:focus {
outline: 0;
}
.react-select-box-clear:hover:before,
.react-select-box-clear:focus:before {
background-color: #0493D1;
}
.react-select-box-hidden {
display: none
}
.react-select-box-options {
margin: 2px 0 0;
position: absolute;
padding: 10px 0;
width: 240px;
top: 100%;
left: 0;
z-index: 4;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 0 2px rgba(0, 0, 0, .3);
}
.react-select-box-options-list {
list-style: none outside;
margin: 0;
padding: 0;
}
.react-select-box-option {
padding: 10px 20px;
margin: 0;
cursor: pointer;
display: block;
line-height: 1.2;
text-decoration: none;
}
.react-select-box-option:hover {
color: #0493D1;
background-color: #f4f4f4;
}
.react-select-box-option-selected {
color: #CBD2D7;
}
.react-select-box-multi .react-select-box-option {
padding-left: 42px;
position: relative;
}
.react-select-box-multi .react-select-box-option:before {
content: ' ';
position: absolute;
line-height: 1;
text-align: center;
left: 20px;
top: 9px;
border-radius: 3px;
height: 12px;
width: 12px;
margin-right: 10px;
border: 1px solid #7B8E9B;
background: #f9f9f9;
vertical-align: middle;
}
.react-select-box-multi .react-select-box-option-selected:before {
content: '✓';
}
.react-select-box-multi .react-select-box-option-selected {
color: #1F3344;
}
.react-select-box-option:focus,
.react-select-box-option-focused {
color: #0493D1;
outline: 0;
background-color: #DDE2E5;
}
.react-select-box-close {
color: #0493D1;
text-transform: uppercase;
background-color: transparent;
border: none;
padding: 5px 0;
display: block;
text-align: center;
width: 100%;
font-weight: bold;
cursor: pointer;
outline: none;
}
.react-select-box-close:hover,
.react-select-box-close:focus {
text-decoration: underline;
}
.react-select-box-empty .react-select-box-close {
color: #CBD2D7;
}
.react-select-box-native {
position: absolute;
left: -99999em;
}
<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>
<div class="react-select-box-container react-select-box-multi react-select-box-empty">
<button id="react-select-box-2" class="react-select-box" tabindex="0" aria-hidden="true">
<div class="react-select-box-label">
Favorite Colors
</div></button>
<div class="react-select-box-options react-select-box-hidden" aria-hidden="true" tabindex="0">
<div class="react-select-box-off-screen">
<a id="react-select-box-2-0" href="#" class="react-select-box-option" tabindex="-1">Red</a>
<a id="react-select-box-2-1" href="#" class="react-select-box-option" tabindex="-1">Green</a>
<a id="react-select-box-2-2" href="#" class="react-select-box-option" tabindex="-1">Blue</a>
</div>
<button class="react-select-box-close">Close</button>
</div>
<div class="react-select-box-native">
<label for="react-select-box-2-native-select">Favorite Colors</label>
<select id="react-select-box-2-native-select" multiple="multiple">
<option value="red">
Red
</option>
<option value="green">
Green
</option>
<option value="blue">
Blue
</option>
</select>
</div>
</div>

Resources