Changing a css variable in styled components from a React props - css

I am using CSS grid to create a dynamic table. The number of columns and rows are dynamic and are based on props I get from an higher component in React.
How can I change a css variable inside a styled component (emotion) to the data I get from a React props?

Here it is in their documentation:
https://www.styled-components.com/docs/basics#passed-props
// Create an Input component that'll render an <input> tag with some styles
const Input = styled.input`
padding: 0.5em;
margin: 0.5em;
color: ${props => props.inputColor || "palevioletred"};
background: papayawhip;
border: none;
border-radius: 3px;
`;
// Render a styled text input with the standard input color, and one with a custom input color
render(
<div>
<Input defaultValue="#probablyup" type="text" />
<Input defaultValue="#geelen" type="text" inputColor="rebeccapurple" />
</div>
);

Related

Change the default color picker box

I'm using Angular6 with material-designs. What I'm trying to do is get color input from mat-form-field. For that I used matinput type="color" inside my input tag. My HTML file is as follows,
<div>
<mat-form-field class="form-field">
<mat-label>Color</mat-label>
<input matInput type="color" formControlName="color"required placeholder="Color">
</mat-form-field>
</div>
Then I have added some CSS on it to design the color picker box according to my need,
input[type="color"] {
-webkit-appearance: none;
border: none;
width: 25px;
height: 25px;
float: right;
}
input[type="color"]::-webkit-color-swatch-wrapper {
padding: 0;
}
input[type="color"]::-webkit-color-swatch {
border: none;
}
Now the output what I'm getting is,
Even though this contains black color in default, the form field didn't get any default input. So what I want to do is get the default color box as follows. (To easily understand the requirement I have designed my expectation using photoshop),
You have to add some styles and need some changes in ts file code to display that box
Here is a working example: https://stackblitz.com/edit/angular-tbkqbt

internal CSS styling in React at the top of code

I'm trying to style a component in my React application, but I do not want to create an external stylesheet because it's a small project. How can I style this image component without using an external stylesheet?
return (
<div>
<Image>
<div>
<img src='./resources/image.png alt='image'>
</div>
</Image>
</div>
);
I've found resources online for using inline styling on a specific element, but I want to make my code clean by putting it at the top of the component like using a style tag at the top of an HTML file. I haven't been able to find anything that resembles this in React.
For inline styles you can define a style object, either at the top of the file, or in your render method, and then refer to it:
var myStyle = { margin: 10 }
return (
<div>
<Image>
<div>
<img style={myStyle} src='./resources/image.png alt='image'>
</div>
</Image>
</div>
)
More info in the docs: https://reactjs.org/docs/dom-elements.html#style
Internal CSS styling in JSX is very similar to how it's done in HTML. The only difference is that you need to declare the style names as variables because they are treated like JS objects. With this in mind, you also need to end each property with a comma instead of a semicolon, and the last property should have no punctuation at the end. Using this approach, you should also use style={} instead of className={}. You can read more about JSX styling here.
const myStyle = {
width: '300px',
height: '300px',
border: '2px solid black'
}
const Image = () => {
return (
<div>
<img style={myStyle} src='./resources/image.png alt='image'>
</div>
);
}
You can do something like this:
const Image = styled.div`
background: #1d9ac2;
img {
border: 1px solid red;
}
`;
There are several solutions for this, and a big debate about which one is "the best".
I don't know which one is the best, but I can tell you which one I use:
Styled components (https://www.styled-components.com/)
With this, you would define an object like this
let styled = require('styled-components');
// Or for fancy people
import styled from 'styled-components';
const Image = styled.div`
background-color: red;
/* You can even put classes or selectors in here that will match the sub-components */
.some_class_used_inside { color: black; }
img { width: 100px }
`
and use it like this
return (
<div>
<Image> {/* This will be the `<div>` with `background-color: red` */}
<div className="some_class_used_inside"> {/* This will now have `color: black` applied */
<img src='./resources/image.png alt='image'> {/* This will have `width: 100px` applied to it */}
</div>
</Image>
</div>
);
Ofcourse, there are many other libraries to do it, and everyone will have to find their own favorite I guess :)

Selector in css file for reactstrap component

What do I want to achieve
So there is a gap between my jumbotron and my footer. I want to remove that gap. I did it already successfully by setting the margin-bottom to 0px; But at that moment, I had to pass an ID to the Jumbotron element. Now I want to achieve that same effect without passing an ID, but with classes.
I don't want to use inline styles. I want it in a separate css file.
In an old library (react-bootstrap not reactstrap) I could select for example all components from a certain type, like I did in the css provided below.
So the mistake is probably the selector in the css file. I couldn't find anything online which specifically shows it in a seperate "css file" way. Only with inline styling.
MainContent.js
import React from 'react';
import './MainContent.css';
import { Jumbotron, Button, Form, FormGroup, Label, Input, Container } from 'reactstrap';
const MainContent = () => {
return (
<Container>
<Jumbotron>
<Form>
<FormGroup>
<Label for="exampleEmail">Email</Label>
<Input type="email" name="email" id="exampleEmail" placeholder="with a placeholder" />
</FormGroup>
<FormGroup>
<Label for="examplePassword">Password</Label>
<Input type="text" name="password" id="examplePassword" placeholder="password placeholder" />
</FormGroup>
<Button>Submit</Button>
</Form>
</Jumbotron>
</Container>
);
}
export default MainContent;
MainContent.css
.Container {
margin-bottom: 0px;
}
.Jumbotron {
margin-bottom: 0px;
}
If you don't want to do it with IDs or with inline-styling, there is a way I would call a hack.
In MainContent.js add className attribute to the component as follows:
<Jumbotron className="jumbotron">
And in MainContent.css add !important in the statement you want to override other stylings:
.Container {
margin-bottom: 0px;
}
.Jumbotron {
margin-bottom: 0px !important;
}
Unless you override like this, margin-bottom: 2rem from node_modules/bootstrap/dist/css/bootstrap.css is used.

Label and buttons attached to a dropdown in Semantic UI React

How can I have a Label and a Button.Group be attached to a Dropdown in Semantic UI for React?
The attached picture shows what I have currently. If I try using the attached attribute, the label or button group become nested within the dropdown.
Edit: Following is the Semantic UI React markup I currently have:
<Label size='big'>Code</Label>
<Dropdown
options={options}
placeholder='Choose a Patch'
search
selection
allowAdditions
value={value}
/>
<Button.Group>
<Button icon='save' content='Save' color='green' />
<Button.Or />
<Button icon='clone' content='Clone' color='yellow' />
<Button icon='cogs' />
</Button.Group>
I got this to work with semantic-ui-react v2.0.3.
Here's the markup I used:
<Container className='refreshable-dropdown'>
<Dropdown className='left attached refreshable-dropdown' multiple select />
<Button className='refreshable-dropdown' attached='right' icon='refresh' />
</Container>
You can see I added a CSS class called refreshable-dropdown. I added a "refresh" button next to my dropdowns. Here's the CSS classes I used:
/* This is for "fluid" dropdowns that take the whole width of
* their container.
*/
.ui.container.refreshable-dropdown {
display: flex;
flex-flow: row nowrap;
width: 100%
}
/* If you want the dropdown "inline" with other content, apply
* the inline CSS class
*/
.ui.container.refreshable-dropdown.inline {
display: flex-inline;
flex-flow: row nowrap;
}
.ui.attached.dropdown.refreshable-dropdown {
border-right: 0;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.ui.attached.button.refreshable-dropdown {
border: 1px solid #2185d0; /* Specific to my button color */
border-right: none;
box-shadow: none !important;
vertical-align: top;
}
.ui.attached.button.refreshable-dropdown:hover {
border-color: #1678c2; /* Specific to my button color*/
}
Note that I left the select attribute on the Dropdown. This causes some different HTML to be generated than other markdowns, so this may not be 100% applicable to your situation. But I hope it'll at least give you some inspiration for making this work for you. Oh, and here's the resulting dropdown:

Target native dom element <input>...</input> with styled-components

I am having trouble getting my styled component to make a change to an <input /> wrapped in a React component. In Dev Tools I can see the style I am trying to override here:
.ui.input input {...}
I think the wrapping component needs to pass className to input i.e
<input className = {this.props.className} ..> ... </input>
but I cannot get the style to override with or without that. I will provide some snippets below.
//styled component
const StyledSearch = styled(Searchbar)`
&.ui.input input{
border: 0px !important;
}
`;
class SearchBar extends Component {
...
render() {
const style = {
display: this.state.showResults ? 'block' : 'none',
maxHeight: 500,
overflowY: 'scroll',
};
return (
<div className="ui search fluid" ref="container">
<div
className={`ui icon fluid input ${this.props.loading ? 'loading' : ''}`}>
<input type="text"
placeholder={this.props.placeholder}
onFocus={this.focus}
className = {this.props.className}
value={this.props.value}
onChange={this.props.onChange}/>
<i className="search icon"></i>
</div>
<div
className="results"
style={style}>
{
this.props.results.map((result, index) => (
<a
className="result"
key={index}
onClick={this.select.bind(this, result)}>
<div className="content">
{
result.get('image') ?
(
<div className="image">
<img src={result.get('image')} style={{ maxWidth: 50 }}/>
</div>
) : null
}
<div className="title">
{result.get('title')}
</div>
<div className="description">
{result.get('description')}
</div>
</div>
</a>
)
)
}
</div>
</div>
);}}
Basically, styled-components creates a new unique class name (in other words, a new namespace) for any DOM or React Components for which the styled function is called.
That means, when you use styled(SearchBar), styled-components wraps SearchBar component and attaches a unique class name to its root DOM. Then it passes that unique class name to the descendent DOMs and components (in your cases, nested div, input, a).
For this method to work, your root DOM must have a className that can be configured from outside. That's why, styled-components expects that, root DOM has the definition ${this.props.className} as the value of its className props. If your component lacks this, styled-components will not be able to create a new namespace which it can use to apply styling specific to it.
So, for your technique to work, you must assign ${this.props.className} as one of the values of className prop defined at the root div of SearchBar.
Working Demo
If you don't have access to SearchBar, you can wrap it with another component. Overhead of this process is that, you have to use an extra DOM level
Working Demo
From what I can tell, you need to apply the styles generated with styled-components to the wrapper element. This is due to the specificity of the .ui.input input external style. Meaning we can't simply target the input element with a new style because the .ui.input input selector is more specific and takes precedence. Here's a simple CSS example showing how the specificity of the .ui.input input selector takes precedence over the input styling:
.ui.input input {
border:2px solid red !important;
}
input {
border: 0px !important;
}
<div class="ui input">
<input />
</div>
This same issue is at play in your case. In the example below I've created a new Wrapper component, which has a style of:
&.ui.input input {
border: 0px !important;
font-size: 24px;
}
defined on it. This targets the inner input element, with more specificity, to override the external styles.
import React from 'react';
import ReactDOM from 'react-dom';
import styled from 'styled-components';
class InputWrapper extends React.Component {
render() {
const Wrapper = styled.div`
&.ui.input input {
border: 0px !important;
font-size: 24px;
}
`;
return(
<Wrapper className="ui input">
<input type="text" placeholder="Input" />
</Wrapper>
)
}
}
ReactDOM.render(
<InputWrapper />,
document.getElementById("app")
);
Here's a WebpackBin example.
Currently at version 4 you can do it as simple as
const Input = styled.input`
border:2px solid red !important;
`;
it will rendered as native input with SC className

Resources