How to display some value with styled-components? - javascript

I'm new to styled-components and I'm bit confused.
Can we display something or add functionality to styled-compoentns.
OR styled-components is component that we can apply css only

styled-components is primarily intended to apply css.
So typically you would use wrapper components that provide the content and use the components obtained from styled-components for decoration.
Once in a while, I have found it useful to use the .attrs constructor to pass children when
the content is very specific to the component.
const ResourceMissingError= styled.div.attrs({
children: 'This resource could not be found'
})`color: red`;
render(<ResourceMissingError />);

Can we display something or add functionality to styled-components?
Yes, styled components are usable as any native component would be. So just as HTML's <button> can be used to display something, you can use a styled button to do so. See below.
Similarly, you can add functionality as you would in a native component, by listening to click events, for instance. The demo below "adds" functionality to the ColorfulButton by handling its click event.
See also how the color is passed as a prop to the ColorfulButton via mycolor="green":
const ColorfulButton = styled.button`
display: inline-block;
color: ${props => props.mycolor || "blue"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
display: block;
`;
class TodoApp extends React.Component {
constructor(props) {
super(props)
this.state = { text: "Learn JavaScript (click me)", done: true }
}
handleClick = e => {
this.setState({...this.state, done: !this.state.done});
}
render() {
return (
<div>
<ColorfulButton onClick={this.handleClick} mycolor="green">{this.state.text}</ColorfulButton>
<br />
{this.state.done ? 'Yes' : 'No'}
</div>
)
}
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"))
<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>
<script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>
<div id="app"></div>

You can make a CSS file and import it in your different components like making class in CSS and use that class in your component as className="". Also, you can refer inline CSS like this way style={{}} make sure the properties name like font-size will be written in fontSize in React inline CSS. Every CSS property that have a dash in the middle of the property name, the dash will be removed and the next letter after dash will be capitalized and also the property value will be in double or single quotation.

Related

conditional className convert to styled component

Im trying to learn and convert my project from css to styled component(https://styled-components.com/), at the moment i have converted all my other components except one component where i am stuck, checked others examples from stackoverflow but it was not same kind.
I have conditional class names
My question is how to convert InfoBox component to use styled component ? do i need to inject the styles through some kind of styled-component wrapper or thats not needed ?
english is not my mother language so could be mistaked
my code:
import React from 'react'
import "./InfoBox.css"
function InfoBox({ isRed, active, activetored, ...props }) {
return (
<div onClick={props.onClick}
className={`infoBox ${active && "infoBox--selected"}
${activetored && "infoBox--selectedtored"}
${isRed && "infoBox--red"} `} >
</div>
)
}
export default InfoBox
<div className="app__stats">
<InfoBox
isRed
active={typeofCase === "cases"}
onClick={(e) => setTypeofCase('cases')}
/>
<InfoBox
isGreen
active={typeofCase === "recovered"}
onClick={(e) => setTypeofCase('recovered')}
/>
<InfoBox
isRed
activetored={typeofCase === "deaths"}
onClick={(e) => setTypeofCase('deaths')}
/>
</div>
css is like this (you can put whatever):
. infoBox--selected {
border-top: 10px solid greenyellow;
}
. infoBox--selectedtored {
border-top: 10px solid red;
}
. infoBox--red {
border-color: darkblue;
}
One of the ideas behind styled-component is to avoid classnames.
Instead of setting the css by class, you have few options. the easiest one will probably be to use your props inside the css code, and change the style by it:
const InfoBox = styeld.div`
border-color: ${props => props.isRed ? 'darkblue' : 'black'};
border-top: ${props => props.active ? '10px solid greenyellow' : 'red'};
...
`;
this way, you don't need classnames (although it can be done with it too, obviously).
Now, instead of the div inside the component, use the InfoBox styled component we just wrote and you good to go.

How to create our own Button Component like antdesign in react.js

I want to create my own Components So I had a look on antDesign which is one of the most popular library for React.js.
My question is how can I create my own customised Button component without using any CSS libraries or Frameworks like (Bootstrap, SemanticUI, etc) in react.js like how antDesign team have created it.
Any help would be appreciated with some explanation and an example.
If you want to make a component simply make a function and use that function wherever required.
ex:
// buttonComponent.js
export default buttonComponent = () => {
<button>Hi I am a button</button>
}
thats all you created your component, now can call this component in your code and use it.
But I guess this is not exactly what you want. There are some factor needs to be kept in mind before making a component mostly when making some complex components. you can do that by asking some question to yourself.
lets take an example of button only, there are certain things a button component must do or have.
What happens when some one click on the button? (sounds dump but probably the most important one)
Does user can change the text of the button, whats the default text of the button?
Does the user can call their own function on click of the button?
What's the default style of the button?
Does the user can disable the button?
Does the button can include icons too?
Does user can change the styles of the button?
How can the user change the default styles by overriding the styles in css or by passing it in props?
....etc
Keeping those in mind for now let's say we are making a small button component with the following two features:
User can click on button and call their own function and if not provided then nothing will happen.
User can change the default style of the button by props or by overriding the css.
then the code will be:
// MyButtonComponent.js
export default MyButtonComponent = ({userFunction, userStyle, children}) => {
<button type="button" onClick={userFunction} style={userStyle} className="my-button-compnonet">
{children}
</button>
}
// MyButtonComponent.css
.my-button-component {
color: #fff;
background-color: #007bff;
border-color: #007bff;
display: inline-block;
font-weight: 400;
text-align: center;
vertical-align: middle;
border: 1px solid transparent;
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: .25rem;
}
that's all our small button component is done.
now to call this component
// mainCompnonet.js
.....
/* callback function on button click */
myFunction = (e) => {
alert("yeah my button component on click");
}
/* override the default style through the props */
myStyle = {
borderRadius: 1rem;
}
.....
<MyButtonComponent userFunction={myFunction} userStyle={myStyle}>
Hi This is my component Button
</MyButtonComponent>
......
// mainCompnonet.js
.my-button-component {
color: #000; /* overrides our component style through css */
}
You can make a common component for Button as follow:
import React from 'react';
import styled from 'styled-components';
const PrimaryButton = styled.button`
color: #fff;
background-color: #1890ff;
border-color: #1890ff;
text-shadow: 0 -1px 0 rgba(0,0,0,0.12);
-webkit-box-shadow: 0 2px 0 rgba(0,0,0,0.045);
box-shadow: 0 2px 0 rgba(0,0,0,0.045);
`
const Button = (props) => {
return (
<PrimaryButton>
{props.text}
</PrimaryButton>
);
};
export default Button;
Here, You can get props from a parent component and design can be done accordingly. Here in example, I have used styled-components as it provides a usage for css according to props. I have just showed here for primary button.
From a calling components,
<Button type='primary' text='Reset' size={10} disabled={false} icon={'imgUrl'} shape='round' />
You can also pass many more things except shown in example.

Styling a nested styled-component from an outer one

Using styled-components, I am trying to style a nested <Input /> component that I have created, which is being used within a different component that has a dropdown appear when typing. I need to add padding-left: 3rem to this nested input but I cannot access it from the component <Dropdown />.
<Dropdown
options={options}
/>
The above is imported where I need it. I need to access the below input from the above <Dropdown />.
<div>
<Input {...props}/> // I need to edit the padding in this component
// rendered input unique to this new component would go here
</div>
The above <Input /> is imported from another component which is used in all instances where I require an input.
export const Dropdown = styled(DropDown)`
padding-left: 3rem !important;
`;
The component works fine but this fails to affect the inner padding of the Input that I need to target.
What do I do?
From what you've said, I'd suggest that the dependency of padding the Input component is with your Dropdown (which you seem to realise already).
Therefore you'd be better off having that "unqiue" styling coupled with your Dropdown component via a wrapping styled component within it.
The following example is crude (and by no means complete or working), but hopefully it illustrates how the ownership of the padding-left should be within the Dropdown and not a sporadic styled component floating some where else in your code base.
./Input/Input.jsx
const Input = ({ value }) => (
<input value={value} />
);
./Dropdown/styled.js
const InputWrapper = styled.div`
position: relative;
padding-left: 3rem !important; /* Your padding */
`;
const Icon = styled.div`
position: absolute;
top: 0;
left: 0;
width: 3rem;
height: 3rem;
background: blue;
`;
const Menu = styled.ul`/* whatever */`;
./Dropdown/Dropdown.jsx
import Input from '...';
import { InputWrapper, Icon, Menu } from './styled';
const Dropdown = ({ options }) => (
<div>
<InputWrapper>
<Icon />
<Input value={'bleh'} />
</InputWrapper>
<Menu>{options}</Menu>
</div>
);
This setup will promote reusable self-contained components.
Figured out the solution below:
export const StyledInput = styled.div`
&& #id-for-input { // specifically on the <Input />
padding-left: 3rem !important;
}
`;
<StyledInput>
<Dropdown />
</StyledInput>

HTML Markup: Write elements textContent via attribute instead of via passing the value as a child?

I'm pretty sure the answer to this is no, but,
Is there any way to write HTML elements like this:
<button innerText="This is the button text" />
<!-- INSTEAD OF LIKE THIS: -->
<button>This is the button text</button>
For an example like this, my request seems unwieldy, but it makes more sense when you have multiple elements that look like this that you're returning via ReactJS.
<button
className="btn"
somePropA="Some Value"
somePropB="Some Value"
somePropC="Some Value"
title="Some title"
>
Some button innerText
</button>
<!-- VERSUS: -->
<button
className="btn"
somePropA="Some Value"
somePropB="Some Value"
somePropC="Some Value"
title="Some title"
innerText="Some button innerText"
/>
I'd love to be able to do this for button, span, etc.
With React, you can create a component for Button (or input, or any other HTML element) and pass the info as props, like this:
From a parent component:
import React, {Component} from 'react';
import Button from './button'; // This is your button component
class App extends Component {
render() {
return (<Button
innerText="Your inner text" // Here, you can pass the text as props. You could also pass a class name, id, etc.
/>);
}
}
export default App;
From a child (Button) component. I'm using a functional stateless component, but you can use a stateful component if you prefer:
import React from 'react';
const Button = ({innerText})=>{
return <button>{innerText}</button>
}
export default Button;
That can easily be done using CSS using its pseudo element and attr() function, like this, and you can target any element with the attribute selector.
For custom attribute one is suppose to use the data-* prefix, so I added that here.
Stack snippet
[data-innerText]::before {
content: attr(data-innerText);
}
/* specifically target span base element */
span[data-innerText] {
display: inline-block;
color: red;
font-size: 20px;
padding: 20px;
letter-spacing: 10px;
text-transform: uppercase;
}
<button data-innerText="This is the button text"></button>
<div>
<span data-innerText="This is a span"></span>
</div>
<div>
<button>And it only adds the text to elements that have the attribute set</button>
</div>
You could do this with Javascript, but there is no way built into HTML. Your javascript would look something like:
document.getElementById("mybtn").value = "Hello";
You can do it for any element, using any attribute with only HTML and CSS's attr() function:
button:after {
content: attr(any-attr);
}
<button any-attr="YOUR TITLE"></button>

CSS doesn't apply to a component

I have a react component that is wrapped up in div:
AccountLogin.jsx:
import './AccountLogin.css';
export default observer(() => (
<div className="content">
Something here
</div>
));
AccountLogin.css:
.content {
color: blue;
background-color: blue;
margin: 500px;
}
But the css doesn't apply to my rendered component AccountLogin.
Any ideas why that could happen?
Looking at rfx-stack source, I can see that files suffixed with .global.css are imported in global scope where as others are imported as css-modules.
So you can either rename your file to AccountLogin.global.css or use the imported class name:
import styles from './AccountLogin.css';
Within component:
<div className={styles.content}>...</div>

Categories