Override default getstream component styles into NextJS Component - css

How can I override the getStream.io components css with custom css ? I have create the component as below and I need to override the css for the various classes of it's components.
As per this README documentation I have import the css file into my Next.JS component and then write my custom css of their component into the /public/style.css file but it is not applying any how.
import React from 'react';
import { StreamChat } from 'stream-chat';
import { Chat, Channel, ChannelHeader, MessageInput, MessageInputSmall, VirtualizedMessageList, Window } from 'stream-chat-react';
import 'stream-chat-react/dist/css/index.css';
const chatClient = StreamChat.getInstance(process.env.GET_STREAM_KEY);
const userToken = process.env.GET_STREAM_TOKEN;
chatClient.disconnectUser()
chatClient.connectUser({id: userId}, userToken);
const channel = chatClient.channel(process.env.TYPE, process.env.ROOM);
const ChatComponent = () => (
<Chat client={chatClient} theme='livestream dark'>
<Channel channel={channel}>
<Window>
<ChannelHeader live />
<VirtualizedMessageList />
</Window>
</Channel>
</Chat>
);
export default ChatComponent;
I have written the below css into style.css file to override the css of the components but below css are not applying.
.str-chat-channel {
max-height: 150px;
}
.str-chat__virtual-message__wrapper {
padding: 10px 40px 10px 15px;
}
.str-chat__virtual-message__wrapper {
align-items: center;
}
.str-chat__virtual-message__wrapper .str-chat__avatar--rounded {
border-radius: 25px;
}

You should move your stream-chat-react global CSS import to your custom _app file then import your own styles.css after it.
// pages/_app.js
import "stream-chat-react/dist/css/index.css";
import "<your-path-to>/style.css"; // Replace with the path to your `style.css`
// ...

Related

disable scrolling on specific page

Is there any way to disable scroll on one single page? I tried to set overflow: hidden on the specific page but that didn't work. I have to set it on the body in index.css to make it work but that obviously disable scroll on all pages. So the only way to do it that comes to my mind is to set CSS class conditionally on the body. Is there any way to conditionally set CSS class in index.js based on the value from a redux store or is there any other way?
my index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom'
import {Provider} from 'react-redux'
import {createStore,applyMiddleware,compose,combineReducers} from "redux";
import thunk from 'redux-thunk'
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import authReducer from './store/reducers/auth'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const rootReducer = combineReducers({
auth: authReducer
})
const store = createStore(rootReducer,
composeEnhancers(applyMiddleware(thunk)));
const app =(
<Provider store={store}>
<BrowserRouter>
<App/>
</BrowserRouter>
</Provider>
)
ReactDOM.render(
<React.StrictMode>
{app}
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.unregister();
If you wanted to set a style on body, you can just run the below code on the page, which will disable scrolling.
document.body.style.overflow='hidden'
Then to re-enable:
document.body.style.overflow='auto'
Only downside is that is isn't very React-like.
Simple solution might be to define specific class to apply overflow: hidden and apply it on document.body whenever you want (for example after explicit component mount).
.overflow-hidden {
overflow: hidden;
}
On mount of specific page call:
document.body.classList.add("overflow-hidden");
or you can directly assign property
document.body.style.overflow = "hidden";
You can wrap your component in another div, and give that wrapper div the overflow:hidden; style, possibly along with a max-height: 70vh; to make sure it doesn't go over the end of the page.
div {
padding: .5rem;
margin: .5rem
}
.no-scroll-wrapper {
max-height: 70vh;
overflow: hidden;
background-color: darkgrey;
padding: 1rem;
}
.large-inner {
height: 1000px;
background-color: grey
}
<body>
<div class="no-scroll-wrapper">
wrapper element disables scrolling
<div class="large-inner">
Content here, very long div, but you can't see the end of it.
</div>
</div>
</body
A simple solution might be to define a specific class to apply overflow: hidden and apply it on the document. body whenever you want and remove the class when you leave the page.
.overflow-hidden {
overflow: hidden;
}
Attach class on the body in the specific page and remove when you live the page, so it won't affect other pages
useEffect(() => {
document.body.classList.add("overflow-hidden");
return () => {
document.body.classList.remove("overflow-hidden");
};
}, []);
This will simply remove the class from the body when you leave the page.
Adding to Luke Storry's and midnightgamer's amazing answer. You can use a custom react hook with useEffect instead of having to add document.body.style.overflow='auto' in every page to re-enable scroll.
import { useEffect } from 'react'
const useOverFlowHidden = () => {
useEffect(() => {
document.body.style.overflow = 'hidden'
return () => {
document.body.style.overflow = 'auto' // cleanup or run on page unmount
}
}, [])
}
export default useOverFlowHidden
Usage:
const Page = () => {
useOverFlowHidden(); // use on pages you want to disable overflow/scroll
return <></>;
}
I use body-scroll-lock npm package:
import {disableBodyScroll,enableBodyScroll,clearAllBodyScrollLocks} from "body-scroll-lock"
const YourPage=(props)=>{
const ref=useRef(null)
useEffect(() => {
if (ref.current) {
// you might add a condition to lock the scroll
if (conditionIsTrue) {
disableBodyScroll(ref.current)
} else {
enableBodyScroll(ref.current)
}
}
return () => {
clearAllBodyScrollLocks()
}
},[addDependencyHere])
return(
<div ref={ref}>
....
</>
)
}
from the above npm package's documentation, you can also use this approach with vanilla js. It is not recommended to access document object in react.js directly
document.body.ontouchmove = (e) => {
e.preventDefault();
return false;
on touch screen devices you can set this css class conditionally to prevent scrolling
touch-action:none

Specificity issue with "composes" keyword using CSS Modules and React

I'm having CSS specificity/import order issues when trying to use CSS modules "composes" keyword.
File structure:
|_ MyComponent.jsx
|_ MyComponent.scss
|_ utilities.scss
MyComponent.jsx
import React from 'react';
import styles from './MyComponent.scss';
const MyComponent = ({ error }) => {
const classes = classnames(
styles.root,
{
[styles.error]: error
}
);
};
export default MyComponent;
MyComponent.scss
.root {
color: #333;
}
.error {
composes: red from './utilities.scss';
}
utilities.scss
.red {
color: red;
}
As you can see in the screenshot below, the .red class is not applying because of an import order issue. Is there a way around this without resorting to something like !important?
Note: I'm using CSS modules with webpack + scss loader.

Generate RTL CSS file in create-react-app and switch between them based on change in state

I'm using create-react-app for a multi-language project.
I want to use some library like "cssJanus" or "rtlcss" to convert the Sass generated CSS file into a separate file and then use that newly generated file when I switch to another language.
Here's how my index.js looks like ...
import React from "react";
import ReactDOM from "react-dom";
import * as serviceWorker from "./serviceWorker";
import { BrowserRouter as Router } from "react-router-dom";
import { Provider } from "react-redux";
import App from "./App";
import { configureStore } from "./store/configureStore";
const store = configureStore();
ReactDOM.render(
<Provider store={store}>
<Router>
<App />
</Router>
</Provider>,
document.getElementById("root")
);
serviceWorker.unregister();
And here's how my "App.js" looks like ...
import React, { Component } from "react";
import "./App.scss";
import { Route, Switch } from "react-router-dom";
import SignIn from "./features/signin/SignIn";
class App extends Component {
render() {
return (
<>
<Switch>
<Route path="/" exact component={SignIn} />
</Switch>
</>
);
}
}
export default App;
As you can see I'm using "./App.scss" file that simply have a bunch of #import statements to another ".scss" files in the "./src/css/" directory ...
/* autoprefixer grid: on */
#import "css/reset";
#import "css/variables";
#import "css/global";
I need your advice on how to do that. How to convert the generated CSS from App.scss to RTL into their own .css file and switch between them and the original generated CSS based on a change in the global state.
I searched a lot for something like this but with no luck.
Or if you have a better approach I'm all ears.
Here is a simple solution that requires ejecting and adding a lightweight webpack-rtl-plugin.
After running
npx create-react-app react-rtl
cd react-rtl
yarn eject
yarn add -D webpack-rtl-plugin #babel/plugin-transform-react-jsx-source
Go to config/webpack.config.js and make some tweaks:
// import the plugin
const WebpackRTLPlugin = require('webpack-rtl-plugin')
// ...
module: { ... }
plugins: [
// ...,
// use the plugin
new WebpackRTLPlugin({ diffOnly: true })
].filter(Boolean),
// ...
On this stage, if you run yarn build and look up build/static/css folder, you should hopefully see additional .rtl.css file that contains your rtl styles.
Then we need to tell webpack to use MiniCssExtractPlugin.loader for development as well so it will serve styles through link tags instead of inline styles:
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
isEnvDevelopment && { loader: MiniCssExtractPlugin.loader }, // <-- use this
// isEnvDevelopment && require.resolve('style-loader'), <-- instead of this
and don't forget the plugin, lol:
module: { ... }
plugins: [
// ...,
// isEnvProduction && <-- comment this out
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
}),
// ...
].filter(Boolean),
And from here you can finally grab your default stylesheet href and use to insert rtl styles. Here's how you could implement it:
class RtlCssBundleService {
constructor() {
this.rtlApplied = false
this.rtlStyles = [];
this.ltrStyles = Array.from(
document.querySelectorAll('link[rel="stylesheet"]')
)
}
insert = () => {
if (this.rtlApplied) { return }
this.rtlApplied = true
if (this.rtlStyles.length) {
return this.rtlStyles.forEach(style => {
document.body.appendChild(style)
})
}
this.rtlStyles = this.ltrStyles.map(styleSheet => {
const link = document.createElement("link")
link.href = styleSheet.href.replace(/\.css$/, '.rtl.css')
link.rel = "stylesheet"
document.body.appendChild(link)
return link
})
}
detach = () => {
this.rtlApplied = false
this.rtlStyles.forEach(style => {
document.body.removeChild(style)
})
}
toggle = () => {
return this.rtlApplied
? this.detach()
: this.insert()
}
}
const rtlStyles = new RtlCssBundleService()
export default rtlStyles
Then use this from any of your components.
So anyway, I'm sure I've missed something and maybe that is a terrible approach, but it seems to work and here is the demo
If you use flexbox and css grid they have RTL support built in. Then use CSS Logical Properties for margin, padding, border, etc. If that is not enough, then you can use [dir="rtl"] .your-class as a fallback.
Now you don't have two separate css files to maintain.
Here is a cross browser margin-right example.
-webkit-margin-end: 25px;
margin-inline-end: 25px;
#supports (not (-webkit-margin-end: 0)) and (not (margin-inline-end: 0)) {
margin-right: 25px;
}
You could wrap that up into a mixin for easier use across your app.
Looking around there is a library called react-with-direction from airbnb that provides a DirectionProvider - component you could wrap your components in based on the language. Hope that helps.

Definitive guide for styling react-tooltip components?

I am using react-tooltip, react-emotion.
I cannot figure out how to style the span in order to override default styles.
Here's what I've got so far:
import React, { PureComponent } from 'react';
import styled from 'react-emotion';
const myTooltip = (Wrapper, toolTip) => {
class TooltipWrap extends PureComponent {
render() {
return (
<span
data-tip={toolTip}
data-delay-show="250"
data-place="bottom"
className={TooltipStyle}
>
<Wrapper
{...this.props}
/>
</span>
);
}
}
return TooltipWrap;
};
export default withToolTip;
const TooltipStyle = styled.span ({
color: 'red !important';
fontSize: '48px !important';
})
Anyone have any tips or a specific definitive guide on how to style this span so I can override the defaults in react-tooltip?
The documentation is pretty spotty, and there's literally no examples anywhere on the web.
I ran into a similar issue but was able to override the default styles using styled components and passing it the ReactTooltip component
import React, { PureComponent } from 'react';
import styled from 'react-emotion';
import ReactTooltip from 'react-tooltip';
const myTooltip = (Wrapper, toolTip) => {
class TooltipWrap extends PureComponent {
render() {
return (
<span
data-tip={toolTip}
data-delay-show="250"
data-place="bottom"
>
// Replace ReactTooltip component with styled one
<ReactTooltipStyled type="dark" />
<Wrapper
{...this.props}
/>
</span>
);
}
}
return TooltipWrap;
};
export default withToolTip;
export const ReactTooltipStyled = styled(ReactTooltip)`
&.place-bottom {
color: red;
font-size: 48px;
}
`;
Using this method all you would need to do is import the newly styled component into your React file and replace the original ReactTooltip with the ReactTooltipStyled component.

Import font into React application

I'm trying to use the Roboto font in my app and having tough time..
I did npm install --save typeface-roboto and added import 'typeface-roboto' to my React component. But still can't get my font to change.
I am trying to do like this :
const React = require('react')
import 'typeface-roboto'
class Example extends React.Component {
render() {
let styles = {
root: {
fontFamily: 'Roboto'
}
}
return (
<div style={styles.root}>
<p>
This text is still not Roboto ?!???!!1
</p>
</div>
)
}
}
module.exports = Example
Am I missing something? Looking for a simple way to do this without any external css file..
Try adding import 'typeface-roboto'; in root file i.e. index.js file.
In my case I added font-family to body element and it is worked.
import this code of line in your main css or scss whatever use use
#import url('https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap');
this will work.
If you want to customize this then go to the google font and select font style font weight whatever you want.
Here i have selected font weight 400,300 and 700
If have not selected the font weight then you can not use other font weight
I had the same issue, couldn't get Roboto fonts for my components anyhow.
I used the webfontloader package.
yarn add webfontloader
or
npm install webfontloader --save
h
Once you do this, add the following code to your index.js or to the JS file which is an entry point to your application
import WebFont from 'webfontloader';
WebFont.load({
google: {
families: ['Titillium Web:300,400,700', 'sans-serif']
}
});
// rest of the index.js code
And now apply the font-family.
You simply just require('typeface-roboto') it.
const React = require('react')
require('typeface-roboto')
class Example extends React.Component {
render() {
let styles = {
root: {
fontFamily: 'Roboto'
}
}
return (
<div style={styles.root}>
<p>
This is now Roboto
</p>
</div>
)
}
}
// or here instead if you fancy
.root {
font-family: 'Roboto';
}
It involves several changes, assuming you want to use CSSinJS:
change style to className
You'll need some kind of library to apply styles.
With react-jss
import React from 'react';
import 'typeface-roboto';
import injectSheet from 'react-jss';
const styles = {
root: {
fontFamily: 'Roboto',
},
};
class Example extends React.Component {
render() {
return (
<div className={styles.root}>
This text is Roboto
</div>
)
}
}
const StyledExample = injectSheet(styles)(Example)
export default StyledExample;
Or with MaterialUI styles:
import React from 'react';
import 'typeface-roboto';
import { withStyles } from '#material-ui/core/styles';
const styles = theme => ({
root: {
fontFamily: 'Roboto',
},
});
function Example(props) {
const { classes } = props;
return (
<div className={classes.root}>
This text is Roboto
</div>
);
}
export default withStyles(styles)(Example);
Or, you could just do it the right way, via Dan's Answer
Or the Styled-Components way:
import styled from 'styled-components'
const ExampleStyled = styled.div`
#font-face {
font-family: 'Roboto';
src: local('Roboto'), url(fonts/Roboto.woff) format('woff');
}
`
const Example = () => (
<ExampleStyled>
This text is Roboto!
</ExampleStyled>
);
export default Example;

Resources