Svelte custom button component or style with css - button

I'm very new to Svelte and I want to build a theme for a website.
When I want buttons to have a certain look and animations, do I create a new Button component and use that every time with slots or do I just create a class for this button that has some css code and use the standard html button?
Of course I can do it both ways, but which one is preferred in svelte?

You could use this strategy for theming your application. You can use $$restProps to capture your classes and in your components, you can also set up the events for the buttons.
App.svelte
<script>
import Button from "./Button.svelte"
</script>
<Button class="primary">
My Button
</Button>
<Button class="danger">
My Button
</Button>
Button.svelte
<script>
let buttonProps = {
class:[$$restProps.class]
}
</script>
<button on:click
on:mouseover
on:mouseenter
on:mouseleave
{...buttonProps}>
<slot/>
</button>
<style>
.primary{
color:green;
}
.danger {
color:red;
}
</style>
Example REPL. Components are the right way to go for build large applications.

Related

How to conditionally render component with async call in svelte and avoid extra calls?

I have a svelte component that can be toggled on or off and that fetches some async data. This async call is slow so I want to avoid making it, and only want to make the call when the component is visible (toggled on).
I want to know if there is a way to render this component once, then re-render only if the async call changes and not when toggling on or off? I almost want to "cache" the component.
I have tried two approaches that both work but have downsides.
See this REPL for full working example of both approaches: https://svelte.dev/repl/397fdf11988c4d4fbb98d375adfc8539?version=3
Both of these approaches use this component to display the result:
<!-- DisplayResult.svelte -->
<script lang="ts">
export let getResultFn;
$: colorPromise = getResultFn();
</script>
{#await colorPromise}
Loading...
{:then color}
The color is {color}
{/await}
Approach 1: Render component then hide
The first is to always render the component and then hide it when not active. The downside to this is that when the async call changes, it is immediately called which is expensive. I would rather only make this call initially when the component is visible (the toggle is used many times so I only want to get new data for open toggles). Furthermore, I cant use transitions here since the component is never re-rendered
<!-- Item.svelte -->
<button on:click={() => { active = !active;}} >
Toggle
</button>
<div
transition:slide
class:hidden={!active}
>
<DisplayResult getResultFn={() => getResults(idx)} />
</div>
<style>
.hidden {
display: none;
}
</style>
Approach 2: Conditionally toggle
The other option is to create the component when visible, then destory when hidden. The good part is this only gets the data when the component is visible but then it makes extra calls every time the component is subsequently toggled. I can also use transitions here which is nice
<!-- Item.svelte -->
<button on:click={() => { active = !active;}} >
Toggle
</button>
{#if active}
<div transition:slide >
<DisplayResult getResultFn={() => getResults(idx)} />
</div>
{/if}
Best of both?
Is there a way to get the best of both worlds and
Only get data initially when component is actually visible so can lazily fetch (like Approach 2)
But then cache call and do not re-render every time (like Approach 1)
re-render only if the async call changes
In your example colors are refetched every time idx changes. Is this neccessary because the color values might change in the db in the meantime?
Assuming that not and that it's ok to load the data once, this could be moved to a seperate file. So the data will persist when the component isn't rendered
REPL
colors.js
export let colors = null
export async function initColors() {
if(!colors) {
await new Promise(f => setTimeout(f, 2000));
colors = ['red', 'yellow', 'blue'];
}
}
DisplayResult.svelte
<script>
import {colors, initColors} from './colors'
export let idx
</script>
{#await initColors()}
Loading...
{:then _}
The color is {colors[idx]}
{/await}
Item.svelte
<script>
import DisplayResult from './DisplayResult.svelte'
import {slide} from "svelte/transition"
export let idx
let active
</script>
<div class="item">
<button on:click={() => { active = !active;}} >
{active ? 'Close' : 'Open'}
</button>
{#if active}
<div transition:slide >
<DisplayResult {idx} />
</div>
{/if}
</div>
<style>
.item {
border: 1px solid black;
padding: 5px;
margin: 5px
}
</style>

How to put Bulma Buttons CSS for the React Components?

The following component is part of To Do List Application. I would like to create four Filter Buttons (All, Active, Completed, Important). May I please ask how to place Bulma CSS Rules for this react component?
Screenshot 1 -
Filter Buttons Component
import React from "react";
function FilterButton(props){
return (
<button
type="button"
className="buttons"
onClick={()=>props.setFilter(props.name)}
>
<span className="visually-hidden">Show</span>
<span>{props.name}</span>
<span className="visually-hidden">tasks</span>
</button>
);
}
export default FilterButton;
You can use button component like this.
<button
className={`button is-${props.name}`}
onClick={()=>props.setFilter(props.name)}
>

Modify style of 'Pay with Card' Stripe button

Is it possible to modify style of "Pay with Card" Stripe button? I've tried modifying by,
adding a new class defined in external style sheet
modifying its own class of stripe-button in external style sheet
and editing it inline with style=""
But I cannot get the button to change its style.
It looks like it might be possible with the custom integration instead of the simple integration (source: https://stripe.com/docs/checkout#integration-simple), but I was hoping there was something simpler.
Button with default style:
Does anyone have experience with this?
(I'm integrating into Ruby on Rails if that makes any difference.)
None of those worked for me. I ended up hiding the button in javascript and making a new one.
<form action="/your-server-side-code" method="POST">
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="xxx"
data-amount="999"
data-name="zzz"
data-locale="auto">
</script>
<script>
// Hide default stripe button, be careful there if you
// have more than 1 button of that class
document.getElementsByClassName("stripe-button-el")[0].style.display = 'none';
</script>
<button type="submit" class="yourCustomClass">Buy my things</button>
</form>
Search for this class:
.stripe-button-el span
I think this is where you have to modify your own button's style.
You may overwrite it within your own external css file.
Although a little hacky, for anyone wanting a super quick and simple way of using a different button along with the "simple integration", especially if you don't have "solid JavaScript skills", you can just hide the Stripe button with;
.stripe-button-el { display: none }
This way, any submit button within the form will call the checkout so you can just use the button you already had before introducing Stripe.
The following will override the background color with the custom color #EB649C. Disabling the background-image is required, as well as styling both the button and it's inside span tag.
button.stripe-button-el,
button.stripe-button-el>span {
background-color: #EB649C !important;
background-image: none;
}
You should use data-label its part of the regular stripe Checkout API:
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="<%= ENV.fetch('STRIPE_PUBLISHABLE_KEY') %>"
data-amount="10000"
data-label="Proceed to Pay with Card"
...
...
data-locale="auto">
</script>
Using jQuery, you can also simply scale the button like this:
<script>
$(function() {
$(".stripe-button-el").css({'transform': 'scale(2)'});
});
</script>
Or replace it by a button with any image you want, like this:
<script>
$(function() {
$(".stripe-button-el").replaceWith('<button type="submit" class="pay"><img src="/assets/paywithcard.jpg"></button>');
});
</script>
You can remove the button styles with Jquery and add your own. Worked a charm for me:
<script type="text/javascript">
$(document).ready(function(){
$(".stripe-button-el span").remove();
$("button.stripe-button-el").removeAttr('style').css({
"display":"inline-block",
"width":"100%",
"padding":"15px",
"background":"#3fb0ac",
"color":"white",
"font-size":"1.3em" }).html("Sign Me Up!");
});
</script>
The .stripe-button-el span actually works.
But you need to add !important in CSS to overwrite the default CSS.
You can try this,
$(".stripe-button-el").find("span").remove();
$(".stripe-button-el").html("Proceed to pay");
Pay with card is inside a span.
For those of you who want to change the background color of the button, make sure you do something like
.stripe-button-el span {
background: #5e366a !important;
background-image:none !important;
background-color: #5e366a !important;
}
in your css file. this will change the actual background of the button fr you. If you wish to have the parent div changed, you can do the same thing without the span or do a direct inline style.

Import classes hover state to other classes in .LESS

Just learning .less and using twitters bootstrap in my project.
If i whant an green button for an form to submit i have to write:
<input type="submit" value="submit" class="btn btn-success" />
But i will be able to skip the class attribute in the input tag.
I will not change the twitter bootstrap file. I will overload them in my default.less file like this:
button, input[type="submit"]{ .btn; .btn-success; }
But then I do not get the hover state and active state to the button and i get errors if i try to make it like this:
button, input[type="submit"]{/* previus code... */ &:hover{ .btn:hover; }}
You may notice what i trying to accomplish. I know I can do this in jquery or javascript but i will be able to do this in my .less-file whitout touching orginal bootsrap-files.
I'm not sure that that is possible without modifying the Bootstrap CSS.
Are you able to modify the bootstrap CSS at all? If so, you could add a .btn-hover class to .btn:hover, and then in button, input[type="submit"]:
&:hover {
.btn-hover;
.btn-success-hover;
}
.btn and .btn-success are classes. These classes are define in buttons.less. They call mixin from mixins.less called .buttonBackground. You can call this mixin for your buttons:
button, input[type="submit"]{
.buttonBackground(#startColor,#endColor);
}
#startColor and #endColor are for button gradient and the hover state uses the #endColor.
Or you can change colour in variables.less (btnInfoBackgroundHighlight) to your own.
Or you can use
.btn-success{
&:hover{
background-color: #yourOwnColor;
}
}

How to create button without icon in CKEditor

When I create toolbar button in CKEditor 3.0 with following code I need to uncomment icon property to get button visible. Otherwise space is occupied but no label is shown. When I hover over it I get caption popping up.
editor.ui.addButton('customButton', {
label: 'Custom Action',
//icon: this.path + 'images/anchor.gif',
command: commandName
});
Do you know how to create toolbar button without icon? Just a pure text.
An easier way is that CKEditor creates a CSS class on your custom label automatically called:
cke_button_<command>
For example, if your command for the button was called 'myCommand', and you set 'label: 'My Command', then CK would render something like:
<a id="cke_27" class="cke_off cke_button_myCommand" ....>
...
<span id="cke_27_label" class="cke_label">My Command</span>
</a>
Therefore (assuming you are using the 'kama' skin - substitute for your skin if not), you can use the following CSS to override the cke_label ==> display:none
.cke_skin_kama .cke_button_myCommand .cke_label {
display: inline;
}
Voila.
This is how I did it. A button looks like this:
<span class="cke_button">
<a id="cke_..." class="cke_off cke_button_cmd" ...>
<span class="cke_icon"/>
<span class="cke_label">Label</span>
</a>
</span>
.cke_label is styled "display:none" by default. This would do exactly what we want:
<span style="display:none;" class="cke_icon"/>
<span style="display:inline;" class="cke_label">Label</span>
So the selectors are a bit tricky, put this in the Style Tag on the page with the editor:
<style type="text/css">
.cke_skin_kama .cke_button_CMDNAMEHERE span.cke_icon{display:none !important;}
.cke_skin_kama .cke_button_CMDNAMEHERE span.cke_label{display:inline;}
</style>
The ckeditor authors applied css to get the label on the source button (presets.css):
/* "Source" button label */
.cke_skin_kama .cke_button_source .cke_label
{
display: inline;
}

Resources