How can I add floating label to react-select? - reactjs

I'm trying to build web app using MaterialUI theme and I need to use autocomplete .. It turns out MUI v2 does not have AutoComplete and docs suggest using alternatives. react-select has all functionality I need - but I cannot figure out how to make it look similarly to other controls - specifically how to make floating label to float away when user starts typing or click on dropdown.
What I did:
created a component (IntegratedSelect) that uses react-select from this demo
cloned this file into CustomAutocomplete.jsx and replaced <Input> with <IntegratedSelect>
modified code to pass id to IntegratedSelect and set that id to Select control
.. and tried a lot of different other approaches (setting refs, using FloatingLabel from #material/react-floating-label etc).. with no luck.
Can you please advise how can I trigger float on the label, or otherwise hookup react-select control with floating label?
Any help will be appreciated!
Regards,
VB
P.S. Gist added: https://gist.github.com/mspclaims/e07bf1ff657fa8eb4756bc0514a164fe

Following this comment on a similar issue on GitHub, I was able to get it to work! In my case, I'm using styled-component but it should work regardless of the styling used
import React from "react";
import styled from "styled-components";
import { components } from "react-select";
export const Control = (props: any) => {
return (
<>
<Label isFloating={props.isFocused || props.hasValue}>Select</Label>
<components.Control {...props} />
</>
);
};
const Label = styled.label<{ isFloating?: boolean }>`
left: 10px;
pointer-events: none;
position: absolute;
transition: 0.2s ease all;
-moz-transition: 0.2s ease all;
-webkit-transition: 0.2s ease all;
z-index: 1;
top: ${(props) => (props.isFloating ? `5px` : `35%`)};
font-size: ${(props) => (props.isFloating ? `0.5rem` : `1rem`)};
`;
You can add your custom control component to Select:
<Select
...
components={{ Control }}
placeholder=""
/>
NOTE: You must ensure your Select component doesn't have an empty default value otherwise, hasValue will always be true

Related

pass props to styled-components selector

I've got a styled-component which gets some additional styles based on a property (active).
The component looks similar to this:
import styled from 'styled-components';
const Button = styled.button`
color: black;
${props => props.active ? `color: red;` : ''}
`;
Within a component test I need to select the active Button which (obviously) doesn't work doing the following:
document.querySelector(Button)
since this targets all Button components, no matter if active or not.
I read the styled-components docs and googled a lot. However I haven't been able to find a way to pass specific props to the styled-components-selector. I expected something similar to the following (which does not work)
document.querySelector(Button({ active: true }))
Is there any way to achieve this or rather how do you select a styled component which has specific props?
I think I've found a solution which is probably the 'right' way when using styled-components.
Instead of defining the active style via props within the button component, I've created another one which extends the button. This of course forces me to use another component for the active button instead of just setting an active property.
However it's not much additional work and super easy to test. So I've decided to go this way.
const Button = styled.button`
color: black;
`;
const ActiveButton = styled(Button)`
color: red;
`;
document.querySelector(ActiveButton);
The correct syntax is this:
const Button = styled.button`
color: black;
color: ${props => props.active ? 'red' : ''};
`;

Question about mixing styled-components with material-ui

Hello I am a react newbie and new to styling as well :)
I am trying to style the material-ui Button component with styled components
I am doing this by overriding global class names, I know material-ui introduced global class names like MuiButton-root etc
I am not clear on the use of "&" in parent selector, for example:
const StyledButton = styled(Button)`
&.MuiButton-root {
width: 500px;
}
.MuiButton-label {
color: ${props => props.labelColor};
justify-content: center;
}
`;
The above code works and can achieve the following:
The Button has a width of 500px
The label has a color of red (labelColor is passed in as a prop)
Please see sandbox below for full code
Question:
Why do I need "&" selector for the MuiButton-root, whereas for the MuiButton-label I don't?
Also is this the best way to style material-ui with styled components?
Please see the following sandbox: https://codesandbox.io/embed/practical-field-sfxcu
The '&' selector is used to target the classes and neighbouring elements/classes. Take a look at cssinjs. Its the underlying system behind MUI's styling.
But in short to answer your question;
const StyledButton = styled(Button)`
&.MuiButton-root { //this targets any class that is added to the main component [1]
width: 500px;
}
.MuiButton-label { //in css-in-js this is effectively '& .MuiButton-label [2]
color: ${props => props.labelColor};
justify-content: center;
}
[1] Targets main classes on component
<StyledButton className='test bob'> << this element is targeted
</StyledButton>
[2] Targets child elements either through class or element type. Note the space between & and the actual class.
<StyledButton className='test bob'>
<span className='MuiButton-label'>test</span> << this element is targeted instead
</StyledButton>
You can also use the element tag directly
span {
color: ${props => props.labelColor};
justify-content: center;
}

Emotion.js how to do composition / conditional styling in react-native?

https://github.com/emotion-js/emotion/tree/master/packages/native
gives example
style={css`
border-radius: 10px;
`}
However, I can't figure out how I can do composition as done in https://emotion.sh/docs/composition with react-native
<div css={[danger, base]}>
Nor I can't do conditional styling as done in https://emotion.sh/docs/styled
const Button = styled.button`
color: ${props =>
props.primary ? 'hotpink' : 'turquoise'};
`
Even if I could do, they use two different methods one using css one using styled . How can I get the two at the same time with react-native?
Question 1: How to do composition in emotion/native in React Native?
It's really simple all you need to is use style property like so:
const style1 = css`
font-size: 40px;
`
const color = css`
color: red;
`
// And then in your component you can pass the all your style objects
// in an array to style property
<Text style={[fontSize, color]}>Hello world</Text>
Question 2: Conditional style in emotion/native in React Native?
const Description = styled.Text`
font-size: ${props => props.fontSize !== undefined ? props.fontSize : "40px"};
color: hotpink;
`
<Description fontSize={"60px"}>
Change code in the editor and watch it change on your phone! Save to get a shareable url.
</Description>
Here's a working exampe as a snack

How to reduce spacing between antd Form.Items?

How does one reduce the amount of space between two Form.Item's in a Form?
for example in any of the antd form examples the spacing between a Form.Item is all the same and (to my eye) rather large.
You need to style the Form.Item component, for example with inline-style:
// The current form item is margin 15px top.
<Form.Item style={{ marginBottom: "0px" }}>
<Input />
</Form.Item>
Or the entire Form by overriding the css-class, for example with CSS-in-JS:
// Apply style to all form
const StyledForm = styled(Form)`
.ant-form-item {
margin-bottom: 0px;
}
`;
Demo:
Same can be achieved with .css file and importing it
First find the style that is achieving what you want to override, the override it by importing custom css. Your example:
.ant-form-inline .ant-form-item {
margin-right: 8px; // default is 16px
}

Styled components for colored tags

Styled components looks great, but I am having trouble organizing my components. My first venture with is a tag list, that automatically colors the tags. After some trial I came up with a component that can be used like this:
// An array of tags. The string hashes determine the color
<ColorTags tags={post.frontmatter.tags} inline/>
It is implemented as follows:
components/
ColorTags // functional component
ColorTagLI // styled component
ColorTagUL // styled component
With:
// ColorTags
import ColorTagLI from './ColorTagLI'
import ColorTagUL from './ColorTagUL'
export default ({tags, inline}) =>
<ColorTagUL>
{tags.map( tag =>
<ColorTagLI key={tag} colorString={tag} inline>
<Link to="/">
{tag}
</Link>
</ColorTagLI>
)}
</ColorTagUL>
// ColorTagUL
export default styled.ul`
list-style-type: none;
margin: 0;
padding: 0;
`
// ColorTagLI
const colorHash = new ColorHash({lightness: [0.4, 0.5, 0.6]});
const hslColor = cString => {
const [h, s, l] = colorHash.hsl(cString)
return `hsl(${h}, ${s*100}%, ${l*100}%)`
}
export default styled.li`
color: white;
background-color: ${props => hslColor(props.colorString)};
display: ${props => props.inline ? 'inline-block' : 'block'};
padding: 0.25rem 0.5rem;
margin: 0.25rem;
> a { text-decoration: none; color: white; }
`
Some questions I have:
What's a good way to discern between styled and regular components? I
decided on appending the HTML tag to the styled components, since
they are always tied to that.
Is it not a problem to have the Link tag inside a Styled component?
Should the ColorTag components be in a folder of themselves? Because they are tightly coupled.
Is using theinline prop a smart way to switch between configurations? It may
result in a lot of conditional statements for margins, padding and
media queries... Perhaps better make two different components?
You can use utility function isStyledComponent.
Why would it be a problem to have a Link component inside styled component?
Matter of opinion, if you believe they are tightly coupled you can create /ColorTag directory with index.js file that exports only what should be exposed.
Yes it may result in a lot of conditional statements, that's why you can extend styles on styled components.
I hope I understood you right and my answers are clear.

Resources