Tailwind Custom Colors Not recompiled with Twin.macro and styled component - babeljs

I'm trying to use a custom color, but I got a problem when I change the color on the tailwind config, Twin.macro does not recompile the style,
p.s: it's worked fine when I use it with className
// tailwind.config.js
module.exports = {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx}',
'./src/components/**/*.{js,ts,jsx,tsx}',
],
important: true,
theme: {
extend: {
colors: {
// primary: '#00bcd4',
primary: '#fde047',
},
},
}
}
// babel-plugin-macros.config.js
module.exports = {
twin: {
preset: 'styled-components',
autoCssProp: false,
},
}
// .babelrc.js
module.exports = {
presets: [['next/babel', { 'preset-react': { runtime: 'automatic' } }]],
plugins: ['babel-plugin-macros', 'babel-plugin-styled-components'],
}
Example of usage
<div className="text-primary">Hello </div> // Color change
<div tw="text-primary">#Dégage_Akhannouch</div> // Color does not change

Related

MUI and Tailwind: Use same color palette

Is there a good approach when I use MUI (Material UI) with Tailwind css to use the same color palette in my code?
(For example MUI theme should use the colors which I define in my tailwind.config)
Currently I have an extra file colors.js and define my hex-colors with const. And then use this variables in both. But I don't really like this solution :/
color.js
type module.exports = {
primaryLightColor: '#757ce8',
primaryMainColor: '#224AA6',
primaryDarkColor: '#042757',
secondaryLightColor: '#BDC1C9',
secondaryMainColor: '#8B969D',
secondaryDarkColor: '#4C5356',
errorColor: '#F44336',
warningColor: '#FF9800',
infoColor: '#A5C8FF',
successColor: '#82C64D',
backgroundColor: '#F7F8FA',
};
theme.tsx
import { createTheme } from '#mui/material';
import {
primaryLightColor,
primaryMainColor,
primaryDarkColor,
secondaryLightColor,
secondaryMainColor,
secondaryDarkColor,
} from './colors';
export const theme = createTheme({
palette: {
primary: {
light: primaryLightColor,
main: primaryMainColor,
dark: primaryDarkColor,
},
secondary: {
light: secondaryLightColor,
main: secondaryMainColor,
dark: secondaryDarkColor,
},
},
});
tailwind.config.js
/** #type {import('tailwindcss').Config} */
const {
primaryLightColor,
primaryMainColor,
primaryDarkColor,
secondaryLightColor,
secondaryMainColor,
secondaryDarkColor,
errorColor,
warningColor,
infoColor,
successColor,
backgroundColor,
} = require('./app/styles/colors.js');
module.exports = {
corePlugins: {
preflight: false,
},
content: ['./app/**/*.{js,ts,jsx,tsx}'],
important: '#root',
theme: {
colors: {
primary: {
light: primaryLightColor,
main: primaryMainColor,
dark: primaryDarkColor,
},
secondary: {
light: secondaryLightColor,
main: secondaryMainColor,
dark: secondaryDarkColor,
},
error: errorColor,
warning: warningColor,
info: infoColor,
success: successColor,
background: backgroundColor,
},
extend: {},
},
plugins: [],
};

How to configure MUI v5 custom font-family?

I have the following:
cont theme = createTheme({
typography: {
allVariants: MetricFontFaces,
fontFamily: 'MetricHPEXS'
} as TypographyOptions,
components: {
MuiFormControl: {
styleOverrides: {
root: {
fontFamily: 'MetricHPEXS'
}
}
},
MuiInput: {
styleOverrides: {
root: {
fontFamily: 'MetricHPEXS'
},
formControl: {
fontFamily: 'MetricHPEXS'
},
input: {
fontFamily: 'MetricHPEXS'
}
}
},
MuiOutlinedInput: {
styleOverrides: {
input: {
fontFamily: 'MetricHPEXS'
}
}
}
}
});
Then I try to use it like this in my storybook:
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
{story()}
<TextField value="sdasdasd" />
</ThemeProvider>
</StyledEngineProvider>
The custom font-family is not applying.
How do I properly create the MUI v5 theme such that all components will accept the same custom font?
In the end, we applied the font settings directly onto the MuiCssBaseline in order to have everything else pick up the font-family. Example:
import { TypographyOptions } from '#mui/material/styles/createTypography';
export const muiThemeOptions = {
typography: {
fontFamily: 'MetricHPEXS'
} as TypographyOptions,
components: {
MuiCssBaseline: {
styleOverrides: MetricFontFaces // <== here
},
...
}
}
Where MetricFontFaces is a giant string with all of the #font-face defined. While this worked on applying the font globally, but because MetricFontFaces is a string, we couldn't apply other CSS styling easily. There is no simple way (at least I could not find them) to supply #font-face via the MuiCssBaseline.

material-ui - how to refer palette in override?

How can I refer the palette in a theme override?
e.g. I want to change the selected Tab to have the secondary color as background, instead of hardcoded blue
const theme = createMuiTheme({
overrides: {
MuiTab: {
root: {
"&$selected": { backgroundColor: "blue" }, // TODO palette.secondary.main instead of blue
}
}
},
palette: {
primary: { main: "black" },
secondary: { main: "blue" }
}
});
You can create palette object that you can refer to:
import { createMuiTheme } from '#material-ui/core';
import createPalette from '#material-ui/core/styles/createPalette';
const palette = createPalette({
primary: { main: "black" },
secondary: { main: "blue" }
});
const theme = createMuiTheme({
overrides: {
MuiTab: {
root: {
"&$selected": { backgroundColor: palette.secondary.main },
}
}
},
palette
});

How do we extend material-ui's CssBaseline?

I'm thinking to do it like the following, but I'm not sure if this is the recommended way to do it:
import * as React from "react"
import { withStyles, createStyles, Theme } from "#material-ui/core"
import CssBaseline from "#material-ui/core/CssBaseline"
// global styles for a Mapper app
class MyCssBaseline extends React.Component {
render() {
return <CssBaseline />
}
}
export default withStyles(styles)(MapperCssBaseline)
function styles(_theme: Theme) {
return createStyles({
"#global": {
fontSize: 12,
// ... custom styles here ...
}
})
}
Is this how? Or is there a more recommended way?
I managed to do it with overrides when creating theme
export const theme: Theme = createMuiTheme({
overrides: {
MuiCssBaseline: {
'#global': {
svg: {
maxWidth: '100%',
maxHeight: '100%',
},
},
},
},
})

Vue-chartjs is rendering my responsive chart too tall for my window

I created a simple responsive HTML + JS chart with chart.js which worked well. I decided to do it within Vue CLI and so have tried to switch it to vue-chartjs but the same chart always renders about 33% taller than my window and so presents vertical scrollbars (the width is fine). I recreated the problem with a sample trivial graph which I render with:
import {Line} from 'vue-chartjs'
export default {
extends: Line,
mounted () {
this.renderChart(data, options)
}
}
Note the data is trivial and the options are {}.
If I use chart.js in my Vue component, instead of vue-chartjs then it works fine. I.e. I do nothing more than delete the above code from my component and change it to the following then it renders fine, just like my sample HTML + chart.js version.
import Chart from 'chart.js'
function mount(el) {
return new Chart(
document.getElementById(el).getContext('2d'), {
type: 'line',
data: data,
options: options,
})
}
export default {
template: '<canvas id="chart"></canvas>',
mounted () {
self.chart = mount('chart')
}
}
I am using the default responsive: true and maintainAspectRatio: false of course, and have no explicit CSS or size settings anywhere.
Why can I not get the chart to render the height correctly when I use vue-chartjs? I am using vue-chartjs version 3.4.2 but have also tried a few versions back. I have looked all over the github bug tracker but seen nothing related.
UPDATE:
You should pass the options as prop or locally. But it's needed to add:
responsive: true
maintainAspectRatio: false
the desired height as well as the options as you said. Here's how it worked for me:
options:
options: {
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}]
},
responsive: true,
maintainAspectRatio: false
}
In template:
<bin-graph-weight :chart-data="datacollection" :styles="myStyles" :options="datacollection.options"/>
graph-component.js:
import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
export default {
extends: Line,
mixins: [reactiveProp],
props: ['options'],
mounted () {
// this.chartData is created in the mixin.
this.renderChart(this.chartData, this.options)
},
// If you want to pass options please create a local options object
watch: {
chartData () {
this.$data._chart.update()
}
}
}
Also had problem with height overflow and responsiveness, fixed by introducing flex parent container that takes up 100% of the space. After setting responsive and ratio options (check out related chartjs doc):
options: {
// ..
responsive: true,
maintainAspectRatio: true
}
I used following css to fill 100% of the parent (where TheChart is vue-chartjs component. Basically need to make sure the chart's parent is always filling 100% of it's own parent):
vue template
<v-container class="chart-container">
<TheChart :chartdata="chartData" :options="chartOptions" />
</v-container>
scss:
.chart-container {
flex-grow: 1;
min-height: 0;
> div {
position: relative;
height: 100%;
}
}
With responsiveness the chart rerenders with promises and actually sets two times.
With a watcher in Vue.js you can rerender every time with changes in the chartData.
Chart component:
<script>
import { Bar, mixins } from 'vue-chartjs';
const { reactiveProp } = mixins;
export default {
extends: Bar,
mixins: [reactiveProp],
props: ['chartOptions'],
mounted() {
this.renderChart(this.chartData, this.chartOptions);
},
watch: {
chartData() {
this.renderChart(this.chartData, this.chartOptions);
},
},
};
</script>
Use together with dynamic styles.
Chart properties:
<template>
<div style="height:300px;">
<bar-chart :styles="myStyles" :chart-data="dataCollection"
:chart-options="chartOptions"></bar-chart>
</div>
</template>
<script>
import BarChart from './ChartBar.vue';
export default {
components: {
BarChart,
},
props: ['dataCollection'],
data() {
return {
myStyles: {
height: '300px',
width: '100%',
position: 'relative',
},
chartOptions: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
},
gridLines: {
display: true,
},
}],
xAxes: [{
ticks: {
beginAtZero: true,
},
gridLines: {
display: false,
},
}],
},
legend: {
display: true,
},
tooltips: {
enabled: true,
mode: 'single',
callbacks: {
label(tooltipItems, data) {
const { datasetIndex, index } = tooltipItems;
const value = data.datasets[datasetIndex].data[index];
if (parseInt(value, 10) > 999) {
return ` ${value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')}`;
}
return ` ${value}`;
},
},
},
responsive: true,
maintainAspectRatio: false,
height: 300,
},
};
},
};
</script>
<style lang="scss" scoped>
</style>