Styled-components and react-bootstrap? - reactjs

Is there a way to use styled-components together with react-bootstrap? react-bootstrap exposes bsClassproperties instead of className for their component which seems to be incompatible with styled-components.
Any experiences?

You can extend the style keeping the original styles of the component from bootstrap. You will find more documentation on using third party libraries like react bootstrap with styled-components here.
const StyledButton = styled(Button)`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
Here is a sandbox for reference: https://codesandbox.io/s/2vpm40qk90

I'd like to offer a better alternative and approach.
I have been using react-bootstrap before and we have found that the current implementation was not porting bootstrap into react entirely and we still needed to rely on external files such as CSS/Fonts which is not styled-components philosophy and best practice.
Considering styled-components offer the css interface, we ported bootstrap 4 with best ES6 practices in a project called bootstrap-styled.
This Twitter Bootstrap v4 implementation of bootstrap is fully implemented for styled-components without a once of CSS or extra files.
This gives several benefits starting with a full js api, theming, modularity and reusability.
To override styles, it can be done through the <ThemeProvider /> or using props.theme on any component. We also export a <BootstrapProvider /> component that include <ThemeProvider /> and provide bootstrap class utilities such as .d-none, etc... in it's scope.
You can see a demo here

Related

Customize React bootstrap Carousel Indicator active class

I am using react bootstrap Carousel in my react js code. I am successfully able to customize react bootstrap Carousel indicators. By using below code..
div.crausal ol li{
height: 0.3em;
width: 4em;
background-color: #E77728 !important;
}
But I am not able to change the color of active class for indicator. I have tried this
div.crausal ol li.active{
background-color: blue !important;
}
But it does not work.
This is my carousel class.
<Carousel className={css_class.crausal} touch={true} controls={false}>
// Carousel items goes here //
</Carousel>
I want to change the color of active class indicator.
If someone can give better carousel option other than react bootstrap to solve this issue that will also do
I found a kind of fix after researching longer. What you can do is add normal bootstrap file in your project, import it in your component file and now react bootstrap classes are overridden by this normal bootstrap import. After that you can customize the normal bootstrap file downloaded in your project (bootstrap.min.css). But this is just a fix.
What you can do is:
div.carousel-indicators .active{
background-color: #E77728 !important;
}

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.

Can't apply Css style to React-datetime using className

I am trying to add border-radius: 5px to React-datetime component using className but not working.
E.g:
import ReactDateTime from ‘react-datetime’;
<ReactDateTime className=‘datetime’ />
.datetime{
border-radius: 5px;
}
I know that react-datetime module provides seperate css styles. But my concern is why it is not accepting when I do using className.
Try using inputProps with className as like below. It should work.
<DateTime inputProps={{className:'datetime'}} />
Have you try to add !important like :
.datetime{
border-radius: 5px !important;
}
If it doesn't work it could probably be an override problem.
You will have probably to check here :
https://github.com/YouCanBookMe/react-datetime/blob/master/example/react-datetime.css
If it doesn't work can we see your config for this package ?
We need to have a look on your complete component and css stylesheet

How to use material-ui (alpha) with styeld-components properly?

I've been trying to use styled-components with the alpha version of material-ui
According to the documentation, this should work out of the box.
This code:
const StyledButton = styled(Button)`
color: red;
text-transform: uppercase;
`;
return <StyledButton>Button</StyledButton>;
will generate something like this:
<button tabindex="0" class="MuiButtonBase-root-3177716317 sc-bdVaJa sxRGN" type="button" role="button">
...
</button>
It looks good.
However, the only problem I have is the order of the injected CSS styles (pic). Styles from styled-components are injected before MUI's styles which make their priority lower.
Is there any way to solve this without using !important?
In the current release (i.e. non-alpha) version, what you've asked would indeed require !important basis:
"Note that CSS properties defined inline are given priority over those defined in a CSS class. You need to use !important to take precedence over the inline style."
Ref: http://www.material-ui.com/#/customization/styles
Perhaps the alpha hasn't quite moved away from this inline requirement yet or it is still a work-in-progress.
What I've done to overcome this sort of thing myself is to (unfortunately) recreate the entire CSS on a standard <button> element when I need such a solution. Here's an example of how I'm doing that with a react-photonkit "theme"
// #flow
import styled from 'styled-components';
const PhotonStyledButton = styled.button`
font-family: Arial, Roboto, Helvetica, sans-serif;
height: 30px;
display: inline-block;
padding: 6px 12px;
margin-bottom: 0;
font-size: 12px !important;
line-height: 1.4;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: default;
background-image: none;
border: 1px solid transparent;
border-radius: $default-border-radius;
box-shadow: 0 1px 1px rgba(0,0,0,.06);
-webkit-app-region: no-drag;
&:focus {
outline: none;
box-shadow: none;
}
color: #333;
border-top-color: #c2c0c2;
border-right-color: #c2c0c2;
border-bottom-color: #a19fa1;
border-left-color: #c2c0c2;
background-color: #fcfcfc;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fcfcfc), color-stop(100%,#f1f1f1));
background-image: -webkit-linear-gradient(top, #fcfcfc 0%, #f1f1f1 100%);
background-image: linear-gradient(to bottom, #fcfcfc 0%, #f1f1f1 100%);
&:active {
background-color: #ddd;
background-image: none;
}
`;
export default PhotonStyledButton;
styled-components in general is compatible with any component library. When you write styled(AnotherComponent) we take that component and inject an automatically generated class name. This means essentially it's the same thing as writing <AnotherComponent className="sc-asdf123" />!
The current version of material-ui specifically is a bit difficult to custom style because it uses inline styles. From the MaterialUI documentation:
Note that CSS properties defined inline are given priority over those defined in a CSS class. You need to use !important to take precedence over the inline style.
This means simply using styled(MaterialButton) won't work as the passed-in styles will mostly just be ignored. You need to bump the specificity of your styles to override the inline styles that material-ui ships with. (this article is a great primer on specificity if you're not familiar with the details)
Answer for the alpha version of material-ui
The current alpha version of material-ui has switched to using JSS under the hood. (which is CSS in JS not inline styles, like styled-components) This means the issue is likely to be that the styled-components styles are injected after the default material-ui styles. (which are injected by JSS)
JSS supports custom injection points so you might be able to add a <!-- jss --> comment to the HEAD of your HTML to make sure JSS injects its CSS before the styled-components injected CSS?
Answer for the current version of material-ui
There are two ways to bump the specificity of the styled-components injected styles, one more tedious and one a bit more "hacky". The first one is adding !important at the end of all of your styles:
const Button = styled(MaterialButton)`
color: blue!important;
`
While this works in most cases it gets tedious very fast when you have lots of custom styling in a component. The better way is to use the class name hack:
const Button = styled(MaterialButton)`
&&& {
color: blue;
}
`
These ampersands get replaced with the automatically generated class name meaning the outputted CSS looks something like this:
.sc-asdf123.sc-asdf123.sc-asdf123 {
color: blue;
}
This bumps specificity by a big margin, thusly overriding the defined inline styles, and is less annoying than having to put !important after each rule.
Now we can use <!-- material-ui --> to make sure the styles are injected after it.
By default, Material-UI will look for a html comment named to inject styles after. By adjusting the placement of this comment within your HTML body you can control the order that CSS rules are applied to your components. (ref)

How to use polymer core icons inside of an angular.js app..?

I am using angular.js to build a SPA and angular-material to for the designing the layout. But turns out that angular material icons are not CSS styleable but polymer's icons are. So I want to use polymer icons inside my angular.js app.. I've included polymer.js in my scripts and import core-icons.html but there is an error..
Uncaught HierarchyRequestError: Failed to execute 'appendChild' on 'Node': Nodes of type 'HTML' may not be inserted inside nodes of type '#document'.
Uncaught TypeError: Cannot read property 'resolveDom' of undefined
How can I use polymer icons inside my angular.js app..??
Angular does not understand ShadowDOM that Polymer makes extensive use of. So when Angular parses and compiles the HTML it does not know what to do which custom elements so it throws an error.
But from Polymer 0.8 this might change and might be compatible with Angular.
One more thing I notices in your Question was that, you added polymer.js instead of webcomponents.js. polymer.js is the Polymer Library which is used in making new elements and interacting with them, where are webcomponents.js is the polyfill for Web components themselves.
I've used polymer icons in an angular project using material angular. In my case I wanted to use the polymer paper-icon-button element as well but I've also done it with just a core-icon element.
I did not need to include polymer.js, just:
polymer.html, core-icon.html, core-icons.html
I used a paper-icon-button so I also included
paper-icon-button.html
and I used am icon from the social set so I included core-icons/social-icons.html as well
for just a core-icon (i had it in a button but i don't think it's necessary)
<button ng-click="toggleLeft()" class="rp-menu-button">
<core-icon icon="menu></core-icon>
</button>
The CSS (LESS):
.rp-menu-button {
background: none;
border: none;
.rp-menu-icon;
}
.rp-menu-icon {
width: 48px;
height: 48px;
color: #toolbar-font-color;
}
Or for a paper-icon-button:
<paper-icon-button class="rp-card-paper-icon" id="share" icon="social:share">
The CSS (LESS):
.rp-card-paper-icon {
text-align: center;
color: #inactive-icon;
&:hover {
color: #active-icon;
}
}
.rp-card-paper-icon::shadow core-icon {
width: 18px;
height: 18px;
}
.rp-card-paper-icon::shadow #ripple {
width: 33px;
height: 33px;
}
.rp-card-paper-icon#share::shadow #ripple {
color: green;
}
So You set the color in the class and the size of the icon in .[class]::shadow core-icon and you can use
.rp-card-paper-icon::shadow #ripple
to style to ripple effect (if you are using a paper-icon-button)

Resources