-
Notifications
You must be signed in to change notification settings - Fork 2
Meesterproef WEEK 07
🕛 27-05-2024 t/m 31-05-2024
| Dag | Taken | reflectie |
|---|---|---|
| MAANDAG 27/05 | ||
| DINSDAG 28/05 | ||
| WOENSDAG 29/05 | ||
| DONDERDAG 30/04 | ||
| VRIJDAG 31/04 |
In dit artikel beschrijf ik hoe ik herbruikbare knopcomponenten in SvelteKit heb gemaakt. We beginnen met de basisstructuur en bouwen stap voor stap verder door verschillende soorten knoppen toe te voegen, zoals primaire en secundaire knoppen, inclusief hun styling en hover-effecten.
Voordat ik begon met het implementeren van de knopcomponenten in SvelteKit, heb ik eerst de verschillende soorten knoppen en hun bijbehorende stijlen in een aparte omgeving zoals CodePen voorbereid. Dit gaf me een duidelijk beeld van welke eigenschappen en stijlen ik nodig had en maakte de implementatie eenvoudiger. Ik gebruik in dit voorbeeld twee knoppen: de secundaire en de primaire knop.
Laten we beginnen met het maken van de basisstructuur van onze knopcomponent. Hier definiëren we de eigenschappen die de knop kan hebben. Het is handig om vooraf de volgende vragen te beantwoorden en op te schrijven:
- Welke soorten knoppen wil ik ondersteunen?
- Moet de knop als een link () of als een button () worden weergegeven?
- Welke varianten (bijv. primaire, secundaire) wil ik ondersteunen?
- Welke aanpassingen moeten mogelijk zijn?
- Moet de knop verschillende groottes hebben?
- Welke stijlopties (kleur, achtergrondkleur) wil ik kunnen instellen?
- Welke functionaliteiten zijn nodig?
- Moet de knop disabled kunnen zijn?
- Welke evenementen (bijv. onClick) moeten ondersteund worden? Met deze vragen in gedachten, heb ik de volgende eigenschappen gedefinieerd in mijn script:
In mijn oude aanpak worden alle mogelijke props in de script-sectie gedefinieerd. Dit omvat zowel HTML-gerelateerde props als stijlgerelateerde props.
<script>
export let className = '';
export let styles = '';
export let size = 'default';
export let type = 'button';
export let href = undefined;
export let disabled = false;
export let backgroundColor = '';
export let color = '';
export let icon = '';
export let title = '';
export let variant = '';
export let onHover = 'false';
export let ariaLabel = '';
function classNames(...classes) {
return classes.filter(Boolean).join(' ');
}
$: className = classNames(
styles,
'btn',
`btn-${size}`,
`btn-${variant}`,
disabled ? 'disabled' : ''
);
</script>
<script>
// HTML props
export let type = 'button';
export let href = '';
export let icon = '';
export let title = '';
export let ariaLabel = '';
export let btnDisabled = 'false'; // Gebruik een string om true/false door te geven via CSS
// Styling props
export let backgroundColor = '';
export let color = '';
export let border = '';
export let boxShadow = '';
export let hoverBorder = '';
export let focusBorder = '';
export let hoverBoxShadow = '';
export let focusBoxShadow = '';
export let btnSize = 'default';
</script>
<style>
.btn {
display: inline-flex;
align-items: center;
vertical-align: middle;
justify-content: center;
gap: 0.5rem;
cursor: pointer;
border-radius: 50em;
text-align: center;
text-decoration: none;
letter-spacing: 1px;
line-height: 1;
outline: none;
border: 0;
transition: box-shadow 0.2s, transform 0.3s;
background-color: var(--bgc);
color: var(--clr);
border: var(--border);
font-size: calc(var(--scale, 1) * 1rem);
padding: var(--btn-padding, 0.5em 1.25em);
box-shadow: var(--box-shadow, 0px 2px 3px 0px rgba(0, 0, 0, 0.25));
}
.btn-icon {
display: flex;
align-items: center;
transition: transform 0.3s ease;
}
.btn:hover .btn-icon {
transform: translateX(5px);
}
.btn:disabled,
.btn[aria-disabled='true'] {
cursor: not-allowed;
opacity: 0.5;
}
.btn:hover {
border: var(--hover-border);
box-shadow: var(--hover-box-shadow);
}
.btn:focus {
border: var(--focus-border);
box-shadow: var(--focus-box-shadow);
transform: scale(1.1);
}
.btn[style*='--btn-size: xs;'] {
--scale: 0.75;
--btn-padding: 0.25em 0.75em;
}
.btn[style*='--btn-size: sm;'] {
--scale: 0.875;
--btn-padding: 0.375em 1em;
}
.btn[style*='--btn-size: lg;'] {
--scale: 1.25;
--btn-padding: 0.75em 1.5em;
}
.btn[style*='--btn-size: xl;'] {
--scale: 1.5;
--btn-padding: 1em 2em;
}
</style>
In de nieuwe benadering definieer ik een PrimaryButton component die gebruik maakt van de BaseButton component en de styling via CSS-variabelen doorgeeft.
<script>
import { BaseButton, ArrowRight } from '$lib/index';
export let disabled = false;
export let type = 'button';
export let title = 'button';
export let size = 'default';
export let href = '';
export let ariaLabel = '';
</script>
<BaseButton
{type}
{href}
{title}
icon={ArrowRight}
{ariaLabel}
backgroundColor="var(--btn-primary-bg)"
color="var(--btn-primary-text-clr)"
border="none"
hoverBorder="1.5px solid var(--btn-primary-bg)"
focusBorder="1.5px solid var(--btn-primary-bg)"
boxShadow="0px 2px 3px 0px rgba(0, 0, 0, 0.25)"
hoverBoxShadow="0 0 rgba(0, 0, 0, 0)"
focusBoxShadow="0 0 rgba(0, 0, 0, 0)"
style="--btn-size: {size}; --btn-disabled: {disabled ? 'true' : 'false'}"
on:click
/>
Ik heb natuurlijk meerderen Primary buttons, dus hierna ga ik kijken wat ik wil meesturen in het component waar PrimaryButton. geimporteerd wordt: Bijvoorbeeld hieronder heb ik de Primary button in het Hero.svelte component geimporteerd
import { PrimaryButton, ArrowRight } from '$lib/index'
<PrimaryButton title="Book a Walk" icon={ArrowRight} size="lg" type="button" on:click />