I just begin with FullCalendar , i'm implementing it in a react project , everything good now but i want to customize the actual calendar , iwant it to respect my customer need.
My question : is it possible to add a classname to the FullCalendar component like this :
( i tried but i can't reach the classname in my css file )
<FullCalendar
className= "FullCalendarMonthClient"
defaultView= "dayGridMonth"
plugins={[dayGridPlugin]}
columnHeaderFormat= {{
weekday: "long"
}}
locale="fr"
events={[
{ title: 'event 1', start: '2019-12-06', end: '2019-12-07' },
{ title: 'event 1', start: '2019-12-06', end: '2019-12-07' }
]}
/>
and after use it to customize my calendar with css. I use on the same page an other calendar , a DayView that why i ask to put a classname in my component so i can style my dayview/monthview without touching the Monthview. Or how can i create my own theme ?
Thanks comunity
You can create a styled wrapper that will overwrite the internal styles.
import FullCalendar from "#fullcalendar/react";
import styled from "#emotion/styled";
export const StyleWrapper = styled.div`
.fc td {
background: red;
}
`
const MyApp = ()=> {
return (
<StyleWrapper>
<FullCalendar/>
</StyleWrapper>
);
}
Indeed, a styled wrapper works. For example, try changing the buttons (next, prev) in the Calendar:
import FullCalendar from "#fullcalendar/react";
import timeGridPlugin from '#fullcalendar/timegrid';
// needed for the style wrapper
import styled from "#emotion/styled";
// add styles as css
export const StyleWrapper = styled.div`
.fc-button.fc-prev-button, .fc-button.fc-next-button, .fc-button.fc-button-primary{
background: red;
background-image: none;
}
`
// component with calendar, surround the calendar with the StyleWrapper
function Schedule({ ...props }) {
return (
<StyleWrapper>
<FullCalendar ... />
</StyleWrapper>
);
}
export default Schedule;
If you happen to be using #fullcalendar/react with #fullcalendar/bootstrap and #fullcalendar/rrule YOU NEED TO CHECK YOUR IMPORTS.
I have having an issue where the rrulePlugin was over-riding my bootstrap theme, It was the way I was importing.
Import in this order solved it for me
import React from 'react';
import {Card, CardBody, CardHeader, Col, Row} from 'reactstrap';
import FullCalendar from '#fullcalendar/react';
import dayGridPlugin from '#fullcalendar/daygrid';
import interactionPlugin from '#fullcalendar/interaction';
import timeGridPlugin from '#fullcalendar/timegrid';
import listPlugin from '#fullcalendar/list';
import rrulePlugin from '#fullcalendar/rrule';
import bootstrapPlugin from '#fullcalendar/bootstrap';
<div>
<CardBody className="p-0">
<FullCalendar
ref={calendarRef}
headerToolbar={false}
plugins={[ // plugins MUST be in this order for mine to work or else I get errors
rrulePlugin,
dayGridPlugin,
bootstrapPlugin,
timeGridPlugin,
interactionPlugin,
listPlugin,
]}
initialView="dayGridMonth"
themeSystem="bootstrap"
dayMaxEvents={2}
height={800}
stickyHeaderDates={false}
editable
selectable
selectMirror
select={info => {
console.log("calendarInfo", info.start.toISOString())
if(info.start < moment().subtract(1, 'day')) {
toast(
<Fragment>
<strong>Select Future date</strong>
</Fragment>
);
} else if(isCompose) {
return (calendarView === "Month View" ? setShowTimeModal(!showTimeModal) : ""),
setAddScheduleStartDate(info.start.toString())
} else {
setAddScheduleStartDate(info.start.toISOString());
setIsOpenScheduleModal(true);
}
}}
views={views}
eventTimeFormat={eventTimeFormat}
eventClick={handleEventClick}
events={calendar}
buttonText={buttonText}
eventDrop={(e) => { return console.log("eventDrop ran======-----======", dispatch(calendarUpdate({start: e.event.start, end: e.event.end, _id: e.event._def.extendedProps._id})))}}
/>
</CardBody>
</div>
Related
I like to change the width of an event in context of React JS.
Similiar questions described here:
How to edit width of event in FullCalendar?
Change Fullcalendar width
...
Unfortunately, in the quoted questions is nothing mentioned how to solve this in a react environment.
I figured it out how to do it. eventRender does no longer exist (v4) but instead different "event render hooks" (v5):
eventClassNames: Specifically for changing the .css of an event
eventContent: To inject content into the event
and others (see:https://fullcalendar.io/docs/event-render-hooks)
Now, depending what you want to achieve, there are two ways to do this in React JS. (Note: I used TypeScript)
Applying CSS change to all events
We can use styled to create our own .css definition for any event and use that as a wrapper (StyleWrapper)
import React from 'react';
import FullCalendar from '#fullcalendar/react';
import timeGridPlugin from '#fullcalendar/timegrid';
import styled from '#emotion/styled';
export interface ISampleProps {}
//our Wrapper that will go around FullCalendar
export const StyleWrapper = styled.div`
.fc-event {
width: 98px !important;
}
`;
//Reacct Functional Component
const Sample: React.FunctionComponent<ISampleProps> = (props) => {
const events = [
/*some events */
];
return (
<>
<div>
<StyleWrapper>
<FullCalendar
plugins={[timeGridPlugin]}
initialView="timeGridWeek"
events={events}
/>
</StyleWrapper>
</div>
</>
);
};
export default Sample;
Apply specific CSS to specific events
With this way, you can tell FullCalendar exactly how an event has to look like depending self-defined props you add to an event. Your self-defined props will be added to extendedProps which will be used in our event render hook eventClassNames
//same imports from earlier (but you don't need "styled" for this one)
const Sample: React.FunctionComponent<ISampleProps> = (props) => {
function eventAddStyle(arg: any) {
//all self-created props are under "extendedProps"
if (arg.event.extendedProps.demanding) {
return ['maxLevel']; //maxLevel and lowLevel are two CSS classes defined in a .css file
} else {
return ['lowLevel'];
}
}
const events = [
{
id: 'a',
title: 'This is just an example',
start: '2022-03-19T12:30:00',
end: '2022-03-19T16:30:00',
backgroundColor: '#74AAEB',
demanding: true //our self-created props
},
{
id: 'b',
title: 'This is another example',
start: '2022-03-17T08:00:00',
end: '2022-03-17T11:30:00',
demanding: false // our self-created props
},
];
return (
<>
<div>
<FullCalendar
plugins={[timeGridPlugin]}
initialView="timeGridWeek"
eventClassNames={eventAddStyle}
events={events}
/>
</div>
</>
);
};
export default Sample;
I would like to center the selected image instead of having it showing on the left hand side.
See image of behaviour:
I'm using the packages from the sandbox below in Next.js 11 with TailwindCSS 2.2.4:
https://codesandbox.io/s/5vn3lvz2n4
Dependencies:
"react-images": "^1.2.0-beta.7",
"react-photo-gallery": "^8.0.0"
I'm having a hard time targeting the CSS class, but I narrowed down to:
class="react-images__view react-images__view--isModal css-1qrom1v css-1ycyyax" using the browser dev tool in Safari.
Below is my PhotoLibrary file:
import React, { useState, useCallback } from "react";
import Gallery from "react-photo-gallery";
import Carousel, { Modal, ModalGateway } from "react-images";
import { photos } from "../data/photoData";
export default function PhotoLibrary() {
const [currentImage, setCurrentImage] = useState(0);
const [viewerIsOpen, setViewerIsOpen] = useState(false);
const openLightbox = useCallback((event, { photo, index }) => {
setCurrentImage(index);
setViewerIsOpen(true);
}, []);
const closeLightbox = () => {
setCurrentImage(0);
setViewerIsOpen(false);
};
return (
<div>
<Gallery photos={photos} onClick={openLightbox} />
<ModalGateway>
{viewerIsOpen ? (
<Modal onClose={closeLightbox}>
<Carousel
currentIndex={currentImage}
views={photos.map((x) => ({
...x,
srcset: x.srcSet,
caption: x.title,
}))}
/>
</Modal>
) : null}
</ModalGateway>
</div>
);
}
Has anyone played around with the carousel in Next.js and able to see what I'm doing wrong? If you have a better solution I'm open to that too.
Add the following CSS to your globals.css file.
.react-images__view-image--isModal {
display: inline-block;
left: 50%
}
i am trying to make a theme system on a react project that uses redux with a reducer that manages themes according to the user's local storage. But here my problem is that I used css files to define my styles on all of my components. However, I have all my logic with 2 javascript objects for light or dark mode. So I can't use js in css files unless I use css variables but I don't know how.
Here is my structure :
In my app.js I imported useSelector and useDispatch from react redux to access the global state :
import React from 'react';
import './App.css';
import Footer from './components/Footer';
import Header from './components/Header';
import Presentation from './components/Presentation';
import Projects from './components/Projects';
import Skills from './components/Skills';
import Timeline from './components/Timeline';
import { switchTheme } from './redux/themeActions';
import { useSelector, useDispatch } from 'react-redux';
import { lightTheme, darkTheme } from './redux/Themes';
function App() {
const theme = useSelector(state => state.themeReducer.theme);
const dispatch = useDispatch();
return (
<div className="App">
<Header />
<input type='checkbox' checked={theme.mode === 'light' ? true : false}
onChange={
() => {
if(theme.mode === 'light') {
dispatch(switchTheme(darkTheme))
} else {
dispatch(switchTheme(lightTheme))
}
}} />
<div className="top">
<div className="leftPart">
<Presentation />
<Skills />
</div>
<Timeline />
</div>
<Projects />
<Footer />
</div>
);
}
export default App;
and in themes.js I have my 2 objects which represent the themes :
export const darkTheme = {
mode: 'dark',
PRIMARY_BACKGROUND_COLOR: '#171933',
SECONDARY_BACKGROUND_COLOR: '#1e2144',
TERTIARY_BACKGROUND_COLOR: '#0a0c29',
PRIMARY_TEXT_COLOR: '#eee',
SECONDARY_TEXT_COLOR: '#ccc',
PRIMARY_BORDER_COLOR: '#aaa'
}
export const lightTheme = {
mode: 'light',
PRIMARY_BACKGROUND_COLOR: '#D3CEC8',
SECONDARY_BACKGROUND_COLOR: '#E5DFD9',
TERTIARY_BACKGROUND_COLOR: '#C1BFBC',
PRIMARY_TEXT_COLOR: '#222',
SECONDARY_TEXT_COLOR: '#333',
PRIMARY_BORDER_COLOR: '#555'
}
You can make use of data attributes.
I have done the same in one my project like so :-
[data-color-mode="light"] {
--color-focus-ring: #7daee2;
--color-link-hover: #0039bd;
--color-primary-bg: #eef6ff;
--color-primary-text: #212121;
--color-primary-border: #98b2c9;
--color-secondary-bg: #c3d7f0;
--color-secondary-text: #1a1a1a;
}
[data-color-mode="dark"] {
--color-focus-ring: #5355d4;
--color-link-hover: #4183c4;
--color-primary-bg: #080808;
--color-primary-text: #f1f1f1;
--color-primary-border: #525252;
--color-secondary-bg: #191919;
--color-secondary-text: #d8d5d5;
}
You can add the attribute to your top-level element (assuming div) like so:-
<div className="appContainer" data-color-mode="light" ref={appRef}> ></div>
Now use that appRef to change the data-color-mode attribute as well update the localstorage in one function. Updating the data-color-mode allows you to toggle between css variable colors easily. In my code, I have done this the following way:-
const toggleColorMode = () => {
const nextMode = mode === "light" ? "dark" : "light";
// container is appRef.current only
container?.setAttribute("data-color-mode", nextMode);
setMode(nextMode);
};
I am not using redux for this. Simply React Context API is being used by me but it's doable in your scenario as well.
You can take more reference from the repo - https://github.com/lapstjup/animeccha/tree/main/src
Note - I think there are other routes where people go with CSS-IN-JS but I haven't explored them yet. This solution is one of the pure css ways.
Fun fact - Github has implemented their newest dark mode in a similar way and that's where I got the idea as well. You can inspect their page to see the same attribute name :D.
The 'Using ClassNames' section of react-select docs states that using the className and classNamePrefix props
ensures compatibility with styled components, CSS modules and
other libraries.
In this CodeSandbox, with CSS modules and node-sass, it seems to work. However, if I replicate the following code on my local machine in a create-react-app, it doesn't work. My CRA uses the Typescript template. Is that the problem? Everything else is just the same.
Select.module.scss
.select {
outline: 1px solid red;
.select__control {
background-color: salmon;
}
}
Select.tsx
import React from 'react';
import RS from 'react-select';
import style from './Select.module.scss';
const options = [
{label: "hi", value: "hi"}
]
function Select(props: any) {
return (
<RS
options={options}
className={style.select}
classNamePrefix={style.select}
/>
)
}
export default Select;
App.tsx
import React from 'react';
import Select from './Select';
function App() {
return (
<div className="App">
<Select />
</div>
);
}
export default App;
I could make it work here by doing:
Select.module.scss
.select {
outline: 1px solid red;
[class$="-control"] {
background-color: salmon;
}
}
Select.tsx
import React from 'react';
import RS from 'react-select';
import style from './Select.module.scss';
const options = [
{label: "hi", value: "hi"}
]
function Select(props: any) {
return (
<RS
options={options}
className={style.select}
/>
)
}
export default Select;
Basically, I removed classNamePrefix from react-select component and changed .select__control to [class$="-control"], which matches all classes ending with -control.
The problem here was because css loader was adding a hash in my classnames eg {select: "styles_select__SQ71h", select__control: "styles_select__control__xcj2p"}.
Not really a problem but something I’m not happy with. I'm using react + typescript + css modules + https://material-ui-next.com/. Problem is that when I need to style material ui components I have to use !important a lot. Question is if there is a way to create styles without important. I create a sample project to reproduce the problem https://github.com/halkar/test-css-modules
material-ui exposes many of their components for styling. There two ways to go about doing this.
Apply styles globally
You could style the components globally and apply it to the theme. An example of this would be something like this (copied from the docs http://www.material-ui.com/#/customization/themes):
import React from 'react';
import {cyan500} from 'material-ui/styles/colors';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import AppBar from 'material-ui/AppBar';
// This replaces the textColor value on the palette
// and then update the keys for each component that depends on it.
// More on Colors: http://www.material-ui.com/#/customization/colors
const muiTheme = getMuiTheme({
palette: {
textColor: cyan500,
},
appBar: {
height: 50,
},
});
class Main extends React.Component {
render() {
// MuiThemeProvider takes the theme as a property and passed it down the hierarchy
// using React's context feature.
return (
<MuiThemeProvider muiTheme={muiTheme}>
<AppBar title="My AppBar" />
</MuiThemeProvider>
);
}
}
export default Main;
As you can see in here, appBar component have a height of 50px meaning that every time you add an appbar component to your app down the tree where you applied the muiTheme, it will give it a height of 50px. This is a list of all the styles you can apply for each component https://github.com/callemall/material-ui/blob/master/src/styles/getMuiTheme.js.
Apply styles using style attribute
To apply the styles to individual components, you can usually use the style property and pass it the styles you want.
This is another example from the docs where a margin of 12px is applied to a RaisedButton.
import React from 'react';
import RaisedButton from 'material-ui/RaisedButton';
const style = {
margin: 12,
};
const RaisedButtonExampleSimple = () => (
<div>
<RaisedButton label="Default" style={style} />
<RaisedButton label="Primary" primary={true} style={style} />
<RaisedButton label="Secondary" secondary={true} style={style} />
<RaisedButton label="Disabled" disabled={true} style={style} />
<br />
<br />
<RaisedButton label="Full width" fullWidth={true} />
</div>
);
export default RaisedButtonExampleSimple;
Now, the styles are defined in the same file but you could define them in a separate file and import them to the file where you are using the components.
If you want to apply multiple styles then you can use the spread operator like so: style={{...style1,...style2}}.
Usually, you are styling a specific thing in the component (root element) with the style property but some components have more than one property to style different elements of the component. Under properties in this page http://www.material-ui.com/#/components/raised-button, you can see that there are style property, labelStyle and rippleStyle to style different parts of RaisedButton.
Check the properties under the component that you are using and see which style property you could use, otherwise check the available global style properties you could override. Hope this helps!
I should've used JssProvider and tell it to put material UI styles before mine in the page head section.
import JssProvider from 'react-jss/lib/JssProvider';
import { create } from 'jss';
import { createGenerateClassName, jssPreset } from 'material-ui/styles';
const generateClassName = createGenerateClassName();
const jss = create(jssPreset());
// We define a custom insertion point that JSS will look for injecting the styles in the DOM.
jss.options.insertionPoint = document.getElementById('jss-insertion-point');
function App() {
return (
<JssProvider jss={jss} generateClassName={generateClassName}>
...
</JssProvider>
);
}
export default App;
you have to use the component API's. You can't set style to the components imported from libraries just with css if the component has API's to get style.
*Update
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Button from 'material-ui/Button';
const styles = {
root: {
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
borderRadius: 3,
border: 0,
color: 'white',
height: 48,
padding: '0 30px',
boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .30)',
},
label: {
textTransform: 'capitalize',
},
};
function Classes(props) {
return (
<Button
classes={{
root: props.classes.root, // class name, e.g. `classes-root-x`
label: props.classes.label, // class name, e.g. `classes-label-x`
}}
>
{props.children ? props.children : 'classes'}
</Button>
);
}
Classes.propTypes = {
children: PropTypes.node,
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(Classes);