mirror of
https://github.com/Lapikud/lapikud.github.io.git
synced 2026-08-08 16:39:14 +00:00
Merge branch 'svelte-henri' into svelte
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -22,3 +22,6 @@ dist-ssr
|
|||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
|
*storybook.log
|
||||||
|
storybook-static
|
||||||
|
|||||||
11
.storybook/main.js
Normal file
11
.storybook/main.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/** @type { import('@storybook/svelte-vite').StorybookConfig } */
|
||||||
|
const config = {
|
||||||
|
stories: ['../src/**/*.stories.svelte'],
|
||||||
|
addons: ['@storybook/addon-svelte-csf'],
|
||||||
|
framework: {
|
||||||
|
name: '@storybook/svelte-vite',
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
13
.storybook/preview.js
Normal file
13
.storybook/preview.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/** @type { import('@storybook/svelte-vite').Preview } */
|
||||||
|
const preview = {
|
||||||
|
parameters: {
|
||||||
|
controls: {
|
||||||
|
matchers: {
|
||||||
|
color: /(background|color)$/i,
|
||||||
|
date: /Date$/i,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default preview;
|
||||||
37
generate-stories.js
Normal file
37
generate-stories.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { readFileSync, writeFileSync } from 'fs';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import { dirname, resolve } from 'path';
|
||||||
|
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
|
const svelteSrc = readFileSync(resolve(__dirname, './src/components/Svg.svelte'), 'utf-8');
|
||||||
|
|
||||||
|
const match = svelteSrc.match(/export const VARIANTS\s*=\s*\[([^\]]+)\]/);
|
||||||
|
if (!match) {
|
||||||
|
console.error('Could not find VARIANTS in Svg.svelte');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const variants = match[1]
|
||||||
|
.split(',')
|
||||||
|
.map(v => v.trim().replace(/['"]/g, ''))
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
const stories = variants.map(v => `<Story name="${v}" args={{ type: '${v}' }} />`).join('\n');
|
||||||
|
|
||||||
|
const output = `<script context="module">
|
||||||
|
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||||
|
import Svg from '../components/Svg.svelte';
|
||||||
|
|
||||||
|
const { Story } = defineMeta({
|
||||||
|
title: 'Components/Svg',
|
||||||
|
component: Svg,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
${stories}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const outPath = resolve(__dirname, './src/stories/Svg.stories.svelte');
|
||||||
|
writeFileSync(outPath, output, 'utf-8');
|
||||||
|
console.log(`✅ Generated ${variants.length} stories: ${variants.join(', ')}`);
|
||||||
1532
package-lock.json
generated
1532
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -6,11 +6,18 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"storybook": "storybook dev -p 6006",
|
||||||
|
"build-storybook": "storybook build",
|
||||||
|
"prestorybook": "node generate-stories.js",
|
||||||
|
"prebuild-storybook": "node generate-stories.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@storybook/addon-svelte-csf": "^5.0.11",
|
||||||
|
"@storybook/svelte-vite": "^10.2.15",
|
||||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
|
"storybook": "^10.2.15",
|
||||||
"svelte": "^5.43.8",
|
"svelte": "^5.43.8",
|
||||||
"vite": "npm:rolldown-vite@7.2.5"
|
"vite": "npm:rolldown-vite@7.2.5"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -23,11 +23,6 @@
|
|||||||
url: https://taltech.ee/et/infotehnoloogia-teaduskond
|
url: https://taltech.ee/et/infotehnoloogia-teaduskond
|
||||||
additionalText:
|
additionalText:
|
||||||
|
|
||||||
- name: HexTech Solutions
|
|
||||||
image: hextech_logo.svg
|
|
||||||
url: https://hextech.ee/
|
|
||||||
additionalText:
|
|
||||||
|
|
||||||
- name: EAS & MKM
|
- name: EAS & MKM
|
||||||
image: eas.svg
|
image: eas.svg
|
||||||
url: https://eis.ee/
|
url: https://eis.ee/
|
||||||
|
|||||||
164
src/app.css
164
src/app.css
@@ -2,54 +2,42 @@
|
|||||||
|
|
||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
/* Overwriting tailwindcss specific variables */
|
||||||
|
@theme {
|
||||||
|
--color-orange-500: #f0941d;
|
||||||
|
--color-orange-300: #ffa940;
|
||||||
|
--color-orange-600: #d67d0a;
|
||||||
|
|
||||||
|
--color-gray-100: #fffdfa;
|
||||||
|
--color-gray-900: #0d0d0d;
|
||||||
|
|
||||||
|
--spacing-0: 0px;
|
||||||
|
--spacing-1: 4px;
|
||||||
|
--spacing-2: 8px;
|
||||||
|
--spacing-3: 16px;
|
||||||
|
--spacing-4: 24px;
|
||||||
|
--spacing-5: 32px;
|
||||||
|
--spacing-6: 48px;
|
||||||
|
|
||||||
|
--max-width-2xl: 700px;
|
||||||
|
--max-width-3xl: 800px;
|
||||||
|
--max-width-4xl: 900px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Design tokens & theme variables (light defaults) */
|
/* Design tokens & theme variables (light defaults) */
|
||||||
:root {
|
:root {
|
||||||
/* color tokens (light defaults) */
|
|
||||||
--orange: #f0941d;
|
|
||||||
--orange-light: #ffa940;
|
|
||||||
--orange-dark: #d67d0a;
|
|
||||||
--black: #000000;
|
|
||||||
--off-black: #0d0d0d;
|
|
||||||
--white: #ffffff;
|
|
||||||
--off-white: #fffdfa;
|
|
||||||
--gray-50: #fafafa;
|
|
||||||
--gray-100: #f5f5f5;
|
|
||||||
--gray-200: #e5e5e5;
|
|
||||||
--gray-300: #d4d4d4;
|
|
||||||
--gray-800: #262626;
|
|
||||||
--gray-900: #171717;
|
|
||||||
|
|
||||||
/* layout tokens */
|
/* layout tokens */
|
||||||
--site-padding: clamp(1rem, 2vw, 2rem); /* horizontal page padding */
|
--site-padding: clamp(1rem, 2vw, 2rem); /* horizontal page padding */
|
||||||
--content-max: 1200px; /* main content max width */
|
--content-max: 1200px; /* main content max width */
|
||||||
--nav-height: 64px;
|
|
||||||
--footer-height: 80px;
|
|
||||||
|
|
||||||
/* spacing scale */
|
/* spacing scale */
|
||||||
--space-0: 0px;
|
--spacing-0: 0px;
|
||||||
--space-1: 4px;
|
--spacing-1: 4px;
|
||||||
--space-2: 8px;
|
--spacing-2: 8px;
|
||||||
--space-3: 16px;
|
--spacing-3: 16px;
|
||||||
--space-4: 24px;
|
--spacing-4: 24px;
|
||||||
--space-5: 32px;
|
--spacing-5: 32px;
|
||||||
--space-6: 48px;
|
--spacing-6: 48px;
|
||||||
|
|
||||||
/* radius / shadows */
|
|
||||||
--radius-sm: 6px;
|
|
||||||
--radius-md: 10px;
|
|
||||||
--radius-lg: 14px;
|
|
||||||
--radius-xl: 20px;
|
|
||||||
--shadow-1: 0 1px 2px rgba(240, 148, 29, 0.2),
|
|
||||||
0 1px 3px rgba(240, 148, 29, 0.12);
|
|
||||||
--shadow-2: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
|
|
||||||
--shadow-3: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
|
|
||||||
--shadow-glow: 0 0 20px rgba(240, 148, 29, 0.3);
|
|
||||||
|
|
||||||
/* breakpoints */
|
|
||||||
--bp-sm: 480px;
|
|
||||||
--bp-md: 768px;
|
|
||||||
--bp-lg: 1024px;
|
|
||||||
--bp-xl: 1280px;
|
|
||||||
|
|
||||||
/* type scale (fluid base + modular sizes) */
|
/* type scale (fluid base + modular sizes) */
|
||||||
--fs-base: clamp(0.95rem, 0.9vw + 0.9rem, 1rem);
|
--fs-base: clamp(0.95rem, 0.9vw + 0.9rem, 1rem);
|
||||||
@@ -59,16 +47,6 @@
|
|||||||
--fs-lg: 1.125rem;
|
--fs-lg: 1.125rem;
|
||||||
--fs-xl: 1.5rem;
|
--fs-xl: 1.5rem;
|
||||||
--line-height: 1.45;
|
--line-height: 1.45;
|
||||||
|
|
||||||
/* derived component tokens that components can rely on */
|
|
||||||
--button-bg: var(--color-surface);
|
|
||||||
--button-text: var(--color-text);
|
|
||||||
--card-bg: linear-gradient(
|
|
||||||
180deg,
|
|
||||||
rgba(255, 255, 255, 0.98),
|
|
||||||
rgba(255, 255, 255, 0.96)
|
|
||||||
);
|
|
||||||
--accent: var(--color-primary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Global box sizing & accessible defaults */
|
/* Global box sizing & accessible defaults */
|
||||||
@@ -88,8 +66,6 @@ html {
|
|||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: var(--color-text);
|
|
||||||
background: var(--color-bg);
|
|
||||||
line-height: var(--line-height);
|
line-height: var(--line-height);
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
@@ -100,22 +76,18 @@ body {
|
|||||||
|
|
||||||
/* Basic link & button defaults that components inherit */
|
/* Basic link & button defaults that components inherit */
|
||||||
a {
|
a {
|
||||||
color: var(--color-primary);
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: 550;
|
font-weight: 550;
|
||||||
}
|
}
|
||||||
a:hover {
|
a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
color: var(--color-primary-600);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button,
|
button,
|
||||||
input[type="button"],
|
input[type="button"],
|
||||||
input[type="submit"] {
|
input[type="submit"] {
|
||||||
font: inherit;
|
font: inherit;
|
||||||
color: var(--button-text);
|
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) */
|
||||||
background: var(--button-bg);
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
padding: 0.5em 0.9em;
|
padding: 0.5em 0.9em;
|
||||||
border-radius: var(--radius-sm);
|
border-radius: var(--radius-sm);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -126,17 +98,10 @@ button:active {
|
|||||||
transform: translateY(1px);
|
transform: translateY(1px);
|
||||||
}
|
}
|
||||||
button:focus {
|
button:focus {
|
||||||
outline: 3px solid color-mix(in srgb, var(--color-primary) 14%, transparent);
|
outline: 3px solid color-mix(in srgb, var(--color-primary) 14%, transparent); /* TODO: change same magic here */
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Simple responsive grid that adapts to available width */
|
|
||||||
.grid {
|
|
||||||
display: grid;
|
|
||||||
gap: var(--space-3);
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Utility: visually hidden (accessible labels) */
|
/* Utility: visually hidden (accessible labels) */
|
||||||
.sr-only,
|
.sr-only,
|
||||||
.visually-hidden {
|
.visually-hidden {
|
||||||
@@ -167,49 +132,34 @@ button:focus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Navbar & footer helpers so components can assume consistent heights */
|
/* Accessibility settings */
|
||||||
.site-header {
|
|
||||||
height: var(--nav-height);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
background: transparent;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 40;
|
|
||||||
border-bottom: 1px solid var(--color-border);
|
|
||||||
backdrop-filter: blur(6px);
|
|
||||||
}
|
|
||||||
.site-footer {
|
|
||||||
height: var(--footer-height);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
border-top: 1px solid var(--color-border);
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Small form controls default */
|
|
||||||
.input {
|
|
||||||
padding: 0.6em 0.8em;
|
|
||||||
border-radius: var(--radius-sm);
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
background: transparent;
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Utility to visually reduce emphasis (muted text) */
|
|
||||||
.muted {
|
|
||||||
color: var(--color-muted);
|
|
||||||
font-size: 0.95em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Accessibility: respect reduced motion */
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
* {
|
* {
|
||||||
animation-duration: 0.001ms !important;
|
animation: none !important;
|
||||||
animation-iteration-count: 1 !important;
|
transition: none !important;
|
||||||
transition-duration: 0.001ms !important;
|
|
||||||
scroll-behavior: auto !important;
|
scroll-behavior: auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Automatically apply final animation states */
|
||||||
|
[data-animation] { /* Everything with animation needs to be marked like this: <div class="fade-in" data-animation>Hello World</div> */
|
||||||
|
all: unset !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-transparency: reduce) {
|
||||||
|
* {
|
||||||
|
background: solid !important;
|
||||||
|
backdrop-filter: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
* {
|
||||||
|
background: Window !important;
|
||||||
|
color: WindowText !important;
|
||||||
|
border-color: WindowText !important;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: Highlight !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +1,10 @@
|
|||||||
<script>
|
<script>
|
||||||
export let onClick = () => {};
|
export let onClick = () => {};
|
||||||
export let buttonHoverStyle = "";
|
|
||||||
export let style = "";
|
|
||||||
|
|
||||||
let isHovered = false;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
on:click={onClick}
|
on:click={onClick}
|
||||||
on:mouseenter={() => (isHovered = true)}
|
class="btn border-[1.5px] px-5 py-2.5 font-medium cursor-pointer flex items-center gap-2 whitespace-nowrap {$$props.class ?? ''}"
|
||||||
on:mouseleave={() => (isHovered = false)}
|
|
||||||
class={`btn border-[1.5px] px-5 py-2.5 font-medium cursor-pointer flex items-center gap-2 whitespace-nowrap ${$$restProps.class}`}
|
|
||||||
style={isHovered && buttonHoverStyle ? buttonHoverStyle : style}
|
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<style>
|
|
||||||
.btn {
|
|
||||||
transition: background-color 0.2s ease, color 0.2s ease;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
export let name = "";
|
export let name = "";
|
||||||
export let buttonClass = "";
|
export let buttonClass = "";
|
||||||
export let panelClassName = "";
|
export let panelClassName = "";
|
||||||
export let buttonHoverStyle = "";
|
|
||||||
|
|
||||||
let isOpen = false;
|
let isOpen = false;
|
||||||
|
|
||||||
@@ -22,7 +21,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="relative inline-block" on:focusout={handleFocusOut}>
|
<div class="relative inline-block" on:focusout={handleFocusOut}>
|
||||||
<Button onClick={toggle} class={buttonClass} {buttonHoverStyle}>
|
<Button onClick={toggle} class={buttonClass}>
|
||||||
{name}
|
{name}
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
<!--
|
<!--
|
||||||
Multi-purpose image/SVG component with optional link wrapper,
|
Multi-purpose image component with optional link wrapper,
|
||||||
hover effects, size variants, and object-fit options.
|
hover effects, size variants, and object-fit options. Includes support for WebP format with fallback to standard formats.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export let src = "";
|
export let webpSrc = ""; // Optional WebP source for browsers that support it
|
||||||
|
export let src = ""; // Fallback (some devices don't support WebP) or primary source if webpSrc is not provided
|
||||||
export let alt = "";
|
export let alt = "";
|
||||||
export let href = null; // optional link URL
|
export let href = null; // optional link URL
|
||||||
export let target = "_blank";
|
export let target = "_blank";
|
||||||
@@ -12,6 +13,12 @@ hover effects, size variants, and object-fit options.
|
|||||||
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 = "";
|
export let className = "";
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
export let srcSet = ""; // always set src if using this
|
||||||
|
export let webpSrcSet = ""; // always set src if using this
|
||||||
|
export let pictureClass = ""; // CSS/Tailwind classes applied to the <picture> element
|
||||||
|
|
||||||
$: objectFitClass = {
|
$: objectFitClass = {
|
||||||
contain: "object-contain",
|
contain: "object-contain",
|
||||||
@@ -25,22 +32,29 @@ hover effects, size variants, and object-fit options.
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if href}
|
{#if href}
|
||||||
<a
|
<a {href} {target} {rel} class="inline-block leading-none">
|
||||||
{href}
|
<picture class={pictureClass}>
|
||||||
{target}
|
{#if webpSrc || webpSrcSet}
|
||||||
{rel}
|
<source srcset={webpSrcSet || webpSrc} type="image/webp" />
|
||||||
class="inline-block leading-none"
|
{/if}
|
||||||
>
|
<img
|
||||||
<img
|
{src}
|
||||||
{src}
|
srcset={srcSet || undefined}
|
||||||
{alt}
|
alt={alt}
|
||||||
class="block h-auto max-w-full {objectFitClass} {hoverClasses} {className}"
|
class="block h-auto max-w-full {objectFitClass} {hoverClasses} {className}"
|
||||||
/>
|
/>
|
||||||
|
</picture>
|
||||||
</a>
|
</a>
|
||||||
{:else}
|
{:else}
|
||||||
<img
|
<picture class={pictureClass}>
|
||||||
{src}
|
{#if webpSrc || webpSrcSet}
|
||||||
{alt}
|
<source srcset={webpSrcSet || webpSrc} type="image/webp" />
|
||||||
class="block h-auto max-w-full {objectFitClass} {hoverClasses} {className}"
|
{/if}
|
||||||
/>
|
<img
|
||||||
|
{src}
|
||||||
|
srcset={srcSet || undefined}
|
||||||
|
alt={alt}
|
||||||
|
class="block h-auto max-w-full {objectFitClass} {hoverClasses} {className}"
|
||||||
|
/>
|
||||||
|
</picture>
|
||||||
{/if}
|
{/if}
|
||||||
26
src/components/README.md
Normal file
26
src/components/README.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# SVG previews
|
||||||
|
|
||||||
|
use `npm run storybook` which opens a browser window with all the SVG variations. You can also edit the SVG properties in storybook controls.
|
||||||
|
|
||||||
|
# Components
|
||||||
|
|
||||||
|
under components are building blocks that are not layout related.
|
||||||
|
|
||||||
|
## details
|
||||||
|
|
||||||
|
- Button: a simple button component with some styling.
|
||||||
|
- Dropdown: a dropdown component that can be used to show/hide content.
|
||||||
|
- Slideshow: a simple slideshow component that can be used to show multiple images in a slideshow format. Includes options to enable/disable autoplay and to set the autoplay interval.
|
||||||
|
- Svg: a component that renders different SVG icons based on the `type` prop. See the VARIANTS constant in `Svg.svelte` or storybook for the available types.
|
||||||
|
- Image (Use for larger images): a component that renders an image with some styling. It accepts a lot of props. Main ones are `src` (the main image source that is used if anything else fails or not provided), `alt` (the alt text for the image), `srcSet` (a string of comma-separated image sources for different screen sizes, jpg or png files), `webpSrc` (the webp image source as a webp file), `webpSrcSet` (a string of comma-separated webp image sources for different screen sizes). We use 2 webp images: 400 and 800 width, and one jpg image 800 width as default src for fallback.
|
||||||
|
|
||||||
|
# Layout components
|
||||||
|
|
||||||
|
under components/layout are components that are used to structure the page, such as Container, Stack, Center, etc.
|
||||||
|
|
||||||
|
- Container: a simple container component that centers its content and adds some padding.
|
||||||
|
- Stack: a component that stacks its children vertically or horizontally.
|
||||||
|
- Center: a component that centers its content both horizontally and vertically.
|
||||||
|
- Section: a component that is used to create sections on the page.
|
||||||
|
- Card: a component that adds some padding, a border, and a shadow to its content, used to create cards on the page.
|
||||||
|
- Grid: a component that creates a CSS grid layout for its children, with customizable columns and gap. It is dynamic and changes automatically with page size, best practice is to set `columns` for desktop and `mobileColumns` for mobile views to control the behavior if needed.
|
||||||
75
src/components/Svg.svelte
Normal file
75
src/components/Svg.svelte
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<script context="module">
|
||||||
|
export const VARIANTS = ['instagram','facebook','github','connector','mirrorV','mirrorH','mirrorVH','branch','branchH'];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export let type;
|
||||||
|
export let className = "";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if type === "connector"}
|
||||||
|
<svg viewBox="0 0 182 66" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<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"/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{:else if type === "mirrorV"}
|
||||||
|
<svg viewBox="0 0 182 66" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g transform="scale(1,-1) translate(0,-66)">
|
||||||
|
<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"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{:else if type === "mirrorH"}
|
||||||
|
<svg viewBox="0 0 182 66" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g transform="scale(-1,1) translate(-182,0)">
|
||||||
|
<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"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{:else if type === "mirrorVH"}
|
||||||
|
<svg viewBox="0 0 182 66" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g transform="scale(-1,-1) translate(-182,-66)">
|
||||||
|
<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"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{:else if type === "branch"}
|
||||||
|
<svg viewBox="0 0 75 74" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0 31.4784H46L68 1.47842M45.5 30.9784L66.5 63.9784"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="5"/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{:else if type === "branchH"}
|
||||||
|
<svg viewBox="0 0 75 74" class={className} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g transform="scale(-1,1) translate(-75,0)">
|
||||||
|
<path d="M0 31.4784H46L68 1.47842M45.5 30.9784L66.5 63.9784"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="5"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{: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">
|
||||||
|
<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>
|
||||||
|
|
||||||
|
{: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">
|
||||||
|
<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>
|
||||||
|
|
||||||
|
{: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">
|
||||||
|
<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>
|
||||||
|
|
||||||
|
{:else}
|
||||||
|
<div>Unknown type: {type}</div>
|
||||||
|
{/if}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// layout components
|
||||||
export { default as Container } from './layout/Container.svelte'
|
export { default as Container } from './layout/Container.svelte'
|
||||||
export { default as Card } from './layout/Card.svelte'
|
export { default as Card } from './layout/Card.svelte'
|
||||||
export { default as Stack } from './layout/Stack.svelte'
|
export { default as Stack } from './layout/Stack.svelte'
|
||||||
@@ -5,6 +6,9 @@ export { default as Grid } from './layout/Grid.svelte'
|
|||||||
export { default as Center } from './layout/Center.svelte'
|
export { default as Center } from './layout/Center.svelte'
|
||||||
export { default as Section } from './layout/Section.svelte'
|
export { default as Section } from './layout/Section.svelte'
|
||||||
|
|
||||||
|
// components
|
||||||
export { default as Button } from './Button.svelte'
|
export { default as Button } from './Button.svelte'
|
||||||
export { default as Dropdown } from './Dropdown.svelte'
|
export { default as Dropdown } from './Dropdown.svelte'
|
||||||
export { default as Slideshow } from './Slideshow.svelte'
|
export { default as Slideshow } from './Slideshow.svelte'
|
||||||
|
export { default as Svg } from './Svg.svelte'
|
||||||
|
export { default as Image } from './Image.svelte'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
export let dir = "row"; // 'row' | 'col' (default: 'row')
|
export let dir = "row"; // 'row' | 'col' (default: 'row')
|
||||||
export let gapClass = "gap-4";
|
export let gap = "gap-4";
|
||||||
export let className = "";
|
export let className = "";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
class={"flex " +
|
class={"flex " +
|
||||||
(dir === "row" ? "flex-row" : "flex-col") +
|
(dir === "row" ? "flex-row" : "flex-col") +
|
||||||
" items-center justify-center " +
|
" items-center justify-center " +
|
||||||
gapClass +
|
gap +
|
||||||
" " +
|
" " +
|
||||||
className}
|
className}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,35 +1,41 @@
|
|||||||
<!--
|
|
||||||
A responsive grid wrapper using CSS Grid. It exposes `min`, `columns`,
|
|
||||||
and `gap` props to control the responsive column minimum width, fixed
|
|
||||||
column count, and spacing. Content is projected into the default slot.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export let min = "220px"; // minimum column width (used when columns is not set)
|
export let min = "220px"; // min column width (used when columns not set)
|
||||||
export let columns = null; // fixed number of columns (e.g., "2", "3", "4")
|
export let columns = null; // fixed number of columns for desktop
|
||||||
export let gap = "var(--space-3)";
|
export let mobileColumns = null; // fixed number of columns for mobile
|
||||||
|
export let gap = "gap-3";
|
||||||
export let className = "";
|
export let className = "";
|
||||||
|
|
||||||
$: gridTemplateColumns = columns
|
$: desktopColumns = columns ? `repeat(${columns}, 1fr)` : '1fr';
|
||||||
? `repeat(${columns}, 1fr)`
|
$: mobileCols = mobileColumns ? `repeat(${mobileColumns}, 1fr)` : '1fr';
|
||||||
: '1fr';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="grid {className}"
|
class="grid {className} {gap}"
|
||||||
style="--min: {min}; --gap: {gap}; --columns: {gridTemplateColumns}; grid-template-columns: var(--columns); gap: var(--gap);"
|
style="
|
||||||
|
--min: {min};
|
||||||
|
--desktop-columns: {desktopColumns};
|
||||||
|
--mobile-columns: {mobileCols};
|
||||||
|
grid-template-columns: var(--mobile-columns);
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* Mobile first: use mobileColumns by default */
|
||||||
|
.grid {
|
||||||
|
grid-template-columns: var(--mobile-columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Desktop / tablet screens */
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.grid {
|
.grid {
|
||||||
grid-template-columns: var(--columns) !important;
|
grid-template-columns: var(--desktop-columns) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid:not([style*="--columns: repeat"]) {
|
/* fallback for when columns are not set, use minmax */
|
||||||
|
.grid:not([style*="--desktop-columns: repeat"]) {
|
||||||
grid-template-columns: repeat(auto-fit, minmax(var(--min), 1fr)) !important;
|
grid-template-columns: repeat(auto-fit, minmax(var(--min), 1fr)) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -1,35 +1,24 @@
|
|||||||
<script>
|
<script>
|
||||||
export let background = "transparent"; // CSS color code or color variable name from app.css
|
export let bg = "";
|
||||||
export let padding = "normal"; // 'none' | 'small' | 'normal' | 'large'
|
export let padding = "normal";
|
||||||
export let fullWidth = false;
|
export let fullWidth = false;
|
||||||
export let id = "";
|
export let id = "";
|
||||||
export let className = "";
|
export let className = "";
|
||||||
|
|
||||||
const paddingClasses = {
|
const paddingClasses = {
|
||||||
none: "py-0",
|
none: "py-0",
|
||||||
|
tight: "py-2 md:py-3",
|
||||||
small: "py-4 md:py-8",
|
small: "py-4 md:py-8",
|
||||||
normal: "py-12 max-md:py-8",
|
normal: "py-12 max-md:py-8",
|
||||||
large: "py-[clamp(3rem,8vw,6rem)] max-md:py-12",
|
large: "py-[clamp(3rem,8vw,6rem)] max-md:py-12",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert background to appropriate CSS value
|
|
||||||
$: backgroundStyle = (() => {
|
|
||||||
if (!background || background === "transparent") return "";
|
|
||||||
// If it starts with # or rgb/rgba or hsl, it's a direct color
|
|
||||||
if (background.startsWith("#") || background.startsWith("rgb") || background.startsWith("hsl")) {
|
|
||||||
return background;
|
|
||||||
}
|
|
||||||
// Otherwise treat as CSS variable name
|
|
||||||
return `var(--${background})`;
|
|
||||||
})();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section
|
<section
|
||||||
{id}
|
{id}
|
||||||
class="w-full {paddingClasses[padding]} {className}"
|
class="w-full {paddingClasses[padding]} {bg} {className}"
|
||||||
style={backgroundStyle ? `background: ${backgroundStyle};` : ""}
|
|
||||||
>
|
>
|
||||||
<div class="{fullWidth ? '' : 'max-w-[1200px]'} mx-auto px-(--site-padding)">
|
<div class="{fullWidth ? '' : 'max-w-[1200px]'} mx-auto px-(--site-padding)">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -3,11 +3,11 @@ A simple stack/column layout that stacks children vertically.
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export let gap = "var(--space-3)";
|
export let gap = "gap-3";
|
||||||
export let align = "stretch";
|
export let align = "stretch";
|
||||||
export let className = "";
|
export let className = "";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col {className}" style="gap: {gap}; align-items: {align};">
|
<div class="flex flex-col {className} {gap}" style="align-items: {align};">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,26 +4,27 @@ import {
|
|||||||
Section,
|
Section,
|
||||||
Container,
|
Container,
|
||||||
Center,
|
Center,
|
||||||
|
Svg,
|
||||||
} from "$components";
|
} from "$components";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Section background="off-black" className="text-white">
|
<Section bg="bg-gray-900" className="text-white">
|
||||||
<Grid>
|
<Grid>
|
||||||
<div>
|
<div>
|
||||||
<h3 class="text-3xl font-light" style="padding-bottom: var(--space-4);">MTÜ Lapikud</h3>
|
<h3 class="text-3xl font-light pb-4">MTÜ Lapikud</h3>
|
||||||
<Container center={false}>
|
<Container center={false}>
|
||||||
<address class="not-italic" style="padding-bottom: var(--space-4);">
|
<address class="not-italic pb-4">
|
||||||
Aadress: <a href="https://maps.app.goo.gl/1pCDMVNaMD29G7y78" style="color: var(--orange)">Akadeemia tee 5, 12616 Tallinn, Eesti</a>
|
Aadress: <a href="https://maps.app.goo.gl/1pCDMVNaMD29G7y78" class="text-orange-500">Akadeemia tee 5, 12616 Tallinn, Eesti</a>
|
||||||
<br/>
|
<br/>
|
||||||
E-post: <a href="mailto:lapikud@lapikud.ee" style="color: var(--orange)">lapikud@lapikud.ee</a>
|
E-post: <a href="mailto:lapikud@lapikud.ee" class="text-orange-500">lapikud@lapikud.ee</a>
|
||||||
<br/>
|
<br/>
|
||||||
Tel: <a href="tel:+37258160799" style="color: var(--orange)">+372 58 160 799</a>
|
Tel: <a href="tel:+37258160799" class="text-orange-500">+372 58 160 799</a>
|
||||||
<br/>
|
<br/>
|
||||||
Messenger: <a href="https://m.me/Lapikud" target="_blank" rel="noopener noreferrer" style="color: var(--orange)">m.me/Lapikud</a>
|
Messenger: <a href="https://m.me/Lapikud" target="_blank" rel="noopener noreferrer" class="text-orange-500">m.me/Lapikud</a>
|
||||||
</address>
|
</address>
|
||||||
<div>
|
<div>
|
||||||
Reg. kood: <a href="https://ariregister.rik.ee/est/company/80167145/" style="color: var(--orange)">80167145</a>
|
Reg. kood: <a href="https://ariregister.rik.ee/est/company/80167145/" class="text-orange-500">80167145</a>
|
||||||
<br/>
|
<br/>
|
||||||
Swedbank EE812200221019551756
|
Swedbank EE812200221019551756
|
||||||
</div>
|
</div>
|
||||||
@@ -31,26 +32,20 @@ import {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Container>
|
<Container>
|
||||||
<h3 class="text-3xl font-light flex justify-center" style="padding-bottom: var(--space-4);">Sotsiaalmeedia</h3>
|
<h3 class="text-3xl font-light flex justify-center pb-4">Sotsiaalmeedia</h3>
|
||||||
<div class="flex items-center justify-center" style="gap: var(--space-4);">
|
<div class="flex items-center justify-center gap-4">
|
||||||
<a href="https://www.instagram.com/lapikud/" target="_blank" rel="noopener noreferrer" aria-label="Instagram" class="transition-opacity duration-200">
|
<a href="https://www.instagram.com/lapikud/" target="_blank" rel="noopener noreferrer" aria-label="Instagram" class="transition-opacity duration-200">
|
||||||
<svg width="32" height="32" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
<Svg type="instagram"/>
|
||||||
<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>
|
|
||||||
</a>
|
</a>
|
||||||
<a href="https://www.facebook.com/Lapikud" target="_blank" rel="noopener noreferrer" aria-label="Facebook" class="transition-opacity duration-200">
|
<a href="https://www.facebook.com/Lapikud" target="_blank" rel="noopener noreferrer" aria-label="Facebook" class="transition-opacity duration-200">
|
||||||
<svg width="32" height="32" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
<Svg type="facebook"/>
|
||||||
<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>
|
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/lapikud" target="_blank" rel="noopener noreferrer" aria-label="GitHub" class="transition-opacity duration-200">
|
<a href="https://github.com/lapikud" target="_blank" rel="noopener noreferrer" aria-label="GitHub" class="transition-opacity duration-200">
|
||||||
<svg width="32" height="32" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
<Svg type="github"/>
|
||||||
<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>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Center><small style="color: var(--orange); padding-top: var(--space-6);">© 2026 MTÜ Lapikud</small></Center>
|
<Center><small class="text-orange-500 pt-6">© 2026 MTÜ Lapikud</small></Center>
|
||||||
</Section>
|
</Section>
|
||||||
@@ -105,9 +105,9 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<Section className="text-black" background="orange" padding="small">
|
<Section className="text-black" bg="bg-orange-500" padding="tight">
|
||||||
{#if $text && Object.keys($text).length > 0}
|
{#if $text && Object.keys($text).length > 0}
|
||||||
<div class="flex items-center w-full relative min-h-16">
|
<div class="flex items-center w-full relative min-h-12">
|
||||||
<!-- 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">
|
||||||
@@ -122,50 +122,47 @@
|
|||||||
<nav class="z-10 hidden md:flex gap-4 justify-end text-xl">
|
<nav class="z-10 hidden md:flex gap-4 justify-end text-xl">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
name={$text.about || 'Meist'}
|
name={$text.about || 'Meist'}
|
||||||
buttonClass="rounded-[5px]"
|
buttonClass="rounded-[5px] hover:text-white"
|
||||||
buttonHoverStyle="color:var(--white)"
|
panelClassName="bg-white text-black"
|
||||||
panelClassName="bg-[var(--white)] text-[var(--black)]"
|
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent" buttonHoverStyle="color:var(--orange)" onClick={() => navigate("/lapikutest")}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("/lapikutest")}
|
||||||
>{$text.aboutPages.info}</Button
|
>{$text.aboutPages.info}</Button
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent" buttonHoverStyle="color:var(--orange)" onClick={() => navigate("/tudengile")}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("/tudengile")}
|
||||||
><Bot />{$text.aboutPages.join}</Button
|
><Bot />{$text.aboutPages.join}</Button
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent" buttonHoverStyle="color:var(--orange)" onClick={() => navigate("/mentorid")}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("/mentorid")}
|
||||||
><HandHeart />{$text.aboutPages.mentors}</Button
|
><HandHeart />{$text.aboutPages.mentors}</Button
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent" buttonHoverStyle="color:var(--orange)" onClick={() => navigate("/juhatus")}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" 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]"
|
buttonClass="rounded-[5px] hover:text-white"
|
||||||
buttonHoverStyle="color:var(--white)"
|
panelClassName="bg-white text-black"
|
||||||
panelClassName="bg-[var(--white)] text-[var(--black)]"
|
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent" buttonHoverStyle="color:var(--orange)" onClick={() => navigate("/koolitused")}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("/koolitused")}
|
||||||
><Presentation />{$text.eventsPages.workshops}</Button
|
><Presentation />{$text.eventsPages.workshops}</Button
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent" buttonHoverStyle="color:var(--orange)" onClick={() => navigate("https://asikarikas.ee/", { external: true })}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("https://asikarikas.ee/", { external: true })}
|
||||||
><Trophy />ASI Karikas</Button
|
><Trophy />ASI Karikas</Button
|
||||||
>
|
>
|
||||||
<Button class="rounded-[5px] bg-transparent" buttonHoverStyle="color:var(--orange)" onClick={() => navigate("https://remondikohvik.lapikud.ee/", { external: true })}
|
<Button class="rounded-[5px] bg-transparent hover:text-orange-500" onClick={() => navigate("https://remondikohvik.lapikud.ee/", { external: true })}
|
||||||
><Coffee />{$text.eventsPages.repair}</Button
|
><Coffee />{$text.eventsPages.repair}</Button
|
||||||
>
|
>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Button buttonHoverStyle="color:var(--white)" class="rounded-[5px]" onClick={() => navigate("/kontakt")}
|
<Button class="rounded-[5px] hover:text-white" onClick={() => navigate("/kontakt")}
|
||||||
>{$text.contact}
|
>{$text.contact}
|
||||||
</Button>
|
</Button>
|
||||||
<Button buttonHoverStyle="color:var(--white)" class="rounded-[5px]" onClick={() => navigate("/helpdesk")}
|
<Button class="rounded-[5px] hover:text-white" 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-2"
|
class="rounded-[5px] px-3 py-1 text-sm ml-2 hover:text-white"
|
||||||
buttonHoverStyle="color:var(--white)"
|
|
||||||
onClick={() => switchLanguageRoute($currentLang === 'est' ? 'en' : 'est')}
|
onClick={() => switchLanguageRoute($currentLang === 'est' ? 'en' : 'est')}
|
||||||
>
|
>
|
||||||
{$currentLang === 'est' ? 'EN' : 'EST'}
|
{$currentLang === 'est' ? 'EN' : 'EST'}
|
||||||
@@ -175,8 +172,7 @@
|
|||||||
<!-- Mobile Hamburger Button - Fixed position -->
|
<!-- Mobile Hamburger Button - Fixed position -->
|
||||||
<Button
|
<Button
|
||||||
onClick={toggleMobileMenu}
|
onClick={toggleMobileMenu}
|
||||||
class="md:hidden p-2 text-white transition-colors bg-transparent absolute right-0"
|
class="md:hidden p-2 text-white transition-colors bg-transparent absolute right-0 hover:text-white"
|
||||||
buttonHoverStyle="color: var(--white)"
|
|
||||||
style="opacity: {mobileMenuOpen ? '0' : '1'}; pointer-events: {mobileMenuOpen ? 'none' : 'auto'};"
|
style="opacity: {mobileMenuOpen ? '0' : '1'}; pointer-events: {mobileMenuOpen ? 'none' : 'auto'};"
|
||||||
aria-label="Toggle menu"
|
aria-label="Toggle menu"
|
||||||
>
|
>
|
||||||
@@ -198,8 +194,7 @@
|
|||||||
<div class="absolute top-8 right-0 px-(--site-padding)">
|
<div class="absolute top-8 right-0 px-(--site-padding)">
|
||||||
<Button
|
<Button
|
||||||
onClick={closeMobileMenu}
|
onClick={closeMobileMenu}
|
||||||
class="ml-auto p-2 transition-colors flex bg-transparent"
|
class="ml-auto p-2 transition-colors flex bg-transparent hover:text-orange-500"
|
||||||
buttonHoverStyle="color: var(--orange)"
|
|
||||||
aria-label="Close menu"
|
aria-label="Close menu"
|
||||||
>
|
>
|
||||||
<X size={32} color="white" />
|
<X size={32} color="white" />
|
||||||
@@ -207,38 +202,34 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Menu Content -->
|
<!-- Menu Content -->
|
||||||
<Stack gap="var(--space-5)" className="flex-1 px-8 pt-24 pb-12 text-white text-xl">
|
<Stack gap="gap-5" className="flex-1 px-8 pt-24 pb-12 text-white text-xl">
|
||||||
<!-- About Section -->
|
<!-- About Section -->
|
||||||
<Stack gap="var(--space-3)">
|
<Stack gap="gap-3">
|
||||||
<h3 class="text-2xl font-bold" style="color: var(--orange)">{$text.about}</h3>
|
<h3 class="text-2xl font-bold text-orange-500">{$text.about}</h3>
|
||||||
<Stack gap="var(--space-2)" className="pl-4">
|
<Stack gap="gap-2" className="pl-4">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleNavigation("/lapikutest")}
|
onClick={() => handleNavigation("/lapikutest")}
|
||||||
class="text-left transition-colors flex items-center gap-2 bg-transparent"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
||||||
buttonHoverStyle="color: var(--orange)"
|
|
||||||
>
|
>
|
||||||
{$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"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
||||||
buttonHoverStyle="color: var(--orange)"
|
|
||||||
>
|
>
|
||||||
<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"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
||||||
buttonHoverStyle="color: var(--orange)"
|
|
||||||
>
|
>
|
||||||
<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"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
||||||
buttonHoverStyle="color: var(--orange)"
|
|
||||||
>
|
>
|
||||||
<Lectern size={20} />
|
<Lectern size={20} />
|
||||||
{$text.aboutPages.board}
|
{$text.aboutPages.board}
|
||||||
@@ -247,29 +238,26 @@
|
|||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<!-- Events Section -->
|
<!-- Events Section -->
|
||||||
<Stack gap="var(--space-3)" >
|
<Stack gap="gap-3" >
|
||||||
<h3 class="text-2xl font-bold" style="color: var(--orange)">{$text.events}</h3>
|
<h3 class="text-2xl font-bold text-orange-500">{$text.events}</h3>
|
||||||
<Stack gap="var(--space-2)" className="pl-4">
|
<Stack gap="gap-2" className="pl-4">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleNavigation("/mentorid")}
|
onClick={() => handleNavigation("/mentorid")}
|
||||||
class="text-left transition-colors flex items-center gap-2 bg-transparent"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
||||||
buttonHoverStyle="color: var(--orange)"
|
|
||||||
>
|
>
|
||||||
<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"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
||||||
buttonHoverStyle="color: var(--orange)"
|
|
||||||
>
|
>
|
||||||
<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"
|
class="text-left transition-colors flex items-center gap-2 bg-transparent hover:text-orange-500"
|
||||||
buttonHoverStyle="color: var(--orange)"
|
|
||||||
>
|
>
|
||||||
<Coffee size={20} />
|
<Coffee size={20} />
|
||||||
{$text.eventsPages.repair}
|
{$text.eventsPages.repair}
|
||||||
@@ -278,27 +266,24 @@
|
|||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<!-- Direct Links -->
|
<!-- Direct Links -->
|
||||||
<Stack gap="var(--space-3)">
|
<Stack gap="gap-3">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleNavigation("/kontakt")}
|
onClick={() => handleNavigation("/kontakt")}
|
||||||
class="text-left text-2xl font-semibold transition-colors bg-transparent"
|
class="text-left text-2xl font-semibold transition-colors bg-transparent hover:text-orange-500"
|
||||||
buttonHoverStyle="color: var(--orange)"
|
|
||||||
>
|
>
|
||||||
{$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"
|
class="text-left text-2xl font-semibold transition-colors bg-transparent hover:text-orange-500"
|
||||||
buttonHoverStyle="color: var(--orange)"
|
|
||||||
>
|
>
|
||||||
{$text.helpdesk}
|
{$text.helpdesk}
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
<!-- Language Switcher -->
|
<!-- Language Switcher -->
|
||||||
<Stack gap="var(--space-3)">
|
<Stack gap="gap-3">
|
||||||
<Button
|
<Button
|
||||||
class="w-full rounded-lg py-3 text-lg"
|
class="w-full rounded-lg py-3 text-lg bg-orange-500 text-black"
|
||||||
style="background-color: var(--orange); color: var(--black)"
|
|
||||||
onClick={() => handleLanguageSwitch($currentLang === 'est' ? 'en' : 'est')}
|
onClick={() => handleLanguageSwitch($currentLang === 'est' ? 'en' : 'est')}
|
||||||
>
|
>
|
||||||
{$currentLang === 'est' ? 'English' : 'Eesti'}
|
{$currentLang === 'est' ? 'English' : 'Eesti'}
|
||||||
|
|||||||
@@ -25,12 +25,12 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Header Section -->
|
<!-- Header Section -->
|
||||||
<Section background="orange">
|
<Section bg="bg-orange-500">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Center>
|
<Center>
|
||||||
<img src="/assets/LapLogo_black_white.png" alt="MTÜ Lapikud" class="max-w-md w-full h-auto" style="padding: var(--space-4);"/>
|
<img src="/assets/LapLogo_black_white.png" alt="MTÜ Lapikud" class="max-w-md w-full h-auto p-4"/>
|
||||||
</Center>
|
</Center>
|
||||||
<p class="text-3xl leading-relaxed" style="padding: var(--space-4);">
|
<p class="text-3xl leading-relaxe p-4">
|
||||||
MTÜ Lapikud on Tallinna Tehnikaülikooli Tarkvaraarendusklubi, mis ühendab endisi
|
MTÜ Lapikud on Tallinna Tehnikaülikooli Tarkvaraarendusklubi, mis ühendab endisi
|
||||||
ja praegusi IT huvilisi tudengeid.
|
ja praegusi IT huvilisi tudengeid.
|
||||||
</p>
|
</p>
|
||||||
@@ -38,42 +38,42 @@
|
|||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
<Section>
|
<Section>
|
||||||
<Grid gap="var(--space-5)">
|
<Grid gap="gap-5">
|
||||||
<Card variant="blur" href="/tudengile">
|
<Card variant="blur" href="/tudengile">
|
||||||
<div class="feature-icon" style="color: var(--orange)">
|
<div class="feature-icon text-orange-500">
|
||||||
<Users size={32} strokeWidth={1.5} />
|
<Users size={32} strokeWidth={1.5} />
|
||||||
</div>
|
</div>
|
||||||
<h3 class="feature-title">Tudengile</h3>
|
<h3 class="feature-title">Tudengile</h3>
|
||||||
<p class="feature-description">
|
<p class="feature-description">
|
||||||
Tule arenda oma oskuseid ja saa ägedaid sõpru! Omanda praktilist kogemust reaalsetest projektidest.
|
Tule arenda oma oskuseid ja saa ägedaid sõpru! Omanda praktilist kogemust reaalsetest projektidest.
|
||||||
</p>
|
</p>
|
||||||
<div style="color: var(--orange)" class="mt-4 font-semibold flex items-center gap-2">
|
<div class="mt-4 font-semibold flex items-center gap-2 text-orange-500">
|
||||||
Liitu meiega <ArrowRight size={16} />
|
Liitu meiega <ArrowRight size={16} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card variant="blur" href="/helpdesk">
|
<Card variant="blur" href="/helpdesk">
|
||||||
<div class="feature-icon" style="color: var(--orange)">
|
<div class="feature-icon text-orange-500">
|
||||||
<Wrench size={32} strokeWidth={1.5} />
|
<Wrench size={32} strokeWidth={1.5} />
|
||||||
</div>
|
</div>
|
||||||
<h3 class="feature-title">Helpdesk</h3>
|
<h3 class="feature-title">Helpdesk</h3>
|
||||||
<p class="feature-description">
|
<p class="feature-description">
|
||||||
HELPDESK on MTÜ Lapikute poolt pakutav arvutiabiteenus. Teenus on suunatud tudengitele, õppejõududele ning kõikidele huvilistele.
|
HELPDESK on MTÜ Lapikute poolt pakutav arvutiabiteenus. Teenus on suunatud tudengitele, õppejõududele ning kõikidele huvilistele.
|
||||||
</p>
|
</p>
|
||||||
<div style="color: var(--orange)" class="mt-4 font-semibold flex items-center gap-2">
|
<div class="mt-4 font-semibold flex items-center gap-2 text-orange-500">
|
||||||
Vaata teenuseid <ArrowRight size={16} />
|
Vaata teenuseid <ArrowRight size={16} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card variant="blur" href="/ourwork">
|
<Card variant="blur" href="/ourwork">
|
||||||
<div class="feature-icon" style="color: var(--orange)">
|
<div class="feature-icon text-orange-500">
|
||||||
<HeartHandshake size={32} strokeWidth={1.5} />
|
<HeartHandshake size={32} strokeWidth={1.5} />
|
||||||
</div>
|
</div>
|
||||||
<h3 class="feature-title">Ettevõttele</h3>
|
<h3 class="feature-title">Ettevõttele</h3>
|
||||||
<p class="feature-description">
|
<p class="feature-description">
|
||||||
Aitame sinu ideed ellu viia! Meie kogenud tudengid on valmis teie projekte realiseerima.
|
Aitame sinu ideed ellu viia! Meie kogenud tudengid on valmis teie projekte realiseerima.
|
||||||
</p>
|
</p>
|
||||||
<div style="color: var(--orange)" class="mt-4 font-semibold flex items-center gap-2">
|
<div class="mt-4 font-semibold flex items-center gap-2 text-orange-500">
|
||||||
Tehtud tööd <ArrowRight size={16} />
|
Tehtud tööd <ArrowRight size={16} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
|
|
||||||
<!-- What We Do Section -->
|
<!-- What We Do Section -->
|
||||||
<Section>
|
<Section>
|
||||||
<Grid gap="var(--space-4)">
|
<Grid gap="gap-4">
|
||||||
<Card variant="blur">
|
<Card variant="blur">
|
||||||
<h2 class="pb-4 text-4xl font-bold">Mida me loome</h2>
|
<h2 class="pb-4 text-4xl font-bold">Mida me loome</h2>
|
||||||
<p>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.</p>
|
<p>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.</p>
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
<!-- Partners Section -->
|
<!-- Partners Section -->
|
||||||
<Section>
|
<Section>
|
||||||
<div class="text-center mb-12">
|
<div class="text-center mb-12">
|
||||||
<h2 class="text-5xl">
|
<h2 class="text-5xl text-orange-500">
|
||||||
Koostööpartnerid
|
Koostööpartnerid
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
@@ -107,7 +107,7 @@
|
|||||||
{#if partner.url}
|
{#if partner.url}
|
||||||
<a href={partner.url} target="_blank" rel="noopener noreferrer" class="partner-item" title={partner.name}>
|
<a href={partner.url} target="_blank" rel="noopener noreferrer" class="partner-item" title={partner.name}>
|
||||||
{#if partner.image}
|
{#if partner.image}
|
||||||
<img src={`/assets/partners_logos/${partner.image}`} alt={partner.name} />
|
<img src={`/assets/partners/${partner.image}`} alt={partner.name} />
|
||||||
{:else}
|
{:else}
|
||||||
<span class="partner-name">{partner.name}</span>
|
<span class="partner-name">{partner.name}</span>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<div class="partner-item">
|
<div class="partner-item">
|
||||||
{#if partner.image}
|
{#if partner.image}
|
||||||
<img src={`/assets/partners_logos/${partner.image}`} alt={partner.name} />
|
<img src={`/assets/partners/${partner.image}`} alt={partner.name} />
|
||||||
{:else}
|
{:else}
|
||||||
<span class="partner-name">{partner.name}</span>
|
<span class="partner-name">{partner.name}</span>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -126,24 +126,7 @@
|
|||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.feature-icon {
|
/* PARTNERS SECTION */
|
||||||
margin-bottom: var(--space-3);
|
|
||||||
display: inline-flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-title {
|
|
||||||
font-size: var(--fs-xl);
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: var(--space-2);
|
|
||||||
color: var(--black);
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-description {
|
|
||||||
color: var(--gray-800);
|
|
||||||
line-height: 1.6;
|
|
||||||
margin-bottom: var(--space-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.partner-item {
|
.partner-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
16
src/stories/Svg.stories.svelte
Normal file
16
src/stories/Svg.stories.svelte
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<script context="module">
|
||||||
|
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||||
|
import Svg from '../components/Svg.svelte';
|
||||||
|
|
||||||
|
const { Story } = defineMeta({
|
||||||
|
title: 'Components/Svg',
|
||||||
|
component: Svg,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Story name="connector" args={{ type: 'connector' }} />
|
||||||
|
<Story name="mirrorV" args={{ type: 'mirrorV' }} />
|
||||||
|
<Story name="mirrorH" args={{ type: 'mirrorH' }} />
|
||||||
|
<Story name="mirrorVH" args={{ type: 'mirrorVH' }} />
|
||||||
|
<Story name="branch" args={{ type: 'branch' }} />
|
||||||
|
<Story name="branchH" args={{ type: 'branchH' }} />
|
||||||
@@ -4,39 +4,5 @@ export default {
|
|||||||
"./index.html",
|
"./index.html",
|
||||||
"./src/**/*.{svelte,js,ts,jsx,tsx}",
|
"./src/**/*.{svelte,js,ts,jsx,tsx}",
|
||||||
],
|
],
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
colors: {
|
|
||||||
orange: {
|
|
||||||
DEFAULT: '#f0941d',
|
|
||||||
light: '#ffa940',
|
|
||||||
dark: '#d67d0a',
|
|
||||||
500: '#f0941d',
|
|
||||||
},
|
|
||||||
gray: {
|
|
||||||
50: '#fafafa',
|
|
||||||
100: '#f5f5f5',
|
|
||||||
200: '#e5e5e5',
|
|
||||||
300: '#d4d4d4',
|
|
||||||
800: '#262626',
|
|
||||||
900: '#171717',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
spacing: {
|
|
||||||
'0': '0px',
|
|
||||||
'1': '4px',
|
|
||||||
'2': '8px',
|
|
||||||
'3': '16px',
|
|
||||||
'4': '24px',
|
|
||||||
'5': '32px',
|
|
||||||
'6': '48px',
|
|
||||||
},
|
|
||||||
maxWidth: {
|
|
||||||
'2xl': '700px',
|
|
||||||
'3xl': '800px',
|
|
||||||
'4xl': '900px',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [],
|
plugins: [],
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user