Compare commits

...

6 commits

8 changed files with 126 additions and 23 deletions

View file

@ -7,7 +7,7 @@
"build": "astro build", "build": "astro build",
"preview": "astro preview", "preview": "astro preview",
"astro": "astro", "astro": "astro",
"test": "playwright test" "test": "playwright clear-cache && playwright test"
}, },
"dependencies": { "dependencies": {
"@astrojs/solid-js": "^5.1.0", "@astrojs/solid-js": "^5.1.0",

View file

@ -1,21 +1,40 @@
import './Background.sass' import './Background.sass'
import { Show } from 'solid-js' import { Show, createSignal } from 'solid-js'
import backgroundAvif from '../../assets/images/background.avif' // import backgroundAvif from '../../assets/images/background.avif'
import backgroundWebp from '../../assets/images/background.webp' // import backgroundWebp from '../../assets/images/background.webp'
import sharp from 'sharp'
import fs from 'fs'
interface Props { interface Props {
image?: boolean image?: boolean
color?: string color?: string
} }
const convertBackground = async (props: Props) => {
const webpOutputPath = 'src/assets/compressed-images/background.webp'
const avifOutputPath = 'src/assets/compressed-images/background.avif'
const inputPath = 'src/assets/images/background.png'
if (!fs.existsSync(webpOutputPath) || !fs.existsSync(avifOutputPath)) {
const webpBuffer = await sharp(inputPath).webp({ quality: 75 }).resize(1920).toBuffer()
await sharp(webpBuffer).toFile(webpOutputPath)
const avifBuffer = await sharp(inputPath).avif({ quality: 60 }).resize(1920).toBuffer()
await sharp(avifBuffer).toFile(avifOutputPath)
}
}
export default (props: Props) => { export default (props: Props) => {
let [imageSrc] = createSignal('src/assets/compressed-images/background.webp')
convertBackground(props)
return ( return (
<> <>
<Show when={props.image}> <Show when={props.image}>
<picture class="fullscreen"> <picture class="fullscreen">
<source srcset={backgroundAvif.src} type="image/avif" /> <source srcset={imageSrc().replace(/\.webp$/, '.avif')} type="image/avif" />
<source srcset={backgroundWebp.src} type="image/webp" /> <source srcset={imageSrc()} type="image/webp" />
<img src={backgroundWebp.src} width="1920" height="auto" decoding="async" loading="lazy" alt="An image background" /> <img src={imageSrc()} width="1920" height="auto" decoding="async" loading="lazy" alt="An image background" />
</picture> </picture>
</Show> </Show>

View file

@ -10,7 +10,7 @@
text-align: center text-align: center
text-decoration: none text-decoration: none
display: inline-block display: inline-block
font-size: 1rem font-size: 0.75rem
font-weight: 700 font-weight: 700
cursor: pointer cursor: pointer
transition: all 0.2s ease-out transition: all 0.2s ease-out

View file

@ -1,4 +1,6 @@
import sharp from 'sharp' import sharp from 'sharp'
import { createSignal } from 'solid-js'
import fs from 'fs'
interface Props { interface Props {
src: string src: string
@ -7,22 +9,28 @@ interface Props {
} }
const convertImage = async (props: Props) => { const convertImage = async (props: Props) => {
const webp = await sharp(`src/assets/images/${props.src}`).webp({ quality: 75 }).resize(props.size).toBuffer() const webpOutputPath = `src/assets/compressed-images/${props.src.split('.').slice(0, -1).join('.')}.webp`
await sharp(webp).toFile(`src/assets/compressed-images/${props.src.split('.').slice(0, -1).join('.')}.webp`) const avifOutputPath = `src/assets/compressed-images/${props.src.split('.').slice(0, -1).join('.')}.avif`
const avif = await sharp(`src/assets/images/${props.src}`).avif({ quality: 60 }).resize(props.size).toBuffer() if (!fs.existsSync(webpOutputPath) || !fs.existsSync(avifOutputPath)) {
await sharp(avif).toFile(`src/assets/compressed-images/${props.src.split('.').slice(0, -1).join('.')}.avif`) const webpBuffer = await sharp(`src/assets/images/${props.src}`).webp({ quality: 75 }).resize(props.size).toBuffer()
await sharp(webpBuffer).toFile(webpOutputPath)
const avifBuffer = await sharp(`src/assets/images/${props.src}`).avif({ quality: 60 }).resize(props.size).toBuffer()
await sharp(avifBuffer).toFile(avifOutputPath)
}
} }
export default (props: Props) => { export default (props: Props) => {
let [imageSrc] = createSignal(`src/assets/compressed-images/${props.src.split('.').slice(0, -1).join('.')}.webp`)
convertImage(props) convertImage(props)
return ( return (
<> <>
<picture class="fullscreen"> <picture >
<source srcset={`src/assets/compressed-images/${props.src.split('.').slice(0, -1).join('.')}.avif`} type="image/avif" /> <source srcset={imageSrc().replace(/\.webp$/, '.avif')} type="image/avif" />
<source srcset={`src/assets/compressed-images/${props.src.split('.').slice(0, -1).join('.')}.webp`} type="image/webp" /> <source srcset={imageSrc()} type="image/webp" />
<img src={`src/assets/compressed-images/${props.src.split('.').slice(0, -1).join('.')}.webp`} width={props.size} height="auto" decoding="async" loading="lazy" alt={props.alt} /> <img src={imageSrc()} width={props.size} height="auto" decoding="async" loading="lazy" alt={props.alt} />
</picture> </picture>
</> </>
) )

View file

@ -1,11 +1,9 @@
interface Props { interface Props {
to: string to: string
children?: any children?: any
} }
export default (props: Props) => { export default (props: Props) => {
return ( return (
<> <>
<a href={props.to} aria-label={`Go to ${props.to}`}> <a href={props.to} aria-label={`Go to ${props.to}`}>

View file

@ -0,0 +1,47 @@
.counter
display: flex
flex-direction: column
align-items: center
gap: 1rem
margin: 2rem
color: white
border: 1px solid rgba(22, 34, 60, 0.5)
padding: 1rem 2rem
border-radius: 16px
background: rgba(134, 152, 217, 0.1)
&__display
font-size: 1.75rem
font-weight: bold
&__buttons
display: flex
justify-content: center
gap: 0.25rem
// &:hover
// background: color.adjust(vars.$primaryColor, $blackness: 20%)
&__decrement
width: 2rem
height: 2.25rem
padding: auto
font-size: 1rem
font-weight: bold
cursor: pointer
text-decoration: none
background-color: rgba(86, 14, 14, 0.915)
border-radius: 8px
color: white
border: 1px solid rgba(255,255,255,0.2)
&:active
transform: scale(0.95)
&__increment
@extend .counter__decrement
background-color: rgb(14, 42, 86, 0.915)
&:active
transform: scale(0.95)

View file

@ -0,0 +1,30 @@
import './Counter.sass'
import { createSignal } from 'solid-js'
let [count, setCount] = createSignal(0)
const increment = () => {
setCount(count() + 1)
}
const decrement = () => {
setCount(count() - 1)
}
export default () => {
return (
<>
<section class="counter">
<div class="counter__display">{count()}</div>
<div class="counter__buttons">
<button class="counter__decrement" onClick={decrement}>
-
</button>
<button class="counter__increment" onClick={increment}>
+
</button>
</div>
</section>
</>
)
}

View file

@ -2,15 +2,18 @@
import Layout from '../layouts/Layout.astro' import Layout from '../layouts/Layout.astro'
import Button from '../builtin-components/Button/Button.tsx' import Button from '../builtin-components/Button/Button.tsx'
import Image from '../builtin-components/Image/Image' import Image from '../builtin-components/Image/Image'
import Link from '../builtin-components/Link/Link'
import Counter from '../components/Counter.tsx'
--- ---
<Layout title="Home"> <Layout title="FWT">
<main class="page"> <main class="page">
<!-- <section class="image"> --> <Link to="https://git.patalcala.com/patalcala9/fwt">
<Image src="fwt.png" size={250} /> <Image src="fwt.png" size={250} />
<!-- </section> --> </Link>
<h1>Fast WebApp Template</h1> <h1>Fast WebApp Template</h1>
<Counter client:load/>
<Button label="Next Page" to="/next" /> <Button label="Next Page" to="/next" />
</main> </main>
@ -24,7 +27,5 @@ import Image from '../builtin-components/Image/Image'
align-content: center align-content: center
margin: 2rem margin: 2rem
height: 90vh height: 90vh
</style> </style>
</Layout> </Layout>