(an alternative for) Creating dynamic CSS in a STYLE element per Svelte component - custom-element

I am learning Svelte by converting my existing (proof concept) Chess Custom Element/WebComponent.
One objective is to highlight the squares a dragging Chesspiece can move to
In my Custom Element it is fairly easy with a Stylesheet (inside Board shadowDOM !!! )
<style id="moveFromSquare"></style>
Then a mousenter on a square creates the CSS with the correct squarename
(for screenshot: local variables at='D5' and piece='black-knight')
let squareMouseEnter = () => {
[boardcustomelement].root.querySelector('moveFromSquare').innerHTML=
piece
? `div[at= "{at}" ]{
box-shadow: inset 0 0 var(--boxshadow-size) var(--boxshadow-color);
}
div[defenders*= "{at}" ]{
font-weight:bold;
color:green;
box-shadow: inset 0 0 var(--boxshadow-size) var(--boxshadow-color);
}`
: ''
}
No need for looping over previous squares to clean classnames,
No need for looping over squares again to set classnames
But I am learning Svelte...
Everything is a Svelte object: Board, Square, Piece (inside Square)
There can be multiple Boards on a page,
since there is no shadowDOM, to apply my CSS approach:
I need to get the svelte-xxxxx className for one Board (what is the easier way?)
then create a (global) <STYLE> element for every board using the svelte-xxxxx className everywere required
But I wonder if there is a more (reactive) Svelte way of creating this?

What I got (for now) is creating the dynamic CSS in a (Svelte) DIV (Childnode of the Board)
than transferring it to the Components STYLE element:
<script>
import {afterUpdate} from 'svelte';
let DynamicStyleDIV;
let parentClass;
let square='D3';//todo handle dynamic update
let CSS = x => `{${x}}`;
afterUpdate(()=>{
parentClass = DynamicStyleDIV.parentNode.className;
let selector = DynamicStyleDIV.className+'-style';
setTimeout(() => document.getElementById(selector).innerHTML = DynamicStyleDIV.innerHTML);
})
</script>
<div bind:this={DynamicStyleDIV} hidden>
.{parentClass} div[at="{square}"][at="{square}"]{CSS('background:gold')}
</div>
<style>
div{/*required because an empty style element is ignored*/}
</style>
But this only works in the Svelte REPL
Where styles are <style> elements in the document, and not rules in bundle.css

Related

Change background color of ion-page element only, not descendent elements, in Ionic Vue

I have an Ionic Vue3 app. I'd like to change the background color of the whole page. I'm new to Ionic but I believe the way this has to be done (due to the use of Web Components/Shadow DOM) is to modify the --ion-background-color CSS custom property rather than trying to set the value of the normal CSS property, so this works:
.ion-page {
--ion-background-color: red;
}
...but this doesn't:
.ion-page {
background-color: red;
}
Fine, so I do the former, but the problem now is that all elements within the page (everything inside the <ion-page></ion-page> element which use that same custom property value now inherit the same background color.
Does anyone know how to scope the change of background colour of the ion-page element such that it doesn't cascade through descendent elements? Thanks :)
The solution here was to use local CSS custom property --background rather than the global property --ion-background-color. So the following works:
.ion-page {
--background: red;
}
I didn't previously realise there were different sets of CSS variables for different scopes.

How to provide style for slots inside the template in sap Spartacus

I have a new template LandingPage3Template.
layoutSlots: {
LandingPage3Template: {
pageFold: 'Section2B',
slots: [
'Section2A',
'Section2B',
'Section2C',
'Section1',
'Section3',
'Section4',
'Section5'
],
}
}
I just wanted to give styles for the slots. Can someone help me to write a custom CSS style to align it properly?
I am using the below-mentioned code but it is not working.
%cx-page-layout {
// my code here
width: 10%;
}
thanks for asking at our SO channel.
The CMS page template name (i.e. "LandingPage3Template") and slots positions (i.e. "Section2A") are mapped to CSS classes in the Spartacus DOM. This means, that you can use pure CSS rules to create the layout.
Page slot position names are not necessarily unique cross all pages (i.e. "Section2A" might also be used in other page templates). But since page slots are nested inside the page template, you can create css rules for page slots that are used inside a given page template.
The following CSS rule shows how you can create a rule for "Section2A" inside "LandingPage3Template".
.LandingPage3Template .Section2A {
width: 10%;
}
While this is valid css and scss syntax, in scss it would look like:
.LandingPage3Template {
.Section2A {
width: 10%;
}
}
Please note that the percentage before a selector (i.e. %cx-page-layout) refers to a so-called placeholder selector. This is used in Spartacus for optional CSS, so that only when the placeholder selectors are used, the CSS ends up in the final CSS. You can read more about the CSS setup in Spartacus at https://sap.github.io/spartacus-docs/css-architecture/.

How to customize the backgorund-color of cancel-button in b-modal?

I need to change the background-colour of the cancel-button with rgb. The only half-way up to now is changing the cancel-variant to e.g danger. However, I need to choose the specific, rgb colour. Does anyone know a solution to my problem?
Thank you
<b-modal v-bind:id="'delete-modal-' + id" cancel-variant=info ok-variant=danger ok-title="delete" cancel-title="back" #ok="deleteModal" title="Caution">
<p class="my-4">Are you sure?</p>
</b-modal>
If you're using SASS you can easily add new variants to your project by adding them to the $theme-colors map.
These will automatically become available to use with bootstrap-vue everywhere you can use a variant.
custom.scss
$theme-colors: (
"cancel": rgb(139, 80, 80)
);
#import 'node_modules/bootstrap/scss/bootstrap';
#import 'node_modules/bootstrap-vue/src/index.scss';
Then import custom.scss in your apps entry point.
If you want a simple CSS solution, the cancel-variant property just adds the class btn-* where * is the string you provide.
Which means you can add the css below to your global stylesheet, to add a new variant (however, doing it this way you'll have to write all the :hover, :active stuff yourself)
.btn-cancel {
color: #fff;
background-color: rgb(213, 213, 213);
border-color: rgb(213, 213, 213);
}
After adding one of the options above you will now have the option to do <b-modal cancel-variant="cancel"></b-modal> to utilize your new variant.

VUEJS Set autofocus to ALL user inputs when component is created

I need to focus all the form user inputs onCreate(), so to make clear to the user that he can edit the fields if he needs to.
The closer thing I found is something like:
<input ref="email" />
const input = this.$refs.email
methods: {
focusInput() {
this.$refs.email.focus();
}
That should work, but I was looking for a better way to do it, without applying the ref attribute to every single input.
Is there a way to wrap them all at once?
I tried attaching the ref to the form <b-form ref="focusInputs">, then, in the method, access the inputs through it
focusInputs() {
this.$refs.focusInputs.input.focus();
}
and call it in created:
created(){
this.focusInputs()
}
But in the console I got:
Error in created hook: "TypeError: Cannot read property 'input' of undefined"
I think that's because I am using bootstrap-vue, so the input tags are <b-form> and <b-form-input> (instead of just <form> and <input>). CSS and Javascript, as far as I know, are not able to access these tags as the can with form or input.
So, do you think is there still a way to wrap them all, or do I need to mark them singularly (either with a class or with ref).
Anyone know?
Thank you,
x
You can create a css class that will apply the bootstrap textbox highlight color to any textboxes you want. The below CSS should do the trick. You can find this CSS in the bootstrap files, I just changed the name and removed the focus requirement.
You cannot however actually "Focus" multiple fields since focus is where the input cursor is set. You can only auto focus one field at a time.
.fillable{
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
}

Ionic 2 - Property Binding to make app invisible

I'm a bit of a noob to ionic so this may be a dumb question.
On the press of a button I want to overlay my entire app with a black image (or make everything invisible) but still have the buttons working underneath.
My app is based on the tab sample app.
So far I've tried the following
app.scss
.dark-overlay {
background-color: #000 !important;
opacity: 1;
}
my-tab.html
<ion-content class="dark-overlay" (ng-hide)="showOverlay">
....
<div tappable (click)="stealthMode()"><img src="assets/img/stealthMode.png" width="100%" scroll="false"></div>
my-tab.ts
stealthMode () {
this.myElements = document.querySelectorAll("dark-overlay");
for (var i = 0; i < myElements.length; i++) {
myElements[i].style.opacity = 0;
}
}
Even if i can get this to work it's not going to be the final answer as setting the opacity in app.scss to 0 still leaves the tabbar visible but I need that to go black too.
I think it's related to property binding.
Any ideas?
Thanks
you need to use pointer-events to let events go through your dark overlay.
I have demonstrated that in this Plunkr (go to second tab which shows home page)
style.css
.dark-overlay{
position:absolute;
width:100%;
height:100%;
background-color:#888;
opacity:0.9;
top:0px;
left:0px;
z-index:1000;
pointer-events: none;
}
and have this in home.html
<button (click)="stealthMode()">Tint</button>
<div class="dark-overlay" [hidden]="showOverlay"></div>
and this in home.ts
showOverlay:boolean = false;
stealthMode(){
this.showOverlay = !this.showOverlay;
}
You can make a binding to render that part dynamically using angular directives.
Check this for clean implementation:
ngIF