Material UI theme module augmentation not working - javascript

I've been reading the MUI documentation, blogs, and other posts on Stackoverflow, yet despite all of that, I can't get my vscode intellisense/typescript to detect my changes.
They're very simple changes, quite similar to what many other examples show, yet nothing.
Could use some help.
mui docs
resource
// theme.ts
export const getDesignTokens = (mode: PaletteMode) => ({
palette: {
mode,
...(mode === "light"
? {
// palette values for light mode
primary: {
light: "#FF7988",
main: "#FE5366",
dark: "#E04052",
},
text: {
primary: "#212121",
secondary: "#616161",
},
background: {
default: "#ffffff",
},
border: {
light: "#EFEFEF",
main: "#D9D9D9",
dark: "#979797",
},
}
: {
// future dark values
}),
...
// theme.d.ts
declare module "#mui/material/styles" {
// allow configuration using `createTheme`
interface PaletteOptions {
border?: {
light: string;
main: string;
dark: string;
};
}
interface Palette {
border: {
light: string;
main: string;
dark: string;
};
}
}
doesn't show the new border property

I had to add the import path to the module at the top of the script and that made things work. Not sure why I had to do this, i didnt notice it elsewhere, but it seems to work.
import "#mui/material"; <--
declare module "#mui/material/styles" {
// allow configuration using `createTheme`
interface PaletteOptions {
border?: {
light: string;
main: string;
dark: string;
};
}
interface Palette {
border: {
light: string;
main: string;
dark: string;
};
}
}

Related

What is difference between def interface and dto inerface in Angular?

I am working on the project, which was started by someone else. There are two interface files in the model folder def and dto. The difference between def and dto interface files is not clear to me. Could any expereince developer let me know what is the difference and when and how to use dto instead of def and viceversa. Thanks in advance.
vendor-def.interface.ts:
import { SourceType, VendorType } from '../shared/enums/vendor-type.enum';
export interface VendorDef {
vendorId: string;
companyCode: string;
name: string;
acronym: string;
alias: string;
legalId: string;
vendorType: VendorType;
sourceType: SourceType;
fiscalCode: string;
}
export interface VendorFormDef {
sourceType: SourceType;
companyCode?: string;
previousMainCompany?: string;
}
export interface InUsageDef {
acronym: boolean;
legalId: boolean;
fiscalCode: boolean;
}
vendor-dto.interface.ts
import { SourceType, VendorType } from '../shared/enums/vendor-type.enum';
export interface VendorDto {
data: VendorDataDto[] | VendorDataDto;
errors?: VendorErrorsDto;
}
export interface VendorDataDto {
attributes: VendorAttributesDto;
id: string;
}
export interface VendorErrorsDto {
code: string;
title: string;
detail: string;
}
export interface VendorCreateDto {
companyCode: string;
name: string;
acronym: string;
legalId: string;
fiscalCode: string;
vendorType: VendorType;
sourceType: SourceType;
}
Basically, it's used to separate what your API gives you from the objects you will manipulate.
VendorDTO is your API response (hence the presence of the data and errors fields)
VendorDef is the definition of the object you will manipulate in your app.
It is common to have a transformer from VendorDTO to VendorDef for when you request the data and a transformer from VendorDef to VendorDTO for when you want to push an addition/update on your API.
It is not restricted to Typescript or Angular, so you might want to check your question's tags.

How to customize theme in Vuetify using Storybook 6?

I want to customize themes in Vuetify using Storybook 6 and I am using #socheatsok78/storybook-addon-vuetify package https://storybook.js.org/addons/#socheatsok78/storybook-addon-vuetify
I did exactly what documentation says but theme is still not working at all. I want to configure vuetify with custom properties and with my own color palette.
preview.js
import '!style-loader!css-loader!sass-loader!./main.scss';
import {
withVuetify,
withThemeProvider,
} from '#socheatsok78/storybook-addon-vuetify/dist/decorators';
import minifyTheme from 'minify-css-string';
export const globalTypes = {
theme: {
dark: false,
options: {
customProperties: true,
minifyTheme,
},
themes: {
light: {
primary: '#007BBF',
secondary: '#008574',
},
dark: {
primary: '#f099aa',
},
},
},
};
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
export const decorators = [withThemeProvider, withVuetify];
main.js
const path = require('path');
module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.#(js|jsx|ts|tsx)'],
addons: [
'#storybook/addon-links',
'#storybook/addon-docs',
'#storybook/addon-essentials',
'#storybook/preset-scss',
'#socheatsok78/storybook-addon-vuetify',
],
webpackFinal: async (config) => {
config.module.rules.push({
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
{
loader: 'sass-resources-loader',
options: {
resources: path.resolve(__dirname, 'main.scss'),
},
},
],
sideEffects: true,
include: path.resolve(__dirname, '../'),
});
return config;
},
};
Ok I fixed the theme, you can find an tutorial how to do this and with all working code down below.
I found a great explanation here:
https://morphatic.com/2020/09/30/configuring-storybook-6-for-vue-2-vuetify-2-3/
preview.html
import '!style-loader!css-loader!sass-loader!./main.scss';
import { withVuetify } from '#socheatsok78/storybook-addon-vuetify/dist/decorators';
import vuetify from './vuetify';
import Vue from 'vue';
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
export const decorators = [
(story, context) => {
const wrapped = story(context);
return Vue.extend({
vuetify,
components: { wrapped },
template: `
<v-app>
<v-container fluid>
<wrapped/>
</v-container>
</v-app>
`,
});
},
withVuetify,
];
main.js
I removed one line from addons
'#socheatsok78/storybook-addon-vuetify',
vuetify.js
import Vue from 'vue';
import Vuetify from 'vuetify';
import minifyTheme from 'minify-css-string';
import theme from './theme';
import LRU from 'lru-cache';
const themeCache = new LRU({
max: 10,
maxAge: 1000 * 60 * 60, // 1 hour
});
Vue.use(Vuetify);
export default new Vuetify({
theme: {
options: {
customProperties: true,
minifyTheme,
themeCache,
},
themes: {
light: theme,
},
},
});
theme.js
export default {
// ... other colors
primary: '#007BBF',
};
Theme works perfect now, only variables are not loaded correctly and I don't know how to solve this, you can read about it in the article comments

Material UI Custom theme color assign Typescript

I created my own custom theme and I'm trying to assing one of the colors I created to a button, but when I'm trying to set it as:
color={theme.pallete.lightGrey}
I'm getting this error:
No overload matches this call
Overload 1 of 3, '(props: { href: string; } & { children?: ReactNode; classes?: Partial<ButtonClasses> | undefined; color?: "inherit" | "primary" | "secondary" | "success" | "error" | "info" | "warning" | undefined; ... 9 more ...; variant?: "text" | ... 2 more ... | undefined; } & Pick<...> & CommonProps & Pick<...>): Element', gave the following error.
Does this means that you can't assign custom colors to the color attribute? Only through styling
If you are using typescript use the global theme approach
in this case,
I have 2 custom colours which are neutral and backgroundSecondary so you need to register the types in material UI types
declare module "#mui/material/styles" {
interface CustomPalette {
neutral: {
main: string;
contrastText: string;
};
backgroundSecondary: string;
}
interface Palette extends CustomPalette {}
interface PaletteOptions extends CustomPalette {}
}
Then register that button show be able to read the custom colors
In my case I only need neutral to be read by the Button component so you do this
declare module "#mui/material/Button" {
interface ButtonPropsColorOverrides {
neutral: true;
}
}
You set up your theme (in most cases this would have already been setup)
let theme = createTheme({
palette: {
primary: {
main: "some-color",
},
secondary: {
main: "some-color",
},
error: {
main: "some-color",
},
neutral: {
main: "#fff",
contrastText: "#002255",
},
backgroundSecondary: "#f8fafc",
},
});
Finally the usage
<Button variant="outlined" color="neutral"> Click Me</Button>

Extend Vuetify components in TypeScript

I'm trying to extend a vuetify component with some default props set in TypeScript. In JavaScript it worked perfectly but I can't figure out how to extend the components in TS. Here is the code for the Component in JS:
import { VTextField } from 'vuetify/lib'
export default {
name: "my-text-field",
extends: VTextField,
props: {
"hide-details": {
type: Boolean,
default: true
},
outlined: {
type: Boolean,
default: true
},
dense: {
type: Boolean,
default: true
},
"single-line": {
type: Boolean,
default: true
},
color: {
type: String,
default: "secondary"
}
}
}
The proper way to do that add in the tsconfig.json
// tsconfig.json
{
"compilerOptions": {
"types": ["vuetify"]
}
}
Now just extend the needful component.
<script lang="ts">
import { VTextField } from 'vuetify/lib'
import { Component, Prop } from 'vue-property-decorator'
#Component({})
export default class TextField extends VTextField {
#Prop({default: 'auto'}) private hideDetails!: boolean|string;
#Prop({default: true}) private outlined!: boolean;
#Prop({default: true}) private dense!: boolean
#Prop({default: true}) private singleLine!: boolean;
#Prop({default: 'secondary'}) private color!: string
}
</script>
I've found a solution by peeking into the VTextArea component of Vuetify. Here's my solution:
import Vue from 'vue'
//#ts-ignore
import VTextField from 'vuetify/lib/components/VTextField/VTextField'
// Create Base Mixins and Define Custom Properties
const base = Vue.extend({ mixins: [VTextField] })
export default base.extend({
name: "my-text-field",
props: {
hideDetails: {
type: Boolean,
default: true
},
outlined: {
type: Boolean,
default: true
},
dense: {
type: Boolean,
default: true
},
singleLine: {
type: Boolean,
default: true
},
color: {
type: String,
default: "secondary"
}
}
})
hope this works for you:
import {Vue, Component, Prop} from 'vue-property-decorator';
import { VIcon, VTextField} from 'vuetify/lib'
interface Item {
text: string;
complete: boolean;
}
#Component({
name: 'TodoItem',
components: {
'v-icon': VIcon,
'v-text-field': VTextField
}
})
export default class TodoItem extends Vue {
#Prop(Object) public item!: Item;
#Prop(Number) public index!: number;
#Prop(Number) public editingId!: number;
public editingContent = 'nihao';
public edit() {
this.$emit('on-edit', this.index)
}
public save() {
alert('k');
}
protected render() {
return (
<li>
{this.editingId === this.index ?
(<div>
{/* tslint:disable-next-line:max-line-length */}
<v-text-field v-model={this.editingContent} append-icon={'mdi-close'} placeholder={this.item.text} on-click:append={this.save}/>
{/*<v-text-field><v-icon color={'red'} slot={'append'}>mdi-close</v-icon></v-text-field>*/}
</div>)
: (<div>
<span>{this.item.text}</span>
<v-icon x-small={true} nativeOn-click={this.edit}>mdi-pencil</v-icon>
</div>)
}
</li>
);
}
}

Cannot find namespace error for model in Angular2/TypeScript

The FeaturedCategories model
export class FeaturedCategories {
categories: Array<{ id: number, title: string, graphic: string, categorycards: Array<{}> }>;
}
Also tried this:
export class FeaturedCategories {
id: number;
title: string;
graphic: string;
categorycards: Object[];
}
The Component
import { Component, ChangeDetectionStrategy, ViewEncapsulation } from '#angular/core';
import { ApiService } from '../shared/services/api.service';
import { FeaturedCategories } from '../shared/models/home/featuredcategories';
#Component({
changeDetection: ChangeDetectionStrategy.Default,
encapsulation: ViewEncapsulation.Emulated,
selector: 'home',
styleUrls: [ './home.component.css' ],
templateUrl: './home.component.html'
})
export class HomeComponent {
testFeaturedCategories: Array<FeaturedCategories>;
constructor(private api: ApiService) {
// we need the data synchronously for the client to set the server response
// we create another method so we have more control for testing
this.universalInit();
}
universalInit() {
console.log('universalInit...')
this.api.getFeatured()
.subscribe(categories => {
console.log('categories', categories);
this.testFeaturedCategories = categories
});
}
}
This will work: testFeaturedCategories: Array<{}>;
However I'm trying to use TypeScript to let my App know what type of model to expect.
This causes the error above:
testFeaturedCategories: FeaturedCategories.categories;
And if I just try this: testFeaturedCategories: FeaturedCategories;
I get a type [{}] is not assignable error.
UPDATE
So I noticed that when I commented out all the keys in my FeaturedCategories model finally the error goes away and
featuredCategories: FeaturedCategories[]; will work.
However now this is just an empty object without keys to expect :(
export class FeaturedCategories {
// id: number;
// title: string;
// graphic: string;
// categorycards: Object[];
}
this is working fine for me.
export class MyComponent {
categories: FeaturedCategories[] = [{
id: 1,
title: "",
graphic: "",
categorycards: [{}]
}];
}
export class FeaturedCategories{
id: number;
title: string;
graphic: string;
categorycards: Object[];
}
My problem was trying to type my Array, instead of just using the Typed objects that exist in the larger Array.
Also had a problem in my service, originally I had this:
/**
* Get featured categories data for homepage
* /wiki
*/
getFeatured(): Observable<[{}]> {
return this.http.get(`${this.getFeaturedUrl}/home`)
// .do(res => console.log('getFeatured res', res.json()))
.map(res => res.json())
.catch(this.handleError);
}
I did not need or could even use a type for my larger Categories array, what I needed was a smaller type for the exact Objects that exist in that larger Array:
export class FeaturedCategory {
id?: number;
type: string;
title: string;
graphic?: string;
video?: string;
categorycards: Array<{}>;
}
So now with the correct Type of Objects inside my Array I added it to the service:
getFeatured(): Observable<[FeaturedCategory]> {
return this.http.get(`${this.getFeaturedUrl}/home`)
.map(res => res.json())
.catch(this.handleError);
}
Now back in my Component I imported the single Typed Object
import { FeaturedCategory } from '../shared/models/home/featuredcategory';
Then typed the variable:
featuredCategories: Array<FeaturedCategory>;
And finally in ngOnInit
ngOnInit() {
this.api.getFeatured()
.subscribe(categories => {
console.log('categories', categories);
this.featuredCategories = categories;
});
}
No more errors :)

Categories

Resources