Mui v5 styleOverrides not working with themes - javascript

I am trying to style using theme overrides as laid out in the documentation here:
I have the following code sandbox:
import * as React from 'react';
import { ThemeProvider, createTheme } from '#mui/material/styles';
import Select from '#mui/material/Select'
import MenuItem from '#mui/material/MenuItem'
const theme = createTheme({
components: {
MuiSelect: {
styleOverrides: {
root: {
background: '#000',
},
},
},
},
});
export default function GlobalThemeOverride() {
return (
<ThemeProvider theme={theme}>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
variant="standard"
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</ThemeProvider>
);
}
The Select box should have a background of #fff however no background is set at all. :(

This looks like a bug to me (or at least missing a feature that is reasonable for developers to expect to be there). The issue is that Select doesn't define any styles of its own at the root level, so it doesn't leverage the code (which would be a call to MUI's styled such as here for the select class) that would take care of looking at the theme and applying the corresponding style overrides. I recommend logging an issue.
There are a couple possible workarounds.
Workaround 1 - Target the select CSS class
This approach may work, but it depends on what all you are trying to do since this targets a child of the root element.
const theme = createTheme({
components: {
MuiSelect: {
styleOverrides: {
select: {
backgroundColor: "#000",
color: "#fff"
}
}
}
}
});
Workaround 2 - Target the MuiInput-root CSS class
The approach below targets the same element as MuiSelect-root by leveraging MuiInput-root (the rendering of the root element of the Select is delegated to the Input component when the variant is "standard") and then qualifying it via "&.MuiSelect-root" so that it only affects Select rather than all inputs.
const theme = createTheme({
components: {
MuiInput: {
styleOverrides: {
root: {
"&.MuiSelect-root": {
backgroundColor: "#000",
color: "#fff"
}
}
}
}
}
});

Related

#next/font works everywhere except one specific component

The bounty expires in 5 days. Answers to this question are eligible for a +50 reputation bounty.
andrilla wants to draw more attention to this question:
I would love to see some ideas of what might be causing this and how I might fix it. Ideally I'd love an actual answer, but just some good ideas of what I might try would be super helpful.
#next/font
Uses Next.js with TypeScript and Tailwind CSS
This is my first time using the new #next/font package. I followed Next.js' tutorial, and it was easy to set up. I'm using both Inter and a custom local typeface called App Takeoff. To actually use both of these typefaces, I'm using Tailwind CSS, where Inter is connected to font-sans and App Takeoff is connected to font-display.
Everything works except in one spot
I have done plenty of testing between files, and for some reason both typefaces work everywhere except my Modal component.
Example
index.tsx
modal.tsx via index.tsx
As you can see, the typefaces work just fine when they aren't inside the modal, but as soon as they're in the modal they don't work.
Here's some relevant code:
// app.tsx
import '#/styles/globals.css'
import type { AppProps } from 'next/app'
import { Inter } from '#next/font/google'
const inter = Inter({
subsets: ['latin'],
variable: '--font-inter'
})
import localFont from '#next/font/local'
const appTakeoff = localFont({
src: [
{
path: '../fonts/app-takeoff/regular.otf',
weight: '400',
style: 'normal'
},
{
path: '../fonts/app-takeoff/regular.eot',
weight: '400',
style: 'normal'
},
{
path: '../fonts/app-takeoff/regular.woff2',
weight: '400',
style: 'normal'
},
{
path: '../fonts/app-takeoff/regular.woff',
weight: '400',
style: 'normal'
},
{
path: '../fonts/app-takeoff/regular.ttf',
weight: '400',
style: 'normal'
}
],
variable: '--font-app-takeoff'
})
const App = ({ Component, pageProps }: AppProps) => {
return (
<div className={`${inter.variable} font-sans ${appTakeoff.variable}`}>
<Component {...pageProps} />
</div>
)
}
export default App
// modal.tsx
import type { FunctionComponent } from 'react'
import type { Modal as ModalProps } from '#/typings/components'
import React, { useState } from 'react'
import { Fragment } from 'react'
import { Transition, Dialog } from '#headlessui/react'
const Modal: FunctionComponent<ModalProps> = ({ trigger, place = 'bottom', className, addClass, children }) => {
const [isOpen, setIsOpen] = useState(false),
openModal = () => setIsOpen(true),
closeModal = () => setIsOpen(false)
const Trigger = () => React.cloneElement(trigger, { onClick: openModal })
const enterFrom = place === 'center'
? '-translate-y-[calc(50%-12rem)]'
: 'translate-y-full sm:-translate-y-[calc(50%-12rem)]'
const mainPosition = place === 'center'
? '-translate-y-1/2'
: 'translate-y-0 sm:-translate-y-1/2'
const leaveTo = place === 'center'
? '-translate-y-[calc(50%+8rem)]'
: 'translate-y-full sm:-translate-y-[calc(50%+8rem)]'
return (
<>
<Trigger />
<Dialog open={isOpen} onClose={closeModal} className='z-50'>
{/* Backdrop */}
<div className='fixed inset-0 bg-zinc-200/50 dark:bg-zinc-900/50 backdrop-blur-sm cursor-pointer' aria-hidden='true' />
<Dialog.Panel
className={`
${className || `
fixed left-1/2
${
place === 'center'
? 'top-1/2 rounded-2xl'
: 'bottom-0 sm:bottom-auto sm:top-1/2 rounded-t-2xl xs:rounded-b-2xl'
}
bg-zinc-50 dark:bg-zinc-900
w-min
-translate-x-1/2
overflow-hidden
px-2 xs:px-6
shadow-3xl shadow-primary-400/10
`}
${addClass || ''}
`}
>
{children}
</Dialog.Panel>
<button
onClick={closeModal}
className='
fixed top-4 right-4
bg-primary-600 hover:bg-primary-400
rounded-full
h-7 w-7 desktop:hover:w-20
overflow-x-hidden
transition-[background-color_width] duration-300 ease-in-out
group/button
'
aria-role='button'
>
Close
</button>
</Dialog>
</>
)
}
export default Modal
I hope this information helps. Let me know if there's anything else that would be helpful to know.
Helpful Update
Thank you Jonathan Wieben for explanation of why this isn't working (See Explanation). The issue simply has to do with the scope of the applied styles, and Headless UI's usage of the React Portal component. If anyone has some ideas of how I can either change where the Portal is rendered or change the scope of the styles, that would be super helpful. Jonathan Wieben pointed out a way to do this, however—from my testing—it doesn't work with Tailwind CSS.
The Dialog component you are using renders in a portal (see here).
you typically want to render them as a sibling to the root-most node of your React application. That way you can rely on natural DOM ordering to ensure that their content is rendered on top of your existing application UI.
You can confirm this by inspecting your modal DOM element in your browser and seeing if it is indeed placed outside the div wrapper from your App component (I suspect it is).
If so, this is the explanation for why the modal content does not render with the expected font: It is rendered outside the component that defines the font.
To get around this, you could define your font on a higher level, e.g. in your head like described here: Next docs.

Stitches theme not updating Radix UI's Dropdown.Content component

so I am currently working with the stitches styling library and the radix-ui library. I am using the theme feature (darkTheme/lightTheme).
It all works perfectly in updating all but one of the radix-ui components.
The Dropdown.Content doesn't get updated right and I don't understand why. I am currently passing in a $backgroundColor to the styles and instead of it changing depending on the theme, it sticks to the color from the default theme.
This is the code from my styles.ts file:
export const DropdownContent = styled(DropdownMenu.Content, {
background: '$backgroundColor',
border: '2px solid $borderColor',
)},
This is a snippet from my stitches.config.ts file:
export const {
styled,
css,
globalCss,
keyframes,
theme,
createTheme,
config,
} = createStitches({
theme: {
colors: {
backgroundColor: '#ffffff',
borderColor: '#E5E8EB',
},
space: {},
fonts: {},
},
media: {},
utils: {},
});
export const darkTheme = createTheme({
colors: {
backgroundColor: '#141416',
borderColor: '#353945',
}
});
This is because the content is rendered directly in the body tag through a React Portal, a default Radix behavior. Try setting open={true} on the Select and inspect the content elements to see for yourself.
You're most likely adding the dark theme class somewhere along your component tree, i.e. on your App component. That will not work for elements outside of that tree, for instance ones rendered in the body tag through a portal.
You need to apply the dark theme class to your body tag, like this:
const [darkTheme, setDarkTheme] = useState(true);
useLayoutEffect(() => {
const { classList } = document.body;
if (darkTheme) classList.add(darkThemeCssClass);
else classList.remove(darkThemeCssClass);
}, [darkTheme]);
This will allow the theme-dependent styling to be applied to all elements on the page, not just ones in your component tree.

how to customize material ui tabs, tabs scroller

Here I am trying to customize this mui tabs, tab color, and tab bottom border color. I have tried to do so by using makestyles and so on but nothing is working.
my code is,
import { makeStyles } from '#mui/styles';
const useStyles = makeStyles({
tab:{
"& .MuiButtonBase-root":{
marginLeft:"25px"
}
},
tabs:{
"& .MuiTabs-indicator":{
ml:"30px"
}
}
})
Besides, I also face issues with customizing mui classes. Though I use a solution that is sx props but I know that is not best practice.
const theme = createTheme({
components: {
MuiTabs: {
styleOverrides: {
indicator: {
backgroundColor: 'orange',
height: 10,
},
},
},
}
})
You can style the selected tab styling with the property '&.MuiTab-root.Mui-selected' as for the border coloring for the current tab, you can use the prop TabIndicatorProps and add a styles property,i.e
export const StyledTab = styled((Tab))({
'&.MuiTab-root.Mui-selected': {
color: 'gold',
},
and
TabIndicatorProps={{
style: {
backgroundColor: '#f1db29'
}
}}

Chakra UI for React: change _focus borderColor not work

I set the default theme on Chakra UI for React with extendTheme().
When I try to change the Select component's style like this, the _focus style does not applied, while the color behaves as expected.
Refs
Chakra-UI Style Props
How to change the placeholder color globally?
Captions
Codes
index.ts
import { extendTheme } from '#chakra-ui/react';
import { Select } from './select';
export const theme = extendTheme({
colors: {
brand: '#008561',
brandLight: '#00b485',
},
components: {
Select,
},
});
select.ts
export const Select = {
parts: ['field'],
baseStyle: ({ colorMode }: any) => ({
field: {
color: 'brandLight',
_focus: {
borderColor: colorMode === 'dark' ? 'brandLight' : 'brand',
},
},
}),
sizes: {},
variants: {},
defaultProps: {},
};
To change the focus border color, you have to access the focusBorderColor selector,
This can either be set in the variant you want to change, or in the defaultProps selector of your component theme.
defaultProps: {
focusBorderColor: 'gray.500',
},
Another workaround I have seen, is to set the global shadows to a chakra color, note that any color you define, can also be accessed like the example below
const colors = { mycolor: "#F39C12" }
const shadows = {
outline: '0 0 0 3px var(--chakra-colors-mycolor-500)',
};
const theme = extendTheme({ config, colors, styles, components, shadows });
Workaround was found here: Chakra-UI Issue-663
Hope this helps your project
This worked for me.
_focusVisible={{
outline: "none",
}}

What does the symbol '&$checked' mean

import React from 'react';
import Checkbox from '#material-ui/core/Checkbox';
import { createMuiTheme, makeStyles, ThemeProvider } from '#material-ui/core/styles';
import { orange } from '#material-ui/core/colors';
const useStyles = makeStyles(theme => ({
root: {
color: theme.status.danger,
'&$checked': {
color: theme.status.danger,
},
},
checked: {},
}));
function CustomCheckbox() {
const classes = useStyles();
return (
<Checkbox
defaultChecked
classes={{
root: classes.root,
checked: classes.checked,
}}
/>
);
}
const theme = createMuiTheme({
status: {
danger: orange[500],
},
});
export default function CustomStyles() {
return (
<ThemeProvider theme={theme}>
<CustomCheckbox />
</ThemeProvider>
);
}
What does the symbol '&$checked' mean used in this CodeSandbox?
Please explain the meaning of each symbol in detail, and the related logic.
Thanks for answering.
The & is a reference to the parent rule ("root" in this case). $ruleName (where "ruleName" is "checked" in this case) references a local rule in the same style sheet.
To clarify some of the terms above, the parameter to makeStyles is used to generate a style sheet potentially with multiple style rules. Each object key (e.g. "root", "checked") is referred to as a "rule name". When you call useStyles the resulting classes object contains a mapping of each rule name to a generated CSS class name.
So in this case let's say that the generated class name for "root" is "root-generated-1" and the generated class name for "checked" is "checked-generated-2", then &$checked is equivalent to .root-generated-1.checked-generated-2 meaning it will match an element that has both the root and checked classes applied to it.
As far as the effect on the Checkbox, the "checked" class is applied to the Checkbox by Material-UI when it is in a "checked" state. This style rule is overriding the default color of a checked Checkbox (the default is the secondary color in the theme).
Related answers and documentation:
https://cssinjs.org/jss-plugin-nested?v=v10.0.0#use--to-reference-selector-of-the-parent-rule
https://cssinjs.org/jss-plugin-nested?v=v10.0.0#use-rulename-to-reference-a-local-rule-within-the-same-style-sheet
Internal implementation of "makeStyles" in React Material-UI?
'&$checked' means you can override the element after checked.
And in your case, you are overriding the colour of checkbox after checked it
"&$checked": {
color: theme.status.danger
}
PFA for detail
You are probably referring to the .color>*:checked element

Categories