mwc-icon 0.7.1 not rendering (with lit-element/pwa-starter-kit)? - lit-element

Has any one got mwc-icon (0.7.1) to work with lit-element (pwa-starter-kit)?
mwc-button renders OK but mwc-icon does not render the icon just the icon index text.
import { html } from 'lit-element';
import { PageViewElement } from './page-view-element.js';
import {Icon} from "#material/mwc-icon" //does not work
import {Button} from "#material/mwc-button"
import { SharedStyles } from './shared-styles.js';
class MyView1 extends PageViewElement {
static get styles() {
return [
SharedStyles
];
}
render() {
return html`
<section>
<h2>Example</h2>
<mwc-icon>bookmark</mwc-icon>
<mwc-button outlined label="outlined"></mwc-button>
`;
}
}
window.customElements.define('my-view1', MyView1);

I think you encounter the same problem I did.
It happens because Chrome process the #font-face attribute only once at first page load.
when you import the mwc styles you expect them to enable in the lit-element render - after the first initial load of the page. that will work, you'll see the new styles except for the #font-face attribute.
That's why you don't see the icon.
A quick workaround is to append the link both on the head section in
index.html and in the lit-element as you did.
you can see example that don't work
and example that work
The difference is the added link in index.html head section.
More details here: github thread
Hope I helped you with this.
I was stuck on it myself for quite some time

Related

How to add a Modal popup to lit element Project

I am developing a project using lit. Already developed two web components using lit.
I need to add image gallery, carousal, and also modal popup to open when click on a button inside those components.
And I saw that https://opensource.adobe.com/spectrum-web-components/components/card/ has already developed those components using lit. I installed one of those component to my lit project. But styles are no showing.
The question is, can I use those spectrum web components to lit project and why is styling now working.
Here is my component code with spectrum button,
import { LitElement, html, css} from 'lit';
import '#spectrum-web-components/button/sp-button.js';
import '#spectrum-web-components/button/sp-clear-button.js';
import { Button, ClearButton } from '#spectrum-web-components/button';
class plans_component extends LitElement {
static properties = {
...
}
static styles = [
...
]
constructor() {
super();
...
}
render() {
return html `
<sp-button size="xl">Extra Large</sp-button>
`
}
}
customElements.define('plans-component', plans_component);
Thanks in advance.

Drawer Component Backdrop blocking users from interacting with page will it is open

I have a Drawer Component anchored at the bottom but I would still like to interact with the page above the drawer but either I can click out of if but the drawer closes so I tried the variants persistent and permanent both didn't work they actually made it so nothing at all happens when I click out of if. I think it has something to do with the spacing or padding above, but if anyone knows how to disable that, it would be greatly appreciated.
I solved it slightly differently, by removing the "inset" CSS property of the .MuiDrawer-modal div:
.MuiDrawer-modal {
inset: unset !important;
}
Figured out my problem, I ended us having to do some height changes to the Paper component and it seemed to work the way I wanted. You can overrided the css with makeStyles method in the #material-ui/core/styles directory. I used the classes property example
// Outside the component
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
drawer: {
css here ...
}
})
// Inside Component
const classes = useStyles() // the make styles returns a function and calling the useStyles returns an object with the css.
// Inside return
<Drawer
anchor="bottom"
classes={{ paper: classes.drawer }}
>
Content...
</Drawer>

Material-UI Theme : How to manage order or priority the .MuiXXX classes are applied?

[EDIT April 19th]
I have created a CODESANDBOX to show the problem, of course, that doesn't occur in sandbox.
The only difference between this code and mine is that I have duplicated the code of the Button component in the SANDBOX example, whereas in my App the Button component is imported from a library (that belongs to the same yarn workspace as the app). The library is built with webpack and babel, excluding React and Material-UI
externals: {
react: "react",
"react-dom": "react-dom",
"react-router": "react-router",
"react-router-dom": "react-router-dom",
"#material-ui/core": "#material-ui/core",
"#material-ui/icons": "#material-ui/icons",
"#material-ui/lab": "#material-ui/lab",
"#material-ui/styles": "#material-ui/styles",
formik: "formik",
},
Inspecting the components in the Browser shows the difference when styling, between sandbox and my app :
on both sides, the class are applied to the component the same way:
in sandbox
in my app
but on sandBox, the MuiButtonBase-root background-color is overridden by the MuiButton-root background-color
whereas it is the opposite in my app. The MuiButton-root backGroundColor seems to be overriden bu the MuiButtonBase-root background-color
However, if I create a component RecreatedButton in the App by just importing the Button component of my UI Library, and re-exported it without changing anything (just passing a specific props the component is requested), then the styling is applied correctly, as in the sandbox example.
this is kind of weird to me...
Why such a behavior ?
just importing and rexporting as is the component
import {
Button as LibraryButton,
EButtonTypes,
IButtonProps,
} from "#mylibrairy/reactcomponentscommon"; <---- importing the button
import React from "react";
const RecreatedButton: React.FC<IButtonProps> = (
props: IButtonProps
): JSX.Element => {
return (
<LibraryButton type={EButtonTypes.BUTTON}>
{props.children}
</LibraryButton>
);
};
export { RecreatedButton };
Using both in app.ts. One got the theme, the other not
import { ThemeProvider } from "#material-ui/core/styles";
import {
Button as LibraryButton,
EButtonTypes,
IButtonProps,
} from "#mylibrairy/reactcomponentscommon"
import React from "react";
import AppBar from "../../UIComponents/AppBar";
import { RecreatedButton } from "../../UIComponents/Button";
import { MUITheme } from "./../../Theming/defaultTheme";
export const MainApp: React.FC = (): JSX.Element => {
return (
<ThemeProvider theme={MUITheme}>
<>
<AppBar />
<LibraryButton type={EButtonTypes.BUTTON}> I'm the library component, directly used as is, and background color is NOT CORRECT ></LibraryButton>
<RecreatedButton>
I'm recreated button, just rexporting the library component, and the backgroundcolor is correct !?!?{" "}
</RecreatedButton>
</>
</ThemeProvider>
);
};
finally I found one solution (not sure that it fixes the root cause as I still do not understand where it comes from).
I Guess it may helps some people here that are facing a similar issue with global theming in Material-Ui.
It turned out that I had to change the way to build my react/material-Ui components library #mylibrairy/reactcomponentscommon.
1- Make sure that in the library, all imports where such as import { Button} from "#material-ui/core" and not for example import Button from "#material-ui/core/Button"
2- Remove the usage of file-loader plugin in the .babelrc to make sure it doesn't change the way to import material-ui components
3- Push #material-ui/core and #material-ui/icons as a dev and peer dependencies in the package.json of the library.
4- Rebuilt the library using webpack and babel to compile typescript tsx to js.
All issues of priority seems to disappear (have done a lot of tests and checked in the chrome dev tools). In the example above, the .MuiButton-root class is well applied after the .MuiButtonBase-root one, thus overriding as expected the backgroundColor.
Would admit that I'm a little bit confused why this fixed the issue...
Rgds
For me, i just had to import "makeStyles" and "createStyles" from "#material-ui/core" not from "#material-ui/core/styles". i just did this and it fixed the issue but took me a lot of time to figure this out.
so import them like this:
import { makeStyles, createStyles } from "#material-ui/core";
not like this:
import { makeStyles, createStyles } from "#material-ui/core/styles";
You may try overriding default globals for MuiButtonBase
const theme = createMuiTheme({
props: {
// Name of the component ⚛️
MuiButtonBase: {
// The default props to change
root:{
backgroundColor: 'red'
}
},
},
});
function DefaultProps() {
return (
<ThemeProvider theme={theme}>
<Button>Change default props</Button>
</ThemeProvider>
);
}
Working sandbox here - https://codesandbox.io/s/override-button-base-7qwd5

LitElement <slot> not wokring

I'm creating my custom accordion element. In which I'll have 2 components 1 for ul and other for li.
Content in file accordion-ul.ts, in which I've a slot where I want my li.
import { html, customElement, property, LitElement } from 'lit-element';
import { Accordion } from 'carbon-components';
#customElement('accordion-panel')
export default class AccordionPanel extends LitElement {
firstUpdated() {
const accordionElement = document.getElementById('accordion');
Accordion.create(accordionElement);
}
connectedCallback() {
super.connectedCallback();
}
render() {
return html`
<ul data-accordion class="accordion" id="accordion">
<slot></slot>
</ul>
`;
}
createRenderRoot() {
return this;
}
}
NOTE: I'm getting an error in the console in the firstUpdated() : Uncaught (in promise) TypeError: Cannot read property 'nodeName' of null.
The way I'm using it for testing:
<accordion-panel><li>test</li></accordion-panel>
IDK, it's not working and nothing is printing on the screen. On inspecting the element, I can see there's empty in DOM.
Your problem is that you're trying to use slots, which are a shadow DOM feature but you're not using shadow DOM (since you're overwriting the createRenderRoot method to prevent the creation of the shadowRoot)
So, if you want to use slots, just remove the createRenderRoot function from your class and use shadow DOM
Edit:
You should also update your firstUpdated method so that this part:
const accordionElement = document.getElementById('accordion');
Uses the element from your shadow DOM
const accordionElement = this.shadowRoot.querySelector('.accordion');
Then again, CarbonComponents styling will probably not work so you'll need to add those in some other way

React-like refs in lit-html / lit-element?

Does lit-html have by any change something like React's ref feature?
For example in the following pseudo-code inputRef would be a callback function or an object { current: ... } where lit-html could pass/set the HTMLElement instance of the input element when the input element is created/attached.
// that #ref pseudo-attribute is fictional
html`<div><input #ref={inputRef}/></div>`
Thanks.
In lit-element you can use #query property decorator. It's just syntactic sugar around this.renderRoot.querySelector().
import { LitElement, html, query } from 'lit-element';
class MyElement extends LitElement {
#query('#first')
first;
render() {
return html`
<div id="first"></div>
<div id="second"></div>
`;
}
}
lit-html renders directly to the dom so you don't really need refs like you do in react, you can use querySelector to get a reference to the rendered input
Here's some sample code if you were only using lit-html
<html>
<head>
<title>lit-html example</title>
<script type="module">
import { render, html } from 'https://cdn.pika.dev/lit-html/^1.1.2';
const app = document.querySelector('.app');
const inputTemplate = label => {
return html `<label>${label}<input value="rendered input content"></label>`;
};
// rendering the template
render(inputTemplate('Some Label'), app);
// after the render we can access it normally
console.log(app.querySelector('input').value);
</script>
</head>
<body>
<div class="app"></div>
<label>
Other random input
<input value="this is not the value">
</label>
</body>
</html>
If you're using LitElement you could access to the inner elements using this.shadowRoot.querySelector if you're using shadow dom or this.querySelector if you aren't
As #WeiChing has mentioned somewhere above, since Lit version 2.0 you can use the newly added directive ref for that:
https://lit.dev/docs/templates/directives/#ref
-- [EDIT - 6th October 2021] ----------------------------
Since lit 2.0.0 has been released my answer below
is completely obsolete and unnecessary!
Please check https://lit.dev/docs/api/directives/#ref
for the right solution.
---------------------------------------------------------
Even if this is not exactly what I have asked for:
Depending on the concrete use case, one option to consider is the use of directives.
In my very special use-case it was for example (with a little luck and a some tricks) possible to simulate more or less that ref object behavior.
const inputRef = useElementRef() // { current: null, bind: (special-lit-html-directive) }
...
return html`<div><input ref=${inputRef.bind}/></div>`
In my use case I could do the following:
Before rendering, set elementRef.current to null
Make sure that elementRef.current cannot be read while the component is rerendered (elementRef.current is not needed while rendering and an exception will be thrown if someone tries to read it in render phase)
That elementRef.bind directive will fill elementRef.current with the actual DOM element if available.
After that, elementRef.current can be read again.
For lit-html v1, you can define your own custom Derivative:
import { html, render, directive } from "lit-html";
function createRef(){ return {value: null}; }
const ref = directive((refObj) => (attributePart) => {
refObj.value = attributePart.committer.element;
});
const inputRef = createRef();
render(html`<input ref=${ref(inputRef)} />`;
// inputRef.value is a reference to rendered HTMLInputElement

Resources