Skip to content

Commit

Permalink
Merge pull request #13 from languageXchange/template
Browse files Browse the repository at this point in the history
v1
  • Loading branch information
xuelink authored Oct 26, 2023
2 parents 6dea1e8 + a37343c commit b846c7e
Show file tree
Hide file tree
Showing 109 changed files with 5,271 additions and 292 deletions.
1,105 changes: 1,096 additions & 9 deletions package-lock.json

Large diffs are not rendered by default.

22 changes: 19 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,43 @@
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --plugin-search-dir . --check . && eslint .",
"format": "prettier --plugin-search-dir . --write ."
"format": "prettier --plugin-search-dir . --write .",
"optimize-images": "image-transmutation --run --sourceFolder './build/images' --targetFolder './build/images' --inputFormats 'jpg' --inputFormats 'jpeg' --inputFormats 'png' --outputFormats 'png' --outputFormats 'webp' --outputFormats 'avif'",
"postbuild": "npm run optimize-images && svelte-sitemap --domain https://languagexchange.net/"
},
"devDependencies": {
"@fontsource/comfortaa": "^5.0.16",
"@neoconfetti/svelte": "^1.0.0",
"@sveltejs/adapter-static": "^2.0.3",
"@sveltejs/kit": "^1.20.4",
"@types/cookie": "^0.5.1",
"@types/dateformat": "^5.0.1",
"@types/prismjs": "^1.26.2",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"dateformat": "^5.0.3",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte": "^2.30.0",
"image-transmutation": "^0.1.3",
"mdsvex": "^0.11.0",
"prettier": "^2.8.0",
"prettier-plugin-svelte": "^2.10.1",
"reading-time": "^1.5.0",
"rehype-autolink-headings": "^7.0.0",
"rehype-external-links": "^3.0.0",
"rehype-slug": "^6.0.0",
"sass": "^1.69.4",
"striptags": "^3.2.0",
"svelte": "^4.0.5",
"svelte-check": "^3.4.3",
"svelte-sitemap": "^2.6.0",
"tslib": "^2.4.1",
"typescript": "^5.0.0",
"vite": "^4.4.2",
"vitest": "^0.32.2"
},
"type": "module"
"type": "module",
"dependencies": {
"@fontsource/comfortaa": "^5.0.17"
}
}
46 changes: 44 additions & 2 deletions src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,53 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<!-- Favicon -->
<!-- TODO: Increase favicons r-->
<!--
<link
rel="apple-touch-icon"
sizes="180x180"
href="%sveltekit.assets%/favicons/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="%sveltekit.assets%/favicons/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="%sveltekit.assets%/favicons/favicon-16x16.png"
/>
<link rel="manifest" href="%sveltekit.assets%/favicons/site.webmanifest" />
<link
rel="mask-icon"
href="%sveltekit.assets%/favicons/safari-pinned-tab.svg"
color="#0ca4a5"
/>
<link rel="shortcut icon" href="%sveltekit.assets%/favicons/favicon.ico" />
-->
<link rel="icon" href="%sveltekit.assets%/favicons/favicon.png" />
<!-- Tell browser this site is responsive -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Tell browser this site supports light and dark mode -->
<meta name="color-scheme" content="light dark" />
<!-- Color for browser url bar in mobile/Safari -->
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#b28cf2" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#4612A1" />
<!-- Disable Google FLOC -->
<meta http-equiv="Permissions-Policy" content="interest-cohort=()" />
<script>
// Calling this here so that it loads as quickly as possible
// Avoiding a flash of light mode in case dark mode is used
const theme = localStorage.getItem('theme-preference') || 'auto';
document.firstElementChild?.setAttribute('data-theme', theme);
</script>
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
<div id="svelte-root">%sveltekit.body%</div>
</body>
</html>
132 changes: 132 additions & 0 deletions src/lib/components/atoms/Button.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<script lang="ts">
import { HttpRegex } from '$lib/utils/regex';
export let color: 'primary' | 'secondary' = 'primary';
export let style: 'solid' | 'understated' | 'clear' = 'solid';
export let size: 'small' | 'medium' | 'large' = 'medium';
export let href: string | undefined = undefined;
export let additionalClass: string | undefined = undefined;
const isExternalLink = !!href && HttpRegex.test(href);
export let target: '_self' | '_blank' = isExternalLink ? '_blank' : '_self';
export let rel = isExternalLink ? 'noopener noreferrer' : undefined;
$: tag = href ? 'a' : 'button';
$: linkProps = {
href,
target,
rel
};
</script>

<svelte:element
this={tag}
{...linkProps}
class={['button', `style--${style}`, `size--${size}`, `color--${color}`, additionalClass].join(
' '
)}
data-sveltekit-preload-data
on:click
{...$$restProps}
>
{#if $$slots['icon']}
<div class="icon">
<slot name="icon" />
</div>
{/if}
<slot />
</svelte:element>

<style lang="scss">
.button {
--main-color: red;
--light-color: blue;
--contrast-color: green;
-webkit-appearance: none;
appearance: none;
cursor: pointer;
text-decoration: none;
transition: all 0.2s ease-in-out;
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
border: none;
border-radius: 20px;
font-weight: 700;
.icon {
width: 24px;
height: 24px;
}
&.color {
&--primary {
--main-color: var(--color--primary-rgb);
--light-color: var(--color--primary-tint-rgb);
--contrast-color: var(--color--primary-contrast);
}
&--secondary {
--main-color: var(--color--secondary-rgb);
--light-color: var(--color--secondary-tint-rgb);
--contrast-color: var(--color--secondary-contrast);
}
}
&.style {
&--solid {
background-color: rgb(var(--main-color));
color: var(--contrast-color);
&:hover {
box-shadow: 0px 0px 1px 7px rgba(var(--main-color), 0.3);
}
}
&--understated {
background-color: rgb(var(--light-color));
color: rgb(var(--main-color));
&:hover {
box-shadow: 0px 0px 1px 7px rgba(var(--main-color), 0.3);
}
}
&--clear {
background-color: transparent;
color: rgb(var(--main-color));
&:hover {
background-color: rgb(var(--light-color));
}
}
}
&.size {
&--small {
padding: 5px 10px;
font-size: 0.75rem;
.icon {
width: 20px;
height: 20px;
}
}
&--medium {
padding: 10px 20px;
font-size: 1rem;
}
&--large {
padding: 15px 30px;
font-size: 1.15rem;
.icon {
width: 28px;
height: 28px;
}
}
}
}
</style>
99 changes: 99 additions & 0 deletions src/lib/components/atoms/Card.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<script lang="ts">
import { HttpRegex } from '$lib/utils/regex';
export let additionalClass: string | undefined = undefined;
export let href: string | undefined = undefined;
const isExternalLink = !!href && HttpRegex.test(href);
export let target: '_self' | '_blank' = isExternalLink ? '_blank' : '_self';
export let rel = isExternalLink ? 'noopener noreferrer' : undefined;
$: tag = href ? 'a' : 'article';
$: linkProps = {
href,
target,
rel
};
</script>

<svelte:element
this={tag}
class="card {additionalClass}"
{...linkProps}
data-sveltekit-preload-data
{...$$restProps}
>
{#if $$slots.image}
<div class="image">
<slot name="image" />
</div>
{/if}
<div class="body">
<div class="content">
<slot name="content" />
</div>
{#if $$slots.footer}
<div class="footer">
<slot name="footer" />
</div>
{/if}
</div>
</svelte:element>

<style lang="scss">
.card {
background: var(--color--card-background);
box-shadow: var(--card-shadow);
color: var(--color--text);
border-radius: 10px;
transition: all 0.4s ease;
position: relative;
overflow: hidden;
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
text-decoration: none;
&[href],
&[onclick] {
cursor: pointer;
&:hover {
box-shadow: var(--card-shadow-hover);
transform: scale(1.01);
}
}
}
.body {
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 10px;
padding: 20px 20px;
flex: 1 0 50%;
.content {
display: flex;
flex-direction: column;
flex: 1;
}
}
.image {
position: relative;
flex: 1 0 max(50%, 330px);
// height: min(100%, 300px);
min-height: 280px;
max-height: 350px;
}
:global(.card [slot='image']) {
width: 100%;
height: 100%;
object-fit: cover;
position: absolute;
}
</style>
59 changes: 59 additions & 0 deletions src/lib/components/atoms/Image.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<script lang="ts">
import { dev } from '$app/environment';
export let src: string;
export let alt: string;
export let fullBleed: boolean | undefined = undefined;
export let formats: string[] = ['avif', 'webp', 'png'];
export let widths: string[] | undefined = undefined;
$: fileName = src.split('.')[0];
function buildSrcset() {
if (dev) return;
let srcset = '';
if (widths) {
for (let i = 0; i < widths.length; i++) {
srcset += `${fileName}-${widths[i]}.${formats[0]} ${widths[i]}w`;
if (i < widths.length - 1) {
srcset += ', ';
}
}
} else {
for (let i = 0; i < formats.length; i++) {
srcset += `${fileName}.${formats[i]}`;
if (i < formats.length - 1) {
srcset += ', ';
}
}
}
return srcset;
}
</script>

<img {src} {alt} loading="lazy" decoding="async" class:full-bleed={fullBleed} />

<!--
<img
srcset={buildSrcset()}
{src}
{alt}
loading="lazy"
decoding="async"
class:full-bleed={fullBleed}
/>
-->

<style lang="scss">
img {
width: 100%;
height: 100%;
object-fit: contain;
}
</style>
Loading

0 comments on commit b846c7e

Please sign in to comment.