Styled components workflow in Mui - how to style - javascript

I am working on a new react project and using material ui with styled components and having some trouble with styling and organization. I've read up on styled components and best practices but I'm still unable to find a solution to styling in big projects.
I've seen many suggestions:
to create styled components for each time some css needs to be added and storing all these components inside styled.ts file. This approach removes all styling and layout concerns into a separate file but is a lot of work to create styled components for everything
to make a wrapper styled components around the main react component and use class names - kind of like importing a css file regularly and working with classes
to make inline css changes if some padding is needed or something and only make styled components for reusable/lengthier css blocks. Doesn't really separate styling and is not as clean since we're leaving inline css but is easier to write
to treat styled components as regular components, have them in separate files and everything. A component is a component, no longer needing to distinguish between stlying and componentization
Not saying any of these are bad suggestions, but they're quite conflicting and I don't have experience with this. I'd just like to know a scalable approach.
tldr: Is there a good and clean workflow for working with styled components for big projects?

Material UI and styled-components are to achieve different purposes in application. MUI has ui written by someone else you can use in your application to save time, However you will have to customise them overriding with your custom css. styled-component will help organise your custom css
styled-component makes application supper clean (best readability over CSS) and easy to maintain ( better maintainability over CSS).
Makes it easy to identify which css are being used and you can easily delete unused styles.
It makes dynamic styling very simple through props with global theme.
You can import your style anywhere in the project and re-use it.
You should, make style.js / style.ts anywhere in your project based on your convenience. As best practice you should make one/many global\style.js where you can keep all re-usable components of your project. and style.js inside your component folder for styles dedicated to that component only.
To get most out of using CSS in JS pattern (in your case it is styled-component) you should use it with styled-system it will help you easily make your ui components responsive with minimum code and help build best re-usable components for your application. See details here Styled System
Here are some examples using styled-system as you need,
Suppose you would like to create a card container to be used anywhere in application UI,
import theme from './themes/theme';
import styled from 'styled-components';
export const Card = styled.div`
transition: ....;
background: ${(props) => (props.backColor || theme.colors.defaultColor)};
box-shadow: 1px 1px 1px rgb(. . . / .%);
border-radius: 8px;
...
`;
Use it anywhere in your application as,
import {Card, ..} from './style.js'
<Card>
....
</Card>
<Card backColor={'#some-color-code'}>
....
</Card>

In my project I have used something like this. I have used components coming from Material UI and passed it into styled-components so that I can write normal CSS. Overriding Material UI styles is a cake-walk as I can look up into MUI Docs to find appropriate classname and override styles for it.
Also the component returned from this file is nothing but a Material UI component itself, but a styled version of it. This allows me to use all MUI related props in my JSX code as well.
import { Button } from "#material-ui/core";
import styled from "styled-components";
export const StyledButton = styled(Button)`
&.MuiButton-root {
border-radius: 5px;
font-family: ${fonts.heebo};
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 24px;
}
`;
Hope this might help.

I spent quite a lot of time trying to answer a similar question myself: How best to create custom styled components in MUI
I'm afraid the answer is that there is not a good solution with MUI.

Related

How to build a UI Component Library with code-splitting for CSS styles

I want to create a UI Component Library where consumers can bundle only the styles for the components they are actually using.
Let's say this question is framework-agnostic since I am more interested to evaluate existing approaches.
The idea would be for a user to be able to
import { Button } from '#mylib/ui`
and not being required to go to their main.ts and add
import '#mylib/ui/styles/main.min.css`
Now, obviously, the first solution is to avoid bundling the CSS together, so a user would be able to import separate stylesheet for each component
import '#mylib/ui/styles/button.min.css';
import '#mylib/ui/styles/accordion.min.css';
Now, this approach works well if you use a handful of components and want to keep the bundle size in check, but it doesn't scale if a consumer starts using dozen of components.
How can I overcome that challenge?
The only approach I can think of is inline styling, which won't work because of missing selectors, media queries, etc.
What I would love to achieve, is a way for consumer to declare what they need, and get the styles for that component without any additional configuration/import, while preserving the ability of only bundle the CSS that belongs to the components that are imported
import { Button } from '#mylib/ui`
I am scratching my head to come up with an idea of how this would work...

How to overcome the overlapping of similar name CSS classes from two CSS frameworks?

I was using Modal of semanctic-ui-react inside a create-react-app project. Inside index.js I had declared the import for the CSS files of the frameworks
import "semantic-ui-css/semantic.min.css"
import "bootstrap/dist/css/bootstrap.css"
I noticed the weird positioning of Modal. After debugging I found a .modal CSS class was getting applied which was coming from the Bootstrap's CSS. Since semantic-ui also has the similar name classes, this caused the overlapping.
On removing the import "bootstrap/dist/css/bootstrap.css", Modal get positioned correctly.
Solution(partial) in my mind:
import CSS file only in the class where it has been used, and not to the index.js
-this has two problems:
1. Suppose EditForm.js uses semantic-ui, I import the semantic.min.css
directly in this file. But what if it's parent class in which
EditForm.js is used, if parent.js is using bootstrap.css then again
the same problem will occur.
2. I am not sure on this, but importing the complete CSS seperately for each files could make those files heavy, please correct me here.
I want to use both the frameworks in my project, what would be the ideal way?
Do you have to use both of them? if so, another solution to consider is implementing SASS/SCSS in your project.
SASS is usually bundled in alot of webpack-using installations out-of-the-box. I have only used it in vanilla, Vue and Angular projects but i'm 100% sure React would have no problems with it and CRA would be able to generate the necessary configuration for it.
If you installed SASS, you have alot of ways to handle this. Two I would think of though are:
You can decide on one library that is your "main" and import it as normal, while the other one you can "scope" within a css rule. This is possible because SASS automatically unwraps the import and inserts it under that css rule, effectively "Scoping" it. CSS does not do that by default.
.smui {
#import "semantic.css";
}
Read more here: https://sass-lang.com/documentation/at-rules/import#nesting
I didn't check semantic UI's sass support, but Bootstrap is built modularly in SASS which allows you to selectively import the parts you need. So let's say you want to use a semantic button within Bootstrap's Grid layout. Instead of bringing over all of bootstrap, you can simply import the grid module.
#import "semantic-ui";
/* Required */
#import "node_modules/bootstrap/scss/functions";
#import "node_modules/bootstrap/scss/variables";
#import "node_modules/bootstrap/scss/mixins";
.bs {
/* Part you actually need */
#import "node_modules/bootstrap/scss/grid";
}
This would reduce the footprint to only what you need, reduce your CSS size, and reduce overlap of styling for elements/classes you do not want to be overwritten.
I would not recommend assigning an id to your component and writing your overrides there. That will force you to use that id everywhere throughout your application, which you do not want to do.
You have two options:
1) The easiest option would be to build your own version of Bootstrap that ONLY contains the styles for components you are actually using in your app. This is also going reduce the number of styles your user has to download to render your app. Just exclude "Modal" from the build (and any other bootstrap components you do not use).
2) Do a class comparison between the two libraries you are using. This should actually be easy to do with developer tools in any browser. You will see each time the component you are targeting matches a class in one of your style sheets. Some rules will be crossed out in one, some will be crossed out in the other. If you want the styles for Semantic UI to take precedence, you will want to make a separate stylesheet that increases specificity for the style properties that are being lost from Semantic UI. My guess is there are probably only a few style properties that are getting overridden or that you do not want.
You can also put the above styles in the style prop on your modal if you do not want to create a separate file and they will be added inline to the component, effectively being more specific than the styles in either CSS file.
This worked for me.
In a custom css file, insert the following rule
.modal {
top: auto !important;
left: auto !important;
height: auto !important;
}

Should every react component have it's own stylesheet?

I just started with React and have a simple question I couldn't find anywhere.
So, should every React component have it's own stylesheet?
For example if I have my main App component which I render to the browser should I just include a css file there and have all my styles in that or is it bettet to have an own css file for every component?
Thanks.
CSS best practices in React are still heavily debated. There are pros and cons to each variation.
What you are probably looking for is modularity in your CSS. While having unique style sheets for your components does accomplish this to some degree I suggest taking a look at CSS modules. Packages like this can keep your CSS contained to a specific component so you don't over-write styles on other components.
Personally, I've done a little bit of both. I use a base style sheet (bootstrap for example). Then I use CSS-modules to help me make components that are unique that I might want to easily port over to other projects.

styled-components and custom styles?

I've been loving checking out styled-components, but getting a bit stuck with the concept of extracting everything out into a component, and how to tweak styles for a particular use case. For example:
<Flex>
<MyStyledTitle>Hello I am a Title</MyStyledTitle>
<MyStyledBodyText>blah</MyStyledBodyText>
</Flex>
Let's say that I wanted to make the following customisations for this use case:
styled title grey (subdued text colour),
the body text to have a right margin of 100px (don't ask why).
The styled-components way, the first part could be done like:
<MyStyledTitle colorTint='subdued' />
or even
<MyStyledTitle>
<SubduedText>MyTitle</SubduedText>
</MyStyledTitle>
Perhaps using a prop for title that lets you configure it to use subdued text or ANOTHER hild component that defines the grey text..
But what about for the second option...
<MyStyledBodyText style={{paddingRight: 100}} />
Inline style? Use a Grid or layout component around it?
At which point does something become a specific styled-component and if not, then how does one customise smaller style changes?
While i really like this idea of removing the mapping between component + class name, I guess i'm feeling a bit torn between the classical idea of having a 'style sheet' file that can contain all the classes and modifier css, then using a presenter to choose between the combinations of css classes.
I might be missing something here, but just keen to see some bigger examples of styled components in practice. Any links / tips would be greatly appreciated!
We've been using styled-components in our project extensively. Few basic patterns/conventions we use are
Components created using StyledComponents are not used across React Components. Under extreme scenarios, we pull them into external files and export.
DIV is the most extensively used styled-component (styled.div). (Ofcourse we do use other html elements like button, table td etc., but styled explicitly).
Different styles for the same HTML element (or) React Component are declared explicitly as different styles. (If you refer to FAQ section of the styled-components docs, you might notice these - https://github.com/styled-components/styled-components/blob/master/docs/faq.md)
Overall to answer your question, we have moved away from the classical stylesheet and as well thinking about combining multiple styles. It has worked well, except that looking up on unit tests is a bit painful.
Thanks

react components using css from non-imported

I am using create-react-app.
So I have overlapping class names e.g. flex being used by several components. However, it seems that when I include the css in one component, every other component now has visibility/usability of that css.
So I was wondering if there was a way to keep the css in scope or something to that effect.

Categories

Resources