feat: Add qwik-react (#103)

This adds the following pages:

The landing page (/)
The pricing page (/pricing)
The contact page (/contact)
The changelog page (/changelog)
Terms Of Service page (/terms)
Privacy Policy (/privacy)
This commit is contained in:
Wanjohi
2024-08-30 16:19:58 +03:00
committed by GitHub
parent d13d3dc5d8
commit 73cec51728
102 changed files with 5096 additions and 105 deletions

View File

@@ -0,0 +1,65 @@
import { component$, useSignal } from "@builder.io/qwik"
import { cn } from "./design"
type Props = {
class?: string
}
const minValue = 2;
const maxValue = 6;
const teamSizes = Array.from({ length: maxValue - minValue + 1 }, (_, i) => i + minValue);
export const TeamCounter = component$(({ class: className }: Props) => {
const teammates = useSignal(2)
const shake = useSignal(false)
return (
<div class={cn("flex items-center justify-center", shake.value && "animate-shake", className)}>
<button
onClick$={() => {
if (teammates.value == minValue) {
shake.value = true
setTimeout(() => {
shake.value = false
}, 500);
} else {
teammates.value = Math.max(minValue, teammates.value - 1)
}
}}
class={cn("size-[30px] rounded-full bg-gray-300 dark:bg-gray-700 flex items-center justify-center active:scale-90", teammates.value <= minValue && "opacity-30")}>
<svg xmlns="http://www.w3.org/2000/svg" class="size-[15px]" viewBox="0 0 256 256"><path fill="currentColor" d="M228 128a12 12 0 0 1-12 12H40a12 12 0 0 1 0-24h176a12 12 0 0 1 12 12" /></svg>
</button>
<div class="flex items-center justify-center mx-2 mt-1">
<p class="text-lg font-normal w-full flex items-center justify-center">
<span
class="w-[2ch] relative inline-block h-[2.625rem] overflow-hidden [mask:linear-gradient(#0000,_#000_35%_65%,_#0000)]">
<span
style={{
translate: `0 calc((${teammates.value - (minValue + 1)} + 1) * (2.625rem * -1))`,
transition: `translate 0.625s linear(0 0%,0.5007 7.21%,0.7803 12.29%,0.8883 14.93%,0.9724 17.63%,1.0343 20.44%,1.0754 23.44%,1.0898 25.22%,1.0984 27.11%,1.1014 29.15%,1.0989 31.4%,1.0854 35.23%,1.0196 48.86%,1.0043 54.06%,0.9956 59.6%,0.9925 68.11%,1 100%)`
}}
class="absolute w-full flex top-0 flex-col">
{teamSizes.map((num) => (
<span
class="w-full font-title h-[2.625rem] flex flex-col items-center justify-center leading-[1rem]"
key={`team-member-${num}`} >+{num}</span>
))}
</span>
</span>
</p>
</div>
<button onClick$={() => {
if (teammates.value == maxValue) {
shake.value = true
setTimeout(() => {
shake.value = false
}, 500);
} else {
teammates.value = Math.min(maxValue, teammates.value + 1)
}
}}
class={cn("size-[30px] rounded-full bg-gray-300 dark:bg-gray-700 flex items-center justify-center active:scale-90", teammates.value >= maxValue && "opacity-30")}>
<svg xmlns="http://www.w3.org/2000/svg" class="size-[15px]" viewBox="0 0 256 256"><path fill="currentColor" d="M228 128a12 12 0 0 1-12 12h-76v76a12 12 0 0 1-24 0v-76H40a12 12 0 0 1 0-24h76V40a12 12 0 0 1 24 0v76h76a12 12 0 0 1 12 12" /></svg>
</button>
</div>
)
})