How can I display the material-ui theme object in storybook - material-ui

I would like to display our theme object in storybook somehow but haven't found a way to even look at theme from inside a component.
Minimally I would like something like what material-ui does showing the theme structure here: https://mui.com/customization/default-theme/
Idealy I would like to map through parts of the object and display colors, font sizes, font weights, spacing etc kind of like this (but it doesn't work because you can't access the theme like this)
const useStyles = makeStyles((theme) => theme.palette.primary);
export const Primary = (): JSX.Element => {
const classes = useStyles;
return (
<>
{Object.keys(classes).map((key) => <Box bgcolor={classes[key]}>{key}</Box>)}
</>
)
};

As the mui.com website is open source, you can implement the minimum by copying the source for the theme explorer on the Default Theme page. You can see how they traverse the theme object, similar in a way to your code snippet.
If you only want to highlight parts of the theme file, you can traverse the object and use some inbuilt components like ColorPalette from #storybook/addon-docs for example. In the MUI project on the palette page, they manually pull out each color using useTheme().
Maybe an storybook addon might be better placed? Example usage with MUI at the bottom of the page: https://storybook.js.org/addons/#react-theming/storybook-addon/

Related

Material UI - Theme is overriding the wrong component

I've made two Material-UI components. Both are using themes. However, the overrides on one theme are being used in the other! I'm losing my mind trying to find a solution to this. Here is the code:
This is being used for component1:
const themeForComponent1 = createMuiTheme({
overrides: {
MuiInputLabel: {
root: {
padding: '13px 0 0 13px !important'
}
},
},
})
...and it is changing stuff in component 2, which happens to also have an element with the class "MuiInputLabel-root".
(edit: If it helps at all, the component is being called in Formik using the Field element via the "as" prop. Each component is using its own ThemeProvider element.)
If you want to have two themes independent you can see the Material UI documentation here
https://material-ui.com/styles/advanced/
But in the fact yo should use two theme providers. I say you that you should use an only theme and customize your component styles using Material UI functions to do that like CSS class

is it possible to override a theme override with component classes prop?

I am wondering if there is a neat trick to use a component classes prop to override some CSS defined in a theme's overrides.
For instance :
If I want all Button components to have a different font-size than the default one. I can use the theme.overrides props to do so :
// this works, all Buttons text is 1.1rem
let theme = createMuiTheme({
overrides: {
MuiButton: {
label: {
"&": {fontSize: "1.1rem"}
}
}
}
})
Now if for some reason one of my button needs to have a different font-size, I was hoping using classes prop would do the job :
const useClasses = makeStyles({
smallerFontSize: {
fontSize: "0.9rem"
}
})
...
const classes = useClasses()
...
<Button
classes={{
// unfortunately this doesn't work, theme overrides is taking precedence
label: classes.smallerFontSize
}}
>
Some smaller text
</Button>
...
Since using classes prop allows us to target and override some component's CSS if default theme values have not been overridden, I find it confusing that theme overrides end up behaving somewhat differently and have a higher specificity than a one time rule.
I'd argue it kind of defeats the purpose of having a customisable theme.
But hopefully I'm missing something and your wisdom will help !
UPDATE
My mistake was to export the created theme and the makeStyles hook from the same module file.
Doing that made Mui insert theme <style> after the hook <style>.
To fix the issue and be able to use classes component props as I wanted to :
export theme and hooks from separate modules
make sure theme module has no dependency on the module exporting the hook
make sure when using ThemeProvider that it has no parent component importing the hook
I still don't quite understand why things worked before I added the overrides property on the theme object though.

How to modify font-size/style of Tooltip component?

Not able to assign custom class to tooltip component in order to update the style of tooltip component
Tried by assigning to classes property
Posted at https://codesandbox.io/s/twilight-fire-907mp
Make your own Tooltip with custom styles and then use it:
const TooltipWithBiggerFontSize = withStyles({
tooltip: {
fontSize: 30
}
})(Tooltip)
As you already did with other components, eg: DialogContent or DialogActions.
Usage
<TooltipWithBiggerFontSize title="Custom Search">
<Publish />
</TooltipWithBiggerFontSize>
BTW, your code is confusing. You are mixing functional and class components. Once, you are styling with withStyles once with makeStyles.
You should choose one method and stick to it. Here is styling docs. It will solve most of your problems.
codesandbox

CSS from code? How to use CSS decoration directly from Vala?

How to use CSS customization directly from Vala? Not like in this example with file. Let's say I want the button to turn red by clicking on it, without using an external css file, as this action is too simple to create a css file with a single field.
I mean smth like this:
label.set_styleSheet("font-size: 17px;")
You still have to create a CssProvider, like in the code you linked to:
var screen = this.get_screen ();
var css_provider = new Gtk.CssProvider();
You can call load_from_data () instead of load_from_path () to load it from a string in memory instead of a file:
https://valadoc.org/gtk+-3.0/Gtk.CssProvider.load_from_data.html
css_provider.load_from_data(".my_class { font-size: 17px; }");
Gtk.StyleContext.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER);
When the CSS provider has loaded the custom styles to be used, you can manipulate every Gtk+ widget with get_style_context ().
The style context has methods to add, remove and query a class, etc.
https://valadoc.org/gtk+-3.0/Gtk.StyleContext.html
label.get_style_context().add_class("my_class");
Since you only have to setup the style provider once, I don't think it is too much overhead.
For anyone who is reading this I have posted both examples with and without file to Git https://gitlab.com/gavr123456789/vala-css-examples/tree/master

Dyamic Color Change of Ionic's ion-toggle and ion-checkbox (use color string at runtime)

I'm trying to dynamically change the color of Ionic's Ion-Toggle and Ion-Checkbox at runtime. I know I can change it to a pre-defined sass variable like this:
<ion-toggle [color]="somePredefinedColor"></ion-toggle>
where "somePredefindedColor" is the string of the predefined sass variable...but because there is a section in my app that adapts to the corporate design colors of a company (which it gets from server as hex-strings) this is not possible.
The closest I got was to query the document by the component's class ".toggle-icon" and set its background color. This works at the first load but as soon as the page is loaded again it falls back to the sass predefined colors...
Have you tried this:
<ion-toggle [style.color]="colorVariable"></ion-toggle>
Where colorVariable is a variable in your component in .ts file, which you can change it dynamically:
if (this.redCondition)
this.colorVariable = 'red';
else
this.colorVariale = 'black';
Alternatively, you can define two CSS classes in your SCSS file, call it red-toggle, and black-toggle. Then you can:
<ion-toggle [class.red-toggle]="redCondition" [class.black-toggle]="!redCondition"></ion-toggle>
These methods are called style and class binding respectively.
If you want to dynamically change a value in your css style, you can use ngStyle directive:
[ngStyle]="{ 'background-color': hexColorString}"
EDIT:
The problem is that ion-toggle after transpile will have two child nodes, and you want to change the style of those child nodes dynamically. These nodes are toggle-icon, and toggle-inner:
This is not the cleanest way of doing it, but you can use the following typescript code, and modify it so that the colors change dynamically:
var div1 = document.getElementById('mytoggle').getElementsByTagName('div');
if(div1[0]){
div1[0].style.backgroundColor = '#0F0';
var div2 = div1[0].getElementsByTagName('div');
if(div2[0])
div2[0].style.backgroundColor = '#00F';
}
Notice that you have to set "mytoggle" as the id of the ion-toggle element in your html file.
Disclaimer: This code is rather hacky and may not work correctly with future versions of Ionic!
You just need to add square brackets on the dynamic attribute that is receiving the variable.
<ion-toggle [color]="somePredefinedColor"></ion-toggle>
Predefined colors can be setup in the theme/variables.scss file under $colors
$colors: (
primary:#48B0F7,
secondary:#10CFBD,
....
somePredefinedColor:#000
)
Which can then be added to the [color] attribute
<ion-toggle [color]="somePredefinedColor"></ion-toggle>