mirror of
https://github.com/Lapikud/lapikud.github.io.git
synced 2026-08-08 19:59:14 +00:00
about us section ready
This commit is contained in:
14
src/app.css
14
src/app.css
@@ -51,7 +51,7 @@
|
|||||||
--fs-md: 1rem;
|
--fs-md: 1rem;
|
||||||
--fs-lg: 1.125rem;
|
--fs-lg: 1.125rem;
|
||||||
--fs-xl: 1.5rem;
|
--fs-xl: 1.5rem;
|
||||||
--line-height: 1.45;
|
--line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Global box sizing & accessible defaults */
|
/* Global box sizing & accessible defaults */
|
||||||
@@ -92,19 +92,7 @@ button,
|
|||||||
input[type="button"],
|
input[type="button"],
|
||||||
input[type="submit"] {
|
input[type="submit"] {
|
||||||
font: inherit;
|
font: inherit;
|
||||||
border: 1px solid var(--color-border); /* TODO: fix css magic (we need the border, but the variable doesnt exist, but you cant remove it either) */
|
|
||||||
padding: 0.5em 0.9em;
|
|
||||||
border-radius: var(--radius-sm);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: box-shadow 120ms ease, transform 120ms ease,
|
|
||||||
border-color 120ms ease;
|
|
||||||
}
|
|
||||||
button:active {
|
|
||||||
transform: translateY(1px);
|
|
||||||
}
|
|
||||||
button:focus {
|
|
||||||
outline: 3px solid color-mix(in srgb, var(--color-primary) 14%, transparent); /* TODO: change same magic here */
|
|
||||||
outline-offset: 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Utility: visually hidden (accessible labels) */
|
/* Utility: visually hidden (accessible labels) */
|
||||||
|
|||||||
@@ -1,10 +1,32 @@
|
|||||||
<script>
|
<script>
|
||||||
export let onClick = () => {};
|
let {
|
||||||
|
onClick = () => {},
|
||||||
|
class: className = "",
|
||||||
|
children,
|
||||||
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
on:click={onClick}
|
onclick={onClick}
|
||||||
class="btn border-[1.5px] px-5 py-2.5 font-medium cursor-pointer flex items-center gap-2 whitespace-nowrap {$$props.class ?? ''}"
|
data-animation
|
||||||
|
class="btn flex p-2.5 {className}"
|
||||||
>
|
>
|
||||||
<slot />
|
{@render children?.()}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.btn {
|
||||||
|
border-width: 2px;
|
||||||
|
border-style: solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
cursor: pointer;
|
||||||
|
align-items: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: color 200ms ease, background-color 200ms ease,
|
||||||
|
border-color 200ms ease, transform 120ms ease, box-shadow 200ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:active {
|
||||||
|
transform: translateY(1px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
<script>
|
<script>
|
||||||
import Button from "./Button.svelte";
|
import Button from "./Button.svelte";
|
||||||
|
|
||||||
export let name = "";
|
let {
|
||||||
export let buttonClass = "";
|
name = "",
|
||||||
export let panelClassName = "";
|
buttonClass = "",
|
||||||
|
panelClass = "",
|
||||||
|
children,
|
||||||
|
} = $props();
|
||||||
|
|
||||||
let isOpen = false;
|
let isOpen = $state(false);
|
||||||
|
|
||||||
const toggle = () => (isOpen = !isOpen);
|
const toggle = () => (isOpen = !isOpen);
|
||||||
const close = () => (isOpen = false);
|
const close = () => (isOpen = false);
|
||||||
@@ -20,7 +23,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="relative inline-block" on:focusout={handleFocusOut}>
|
<div class="relative inline-block" onfocusout={handleFocusOut}>
|
||||||
<Button onClick={toggle} class={`${buttonClass} gap-0`}>
|
<Button onClick={toggle} class={`${buttonClass} gap-0`}>
|
||||||
{name}
|
{name}
|
||||||
<svg
|
<svg
|
||||||
@@ -41,11 +44,11 @@
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="{panelClassName} absolute mt-2 rounded-md shadow-lg overflow-visible flex flex-col"
|
class="{panelClass} absolute mt-2 rounded-md shadow-lg overflow-visible flex flex-col"
|
||||||
style:visibility={isOpen ? "visible" : "hidden"}
|
style:visibility={isOpen ? "visible" : "hidden"}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<slot />
|
{@render children?.()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ hover effects, size variants, and object-fit options. Includes support for WebP
|
|||||||
export let rel = "noopener noreferrer";
|
export let rel = "noopener noreferrer";
|
||||||
export let objectFit = "contain"; // 'contain' | 'cover' | 'fill' | 'none' | 'scale-down'
|
export let objectFit = "contain"; // 'contain' | 'cover' | 'fill' | 'none' | 'scale-down'
|
||||||
export let hover = false;
|
export let hover = false;
|
||||||
export let className = "";
|
|
||||||
|
|
||||||
// optional srcset for responsive images (w descriptors means width-based, x descriptors means pixel density-based)
|
// optional srcset for responsive images (w descriptors means width-based, x descriptors means pixel density-based)
|
||||||
// e.g. "image-400.jpg 400w, image-800.jpg 800w"
|
// e.g. "image-400.jpg 400w, image-800.jpg 800w"
|
||||||
@@ -41,7 +40,7 @@ hover effects, size variants, and object-fit options. Includes support for WebP
|
|||||||
{src}
|
{src}
|
||||||
srcset={srcSet || undefined}
|
srcset={srcSet || undefined}
|
||||||
alt={alt}
|
alt={alt}
|
||||||
class="block h-auto max-w-full {objectFitClass} {hoverClasses} {className}"
|
class="block h-auto max-w-full {objectFitClass} {hoverClasses} {$$props.class ?? ''}"
|
||||||
/>
|
/>
|
||||||
</picture>
|
</picture>
|
||||||
</a>
|
</a>
|
||||||
@@ -54,7 +53,7 @@ hover effects, size variants, and object-fit options. Includes support for WebP
|
|||||||
{src}
|
{src}
|
||||||
srcset={srcSet || undefined}
|
srcset={srcSet || undefined}
|
||||||
alt={alt}
|
alt={alt}
|
||||||
class="block h-auto max-w-full {objectFitClass} {hoverClasses} {className}"
|
class="block h-auto max-w-full {objectFitClass} {hoverClasses} {$$props.class ?? ''}"
|
||||||
/>
|
/>
|
||||||
</picture>
|
</picture>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,5 +1,20 @@
|
|||||||
<script>
|
<script>
|
||||||
import { onDestroy } from 'svelte';
|
import { onDestroy } from 'svelte';
|
||||||
|
import Image from './Image.svelte';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Images can be either strings or objects with optimization options:
|
||||||
|
*
|
||||||
|
* String format (simple):
|
||||||
|
* images={["image1.jpg", "image2.jpg"]}
|
||||||
|
*
|
||||||
|
* Object format (multiple image options):
|
||||||
|
* images={[
|
||||||
|
* { src: "image1.jpg", webpSrc: "image1.webp", alt: "Description" },
|
||||||
|
* { src: "image2.jpg", webpSrc: "image2.webp", alt: "Description" }
|
||||||
|
* ]}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
export let images = [];
|
export let images = [];
|
||||||
export let width = '100%';
|
export let width = '100%';
|
||||||
@@ -16,6 +31,15 @@
|
|||||||
let current = startIndex;
|
let current = startIndex;
|
||||||
let timer;
|
let timer;
|
||||||
|
|
||||||
|
$: currentImage = images[current];
|
||||||
|
$: isObjectImage = typeof currentImage === 'object' && currentImage !== null;
|
||||||
|
$: imageSrc = typeof currentImage === 'string' ? currentImage : currentImage?.src || '';
|
||||||
|
$: imageAlt = typeof currentImage === 'string' ? '' : currentImage?.alt || '';
|
||||||
|
$: imageWebpSrc = isObjectImage ? currentImage?.webpSrc || '' : '';
|
||||||
|
$: imageSrcSet = isObjectImage ? currentImage?.srcSet || '' : '';
|
||||||
|
$: imageWebpSrcSet = isObjectImage ? currentImage?.webpSrcSet || '' : '';
|
||||||
|
$: imageClass = isObjectImage ? currentImage?.class || '' : '';
|
||||||
|
|
||||||
const next = () => {
|
const next = () => {
|
||||||
if (current < images.length - 1) {
|
if (current < images.length - 1) {
|
||||||
current += 1;
|
current += 1;
|
||||||
@@ -51,10 +75,14 @@
|
|||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
>
|
>
|
||||||
{#if images.length}
|
{#if images.length}
|
||||||
<img
|
<Image
|
||||||
src={typeof images[current] === 'string' ? images[current] : images[current].src}
|
src={imageSrc}
|
||||||
alt={typeof images[current] === 'string' ? '' : images[current].alt || ''}
|
alt={imageAlt}
|
||||||
class="slide"
|
webpSrc={imageWebpSrc}
|
||||||
|
srcSet={imageSrcSet}
|
||||||
|
webpSrcSet={imageWebpSrcSet}
|
||||||
|
objectFit="cover"
|
||||||
|
class={`w-full h-full block ${imageClass}`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{#if interactive && images.length > 1}
|
{#if interactive && images.length > 1}
|
||||||
@@ -82,13 +110,6 @@
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slide {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* interactive controls */
|
/* interactive controls */
|
||||||
.prev,
|
.prev,
|
||||||
.next {
|
.next {
|
||||||
|
|||||||
@@ -4,17 +4,16 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
export let type;
|
export let type;
|
||||||
export let className = "";
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if type === "connector"}
|
{#if type === "connector"}
|
||||||
<svg viewBox="0 0 182 66" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 182 66" class={$$props.class ?? ''} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M0 63.5H67.5L102.5 15.5H156" stroke="currentColor" stroke-width="5"/>
|
<path d="M0 63.5H67.5L102.5 15.5H156" stroke="currentColor" stroke-width="5"/>
|
||||||
<circle cx="166" cy="15.5" r="10" stroke="currentColor" stroke-width="5"/>
|
<circle cx="166" cy="15.5" r="10" stroke="currentColor" stroke-width="5"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
{:else if type === "mirrorV"}
|
{:else if type === "mirrorV"}
|
||||||
<svg viewBox="0 0 182 66" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 182 66" class={$$props.class ?? ''} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<g transform="scale(1,-1) translate(0,-66)">
|
<g transform="scale(1,-1) translate(0,-66)">
|
||||||
<path d="M0 63.5H67.5L102.5 15.5H156" stroke="currentColor" stroke-width="5"/>
|
<path d="M0 63.5H67.5L102.5 15.5H156" stroke="currentColor" stroke-width="5"/>
|
||||||
<circle cx="166" cy="15.5" r="10" stroke="currentColor" stroke-width="5"/>
|
<circle cx="166" cy="15.5" r="10" stroke="currentColor" stroke-width="5"/>
|
||||||
@@ -22,7 +21,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
{:else if type === "mirrorH"}
|
{:else if type === "mirrorH"}
|
||||||
<svg viewBox="0 0 182 66" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 182 66" class={$$props.class ?? ''} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<g transform="scale(-1,1) translate(-182,0)">
|
<g transform="scale(-1,1) translate(-182,0)">
|
||||||
<path d="M0 63.5H67.5L102.5 15.5H156" stroke="currentColor" stroke-width="5"/>
|
<path d="M0 63.5H67.5L102.5 15.5H156" stroke="currentColor" stroke-width="5"/>
|
||||||
<circle cx="166" cy="15.5" r="10" stroke="currentColor" stroke-width="5"/>
|
<circle cx="166" cy="15.5" r="10" stroke="currentColor" stroke-width="5"/>
|
||||||
@@ -30,7 +29,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
{:else if type === "mirrorVH"}
|
{:else if type === "mirrorVH"}
|
||||||
<svg viewBox="0 0 182 66" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 182 66" class={$$props.class ?? ''} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<g transform="scale(-1,-1) translate(-182,-66)">
|
<g transform="scale(-1,-1) translate(-182,-66)">
|
||||||
<path d="M0 63.5H67.5L102.5 15.5H156" stroke="currentColor" stroke-width="5"/>
|
<path d="M0 63.5H67.5L102.5 15.5H156" stroke="currentColor" stroke-width="5"/>
|
||||||
<circle cx="166" cy="15.5" r="10" stroke="currentColor" stroke-width="5"/>
|
<circle cx="166" cy="15.5" r="10" stroke="currentColor" stroke-width="5"/>
|
||||||
@@ -38,14 +37,14 @@
|
|||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
{:else if type === "branch"}
|
{:else if type === "branch"}
|
||||||
<svg viewBox="0 0 75 74" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 75 74" class={$$props.class ?? ''} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M0 31.4784H46L68 1.47842M45.5 30.9784L66.5 63.9784"
|
<path d="M0 31.4784H46L68 1.47842M45.5 30.9784L66.5 63.9784"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
stroke-width="5"/>
|
stroke-width="5"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
{:else if type === "branchH"}
|
{:else if type === "branchH"}
|
||||||
<svg viewBox="0 0 75 74" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 75 74" class={$$props.class ?? ''} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<g transform="scale(-1,1) translate(-75,0)">
|
<g transform="scale(-1,1) translate(-75,0)">
|
||||||
<path d="M0 31.4784H46L68 1.47842M45.5 30.9784L66.5 63.9784"
|
<path d="M0 31.4784H46L68 1.47842M45.5 30.9784L66.5 63.9784"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -54,19 +53,19 @@
|
|||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
{:else if type === "instagram"}
|
{:else if type === "instagram"}
|
||||||
<svg class="w-8 h-8 {className}" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
<svg class="w-8 h-8 {$$props.class ?? ''}" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
|
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
{:else if type === "facebook"}
|
{:else if type === "facebook"}
|
||||||
|
|
||||||
<svg class="w-8 h-8 {className}" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
<svg class="w-8 h-8 {$$props.class ?? ''}" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
|
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
{:else if type === "github"}
|
{:else if type === "github"}
|
||||||
|
|
||||||
<svg class="w-8 h-8 {className}" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
<svg class="w-8 h-8 {$$props.class ?? ''}" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
<script>
|
<script>
|
||||||
export let href = "";
|
let {
|
||||||
export let variant = "default"; // 'default' | 'animated' | 'animated-neutral' | 'glass' | 'blur'
|
href = "",
|
||||||
export let className = "";
|
variant = "default", // 'default' | 'animated' | 'animated-neutral' | 'glass' | 'blur'
|
||||||
|
class: className = "",
|
||||||
|
children,
|
||||||
|
} = $props();
|
||||||
|
|
||||||
const variantClasses = {
|
const variantClasses = {
|
||||||
default: "card-default",
|
default: "card-default",
|
||||||
@@ -14,11 +17,11 @@
|
|||||||
|
|
||||||
{#if href}
|
{#if href}
|
||||||
<a {href} class={`card ${variantClasses[variant]} ${className}`}>
|
<a {href} class={`card ${variantClasses[variant]} ${className}`}>
|
||||||
<slot />
|
{@render children?.()}
|
||||||
</a>
|
</a>
|
||||||
{:else}
|
{:else}
|
||||||
<div class={`card ${variantClasses[variant]} ${className}`}>
|
<div class={`card ${variantClasses[variant]} ${className}`}>
|
||||||
<slot />
|
{@render children?.()}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
<script>
|
<script>
|
||||||
export let dir = "row"; // 'row' | 'col' (default: 'row')
|
let {
|
||||||
export let gap = "gap-4";
|
dir = "row", // 'row' | 'col' (default: 'row')
|
||||||
export let className = "";
|
gap = "gap-4",
|
||||||
|
class: className = "",
|
||||||
|
children,
|
||||||
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -12,5 +15,5 @@
|
|||||||
" " +
|
" " +
|
||||||
className}
|
className}
|
||||||
>
|
>
|
||||||
<slot />
|
{@render children?.()}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
<!--
|
<!--
|
||||||
A responsive container that centers content and optionally
|
A responsive container that centers content and optionally
|
||||||
removes the max-width when `fluid` is true. Use `className` to
|
removes the max-width when `fluid` is true. Use the `class`
|
||||||
add additional CSS classes to the root element. Content is
|
add additional CSS classes to the root element. Content is
|
||||||
projected via the default slot.
|
projected via the default slot.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export let maxWidth = false; // true removes max-width
|
let {
|
||||||
export let center = true; // false prevents centering and removes horizontal padding
|
maxWidth = false, // true removes max-width
|
||||||
export let className = "";
|
center = true, // false prevents centering and removes horizontal padding
|
||||||
|
class: className = "",
|
||||||
|
children,
|
||||||
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-full {center ? 'px-[var(--page-padding-inline)]' : ''} {maxWidth ? '' : 'max-w-[var(--page-max-width)]'} {center ? 'mx-auto' : ''} {className}">
|
<div class="w-full {center ? 'px-(--page-padding-inline)' : ''} {maxWidth ? '' : 'max-w-(--page-max-width)'} {center ? 'mx-auto' : ''} {className}">
|
||||||
<slot />
|
{@render children?.()}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
<script>
|
<script>
|
||||||
export let min = "220px"; // min column width (used when columns not set)
|
let {
|
||||||
export let columns = null; // fixed number of columns for desktop
|
min = "220px", // min column width (used when columns not set)
|
||||||
export let largeColumns = null; // fixed number of columns for large desktop
|
columns = null, // fixed number of columns for desktop
|
||||||
export let mobileColumns = null; // fixed number of columns for mobile
|
largeColumns = null, // fixed number of columns for large desktop
|
||||||
export let gap = "gap-3";
|
mobileColumns = null, // fixed number of columns for mobile
|
||||||
export let className = "";
|
gap = "gap-3",
|
||||||
|
class: className = "",
|
||||||
|
children,
|
||||||
|
} = $props();
|
||||||
|
|
||||||
$: desktopColumns = columns ? `repeat(${columns}, 1fr)` : '1fr';
|
const desktopColumns = $derived(columns ? `repeat(${columns}, 1fr)` : "1fr");
|
||||||
$: largeDesktopColumns = largeColumns ? `repeat(${largeColumns}, 1fr)` : desktopColumns;
|
const largeDesktopColumns = $derived(
|
||||||
$: mobileCols = mobileColumns ? `repeat(${mobileColumns}, 1fr)` : '1fr';
|
largeColumns ? `repeat(${largeColumns}, 1fr)` : desktopColumns
|
||||||
|
);
|
||||||
|
const mobileCols = $derived(mobileColumns ? `repeat(${mobileColumns}, 1fr)` : "1fr");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -21,7 +26,7 @@
|
|||||||
grid-template-columns: var(--mobile-columns);
|
grid-template-columns: var(--mobile-columns);
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<slot />
|
{@render children?.()}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
padding = "normal",
|
padding = "normal",
|
||||||
fullWidth = false,
|
fullWidth = false,
|
||||||
id = "",
|
id = "",
|
||||||
className = "",
|
class: className = "",
|
||||||
contentClassName = "",
|
contentClass = "",
|
||||||
children
|
children
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
class="relative w-full {bg} {className}"
|
class="relative w-full {bg} {className}"
|
||||||
style={background ? `background: ${background};` : undefined}
|
style={background ? `background: ${background};` : undefined}
|
||||||
>
|
>
|
||||||
<div class="w-full {fullWidth ? '' : 'max-w-(--page-max-width)'} mx-auto px-(--page-padding-inline) {paddingClasses[padding]} {contentClassName}">
|
<div class="w-full {fullWidth ? '' : 'max-w-(--page-max-width)'} mx-auto px-(--page-padding-inline) {paddingClasses[padding]} {contentClass}">
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -3,11 +3,14 @@ A simple stack/column layout that stacks children vertically.
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export let gap = "gap-3";
|
let {
|
||||||
export let align = "stretch";
|
gap = "gap-3",
|
||||||
export let className = "";
|
align = "stretch",
|
||||||
|
class: className = "",
|
||||||
|
children
|
||||||
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col {className} {gap}" style="align-items: {align};">
|
<div class="flex flex-col {className} {gap}" style="align-items: {align};">
|
||||||
<slot />
|
{@render children?.()}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Section bg="bg-gray-900" className="text-white">
|
<Section bg="bg-gray-900" class="text-white">
|
||||||
<Grid>
|
<Grid>
|
||||||
<div>
|
<div>
|
||||||
<h3 class="text-3xl font-light pb-4">MTÜ Lapikud</h3>
|
<h3 class="text-3xl font-light pb-4">MTÜ Lapikud</h3>
|
||||||
|
|||||||
@@ -103,16 +103,35 @@
|
|||||||
.menu-closing {
|
.menu-closing {
|
||||||
animation: collapseToButton 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
animation: collapseToButton 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mobile-menu-overlay {
|
||||||
|
height: 100vh;
|
||||||
|
max-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (height: 100svh) {
|
||||||
|
.mobile-menu-overlay {
|
||||||
|
height: 100svh;
|
||||||
|
max-height: 100svh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (height: 100dvh) {
|
||||||
|
.mobile-menu-overlay {
|
||||||
|
height: 100dvh;
|
||||||
|
max-height: 100dvh;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<header class="fixed inset-x-0 top-0 z-50 text-white">
|
<header class="fixed inset-x-0 top-0 z-50 text-white">
|
||||||
<Container maxWidth={true} center={false} className="py-0">
|
<Container maxWidth={true} center={false} class="py-0">
|
||||||
{#if $text && Object.keys($text).length > 0}
|
{#if $text && Object.keys($text).length > 0}
|
||||||
<div class="flex items-center w-full relative min-h-10">
|
<div class="flex items-center w-full relative min-h-10">
|
||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
{#if currentPath !== "/"}
|
{#if currentPath !== "/"}
|
||||||
<div class="absolute left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2 md:relative md:left-auto md:translate-x-0 md:top-auto md:translate-y-0">
|
<div class="absolute left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2 md:relative md:left-auto md:translate-x-0 md:top-auto md:translate-y-0">
|
||||||
<Button onClick={() => handleNavigation("/")}>
|
<Button onClick={() => handleNavigation("/")} class="border-transparent">
|
||||||
<img src="assets/LapLogo_black_white.png" alt="Lapikud Logo" class="h-14" />
|
<img src="assets/LapLogo_black_white.png" alt="Lapikud Logo" class="h-14" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -123,47 +142,47 @@
|
|||||||
<nav class="z-10 hidden md:flex gap-1 justify-end text-lg">
|
<nav class="z-10 hidden md:flex gap-1 justify-end text-lg">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
name={$text.about || 'Meist'}
|
name={$text.about || 'Meist'}
|
||||||
buttonClass="rounded-[5px] hover:text-white"
|
buttonClass="rounded-[5px] hover:text-white border-transparent"
|
||||||
panelClassName="bg-white text-black"
|
panelClass="bg-white text-black"
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("/lapikutest")}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500 border-transparent" onClick={() => navigate("/lapikutest")}
|
||||||
>{$text.aboutPages.info}</Button
|
>{$text.aboutPages.info}</Button
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("/tudengile")}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500 border-transparent" onClick={() => navigate("/tudengile")}
|
||||||
><Bot />{$text.aboutPages.join}</Button
|
><Bot />{$text.aboutPages.join}</Button
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("/mentorid")}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500 border-transparent" onClick={() => navigate("/mentorid")}
|
||||||
><HandHeart />{$text.aboutPages.mentors}</Button
|
><HandHeart />{$text.aboutPages.mentors}</Button
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("/juhatus")}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500 border-transparent" onClick={() => navigate("/juhatus")}
|
||||||
><Lectern />{$text.aboutPages.board}</Button
|
><Lectern />{$text.aboutPages.board}</Button
|
||||||
>
|
>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
name={$text.events}
|
name={$text.events}
|
||||||
buttonClass="rounded-[5px] hover:text-white"
|
buttonClass="rounded-[5px] hover:text-white border-transparent"
|
||||||
panelClassName="bg-white text-black"
|
panelClass="bg-white text-black"
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("/koolitused")}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500 border-transparent" onClick={() => navigate("/koolitused")}
|
||||||
><Presentation />{$text.eventsPages.workshops}</Button
|
><Presentation />{$text.eventsPages.workshops}</Button
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("https://asikarikas.ee/", { external: true })}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500 border-transparent" onClick={() => navigate("https://asikarikas.ee/", { external: true })}
|
||||||
><Trophy />ASI Karikas</Button
|
><Trophy />ASI Karikas</Button
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("https://remondikohvik.lapikud.ee/", { external: true })}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500 border-transparent" onClick={() => navigate("https://remondikohvik.lapikud.ee/", { external: true })}
|
||||||
><Coffee />{$text.eventsPages.repair}</Button
|
><Coffee />{$text.eventsPages.repair}</Button
|
||||||
>
|
>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Button class="rounded-[5px] hover:text-white" onClick={() => navigate("/kontakt")}
|
<Button class="rounded-[5px] hover:text-white border-transparent" onClick={() => navigate("/kontakt")}
|
||||||
>{$text.contact}
|
>{$text.contact}
|
||||||
</Button>
|
</Button>
|
||||||
<Button class="rounded-[5px] hover:text-white" onClick={() => navigate("/helpdesk")}
|
<Button class="rounded-[5px] hover:text-white border-transparent" onClick={() => navigate("/helpdesk")}
|
||||||
>{$text.helpdesk}
|
>{$text.helpdesk}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<!-- Language Switcher -->
|
<!-- Language Switcher -->
|
||||||
<Button
|
<Button
|
||||||
class="rounded-[5px] px-3 py-1 text-sm ml-4 hover:text-white"
|
class="rounded-[5px] px-3 py-1 text-sm ml-4 hover:text-white border-transparent"
|
||||||
onClick={() => switchLanguageRoute($currentLang === 'est' ? 'en' : 'est')}
|
onClick={() => switchLanguageRoute($currentLang === 'est' ? 'en' : 'est')}
|
||||||
>
|
>
|
||||||
{$currentLang === 'est' ? 'EN' : 'EST'}
|
{$currentLang === 'est' ? 'EN' : 'EST'}
|
||||||
@@ -174,8 +193,8 @@
|
|||||||
{#if !mobileMenuOpen}
|
{#if !mobileMenuOpen}
|
||||||
<Button
|
<Button
|
||||||
onClick={toggleMobileMenu}
|
onClick={toggleMobileMenu}
|
||||||
class="md:hidden p-2 text-white transition-colors bg-transparent absolute right-0 hover:text-white"
|
class="mobile-only p-2 text-white transition-colors bg-transparent absolute right-0 hover:text-white border-transparent"
|
||||||
aria-label="Toggle menu"
|
aria-label="Toggle navigation menu"
|
||||||
>
|
>
|
||||||
<Menu size={32} />
|
<Menu size={32} />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -189,15 +208,16 @@
|
|||||||
<!-- Full Screen Mobile Menu -->
|
<!-- Full Screen Mobile Menu -->
|
||||||
{#if mobileMenuOpen}
|
{#if mobileMenuOpen}
|
||||||
<div
|
<div
|
||||||
class="fixed inset-0 z-100 bg-black/95 md:hidden overflow-y-auto"
|
class="mobile-menu-overlay fixed inset-0 z-100 bg-black/95 mobile-only overflow-y-auto"
|
||||||
|
data-animation
|
||||||
class:menu-opening={!isClosing}
|
class:menu-opening={!isClosing}
|
||||||
class:menu-closing={isClosing}
|
class:menu-closing={isClosing}
|
||||||
>
|
>
|
||||||
<Stack className="min-h-full">
|
<Stack class="min-h-full">
|
||||||
<div class="absolute top-6 right-4">
|
<div class="absolute top-6 right-4">
|
||||||
<Button
|
<Button
|
||||||
onClick={closeMobileMenu}
|
onClick={closeMobileMenu}
|
||||||
class="ml-auto p-2 transition-colors flex bg-transparent hover:text-orange-500"
|
class="ml-auto p-2 transition-colors flex bg-transparent hover:text-orange-500 border-transparent"
|
||||||
aria-label="Close menu"
|
aria-label="Close menu"
|
||||||
>
|
>
|
||||||
<X size={32} color="white" />
|
<X size={32} color="white" />
|
||||||
@@ -205,34 +225,34 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Menu Content -->
|
<!-- Menu Content -->
|
||||||
<Stack gap="gap-5" className="flex-1 px-8 pt-24 pb-12 text-white text-xl">
|
<Stack gap="gap-5" class="flex-1 px-8 pt-24 pb-12 text-white text-xl">
|
||||||
<!-- About Section -->
|
<!-- About Section -->
|
||||||
<Stack gap="gap-3">
|
<Stack gap="gap-3">
|
||||||
<h3 class="text-2xl font-bold text-orange-500">{$text.about}</h3>
|
<h3 class="text-2xl font-bold text-orange-500">{$text.about}</h3>
|
||||||
<Stack gap="gap-2" className="pl-4">
|
<Stack gap="gap-2" class="pl-4">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleNavigation("/lapikutest")}
|
onClick={() => handleNavigation("/lapikutest")}
|
||||||
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500 border-transparent"
|
||||||
>
|
>
|
||||||
{$text.aboutPages.info}
|
{$text.aboutPages.info}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleNavigation("/tudengile")}
|
onClick={() => handleNavigation("/tudengile")}
|
||||||
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500 border-transparent"
|
||||||
>
|
>
|
||||||
<Bot size={20} />
|
<Bot size={20} />
|
||||||
{$text.aboutPages.join}
|
{$text.aboutPages.join}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleNavigation("/mentorid")}
|
onClick={() => handleNavigation("/mentorid")}
|
||||||
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500 border-transparent"
|
||||||
>
|
>
|
||||||
<HandHeart size={20} />
|
<HandHeart size={20} />
|
||||||
{$text.aboutPages.mentors}
|
{$text.aboutPages.mentors}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleNavigation("/juhatus")}
|
onClick={() => handleNavigation("/juhatus")}
|
||||||
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500 border-transparent"
|
||||||
>
|
>
|
||||||
<Lectern size={20} />
|
<Lectern size={20} />
|
||||||
{$text.aboutPages.board}
|
{$text.aboutPages.board}
|
||||||
@@ -243,24 +263,24 @@
|
|||||||
<!-- Events Section -->
|
<!-- Events Section -->
|
||||||
<Stack gap="gap-3" >
|
<Stack gap="gap-3" >
|
||||||
<h3 class="text-2xl font-bold text-orange-500">{$text.events}</h3>
|
<h3 class="text-2xl font-bold text-orange-500">{$text.events}</h3>
|
||||||
<Stack gap="gap-2" className="pl-4">
|
<Stack gap="gap-2" class="pl-4">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleNavigation("/koolitused")}
|
onClick={() => handleNavigation("/koolitused")}
|
||||||
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500 border-transparent"
|
||||||
>
|
>
|
||||||
<Presentation size={20} />
|
<Presentation size={20} />
|
||||||
{$text.eventsPages.workshops}
|
{$text.eventsPages.workshops}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleNavigation("https://asikarikas.ee/", { external: true })}
|
onClick={() => handleNavigation("https://asikarikas.ee/", { external: true })}
|
||||||
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500 border-transparent"
|
||||||
>
|
>
|
||||||
<Trophy size={20} />
|
<Trophy size={20} />
|
||||||
ASI Karikas
|
ASI Karikas
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleNavigation("https://remondikohvik.lapikud.ee/", { external: true })}
|
onClick={() => handleNavigation("https://remondikohvik.lapikud.ee/", { external: true })}
|
||||||
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500 border-transparent"
|
||||||
>
|
>
|
||||||
<Coffee size={20} />
|
<Coffee size={20} />
|
||||||
{$text.eventsPages.repair}
|
{$text.eventsPages.repair}
|
||||||
@@ -272,13 +292,13 @@
|
|||||||
<Stack gap="gap-3">
|
<Stack gap="gap-3">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleNavigation("/kontakt")}
|
onClick={() => handleNavigation("/kontakt")}
|
||||||
class="text-left text-2xl font-semibold transition-colors bg-transparent hover:text-orange-500"
|
class="text-left text-2xl font-semibold transition-colors bg-transparent hover:text-orange-500 border-transparent"
|
||||||
>
|
>
|
||||||
{$text.contact}
|
{$text.contact}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleNavigation("/helpdesk")}
|
onClick={() => handleNavigation("/helpdesk")}
|
||||||
class="text-left text-2xl font-semibold transition-colors bg-transparent hover:text-orange-500"
|
class="text-left text-2xl font-semibold transition-colors bg-transparent hover:text-orange-500 border-transparent"
|
||||||
>
|
>
|
||||||
{$text.helpdesk}
|
{$text.helpdesk}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -286,7 +306,7 @@
|
|||||||
<!-- Language Switcher -->
|
<!-- Language Switcher -->
|
||||||
<Stack gap="gap-3">
|
<Stack gap="gap-3">
|
||||||
<Button
|
<Button
|
||||||
class="w-full rounded-lg py-3 text-lg bg-orange-500 text-black"
|
class="w-full rounded-lg py-3 text-lg bg-orange-500 text-black border-transparent"
|
||||||
onClick={() => handleLanguageSwitch($currentLang === 'est' ? 'en' : 'est')}
|
onClick={() => handleLanguageSwitch($currentLang === 'est' ? 'en' : 'est')}
|
||||||
>
|
>
|
||||||
{$currentLang === 'est' ? 'English' : 'Eesti'}
|
{$currentLang === 'est' ? 'English' : 'Eesti'}
|
||||||
|
|||||||
@@ -1 +1,9 @@
|
|||||||
{}
|
{
|
||||||
|
"homeAbout": {
|
||||||
|
"title": "About us",
|
||||||
|
"description": "Our main goal is to create professional added value for TalTech IT students. We involve students in practical solutions where ideas can be implemented in real life and technical skills can be used in meaningful ways. Our projects often grow into useful and exciting thesis topics with clear practical value.",
|
||||||
|
"moreInfo": "More info",
|
||||||
|
"contact": "Contact",
|
||||||
|
"imageAlt": "Lapikud students working on a project"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1 +1,9 @@
|
|||||||
{}
|
{
|
||||||
|
"homeAbout": {
|
||||||
|
"title": "Meist",
|
||||||
|
"description": "Meie põhieesmärgiks on Tallinna Tehnikaülikooli IT tudengitele erialase lisandväärtuse loomine. Kaasame tudengeid praktilistesse lahendustesse, kus saab ideid reaalselt ellu viia ja oma oskusi päriselt kasutada. Meie projektidest kasvavad välja huvitavad ja tarvilikud lõputööd, millel on selge praktiline väärtus.",
|
||||||
|
"moreInfo": "Rohkem infot",
|
||||||
|
"contact": "Kontakt",
|
||||||
|
"imageAlt": "Lapikute tudengid projekti kallal"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<div bind:this={sectionElement}>
|
<div bind:this={sectionElement}>
|
||||||
<Section >
|
<Section >
|
||||||
<Center dir="col" className="w-full">
|
<Center dir="col" class="w-full">
|
||||||
<div class="w-full max-w-4xl">
|
<div class="w-full max-w-4xl">
|
||||||
<iframe
|
<iframe
|
||||||
style="border: 0;"
|
style="border: 0;"
|
||||||
|
|||||||
@@ -1,17 +1,31 @@
|
|||||||
<script>
|
<script>
|
||||||
import {Section, Stack, Grid, Center, Image, Svg, Button} from "$components";
|
import {Section, Stack, Grid, Center, Image, Svg, Button} from "$components";
|
||||||
import { navigate } from "$lib/router/router.js";
|
import { navigate } from "$lib/router/router.js";
|
||||||
|
import { text, currentLang } from "$lib";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import yaml from 'js-yaml';
|
||||||
|
|
||||||
|
import ArrowRight from "lucide-svelte/icons/arrow-right";
|
||||||
|
|
||||||
|
// Partners data
|
||||||
|
let partners = [];
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
const response = await fetch('/_data/partners.yml');
|
||||||
|
const yamlText = await response.text();
|
||||||
|
partners = yaml.load(yamlText);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Hero Section -->
|
<!-- Hero Section -->
|
||||||
<Section className="relative min-h-screen overflow-hidden" padding="none" bg="bg-gray-900" id="hero">
|
<Section class="relative min-h-screen overflow-hidden" padding="none" bg="bg-gray-900" id="hero">
|
||||||
<div class="relative min-h-screen flex items-center">
|
<div class="relative min-h-screen flex items-center">
|
||||||
<div class="absolute inset-0 left-1/2 w-screen -translate-x-1/2" aria-hidden="true">
|
<div class="absolute inset-0 left-1/2 w-screen -translate-x-1/2" aria-hidden="true">
|
||||||
<Image
|
<Image
|
||||||
src="/assets/hero.jpg"
|
src="/assets/hero.jpg"
|
||||||
alt="illustrative hero image"
|
alt="illustrative hero image"
|
||||||
objectFit="cover"
|
objectFit="cover"
|
||||||
className="w-full h-full"
|
class="w-full h-full"
|
||||||
pictureClass="block w-full h-full"
|
pictureClass="block w-full h-full"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -21,15 +35,15 @@ import { navigate } from "$lib/router/router.js";
|
|||||||
>
|
>
|
||||||
<Svg
|
<Svg
|
||||||
type="mirrorH"
|
type="mirrorH"
|
||||||
className="absolute right-0 top-[16%] w-[clamp(8.125rem,14vw,14.375rem)] text-[#E18E38]"
|
class="absolute right-0 top-[16%] w-[clamp(8.125rem,14vw,14.375rem)] text-[#E18E38]"
|
||||||
/>
|
/>
|
||||||
<Svg
|
<Svg
|
||||||
type="branchH"
|
type="branchH"
|
||||||
className="absolute right-0 top-[52%] -translate-y-1/2 w-[clamp(3.5rem,6vw,5.875rem)] text-[#E18E38]"
|
class="absolute right-0 top-[52%] -translate-y-1/2 w-[clamp(3.5rem,6vw,5.875rem)] text-[#E18E38]"
|
||||||
/>
|
/>
|
||||||
<Svg
|
<Svg
|
||||||
type="mirrorVH"
|
type="mirrorVH"
|
||||||
className="absolute right-0 bottom-[12%] w-[clamp(8.125rem,14vw,14.375rem)] text-[#E18E38]"
|
class="absolute right-0 bottom-[12%] w-[clamp(8.125rem,14vw,14.375rem)] text-[#E18E38]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="pointer-events-none absolute inset-y-0 left-1/2 w-screen -translate-x-1/2 bg-linear-to-r from-black/65 via-black/35 to-transparent" aria-hidden="true"></div>
|
<div class="pointer-events-none absolute inset-y-0 left-1/2 w-screen -translate-x-1/2 bg-linear-to-r from-black/65 via-black/35 to-transparent" aria-hidden="true"></div>
|
||||||
@@ -53,63 +67,205 @@ import { navigate } from "$lib/router/router.js";
|
|||||||
</div>
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
|
<!-- Second Section -->
|
||||||
<Section className="relative overflow-hidden">
|
<Section class="relative overflow-hidden" id="services">
|
||||||
<div class="pointer-events-none absolute inset-x-0 left-1/2 top-15 z-0 w-screen -translate-x-1/2" aria-hidden="true">
|
<div class="pointer-events-none absolute inset-x-0 left-1/2 top-15 z-0 w-screen -translate-x-1/2" aria-hidden="true">
|
||||||
<Svg
|
<Svg
|
||||||
type="connector"
|
type="connector"
|
||||||
className="absolute left-0 w-[clamp(8.125rem,14vw,14.375rem)] text-orange-500"
|
class="absolute left-0 w-[clamp(8.125rem,14vw,14.375rem)] text-orange-500"
|
||||||
/>
|
/>
|
||||||
<Svg
|
<Svg
|
||||||
type="mirrorH"
|
type="mirrorH"
|
||||||
className="absolute right-0 w-[clamp(8.125rem,14vw,14.375rem)] text-orange-500"
|
class="absolute right-0 w-[clamp(8.125rem,14vw,14.375rem)] text-orange-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Grid columns={2} largeColumns={3} mobileColumns={1} className="relative z-10 items-start mt-12 md:mt-20" gap="gap-12 md:gap-16 lg:gap-24">
|
<Grid columns={2} largeColumns={3} mobileColumns={1} class="relative z-10 items-start mt-12 md:mt-20" gap="gap-12 md:gap-16 lg:gap-24">
|
||||||
<Center dir="col" className="w-full max-w-sm justify-start mx-auto">
|
<Center dir="col" class="w-full max-w-sm justify-start mx-auto">
|
||||||
<div class="w-[min(72vw,240px)] md:w-[min(26vw,280px)] lg:w-[min(23vw,300px)] aspect-square rounded-full overflow-hidden">
|
<div class="w-[min(72vw,240px)] md:w-[min(26vw,280px)] lg:w-[min(23vw,300px)] aspect-square rounded-full overflow-hidden">
|
||||||
<Image
|
<Image
|
||||||
src="/assets/student-images/image_1.jpg"
|
src="/assets/student-images/image_1.jpg"
|
||||||
webpSrc=""
|
webpSrc=""
|
||||||
alt="Tudengile Pilt"
|
alt="Tudengile Pilt"
|
||||||
objectFit="cover"
|
objectFit="cover"
|
||||||
className="w-full h-full rounded-full object-[center_35%]"
|
class="w-full h-full rounded-full object-[center_35%]"
|
||||||
pictureClass="block w-full h-full"
|
pictureClass="block w-full h-full"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="w-full min-h-10 text-center text-2xl font-semibold flex items-center justify-center">Tudengile</h3>
|
<h3 class="w-full min-h-10 text-center text-2xl font-semibold flex items-center justify-center">Tudengile</h3>
|
||||||
<p class="w-full max-w-[26ch] text-center text-base leading-[160%]">Tule arenda oma oskuseid ja saa ägedaid sõpru! Omanda praktilist kogemust reaalsetest projektidest.</p>
|
<p class="w-full max-w-[26ch] text-center text-base">Tule arenda oma oskuseid ja saa ägedaid sõpru! Omanda praktilist kogemust reaalsetest projektidest.</p>
|
||||||
</Center>
|
</Center>
|
||||||
|
|
||||||
<Center dir="col" className="w-full max-w-sm justify-start mx-auto">
|
<Center dir="col" class="w-full max-w-sm justify-start mx-auto">
|
||||||
<div class="w-[min(72vw,240px)] md:w-[min(26vw,280px)] lg:w-[min(23vw,300px)] aspect-square rounded-full overflow-hidden">
|
<div class="w-[min(72vw,240px)] md:w-[min(26vw,280px)] lg:w-[min(23vw,300px)] aspect-square rounded-full overflow-hidden">
|
||||||
<Image
|
<Image
|
||||||
src="/assets/helpdesk/helpdesk_bg.jpg"
|
src="/assets/helpdesk/helpdesk_bg.jpg"
|
||||||
webpSrc=""
|
webpSrc=""
|
||||||
alt="Helpdesk Pilt"
|
alt="Helpdesk Pilt"
|
||||||
objectFit="cover"
|
objectFit="cover"
|
||||||
className="w-full h-full rounded-full object-[center_38%]"
|
class="w-full h-full rounded-full object-[center_38%]"
|
||||||
pictureClass="block w-full h-full"
|
pictureClass="block w-full h-full"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="w-full min-h-10 text-center text-2xl font-semibold flex items-center justify-center">Helpdesk</h3>
|
<h3 class="w-full min-h-10 text-center text-2xl font-semibold flex items-center justify-center">Helpdesk</h3>
|
||||||
<p class="w-full max-w-[26ch] text-center text-base leading-[160%]">HELPDESK on MTÜ Lapikute poolt pakutav arvutiabiteenus. Teenus on suunatud tudengitele, õppejõududele ning kõikidele huvilistele.</p>
|
<p class="w-full max-w-[26ch] text-center text-base">HELPDESK on MTÜ Lapikute poolt pakutav arvutiabiteenus. Teenus on suunatud tudengitele, õppejõududele ning kõikidele huvilistele.</p>
|
||||||
</Center>
|
</Center>
|
||||||
|
|
||||||
<Center dir="col" className="w-full max-w-sm justify-start mx-auto md:col-span-2 lg:col-span-1">
|
<Center dir="col" class="w-full max-w-sm justify-start mx-auto md:col-span-2 lg:col-span-1">
|
||||||
<div class="w-[min(72vw,240px)] md:w-[min(26vw,280px)] lg:w-[min(23vw,300px)] aspect-square rounded-full overflow-hidden">
|
<div class="w-[min(72vw,240px)] md:w-[min(26vw,280px)] lg:w-[min(23vw,300px)] aspect-square rounded-full overflow-hidden">
|
||||||
<Image
|
<Image
|
||||||
src="/assets/asi-karikas-2023-images/miina_harma.jpeg"
|
src="/assets/asi-karikas-2023-images/miina_harma.jpeg"
|
||||||
webpSrc=""
|
webpSrc=""
|
||||||
alt="Ettevõttele Pilt"
|
alt="Ettevõttele Pilt"
|
||||||
objectFit="cover"
|
objectFit="cover"
|
||||||
className="w-full h-full rounded-full object-[center_25%]"
|
class="w-full h-full rounded-full object-[center_25%]"
|
||||||
pictureClass="block w-full h-full"
|
pictureClass="block w-full h-full"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="w-full min-h-10 text-center text-2xl font-semibold flex items-center justify-center">Ettevõttele</h3>
|
<h3 class="w-full min-h-10 text-center text-2xl font-semibold flex items-center justify-center">Ettevõttele</h3>
|
||||||
<p class="w-full max-w-[26ch] text-center text-base leading-[160%]">Aitame sinu ideed ellu viia! Meie kogenud tudengid on valmis teie projekte realiseerima.</p>
|
<p class="w-full max-w-[26ch] text-center text-base">Aitame sinu ideed ellu viia! Meie kogenud tudengid on valmis teie projekte realiseerima.</p>
|
||||||
</Center>
|
</Center>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
|
<!-- About Us Section -->
|
||||||
|
<Section
|
||||||
|
bg="bg-gray-900"
|
||||||
|
class="relative overflow-hidden text-white"
|
||||||
|
padding="none"
|
||||||
|
fullWidth={true}
|
||||||
|
contentClass="!px-0 !py-0"
|
||||||
|
>
|
||||||
|
<Grid
|
||||||
|
columns={2}
|
||||||
|
largeColumns={2}
|
||||||
|
mobileColumns={1}
|
||||||
|
gap="gap-y-0 md:gap-x-[clamp(5.75rem,9vw,9.75rem)] lg:gap-x-[clamp(6rem,9vw,10.5rem)]"
|
||||||
|
class=""
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="relative flex items-center py-12 md:py-16 lg:py-20 pr-(--page-padding-inline)"
|
||||||
|
style="padding-left: max(var(--page-padding-inline), calc((100vw - var(--page-max-width)) / 2 + var(--page-padding-inline)));"
|
||||||
|
>
|
||||||
|
<div class="flex max-w-[54ch] flex-col justify-center gap-8">
|
||||||
|
<div class="space-y-5">
|
||||||
|
<h2 class="text-4xl font-semibold text-orange-500">
|
||||||
|
{$text["homeAbout"]?.title || "Meist"}
|
||||||
|
</h2>
|
||||||
|
<p class="text-base">
|
||||||
|
{$text["homeAbout"]?.description || "Viga teksti laadimisel. Palun proovi lehte uuesti laadida."}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col items-start gap-6">
|
||||||
|
<Button
|
||||||
|
class="rounded-md border-3 border-orange-500 bg-transparent px-10 py-2 transition-colors hover:bg-orange-500/10"
|
||||||
|
onClick={() => navigate($currentLang === "en" ? "/aboutus" : "/lapikutest")}
|
||||||
|
>
|
||||||
|
{$text["homeAbout"]?.moreInfo || "Rohkem infot"}
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<Button
|
||||||
|
class="rounded-md border-orange-500 bg-orange-500 px-20 py-2 transition-colors hover:border-orange-300 hover:bg-orange-300"
|
||||||
|
onClick={() => navigate($currentLang === "en" ? "/contact" : "/kontakt")}
|
||||||
|
>
|
||||||
|
{$text["homeAbout"]?.contact || "Kontakt"}
|
||||||
|
</Button>
|
||||||
|
<ArrowRight class="h-12 w-12 text-orange-500 md:h-14 md:w-14" strokeWidth={2.4} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="relative overflow-hidden min-h-80 md:min-h-0 md:h-full md:self-stretch">
|
||||||
|
<div class="absolute inset-0">
|
||||||
|
<Image
|
||||||
|
src="/assets/image.png"
|
||||||
|
alt={$text["homeAbout"]?.imageAlt || "Lapikud team"}
|
||||||
|
objectFit="cover"
|
||||||
|
class="h-full w-full max-w-none!"
|
||||||
|
pictureClass="block h-full w-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pointer-events-none absolute inset-0 bg-black/50"></div>
|
||||||
|
|
||||||
|
<div class="pointer-events-none absolute bottom-3 inset-x-0 z-10 hidden w-full lg:block" aria-hidden="true">
|
||||||
|
<div class="ml-auto h-5 w-[84%] bg-orange-500 mb-3"></div>
|
||||||
|
<div class="ml-auto h-3 w-[96%] bg-orange-500"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<div class="pointer-events-none absolute inset-y-0 left-1/2 z-20 hidden -translate-x-1/2 items-center gap-3 md:flex" aria-hidden="true">
|
||||||
|
<div class="h-[82%] w-3 bg-orange-500/50"></div>
|
||||||
|
<div class="h-[88%] w-8 bg-orange-500/50"></div>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<!-- Spacer-->
|
||||||
|
<Section bg="bg-orange-500" class="h-3"/>
|
||||||
|
|
||||||
|
<!-- What we do -->
|
||||||
|
<Section>
|
||||||
|
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<!-- Partners Section -->
|
||||||
|
<Section>
|
||||||
|
<div class="text-center mb-12">
|
||||||
|
<h2 class="text-3xl text-orange-500">
|
||||||
|
Koostööpartnerid
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Center class="flex-wrap">
|
||||||
|
{#each partners as partner}
|
||||||
|
{#if partner.url}
|
||||||
|
<a
|
||||||
|
href={partner.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="flex h-[170px] items-center justify-center p-3 no-underline transition-all duration-300 hover:scale-105"
|
||||||
|
title={partner.name}
|
||||||
|
>
|
||||||
|
{#if partner.image}
|
||||||
|
<Image
|
||||||
|
src={`/assets/partners/${partner.image}`}
|
||||||
|
alt={partner.name}
|
||||||
|
objectFit="contain"
|
||||||
|
class="w-auto max-h-[150px] transition-all duration-300"
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<span class="font-semibold text-center">{partner.name}</span>
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
{:else}
|
||||||
|
<div class="flex h-[170px] items-center justify-center p-3 transition-all duration-300">
|
||||||
|
{#if partner.image}
|
||||||
|
<Image
|
||||||
|
src={`/assets/partners/${partner.image}`}
|
||||||
|
alt={partner.name}
|
||||||
|
objectFit="contain"
|
||||||
|
class="w-auto max-h-[150px] transition-all duration-300"
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<span class="font-semibold text-center">{partner.name}</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</Center>
|
||||||
|
<Center class="m-10">
|
||||||
|
<Button
|
||||||
|
class="rounded-md border-orange-500 bg-transparent px-20 py-3 transition-colors hover:bg-orange-500/10"
|
||||||
|
onClick={() => navigate("/partners")}
|
||||||
|
>
|
||||||
|
Rohkem infot partnerluste kohta
|
||||||
|
</Button>
|
||||||
|
</Center>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<!-- Spacer-->
|
||||||
|
<Section bg="bg-orange-500" class="h-3"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user