iftrace: rebuild site with fulldev ui astro
This commit is contained in:
parent
8d3610b5d8
commit
e70d1ead43
395 changed files with 23806 additions and 15151 deletions
18
ifttt-src/.gitignore
vendored
Normal file
18
ifttt-src/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
node_modules/
|
||||||
|
.astro/
|
||||||
|
|
||||||
|
# build output (written to ../ifttt)
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# logs
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# env
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
|
||||||
|
# OS/editor
|
||||||
|
.DS_Store
|
||||||
14
ifttt-src/astro.config.mjs
Normal file
14
ifttt-src/astro.config.mjs
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
|
import { defineConfig } from "astro/config";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
site: "https://infrafabric.io",
|
||||||
|
output: "static",
|
||||||
|
outDir: "../ifttt",
|
||||||
|
build: {
|
||||||
|
assets: "assets/_astro",
|
||||||
|
},
|
||||||
|
vite: {
|
||||||
|
plugins: [tailwindcss()],
|
||||||
|
},
|
||||||
|
});
|
||||||
6264
ifttt-src/package-lock.json
generated
Normal file
6264
ifttt-src/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
25
ifttt-src/package.json
Normal file
25
ifttt-src/package.json
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"name": "iftrace-site",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "astro dev",
|
||||||
|
"build": "astro build",
|
||||||
|
"preview": "astro preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@tailwindcss/vite": "^4.1.14",
|
||||||
|
"astro": "^5.16.6",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"lucide-static": "^0.546.0",
|
||||||
|
"sharp": "^0.34.5",
|
||||||
|
"tailwind-merge": "^3.3.1",
|
||||||
|
"tailwindcss": "^4.1.14",
|
||||||
|
"tw-animate-css": "^1.4.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^24.8.1",
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
ifttt-src/public/assets/eyes-only-dave.png
Normal file
BIN
ifttt-src/public/assets/eyes-only-dave.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
BIN
ifttt-src/public/assets/fonts/inter/InterVariable-Italic.woff2
Normal file
BIN
ifttt-src/public/assets/fonts/inter/InterVariable-Italic.woff2
Normal file
Binary file not shown.
BIN
ifttt-src/public/assets/fonts/inter/InterVariable.woff2
Normal file
BIN
ifttt-src/public/assets/fonts/inter/InterVariable.woff2
Normal file
Binary file not shown.
92
ifttt-src/public/assets/fonts/inter/LICENSE.txt
Normal file
92
ifttt-src/public/assets/fonts/inter/LICENSE.txt
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION AND CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
60
ifttt-src/public/assets/if-logo-simple.svg
Normal file
60
ifttt-src/public/assets/if-logo-simple.svg
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="1024"
|
||||||
|
height="1024"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
role="img"
|
||||||
|
aria-labelledby="title desc"
|
||||||
|
>
|
||||||
|
<title id="title">if. mark</title>
|
||||||
|
<desc id="desc">Stylized “if.” mark with subtle gradient and shadow.</desc>
|
||||||
|
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="ifBlue" x1="70" y1="0" x2="440" y2="0" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0" stop-color="#0b253b" />
|
||||||
|
<stop offset="0.44" stop-color="#164d7a" />
|
||||||
|
<stop offset="0.56" stop-color="#1b5a8e" />
|
||||||
|
<stop offset="1" stop-color="#0b253b" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
<filter id="ifShadow" x="-40%" y="-40%" width="180%" height="180%">
|
||||||
|
<feOffset in="SourceAlpha" dx="0" dy="14" result="off" />
|
||||||
|
<feGaussianBlur in="off" stdDeviation="12" result="blur" />
|
||||||
|
<feColorMatrix
|
||||||
|
in="blur"
|
||||||
|
type="matrix"
|
||||||
|
values="0 0 0 0 0
|
||||||
|
0 0 0 0 0
|
||||||
|
0 0 0 0 0
|
||||||
|
0 0 0 0.28 0"
|
||||||
|
result="shadow"
|
||||||
|
/>
|
||||||
|
<feMerge>
|
||||||
|
<feMergeNode in="shadow" />
|
||||||
|
<feMergeNode in="SourceGraphic" />
|
||||||
|
</feMerge>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Mark group:
|
||||||
|
- i (stem + dot)
|
||||||
|
- f (stem + top bar + crossbar)
|
||||||
|
- period dot
|
||||||
|
-->
|
||||||
|
<g filter="url(#ifShadow)" transform="translate(75 15)" fill="url(#ifBlue)">
|
||||||
|
<!-- i -->
|
||||||
|
<circle cx="35" cy="125" r="32" />
|
||||||
|
<rect x="0" y="170" width="70" height="220" rx="8" />
|
||||||
|
|
||||||
|
<!-- f -->
|
||||||
|
<rect x="120" y="140" width="86" height="250" rx="10" />
|
||||||
|
<rect x="120" y="110" width="150" height="90" rx="45" />
|
||||||
|
<rect x="120" y="240" width="140" height="80" rx="28" />
|
||||||
|
|
||||||
|
<!-- . -->
|
||||||
|
<circle cx="330" cy="358" r="32" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
72
ifttt-src/public/assets/ifttt-quotes.json
Normal file
72
ifttt-src/public/assets/ifttt-quotes.json
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"text": "Footnotes aren't decorations. They're load-bearing walls.",
|
||||||
|
"source": "IF.Trace paper (v2.3)",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/review/ifttt-paper-update/2025-12-28/review-pack.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "If there's no IF.Trace trace, it didn't happen—or shouldn't be trusted.",
|
||||||
|
"source": "IF.Trace doctrine",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/review/ifttt-paper-update/2025-12-28/review-pack.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "No trace, no trust. Simple as that.",
|
||||||
|
"source": "IF.Trace doctrine",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/review/ifttt-paper-update/2025-12-28/review-pack.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Trust isn't claimed. It's proven.",
|
||||||
|
"source": "IF.Trace paper (v2.3)",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/review/ifttt-paper-update/2025-12-28/review-pack.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "We don’t claim trust. We publish receipts.",
|
||||||
|
"source": "IF.Trace stance",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/review/ifttt-paper-update/2025-12-28/review-pack.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Your auditor shouldn’t need your credentials.",
|
||||||
|
"source": "IF.Trace public receipts",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/ifttt/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Third parties verify. We just publish the math.",
|
||||||
|
"source": "IF.Trace posture",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/ifttt/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Receipts must be readable and verifiable without credentials.",
|
||||||
|
"source": "IF.Trace public receipt surface",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/ifttt/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Design constraint: black/white clarity. No “maybe”.",
|
||||||
|
"source": "IF.Trace ops (full stack)",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/ifttt/api/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "We do not claim “quantum-secure”. We claim “quantum-ready”.",
|
||||||
|
"source": "IF.Trace tech stack",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/ifttt/api/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "The stenographer doesn't make the therapy cold. The stenographer makes it accountable.",
|
||||||
|
"source": "IF.emotion on IF.Trace",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/review/ifttt-paper-update/2025-12-28/review-pack.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "That's the moat.",
|
||||||
|
"source": "IF.Trace paper (v2.3)",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/review/ifttt-paper-update/2025-12-28/review-pack.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "The moat is not the AI. The moat is the proof.",
|
||||||
|
"source": "IF.Trace paper (v2.3)",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/review/ifttt-paper-update/2025-12-28/review-pack.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "If it’s not verifiable, label it as a gap. Do not endorse it.",
|
||||||
|
"source": "IF.Trace stance",
|
||||||
|
"href": "https://infrafabric.io/static/hosted/ifttt/"
|
||||||
|
}
|
||||||
|
]
|
||||||
BIN
ifttt-src/public/assets/red-team-doc-1024-559.jpg
Normal file
BIN
ifttt-src/public/assets/red-team-doc-1024-559.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
BIN
ifttt-src/public/assets/red-team-stamp-600.png
Normal file
BIN
ifttt-src/public/assets/red-team-stamp-600.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 561 KiB |
66
ifttt-src/public/review/index.md
Normal file
66
ifttt-src/public/review/index.md
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
# IF.Trace Website — External Review Packet
|
||||||
|
|
||||||
|
- Generated: `2025-12-30`
|
||||||
|
- Owner: Danny Stocker (`ds@infrafabric.io`)
|
||||||
|
|
||||||
|
This packet is for external reviewers to evaluate the IF.Trace website (copy, structure, and claims) without needing to crawl or guess context.
|
||||||
|
|
||||||
|
## What this is
|
||||||
|
|
||||||
|
- A public-facing explanation of IF.Trace: “confidential documents → open verification”.
|
||||||
|
- A set of pages that describe who this is for, how verification works, and what the proof does/does not claim.
|
||||||
|
- A request for critical feedback on clarity, honesty, and missing pieces.
|
||||||
|
|
||||||
|
## What this is not
|
||||||
|
|
||||||
|
- Not a claim that IF.Trace guarantees compliance, intent, or correctness of interpretation.
|
||||||
|
- Not a request for marketing language or hype.
|
||||||
|
- Not a request to “agree” or be supportive — please be direct.
|
||||||
|
|
||||||
|
## Response metadata (required)
|
||||||
|
|
||||||
|
Please include:
|
||||||
|
|
||||||
|
- `llm_name`:
|
||||||
|
- `probable_model`:
|
||||||
|
- `cutoff_date`:
|
||||||
|
- `response_date_utc`:
|
||||||
|
- `web_access_used`: yes/no (list any URLs you relied on)
|
||||||
|
|
||||||
|
## Live entry points
|
||||||
|
|
||||||
|
- https://infrafabric.io/
|
||||||
|
- https://infrafabric.io/verticals/
|
||||||
|
- https://infrafabric.io/pricing/
|
||||||
|
- https://infrafabric.io/api/
|
||||||
|
- https://infrafabric.io/whitepaper/
|
||||||
|
- https://infrafabric.io/about/
|
||||||
|
- https://infrafabric.io/governance/
|
||||||
|
- https://infrafabric.io/fr/
|
||||||
|
|
||||||
|
## Core demo links (used throughout)
|
||||||
|
|
||||||
|
- https://infrafabric.io/static/trace/6qRgcR01kw_qNo63Dbs_ob9n
|
||||||
|
- https://infrafabric.io/static/pack/6qRgcR01kw_qNo63Dbs_ob9n
|
||||||
|
- https://infrafabric.io/static/pack/6qRgcR01kw_qNo63Dbs_ob9n.md
|
||||||
|
- https://infrafabric.io/static/hosted/review/trace-bundles/b6547c03/index.html
|
||||||
|
- https://infrafabric.io/static/hosted/iftrace.html
|
||||||
|
- https://infrafabric.io/static/hosted/iftrace.py
|
||||||
|
- https://infrafabric.io/static/hosted/review/ifttt-paper-update/2025-12-28/review-pack.html
|
||||||
|
|
||||||
|
## Questions for reviewers
|
||||||
|
|
||||||
|
1. In your own words: what does IF.Trace do?
|
||||||
|
2. What feels unclear, hand-wavy, or like “compliance theater”?
|
||||||
|
3. Where do we over-claim (even accidentally)?
|
||||||
|
4. What is missing to make a third party comfortable verifying a claim?
|
||||||
|
5. Which page is strongest? Which page is weakest?
|
||||||
|
6. Does the site make it obvious what is verified vs not verified?
|
||||||
|
7. What would you remove to make it more honest?
|
||||||
|
8. What would you add to make it more useful for real reviewers (audit/legal/security/research)?
|
||||||
|
|
||||||
|
## Bias notice
|
||||||
|
|
||||||
|
This packet intentionally avoids conversion stats, testimonials, and “success stories”.
|
||||||
|
Please focus on falsifiability, clarity, and what a skeptical third party would challenge.
|
||||||
|
|
||||||
64
ifttt-src/src/components/blocks/article-1.astro
Normal file
64
ifttt-src/src/components/blocks/article-1.astro
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
item?: {
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, title, description, image, item } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} style={{ "--container": "672px" }}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
{title && <h1>{title}</h1>}
|
||||||
|
{description && <p>{description}</p>}
|
||||||
|
</SectionProse>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia>
|
||||||
|
<Avatar class="size-10">
|
||||||
|
<AvatarImage src={item?.image?.src} alt={item?.image?.alt} />
|
||||||
|
</Avatar>
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{item?.title}</ItemTitle>
|
||||||
|
<ItemDescription>{item?.description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image sizes="(min-width: 672px) 672px, 100vw" priority {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</Section>
|
||||||
64
ifttt-src/src/components/blocks/article-2.astro
Normal file
64
ifttt-src/src/components/blocks/article-2.astro
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
item?: {
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, title, description, image, item } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} style={{ "--container": "672px" }}>
|
||||||
|
<SectionContent class="items-center">
|
||||||
|
<SectionProse class="text-center text-balance">
|
||||||
|
{title && <h1>{title}</h1>}
|
||||||
|
{description && <p>{description}</p>}
|
||||||
|
</SectionProse>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia>
|
||||||
|
<Avatar class="size-10">
|
||||||
|
<AvatarImage src={image?.src} alt={image?.alt} />
|
||||||
|
</Avatar>
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{item?.title}</ItemTitle>
|
||||||
|
<ItemDescription>{item?.description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image sizes="(min-width: 672px) 672px, 100vw" priority {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</Section>
|
||||||
103
ifttt-src/src/components/blocks/articles-1.astro
Normal file
103
ifttt-src/src/components/blocks/articles-1.astro
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
item?: {
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, image, href, item }) => (
|
||||||
|
<Tile href={href}>
|
||||||
|
<TileMedia class="aspect-video">
|
||||||
|
<Image sizes="600px" {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle class="line-clamp-2">{title}</TileTitle>
|
||||||
|
<TileDescription class="line-clamp-2">
|
||||||
|
{description}
|
||||||
|
</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia>
|
||||||
|
<Avatar class="size-10">
|
||||||
|
<AvatarImage src={item?.image?.src} alt={item?.image?.alt} />
|
||||||
|
</Avatar>
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{item?.title}</ItemTitle>
|
||||||
|
<ItemDescription>{item?.description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
104
ifttt-src/src/components/blocks/articles-2.astro
Normal file
104
ifttt-src/src/components/blocks/articles-2.astro
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
item?: {
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit class="@5xl:grid-cols-[2fr_3fr]">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid size="lg">
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, image, href, item }) => (
|
||||||
|
<Tile href={href}>
|
||||||
|
<TileMedia>
|
||||||
|
<Image sizes="820px" {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia>
|
||||||
|
<Avatar class="size-10">
|
||||||
|
<AvatarImage src={item?.image?.src} alt={item?.image?.alt} />
|
||||||
|
</Avatar>
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{item?.title}</ItemTitle>
|
||||||
|
<ItemDescription>{item?.description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
101
ifttt-src/src/components/blocks/articles-3.astro
Normal file
101
ifttt-src/src/components/blocks/articles-3.astro
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
item?: {
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSpread class="@5xl:items-end">
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions class="-mx-3 -my-2">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }) => (
|
||||||
|
<Button variant="link" {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionSpread>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, image, href, item }) => (
|
||||||
|
<Tile href={href}>
|
||||||
|
<TileMedia>
|
||||||
|
<Image sizes="600px" {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia>
|
||||||
|
<Avatar class="size-10">
|
||||||
|
<AvatarImage src={item?.image?.src} alt={item?.image?.alt} />
|
||||||
|
</Avatar>
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{item?.title}</ItemTitle>
|
||||||
|
<ItemDescription>{item?.description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
103
ifttt-src/src/components/blocks/articles-4.astro
Normal file
103
ifttt-src/src/components/blocks/articles-4.astro
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
item?: {
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, image, href, item }) => (
|
||||||
|
<Tile href={href} variant="floating">
|
||||||
|
<TileMedia class="-mx-6 -mt-6 aspect-video">
|
||||||
|
<Image sizes="600px" {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle class="line-clamp-2">{title}</TileTitle>
|
||||||
|
<TileDescription class="line-clamp-2">
|
||||||
|
{description}
|
||||||
|
</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia>
|
||||||
|
<Avatar class="size-10">
|
||||||
|
<AvatarImage src={item?.image?.src} alt={item?.image?.alt} />
|
||||||
|
</Avatar>
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{item?.title}</ItemTitle>
|
||||||
|
<ItemDescription>{item?.description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
25
ifttt-src/src/components/blocks/banner-1.astro
Normal file
25
ifttt-src/src/components/blocks/banner-1.astro
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
import {
|
||||||
|
Banner,
|
||||||
|
BannerContent,
|
||||||
|
BannerDescription,
|
||||||
|
BannerTitle,
|
||||||
|
} from "@/components/ui/banner"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
icon?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const { icon, title, description } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Banner>
|
||||||
|
<BannerContent>
|
||||||
|
<Icon class="size-5" name={icon} />
|
||||||
|
<BannerTitle>{title}</BannerTitle>
|
||||||
|
<BannerDescription>{description}</BannerDescription>
|
||||||
|
</BannerContent>
|
||||||
|
</Banner>
|
||||||
25
ifttt-src/src/components/blocks/banner-2.astro
Normal file
25
ifttt-src/src/components/blocks/banner-2.astro
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
import {
|
||||||
|
Banner,
|
||||||
|
BannerContent,
|
||||||
|
BannerDescription,
|
||||||
|
BannerTitle,
|
||||||
|
} from "@/components/ui/banner"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
icon?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const { icon, title, description } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Banner>
|
||||||
|
<BannerContent class="justify-center pr-6">
|
||||||
|
<Icon class="size-5" name={icon} />
|
||||||
|
<BannerTitle>{title}</BannerTitle>
|
||||||
|
<BannerDescription>{description}</BannerDescription>
|
||||||
|
</BannerContent>
|
||||||
|
</Banner>
|
||||||
66
ifttt-src/src/components/blocks/blocks-1.astro
Normal file
66
ifttt-src/src/components/blocks/blocks-1.astro
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { Section, SectionContent } from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, ...props } = Astro.props
|
||||||
|
|
||||||
|
const allBlocks = import.meta.glob("src/components/blocks/**/*.astro", {
|
||||||
|
eager: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
const sortedBlocks = Object.entries(allBlocks).sort(([a], [b]) =>
|
||||||
|
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" })
|
||||||
|
)
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("@container flex flex-col px-4 py-8", className)} id={id}>
|
||||||
|
<SectionContent
|
||||||
|
class="grid grid-cols-1 gap-6 @3xl:grid-cols-2 @5xl:grid-cols-3"
|
||||||
|
>
|
||||||
|
{
|
||||||
|
sortedBlocks.map(([path, block]: [string, any]) => {
|
||||||
|
const id = path.split("/").pop()?.split(".")[0]
|
||||||
|
const BlockComponent = block.default
|
||||||
|
return BlockComponent ? (
|
||||||
|
<div class="no-scrollbar flex flex-col gap-2">
|
||||||
|
<div class="flex flex-row items-center justify-between">
|
||||||
|
<Badge variant="secondary" href={`/blocks/${id}/`}>
|
||||||
|
{id}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
id={id}
|
||||||
|
class="relative overflow-hidden rounded-lg border-2 border-dashed"
|
||||||
|
>
|
||||||
|
<div class="bg-background no-scrollbar relative aspect-video overflow-x-hidden">
|
||||||
|
<div class="@container h-full w-[200%] origin-top-left scale-50">
|
||||||
|
<BlockComponent {...props}>
|
||||||
|
<Fragment set:html={props?.html} />
|
||||||
|
</BlockComponent>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</SectionContent>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.no-scrollbar {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
95
ifttt-src/src/components/blocks/blocks-2.astro
Normal file
95
ifttt-src/src/components/blocks/blocks-2.astro
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
---
|
||||||
|
import fs from "fs"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import Block from "@/components/block.astro"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
items?: any[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, title, description, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("", className)} id={id}>
|
||||||
|
<SectionSpread>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
{title && <h1>{title}</h1>}
|
||||||
|
{description && <p>{description}</p>}
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
</SectionSpread>
|
||||||
|
<SectionGrid class="grid-cols-1 sm:grid-cols-1 @6xl:grid-cols-2">
|
||||||
|
{
|
||||||
|
items?.map(({ block, href, ...props }) => {
|
||||||
|
if (!block) return null
|
||||||
|
const fileContent = fs.readFileSync(
|
||||||
|
`src/components/blocks/${block}.astro`,
|
||||||
|
"utf8"
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
<div class="group relative aspect-video overflow-hidden rounded-lg border">
|
||||||
|
<div class="bg-background @container h-full w-[400%] origin-top-left scale-25 @xl:w-[200%] @xl:scale-50">
|
||||||
|
<Block block={block} {...props} />
|
||||||
|
</div>
|
||||||
|
<div class="bg-background absolute bottom-0 left-0 hidden w-full items-center justify-between border-t p-4 text-sm shadow-lg group-hover:flex">
|
||||||
|
<Button variant="outline" size="sm" href={href}>
|
||||||
|
<Icon name="eye" class="[&:is(.copied_&)]:hidden" />
|
||||||
|
{block}
|
||||||
|
</Button>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<Button
|
||||||
|
class="copy"
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
data-copy={fileContent}
|
||||||
|
>
|
||||||
|
<Icon name="copy" class="[&:is(.copied_&)]:hidden" />
|
||||||
|
<Icon name="check" class="hidden [&:is(.copied_&)]:block" />
|
||||||
|
Copy code
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
class="copy"
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
data-copy={`npx shadcn@latest add @fulldev/${block}`}
|
||||||
|
>
|
||||||
|
<Icon name="terminal" class="[&:is(.copied_&)]:hidden" />
|
||||||
|
<Icon name="check" class="hidden [&:is(.copied_&)]:block" />
|
||||||
|
npx shadcn add
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const buttons = document.querySelectorAll("button.copy")
|
||||||
|
buttons.forEach((button) => {
|
||||||
|
button.addEventListener("click", () => {
|
||||||
|
const copy = button.getAttribute("data-copy") || ""
|
||||||
|
navigator.clipboard.writeText(copy)
|
||||||
|
button.classList.add("copied")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
sessionStorage.removeItem("closedBanners")
|
||||||
|
</script>
|
||||||
93
ifttt-src/src/components/blocks/blocks-3.astro
Normal file
93
ifttt-src/src/components/blocks/blocks-3.astro
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
---
|
||||||
|
import fs from "fs"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Marquee, MarqueeContent } from "@/components/ui/marquee"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import Block from "@/components/block.astro"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
items?: any[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("", className)} id={id}>
|
||||||
|
<SectionSpread>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
</SectionSpread>
|
||||||
|
<Marquee class="-mx-(--section-px)">
|
||||||
|
<MarqueeContent pauseOnHover>
|
||||||
|
{
|
||||||
|
items?.map(({ block, href, ...props }) => {
|
||||||
|
if (!block) return null
|
||||||
|
const fileContent = fs.readFileSync(
|
||||||
|
`src/components/blocks/${block}.astro`,
|
||||||
|
"utf8"
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
<div class="group relative aspect-video w-[320px] overflow-hidden rounded-lg border @5xl:w-[640px]">
|
||||||
|
<div class="bg-background @container h-full w-[400%] origin-top-left scale-25 @5xl:w-[200%] @5xl:scale-50">
|
||||||
|
<Block block={block} {...props} />
|
||||||
|
</div>
|
||||||
|
<div class="bg-background absolute bottom-0 left-0 hidden w-full items-center justify-between border-t p-4 text-sm shadow-lg group-hover:flex">
|
||||||
|
<h3 class="text-sm font-medium">
|
||||||
|
<a href={href}>{block}</a>
|
||||||
|
</h3>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<Button
|
||||||
|
class="copy"
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
data-copy={fileContent}
|
||||||
|
>
|
||||||
|
<Icon name="copy" class="[&:is(.copied_&)]:hidden" />
|
||||||
|
<Icon name="check" class="hidden [&:is(.copied_&)]:block" />
|
||||||
|
Copy code
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
class="copy"
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
data-copy={`npx shadcn add @fulldev/${block}`}
|
||||||
|
>
|
||||||
|
<Icon name="terminal" class="[&:is(.copied_&)]:hidden" />
|
||||||
|
<Icon name="check" class="hidden [&:is(.copied_&)]:block" />
|
||||||
|
npx shadcn add
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</MarqueeContent>
|
||||||
|
</Marquee>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const buttons = document.querySelectorAll("button.copy")
|
||||||
|
buttons.forEach((button) => {
|
||||||
|
button.addEventListener("click", () => {
|
||||||
|
const copy = button.getAttribute("data-copy") || ""
|
||||||
|
navigator.clipboard.writeText(copy)
|
||||||
|
button.classList.add("copied")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
110
ifttt-src/src/components/blocks/blocks-4.astro
Normal file
110
ifttt-src/src/components/blocks/blocks-4.astro
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
---
|
||||||
|
import fs from "fs"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Marquee, MarqueeContent } from "@/components/ui/marquee"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import Block from "@/components/block.astro"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
items?: any[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("", className)} id={id}>
|
||||||
|
<SectionSpread>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
</SectionSpread>
|
||||||
|
<div class="flex flex-col gap-6">
|
||||||
|
{
|
||||||
|
(["left", "right"] as const).map((direction) => (
|
||||||
|
<Marquee class="-mx-(--section-px) mask-x-from-95%">
|
||||||
|
<MarqueeContent
|
||||||
|
class="animation-duration-80000"
|
||||||
|
direction={direction}
|
||||||
|
pauseOnHover
|
||||||
|
>
|
||||||
|
{items?.map(({ block, href, ...props }) => {
|
||||||
|
if (!block) return null
|
||||||
|
const fileContent = fs.readFileSync(
|
||||||
|
`src/components/blocks/${block}.astro`,
|
||||||
|
"utf8"
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
<div class="group relative aspect-video w-[320px] overflow-hidden rounded-lg border @5xl:w-[640px]">
|
||||||
|
<div class="bg-background @container h-full w-[400%] origin-top-left scale-25 @5xl:w-[200%] @5xl:scale-50">
|
||||||
|
<Block block={block} {...props} />
|
||||||
|
</div>
|
||||||
|
<div class="bg-background absolute bottom-0 left-0 hidden w-full items-center justify-between border-t p-4 text-sm shadow-lg group-hover:flex">
|
||||||
|
<h3 class="text-sm font-medium">
|
||||||
|
<a href={href}>{block}</a>
|
||||||
|
</h3>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<Button
|
||||||
|
class="copy"
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
data-copy={fileContent}
|
||||||
|
>
|
||||||
|
<Icon name="copy" class="[&:is(.copied_&)]:hidden" />
|
||||||
|
<Icon
|
||||||
|
name="check"
|
||||||
|
class="hidden [&:is(.copied_&)]:block"
|
||||||
|
/>
|
||||||
|
Copy code
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
class="copy"
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
data-copy={`npx shadcn@latest add @fulldev/${block}`}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name="terminal"
|
||||||
|
class="[&:is(.copied_&)]:hidden"
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
name="check"
|
||||||
|
class="hidden [&:is(.copied_&)]:block"
|
||||||
|
/>
|
||||||
|
npx shadcn add
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</MarqueeContent>
|
||||||
|
</Marquee>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const buttons = document.querySelectorAll("button.copy")
|
||||||
|
buttons.forEach((button) => {
|
||||||
|
button.addEventListener("click", () => {
|
||||||
|
const copy = button.getAttribute("data-copy") || ""
|
||||||
|
navigator.clipboard.writeText(copy)
|
||||||
|
button.classList.add("copied")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
55
ifttt-src/src/components/blocks/contact-1.astro
Normal file
55
ifttt-src/src/components/blocks/contact-1.astro
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
---
|
||||||
|
import { AutoForm } from "@/components/ui/auto-form"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
form?: any
|
||||||
|
items?: {
|
||||||
|
icon?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, form, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} style="--section-width: 672px;">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ icon, title, description, href }) => (
|
||||||
|
<Item href={href} variant="outline">
|
||||||
|
<ItemMedia variant="icon">
|
||||||
|
<Icon href={href} name={icon} />
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{title}</ItemTitle>
|
||||||
|
<ItemDescription>{description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
<AutoForm {...form} />
|
||||||
|
</Section>
|
||||||
60
ifttt-src/src/components/blocks/contact-2.astro
Normal file
60
ifttt-src/src/components/blocks/contact-2.astro
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
---
|
||||||
|
import { AutoForm } from "@/components/ui/auto-form"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
form?: any
|
||||||
|
items?: {
|
||||||
|
icon?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, form, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit
|
||||||
|
class="items-start @5xl:grid-cols-[3fr_2fr] @5xl:*:sticky @5xl:*:top-[calc(var(--section-py)+var(--header-height,0px))]"
|
||||||
|
>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionGrid class="flex max-w-md flex-col">
|
||||||
|
{
|
||||||
|
items?.map(({ icon, title, description, href }) => (
|
||||||
|
<Item href={href} variant="muted">
|
||||||
|
<ItemMedia variant="icon">
|
||||||
|
<Icon href={href} name={icon} />
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{title}</ItemTitle>
|
||||||
|
<ItemDescription>{description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</SectionContent>
|
||||||
|
<AutoForm {...form} />
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
69
ifttt-src/src/components/blocks/contact-3.astro
Normal file
69
ifttt-src/src/components/blocks/contact-3.astro
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
---
|
||||||
|
import { AutoForm } from "@/components/ui/auto-form"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
form?: any
|
||||||
|
items?: {
|
||||||
|
icon?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, form, items, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit class="gap-x-32">
|
||||||
|
<SectionContent class="gap-16">
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionGrid class="max-w-2xl grid-cols-1!">
|
||||||
|
{
|
||||||
|
items?.map(({ icon, title, description, href }) => (
|
||||||
|
<Item href={href} variant="outline">
|
||||||
|
<ItemMedia variant="icon">
|
||||||
|
<Icon href={href} name={icon} />
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{title}</ItemTitle>
|
||||||
|
<ItemDescription>{description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
<AutoForm {...form} />
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia
|
||||||
|
class="-mr-(--section-px) p-1 @5xl:z-90 @5xl:-mt-[calc(var(--section-py)+var(--header-height,0px))]"
|
||||||
|
>
|
||||||
|
<Image {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
62
ifttt-src/src/components/blocks/content-1.astro
Normal file
62
ifttt-src/src/components/blocks/content-1.astro
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, list, links, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<List>
|
||||||
|
{
|
||||||
|
list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</List>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image sizes="(min-width: 1536px) 1536px, 100vw" {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
68
ifttt-src/src/components/blocks/content-2.astro
Normal file
68
ifttt-src/src/components/blocks/content-2.astro
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, list, links, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit class="@5xl:items-center">
|
||||||
|
<SectionContent class="max-w-xl">
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<List>
|
||||||
|
{
|
||||||
|
list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</List>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image
|
||||||
|
sizes="(min-width: 1536px) 768px, (min-width: 1024px) 50vw, 100vw"
|
||||||
|
{...image}
|
||||||
|
/>
|
||||||
|
</SectionMedia>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
67
ifttt-src/src/components/blocks/content-3.astro
Normal file
67
ifttt-src/src/components/blocks/content-3.astro
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, list, links, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSpread class="@5xl:items-end">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<List>
|
||||||
|
{
|
||||||
|
list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</List>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
</SectionSpread>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image sizes="(min-width: 1536px) 1536px, 100vw" {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
68
ifttt-src/src/components/blocks/content-4.astro
Normal file
68
ifttt-src/src/components/blocks/content-4.astro
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, list, links, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit class="@5xl:grid-cols-[1fr_2fr] @5xl:items-center">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<List>
|
||||||
|
{
|
||||||
|
list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</List>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image
|
||||||
|
sizes="(min-width: 1536px) 1024px, (min-width: 1024px) 66vw, 100vw"
|
||||||
|
{...image}
|
||||||
|
/>
|
||||||
|
</SectionMedia>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
76
ifttt-src/src/components/blocks/content-5.astro
Normal file
76
ifttt-src/src/components/blocks/content-5.astro
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, list, links, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section
|
||||||
|
class={cn(
|
||||||
|
"border-primary/20 my-0 -mt-px rounded-none shadow-none",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
id={id}
|
||||||
|
variant="floating"
|
||||||
|
>
|
||||||
|
<SectionSplit class="@5xl:items-center">
|
||||||
|
<SectionContent class="max-w-xl">
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<List>
|
||||||
|
{
|
||||||
|
list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</List>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "outline" : "ghost"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image
|
||||||
|
sizes="(min-width: 1536px) 768px, (min-width: 1024px) 50vw, 100vw"
|
||||||
|
{...image}
|
||||||
|
/>
|
||||||
|
</SectionMedia>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
76
ifttt-src/src/components/blocks/content-6.astro
Normal file
76
ifttt-src/src/components/blocks/content-6.astro
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, list, links, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section
|
||||||
|
class={cn(
|
||||||
|
"border-primary/20 my-0 -mt-px rounded-none shadow-none",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
id={id}
|
||||||
|
variant="floating"
|
||||||
|
>
|
||||||
|
<SectionSplit class="@5xl:items-center">
|
||||||
|
<SectionContent class="max-w-xl">
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<List>
|
||||||
|
{
|
||||||
|
list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</List>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "outline" : "ghost"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia class="@5xl:order-first">
|
||||||
|
<Image
|
||||||
|
sizes="(min-width: 1536px) 768px, (min-width: 1024px) 50vw, 100vw"
|
||||||
|
{...image}
|
||||||
|
/>
|
||||||
|
</SectionMedia>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
78
ifttt-src/src/components/blocks/cta-1.astro
Normal file
78
ifttt-src/src/components/blocks/cta-1.astro
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, item } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} variant="floating">
|
||||||
|
<SectionContent class="items-center">
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription>
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
<SectionProse class="text-center" size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions class="justify-center">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
</Section>
|
||||||
88
ifttt-src/src/components/blocks/cta-2.astro
Normal file
88
ifttt-src/src/components/blocks/cta-2.astro
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, image, item } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} variant="floating">
|
||||||
|
<SectionSplit class="@5xl:items-center">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-4">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-10 ring-2">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription>
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia
|
||||||
|
class="-mx-(--section-px) rounded-none @5xl:-my-(--section-py) @5xl:-ml-0"
|
||||||
|
>
|
||||||
|
<Image sizes="(1536px) 768px, (1024px) 50vw, 100vw" {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
82
ifttt-src/src/components/blocks/cta-3.astro
Normal file
82
ifttt-src/src/components/blocks/cta-3.astro
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, item } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section
|
||||||
|
class={cn("bg-accent/50 shadow-none", className)}
|
||||||
|
id={id}
|
||||||
|
variant="floating"
|
||||||
|
>
|
||||||
|
<SectionSpread class="@5xl:items-center">
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "secondary"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription>
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
</SectionSpread>
|
||||||
|
</Section>
|
||||||
83
ifttt-src/src/components/blocks/cta-4.astro
Normal file
83
ifttt-src/src/components/blocks/cta-4.astro
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, item, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} variant="floating">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription class="text-foreground">
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia class="absolute inset-0 size-full opacity-50">
|
||||||
|
<Image sizes="(1536px) 1536px, 100vw" {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
88
ifttt-src/src/components/blocks/cta-5.astro
Normal file
88
ifttt-src/src/components/blocks/cta-5.astro
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, image, item } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} variant="floating">
|
||||||
|
<SectionSpread class="@5xl:items-center">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription class="text-foreground">
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
</SectionSpread>
|
||||||
|
<SectionMedia class="absolute inset-0 size-full opacity-50">
|
||||||
|
<Image sizes="(1536px) 1536px, 100vw" {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
78
ifttt-src/src/components/blocks/cta-6.astro
Normal file
78
ifttt-src/src/components/blocks/cta-6.astro
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, item } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("bg-accent/50", className)} id={id}>
|
||||||
|
<SectionSpread class="@5xl:items-center">
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "secondary"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription>
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
</SectionSpread>
|
||||||
|
</Section>
|
||||||
90
ifttt-src/src/components/blocks/cta-7.astro
Normal file
90
ifttt-src/src/components/blocks/cta-7.astro
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, image, item } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} size="lg">
|
||||||
|
<SectionMedia class="absolute inset-0 size-full rounded-none mask-y-from-0%">
|
||||||
|
<Image sizes="(1536px) 1536px, 100vw" {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
<SectionSpread class="relative @5xl:items-center">
|
||||||
|
<SectionProse size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionContent class="shrink-0">
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
class="w-full"
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription class="text-foreground">
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
</SectionSpread>
|
||||||
|
</Section>
|
||||||
91
ifttt-src/src/components/blocks/cta-8.astro
Normal file
91
ifttt-src/src/components/blocks/cta-8.astro
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, item } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section
|
||||||
|
class={cn(
|
||||||
|
"border-primary/20 my-0 -mt-px rounded-none shadow-none",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
id={id}
|
||||||
|
variant="floating"
|
||||||
|
size="lg"
|
||||||
|
>
|
||||||
|
<SectionContent
|
||||||
|
class={cn(
|
||||||
|
"before:from-primary/20 relative items-center before:absolute before:top-full before:left-0 before:-z-10 before:h-[200%] before:w-full before:animate-pulse before:rounded-full before:bg-gradient-to-b before:to-transparent before:blur-3xl"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription>
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
<SectionProse class="text-center" size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions class="justify-center">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "outline"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
</Section>
|
||||||
61
ifttt-src/src/components/blocks/faqs-1.astro
Normal file
61
ifttt-src/src/components/blocks/faqs-1.astro
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
---
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<Accordion>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description }) => (
|
||||||
|
<AccordionItem>
|
||||||
|
<AccordionTrigger>{title}</AccordionTrigger>
|
||||||
|
<AccordionContent>{description}</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Accordion>
|
||||||
|
</Section>
|
||||||
64
ifttt-src/src/components/blocks/faqs-2.astro
Normal file
64
ifttt-src/src/components/blocks/faqs-2.astro
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
---
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<Accordion>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description }) => (
|
||||||
|
<AccordionItem>
|
||||||
|
<AccordionTrigger>{title}</AccordionTrigger>
|
||||||
|
<AccordionContent>{description}</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Accordion>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
61
ifttt-src/src/components/blocks/faqs-3.astro
Normal file
61
ifttt-src/src/components/blocks/faqs-3.astro
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
---
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSpread class="@5xl:items-end">
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionSpread>
|
||||||
|
<Accordion>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description }) => (
|
||||||
|
<AccordionItem>
|
||||||
|
<AccordionTrigger>{title}</AccordionTrigger>
|
||||||
|
<AccordionContent>{description}</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Accordion>
|
||||||
|
</Section>
|
||||||
61
ifttt-src/src/components/blocks/faqs-4.astro
Normal file
61
ifttt-src/src/components/blocks/faqs-4.astro
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
---
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} style="--section-width: 672px;">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<Accordion>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description }) => (
|
||||||
|
<AccordionItem>
|
||||||
|
<AccordionTrigger>{title}</AccordionTrigger>
|
||||||
|
<AccordionContent>{description}</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Accordion>
|
||||||
|
</Section>
|
||||||
90
ifttt-src/src/components/blocks/features-1.astro
Normal file
90
ifttt-src/src/components/blocks/features-1.astro
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileActions,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
icon?: string
|
||||||
|
href?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, icon, links }) => (
|
||||||
|
<Tile>
|
||||||
|
<TileMedia variant="icon">
|
||||||
|
<Icon name={icon} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
<TileActions>
|
||||||
|
{links?.map(({ icon, text, href, target }) => (
|
||||||
|
<Button
|
||||||
|
class="h-auto p-0"
|
||||||
|
variant="link"
|
||||||
|
href={href}
|
||||||
|
target={target}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</TileActions>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
90
ifttt-src/src/components/blocks/features-2.astro
Normal file
90
ifttt-src/src/components/blocks/features-2.astro
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileActions,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
icon?: string
|
||||||
|
href?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent class="items-center">
|
||||||
|
<SectionProse class="text-center">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions class="justify-center">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, icon, links }) => (
|
||||||
|
<Tile class="items-center">
|
||||||
|
<TileMedia variant="icon">
|
||||||
|
<Icon name={icon} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent class="items-center text-center text-balance">
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
<TileActions class="justify-center">
|
||||||
|
{links?.map(({ icon, text, href, target }) => (
|
||||||
|
<Button
|
||||||
|
class="h-auto p-0"
|
||||||
|
variant="link"
|
||||||
|
href={href}
|
||||||
|
target={target}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</TileActions>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
58
ifttt-src/src/components/blocks/features-3.astro
Normal file
58
ifttt-src/src/components/blocks/features-3.astro
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
---
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileSplit,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent class="@5xl:items-center">
|
||||||
|
<SectionProse class="@5xl:text-center">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, href, image }) => (
|
||||||
|
<Tile href={href}>
|
||||||
|
<TileSplit class="items-center">
|
||||||
|
<TileMedia>
|
||||||
|
<Image sizes="230px" {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
</TileSplit>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
95
ifttt-src/src/components/blocks/features-4.astro
Normal file
95
ifttt-src/src/components/blocks/features-4.astro
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileActions,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
icon?: string
|
||||||
|
href?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit class="@5xl:grid-cols-[1fr_2fr]">
|
||||||
|
<SectionContent
|
||||||
|
class="@5xl:sticky @5xl:top-[calc(var(--section-py)+var(--header-height,0px))]"
|
||||||
|
>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid size="lg">
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, icon, links }) => (
|
||||||
|
<Tile>
|
||||||
|
<TileMedia variant="icon">
|
||||||
|
<Icon name={icon} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
<TileActions>
|
||||||
|
{links?.map(({ icon, text, href, target }) => (
|
||||||
|
<Button
|
||||||
|
class="h-auto p-0"
|
||||||
|
variant="link"
|
||||||
|
href={href}
|
||||||
|
target={target}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</TileActions>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
100
ifttt-src/src/components/blocks/features-5.astro
Normal file
100
ifttt-src/src/components/blocks/features-5.astro
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileActions,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
icon?: string
|
||||||
|
href?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section
|
||||||
|
class={cn(
|
||||||
|
"border-primary/20 my-0 -mt-px rounded-none shadow-none",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
id={id}
|
||||||
|
variant="floating"
|
||||||
|
>
|
||||||
|
<SectionContent class="items-center">
|
||||||
|
<SectionProse class="text-center">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions class="justify-center">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, icon, links }) => (
|
||||||
|
<Tile class="items-center">
|
||||||
|
<TileMedia class="bg-primary/5 border-primary/20" variant="icon">
|
||||||
|
<Icon class="text-primary" name={icon} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent class="items-center text-center text-balance">
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription class="text-foreground">
|
||||||
|
{description}
|
||||||
|
</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
<TileActions class="justify-center">
|
||||||
|
{links?.map(({ icon, text, href, target }) => (
|
||||||
|
<Button
|
||||||
|
class="h-auto p-0"
|
||||||
|
variant="link"
|
||||||
|
href={href}
|
||||||
|
target={target}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</TileActions>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
72
ifttt-src/src/components/blocks/features-6.astro
Normal file
72
ifttt-src/src/components/blocks/features-6.astro
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileDescription,
|
||||||
|
TileSplit,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
icon?: string
|
||||||
|
href?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid class="grid-cols-1! gap-12">
|
||||||
|
{
|
||||||
|
items?.map(({ title, description }) => (
|
||||||
|
<Tile class="border-t pt-12">
|
||||||
|
<TileSplit>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileSplit>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
92
ifttt-src/src/components/blocks/footer-1.astro
Normal file
92
ifttt-src/src/components/blocks/footer-1.astro
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
---
|
||||||
|
import {
|
||||||
|
Footer,
|
||||||
|
FooterDescription,
|
||||||
|
FooterGrid,
|
||||||
|
FooterGroup,
|
||||||
|
FooterGroupLabel,
|
||||||
|
FooterMenu,
|
||||||
|
FooterMenuItem,
|
||||||
|
FooterMenuLink,
|
||||||
|
FooterSplit,
|
||||||
|
} from "@/components/ui/footer"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Logo, LogoImage, LogoText } from "@/components/ui/logo"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
logo?: {
|
||||||
|
src?: string
|
||||||
|
alt?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}
|
||||||
|
description?: string
|
||||||
|
socials?: string[]
|
||||||
|
menus?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
links?: {
|
||||||
|
href?: string
|
||||||
|
text?: string
|
||||||
|
icon?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { logo, description, links, socials, menus } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Footer>
|
||||||
|
<FooterSplit class="@5xl:grid-cols-[1fr_3fr]">
|
||||||
|
<FooterGroup>
|
||||||
|
<Logo href={logo?.href || "/"}>
|
||||||
|
<LogoImage src={logo?.src} alt={logo?.alt} />
|
||||||
|
<LogoText>{logo?.text}</LogoText>
|
||||||
|
</Logo>
|
||||||
|
<FooterDescription>{description}</FooterDescription>
|
||||||
|
<FooterMenu>
|
||||||
|
{
|
||||||
|
links?.map(({ href, icon, text }) => (
|
||||||
|
<FooterMenuItem>
|
||||||
|
<FooterMenuLink href={href}>
|
||||||
|
<Icon href={href} name={icon} />
|
||||||
|
{text}
|
||||||
|
</FooterMenuLink>
|
||||||
|
</FooterMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</FooterMenu>
|
||||||
|
<FooterMenu orientation="horizontal">
|
||||||
|
{
|
||||||
|
socials?.map((social) => (
|
||||||
|
<FooterMenuItem>
|
||||||
|
<FooterMenuLink href={social}>
|
||||||
|
<Icon href={social} />
|
||||||
|
</FooterMenuLink>
|
||||||
|
</FooterMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</FooterMenu>
|
||||||
|
</FooterGroup>
|
||||||
|
<FooterGrid class="@5xl:justify-end">
|
||||||
|
{
|
||||||
|
menus?.map((menu) => (
|
||||||
|
<FooterGroup>
|
||||||
|
<FooterGroupLabel>{menu.text}</FooterGroupLabel>
|
||||||
|
<FooterMenu>
|
||||||
|
{menu.links?.map(({ href, text }) => (
|
||||||
|
<FooterMenuItem>
|
||||||
|
<FooterMenuLink href={href}>{text}</FooterMenuLink>
|
||||||
|
</FooterMenuItem>
|
||||||
|
))}
|
||||||
|
</FooterMenu>
|
||||||
|
</FooterGroup>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</FooterGrid>
|
||||||
|
</FooterSplit>
|
||||||
|
</Footer>
|
||||||
61
ifttt-src/src/components/blocks/footer-2.astro
Normal file
61
ifttt-src/src/components/blocks/footer-2.astro
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
---
|
||||||
|
import {
|
||||||
|
Footer,
|
||||||
|
FooterCopyright,
|
||||||
|
FooterDescription,
|
||||||
|
FooterGroup,
|
||||||
|
FooterMenu,
|
||||||
|
FooterMenuItem,
|
||||||
|
FooterMenuLink,
|
||||||
|
} from "@/components/ui/footer"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Logo, LogoImage, LogoText } from "@/components/ui/logo"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
logo?: {
|
||||||
|
src?: string
|
||||||
|
alt?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}
|
||||||
|
description?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
socials?: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { logo, description, links, socials } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Footer class="items-center">
|
||||||
|
<FooterGroup class="items-center">
|
||||||
|
<Logo href={logo?.href || "/"}>
|
||||||
|
<LogoImage src={logo?.src} alt={logo?.alt} />
|
||||||
|
<LogoText>{logo?.text}</LogoText>
|
||||||
|
</Logo>
|
||||||
|
<FooterDescription>{description}</FooterDescription>
|
||||||
|
<FooterMenu orientation="horizontal">
|
||||||
|
{
|
||||||
|
links?.map(({ href, text }) => (
|
||||||
|
<FooterMenuItem>
|
||||||
|
<FooterMenuLink href={href}>{text}</FooterMenuLink>
|
||||||
|
</FooterMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</FooterMenu>
|
||||||
|
<FooterMenu orientation="horizontal">
|
||||||
|
{
|
||||||
|
socials?.map((social) => (
|
||||||
|
<FooterMenuItem>
|
||||||
|
<FooterMenuLink href={social}>
|
||||||
|
<Icon href={social} />
|
||||||
|
</FooterMenuLink>
|
||||||
|
</FooterMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</FooterMenu>
|
||||||
|
</FooterGroup>
|
||||||
|
<FooterCopyright>{logo?.text}</FooterCopyright>
|
||||||
|
</Footer>
|
||||||
102
ifttt-src/src/components/blocks/footer-3.astro
Normal file
102
ifttt-src/src/components/blocks/footer-3.astro
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
---
|
||||||
|
import {
|
||||||
|
Footer,
|
||||||
|
FooterCopyright,
|
||||||
|
FooterDescription,
|
||||||
|
FooterGrid,
|
||||||
|
FooterGroup,
|
||||||
|
FooterGroupLabel,
|
||||||
|
FooterMenu,
|
||||||
|
FooterMenuItem,
|
||||||
|
FooterMenuLink,
|
||||||
|
FooterSplit,
|
||||||
|
FooterSpread,
|
||||||
|
} from "@/components/ui/footer"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Logo, LogoImage, LogoText } from "@/components/ui/logo"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
logo?: {
|
||||||
|
src?: string
|
||||||
|
alt?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}
|
||||||
|
description?: string
|
||||||
|
socials?: string[]
|
||||||
|
menus?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
links?: {
|
||||||
|
href?: string
|
||||||
|
text?: string
|
||||||
|
icon?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { logo, description, links, socials, menus } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Footer>
|
||||||
|
<FooterSplit class="@5xl:grid-cols-[1fr_3fr]">
|
||||||
|
<FooterDescription class="text-base">{description}</FooterDescription>
|
||||||
|
<FooterGrid class="@5xl:justify-end">
|
||||||
|
{
|
||||||
|
menus?.map((menu) => (
|
||||||
|
<FooterGroup>
|
||||||
|
<FooterGroupLabel>{menu.text}</FooterGroupLabel>
|
||||||
|
<FooterMenu>
|
||||||
|
{menu.links?.map(({ href, text }) => (
|
||||||
|
<FooterMenuItem>
|
||||||
|
<FooterMenuLink href={href}>{text}</FooterMenuLink>
|
||||||
|
</FooterMenuItem>
|
||||||
|
))}
|
||||||
|
</FooterMenu>
|
||||||
|
</FooterGroup>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</FooterGrid>
|
||||||
|
</FooterSplit>
|
||||||
|
<Logo class="h-auto max-h-none w-full max-w-none" href={logo?.href || "/"}>
|
||||||
|
<LogoImage
|
||||||
|
src={logo?.src}
|
||||||
|
alt={logo?.alt}
|
||||||
|
sizes="(min-width: 1536px) 1536px, 100vw"
|
||||||
|
class="h-auto max-h-none w-full max-w-none object-contain"
|
||||||
|
/>
|
||||||
|
<LogoText>{logo?.text}</LogoText>
|
||||||
|
</Logo>
|
||||||
|
<FooterSpread>
|
||||||
|
<FooterCopyright>{logo?.text}</FooterCopyright>
|
||||||
|
<FooterMenu
|
||||||
|
orientation="horizontal"
|
||||||
|
class="@5xl:absolute @5xl:left-1/2 @5xl:-translate-x-1/2"
|
||||||
|
>
|
||||||
|
{
|
||||||
|
socials?.map((social) => (
|
||||||
|
<FooterMenuItem>
|
||||||
|
<FooterMenuLink href={social}>
|
||||||
|
<Icon href={social} />
|
||||||
|
</FooterMenuLink>
|
||||||
|
</FooterMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</FooterMenu>
|
||||||
|
<FooterMenu orientation="horizontal">
|
||||||
|
{
|
||||||
|
links?.map(({ href, text }) => (
|
||||||
|
<FooterMenuItem>
|
||||||
|
<FooterMenuLink class="text-xs" href={href}>
|
||||||
|
{text}
|
||||||
|
</FooterMenuLink>
|
||||||
|
</FooterMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</FooterMenu>
|
||||||
|
</FooterSpread>
|
||||||
|
</Footer>
|
||||||
200
ifttt-src/src/components/blocks/header-1.astro
Normal file
200
ifttt-src/src/components/blocks/header-1.astro
Normal file
|
|
@ -0,0 +1,200 @@
|
||||||
|
---
|
||||||
|
import MenuIcon from "lucide-static/icons/menu.svg"
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import {
|
||||||
|
Collapsible,
|
||||||
|
CollapsibleContent,
|
||||||
|
CollapsibleTrigger,
|
||||||
|
} from "@/components/ui/collapsible"
|
||||||
|
import { Header, HeaderActions } from "@/components/ui/header"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Logo, LogoImage, LogoText } from "@/components/ui/logo"
|
||||||
|
import {
|
||||||
|
NavigationMenu,
|
||||||
|
NavigationMenuContent,
|
||||||
|
NavigationMenuItem,
|
||||||
|
NavigationMenuLink,
|
||||||
|
NavigationMenuList,
|
||||||
|
NavigationMenuSub,
|
||||||
|
NavigationMenuSubItem,
|
||||||
|
NavigationMenuSubLink,
|
||||||
|
NavigationMenuTrigger,
|
||||||
|
} from "@/components/ui/navigation-menu"
|
||||||
|
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"
|
||||||
|
import {
|
||||||
|
SidebarMenu,
|
||||||
|
SidebarMenuButton,
|
||||||
|
SidebarMenuItem,
|
||||||
|
SidebarMenuSub,
|
||||||
|
SidebarMenuSubButton,
|
||||||
|
SidebarMenuSubItem,
|
||||||
|
} from "@/components/ui/sidebar"
|
||||||
|
import { ThemeToggle } from "@/components/ui/theme-toggle"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
logo?: {
|
||||||
|
src?: string
|
||||||
|
alt?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
socials?: string[]
|
||||||
|
menus?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { logo, menus, links, socials } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Header>
|
||||||
|
<Logo href={logo?.href || "/"}>
|
||||||
|
<LogoImage src={logo?.src} alt={logo?.alt} />
|
||||||
|
<LogoText>{logo?.text}</LogoText>
|
||||||
|
</Logo>
|
||||||
|
<NavigationMenu class="mr-auto @max-5xl:hidden">
|
||||||
|
<NavigationMenuList>
|
||||||
|
{
|
||||||
|
menus?.map((menu) => (
|
||||||
|
<NavigationMenuItem>
|
||||||
|
{menu.links && menu.links.length > 0 ? (
|
||||||
|
<>
|
||||||
|
<NavigationMenuTrigger
|
||||||
|
class="inline-flex h-8 items-center bg-transparent px-3 py-0"
|
||||||
|
href={menu.href}
|
||||||
|
>
|
||||||
|
{menu.text}
|
||||||
|
</NavigationMenuTrigger>
|
||||||
|
<NavigationMenuContent>
|
||||||
|
<NavigationMenuSub>
|
||||||
|
{menu.links?.map((link) => (
|
||||||
|
<NavigationMenuSubItem>
|
||||||
|
<NavigationMenuSubLink href={link.href}>
|
||||||
|
{link.text}
|
||||||
|
</NavigationMenuSubLink>
|
||||||
|
</NavigationMenuSubItem>
|
||||||
|
))}
|
||||||
|
</NavigationMenuSub>
|
||||||
|
</NavigationMenuContent>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<NavigationMenuLink
|
||||||
|
class="inline-flex h-8 items-center bg-transparent px-3 py-0"
|
||||||
|
variant="trigger"
|
||||||
|
href={menu.href}
|
||||||
|
>
|
||||||
|
{menu.text}
|
||||||
|
</NavigationMenuLink>
|
||||||
|
)}
|
||||||
|
</NavigationMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</NavigationMenuList>
|
||||||
|
</NavigationMenu>
|
||||||
|
<HeaderActions class="@max-5xl:hidden">
|
||||||
|
{
|
||||||
|
socials?.map((social) => (
|
||||||
|
<>
|
||||||
|
<Button variant="ghost" size="icon-sm" href={social} target="_blank">
|
||||||
|
<Icon href={social} />
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
<ThemeToggle />
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === links.length - 1 ? "default" : "outline"}
|
||||||
|
size="sm"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</HeaderActions>
|
||||||
|
<Sheet class="first:ml-auto">
|
||||||
|
<SheetTrigger
|
||||||
|
class="@5xl:hidden"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
name="open-menu-button"
|
||||||
|
>
|
||||||
|
<MenuIcon class="size-5" />
|
||||||
|
</SheetTrigger>
|
||||||
|
<SheetContent class="overflow-y-auto px-4 py-12">
|
||||||
|
<SidebarMenu>
|
||||||
|
{
|
||||||
|
menus?.map((menu) => (
|
||||||
|
<SidebarMenuItem>
|
||||||
|
{menu.links && menu.links.length > 0 ? (
|
||||||
|
<Collapsible>
|
||||||
|
<CollapsibleTrigger>
|
||||||
|
<SidebarMenuButton class="h-10 rounded-md px-4 text-xl">
|
||||||
|
{menu.text}
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
<CollapsibleContent>
|
||||||
|
<SidebarMenuSub>
|
||||||
|
{menu.links?.map((link) => (
|
||||||
|
<SidebarMenuSubItem>
|
||||||
|
<SidebarMenuSubButton href={link.href}>
|
||||||
|
{link.text}
|
||||||
|
</SidebarMenuSubButton>
|
||||||
|
</SidebarMenuSubItem>
|
||||||
|
))}
|
||||||
|
</SidebarMenuSub>
|
||||||
|
</CollapsibleContent>
|
||||||
|
</Collapsible>
|
||||||
|
) : (
|
||||||
|
<SidebarMenuButton
|
||||||
|
class="h-10 w-full rounded-md px-4 text-xl has-[>svg]:px-4"
|
||||||
|
href={menu.href}
|
||||||
|
>
|
||||||
|
{menu.text}
|
||||||
|
</SidebarMenuButton>
|
||||||
|
)}
|
||||||
|
</SidebarMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SidebarMenu>
|
||||||
|
<HeaderActions class="flex flex-col gap-2">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === links.length - 1 ? "default" : "secondary"}
|
||||||
|
class="w-full"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</HeaderActions>
|
||||||
|
<HeaderActions>
|
||||||
|
{
|
||||||
|
socials?.map((social) => (
|
||||||
|
<Button variant="ghost" size="icon" href={social}>
|
||||||
|
<Icon href={social} />
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</HeaderActions>
|
||||||
|
</SheetContent>
|
||||||
|
</Sheet>
|
||||||
|
</Header>
|
||||||
195
ifttt-src/src/components/blocks/header-2.astro
Normal file
195
ifttt-src/src/components/blocks/header-2.astro
Normal file
|
|
@ -0,0 +1,195 @@
|
||||||
|
---
|
||||||
|
import MenuIcon from "lucide-static/icons/menu.svg"
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import {
|
||||||
|
Collapsible,
|
||||||
|
CollapsibleContent,
|
||||||
|
CollapsibleTrigger,
|
||||||
|
} from "@/components/ui/collapsible"
|
||||||
|
import { Header, HeaderActions } from "@/components/ui/header"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Logo, LogoImage, LogoText } from "@/components/ui/logo"
|
||||||
|
import {
|
||||||
|
NavigationMenu,
|
||||||
|
NavigationMenuContent,
|
||||||
|
NavigationMenuItem,
|
||||||
|
NavigationMenuLink,
|
||||||
|
NavigationMenuList,
|
||||||
|
NavigationMenuSub,
|
||||||
|
NavigationMenuSubItem,
|
||||||
|
NavigationMenuSubLink,
|
||||||
|
NavigationMenuTrigger,
|
||||||
|
} from "@/components/ui/navigation-menu"
|
||||||
|
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"
|
||||||
|
import {
|
||||||
|
SidebarMenu,
|
||||||
|
SidebarMenuButton,
|
||||||
|
SidebarMenuItem,
|
||||||
|
SidebarMenuSub,
|
||||||
|
SidebarMenuSubButton,
|
||||||
|
SidebarMenuSubItem,
|
||||||
|
} from "@/components/ui/sidebar"
|
||||||
|
import { ThemeToggle } from "@/components/ui/theme-toggle"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
logo?: {
|
||||||
|
src?: string
|
||||||
|
alt?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
socials?: string[]
|
||||||
|
menus?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { logo, menus, links, socials } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Header>
|
||||||
|
<Logo href={logo?.href || "/"}>
|
||||||
|
<LogoImage src={logo?.src} alt={logo?.alt} />
|
||||||
|
<LogoText>{logo?.text}</LogoText>
|
||||||
|
</Logo>
|
||||||
|
<NavigationMenu class="absolute left-1/2 -translate-x-1/2 @max-5xl:hidden">
|
||||||
|
<NavigationMenuList>
|
||||||
|
{
|
||||||
|
menus?.map((menu) => (
|
||||||
|
<NavigationMenuItem>
|
||||||
|
{menu.links && menu.links.length > 0 ? (
|
||||||
|
<>
|
||||||
|
<NavigationMenuTrigger
|
||||||
|
class="inline-flex h-8 items-center bg-transparent px-3 py-0"
|
||||||
|
href={menu.href}
|
||||||
|
>
|
||||||
|
{menu.text}
|
||||||
|
</NavigationMenuTrigger>
|
||||||
|
<NavigationMenuContent>
|
||||||
|
<NavigationMenuSub>
|
||||||
|
{menu.links?.map((link) => (
|
||||||
|
<NavigationMenuSubItem>
|
||||||
|
<NavigationMenuSubLink href={link.href}>
|
||||||
|
{link.text}
|
||||||
|
</NavigationMenuSubLink>
|
||||||
|
</NavigationMenuSubItem>
|
||||||
|
))}
|
||||||
|
</NavigationMenuSub>
|
||||||
|
</NavigationMenuContent>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<NavigationMenuLink
|
||||||
|
class="inline-flex h-8 items-center bg-transparent px-3 py-0"
|
||||||
|
variant="trigger"
|
||||||
|
href={menu.href}
|
||||||
|
>
|
||||||
|
{menu.text}
|
||||||
|
</NavigationMenuLink>
|
||||||
|
)}
|
||||||
|
</NavigationMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</NavigationMenuList>
|
||||||
|
</NavigationMenu>
|
||||||
|
<HeaderActions class="@max-5xl:hidden">
|
||||||
|
<ThemeToggle />
|
||||||
|
{
|
||||||
|
socials?.map((social) => (
|
||||||
|
<Button variant="ghost" size="icon-sm" href={social} target="_blank">
|
||||||
|
<Icon href={social} />
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === links.length - 1 ? "default" : "ghost"}
|
||||||
|
size="sm"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</HeaderActions>
|
||||||
|
<Sheet>
|
||||||
|
<SheetTrigger
|
||||||
|
class="@5xl:hidden"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
name="open-menu-button"
|
||||||
|
>
|
||||||
|
<MenuIcon class="size-5" />
|
||||||
|
</SheetTrigger>
|
||||||
|
<SheetContent class="overflow-y-auto px-4 py-12">
|
||||||
|
<SidebarMenu>
|
||||||
|
{
|
||||||
|
menus?.map((menu) => (
|
||||||
|
<SidebarMenuItem>
|
||||||
|
{menu.links && menu.links.length > 0 ? (
|
||||||
|
<Collapsible>
|
||||||
|
<CollapsibleTrigger>
|
||||||
|
<SidebarMenuButton>{menu.text}</SidebarMenuButton>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
<CollapsibleContent>
|
||||||
|
<SidebarMenuSub>
|
||||||
|
{menu.links?.map((link) => (
|
||||||
|
<SidebarMenuSubItem>
|
||||||
|
<SidebarMenuSubButton href={link.href}>
|
||||||
|
{link.text}
|
||||||
|
</SidebarMenuSubButton>
|
||||||
|
</SidebarMenuSubItem>
|
||||||
|
))}
|
||||||
|
</SidebarMenuSub>
|
||||||
|
</CollapsibleContent>
|
||||||
|
</Collapsible>
|
||||||
|
) : (
|
||||||
|
<SidebarMenuButton
|
||||||
|
class="h-10 w-full rounded-md px-4 text-xl has-[>svg]:px-4"
|
||||||
|
href={menu.href}
|
||||||
|
>
|
||||||
|
{menu.text}
|
||||||
|
</SidebarMenuButton>
|
||||||
|
)}
|
||||||
|
</SidebarMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SidebarMenu>
|
||||||
|
<HeaderActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === links.length - 1 ? "default" : "ghost"}
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</HeaderActions>
|
||||||
|
<HeaderActions>
|
||||||
|
{
|
||||||
|
socials?.map((social) => (
|
||||||
|
<Button variant="ghost" size="icon" href={social}>
|
||||||
|
<Icon href={social} />
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</HeaderActions>
|
||||||
|
</SheetContent>
|
||||||
|
</Sheet>
|
||||||
|
</Header>
|
||||||
213
ifttt-src/src/components/blocks/header-3.astro
Normal file
213
ifttt-src/src/components/blocks/header-3.astro
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
---
|
||||||
|
import MenuIcon from "lucide-static/icons/menu.svg"
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import {
|
||||||
|
Collapsible,
|
||||||
|
CollapsibleContent,
|
||||||
|
CollapsibleTrigger,
|
||||||
|
} from "@/components/ui/collapsible"
|
||||||
|
import { Header, HeaderActions } from "@/components/ui/header"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Logo, LogoImage, LogoText } from "@/components/ui/logo"
|
||||||
|
import {
|
||||||
|
NavigationMenu,
|
||||||
|
NavigationMenuContent,
|
||||||
|
NavigationMenuItem,
|
||||||
|
NavigationMenuLink,
|
||||||
|
NavigationMenuList,
|
||||||
|
NavigationMenuSub,
|
||||||
|
NavigationMenuSubItem,
|
||||||
|
NavigationMenuSubLink,
|
||||||
|
NavigationMenuTrigger,
|
||||||
|
} from "@/components/ui/navigation-menu"
|
||||||
|
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"
|
||||||
|
import {
|
||||||
|
SidebarMenu,
|
||||||
|
SidebarMenuButton,
|
||||||
|
SidebarMenuItem,
|
||||||
|
SidebarMenuSub,
|
||||||
|
SidebarMenuSubButton,
|
||||||
|
SidebarMenuSubItem,
|
||||||
|
} from "@/components/ui/sidebar"
|
||||||
|
import { ThemeToggle } from "@/components/ui/theme-toggle"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
logo?: {
|
||||||
|
src?: string
|
||||||
|
alt?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
socials?: string[]
|
||||||
|
menus?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { logo, menus, links, socials } = Astro.props
|
||||||
|
|
||||||
|
const githubStarCount = (
|
||||||
|
await (await fetch("https://api.github.com/repos/fulldotdev/ui")).json()
|
||||||
|
).stargazers_count
|
||||||
|
---
|
||||||
|
|
||||||
|
<Header class="bg-background/60 backdrop-blur-md">
|
||||||
|
<Logo href={logo?.href || "/"}>
|
||||||
|
<LogoImage src={logo?.src} alt={logo?.alt} />
|
||||||
|
<LogoText>{logo?.text}</LogoText>
|
||||||
|
</Logo>
|
||||||
|
<NavigationMenu class="mr-auto @max-5xl:hidden">
|
||||||
|
<NavigationMenuList>
|
||||||
|
{
|
||||||
|
menus?.map((menu) => (
|
||||||
|
<NavigationMenuItem>
|
||||||
|
{menu.links && menu.links.length > 0 ? (
|
||||||
|
<>
|
||||||
|
<NavigationMenuTrigger
|
||||||
|
class="inline-flex h-8 items-center bg-transparent px-3 py-0"
|
||||||
|
href={menu.href}
|
||||||
|
>
|
||||||
|
{menu.text}
|
||||||
|
</NavigationMenuTrigger>
|
||||||
|
<NavigationMenuContent>
|
||||||
|
<NavigationMenuSub>
|
||||||
|
{menu.links?.map((link) => (
|
||||||
|
<NavigationMenuSubItem>
|
||||||
|
<NavigationMenuSubLink href={link.href}>
|
||||||
|
{link.text}
|
||||||
|
</NavigationMenuSubLink>
|
||||||
|
</NavigationMenuSubItem>
|
||||||
|
))}
|
||||||
|
</NavigationMenuSub>
|
||||||
|
</NavigationMenuContent>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<NavigationMenuLink
|
||||||
|
class="inline-flex h-8 items-center bg-transparent px-3 py-0"
|
||||||
|
variant="trigger"
|
||||||
|
href={menu.href}
|
||||||
|
>
|
||||||
|
{menu.text}
|
||||||
|
</NavigationMenuLink>
|
||||||
|
)}
|
||||||
|
</NavigationMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</NavigationMenuList>
|
||||||
|
</NavigationMenu>
|
||||||
|
<HeaderActions class="@max-5xl:hidden">
|
||||||
|
<ThemeToggle />
|
||||||
|
{
|
||||||
|
socials?.map((social) => (
|
||||||
|
<>
|
||||||
|
<Button variant="ghost" size="icon-sm" href={social} target="_blank">
|
||||||
|
<Icon href={social} />
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === links.length - 1 ? "default" : "outline"}
|
||||||
|
size="sm"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
href="https://github.com/fulldotdev/ui"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<Icon name="github" />
|
||||||
|
{githubStarCount}
|
||||||
|
</Button>
|
||||||
|
</HeaderActions>
|
||||||
|
<Sheet class="first:ml-auto @5xl:hidden">
|
||||||
|
<SheetTrigger
|
||||||
|
class="@5xl:hidden"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
name="open-menu-button"
|
||||||
|
>
|
||||||
|
<MenuIcon class="size-5" />
|
||||||
|
</SheetTrigger>
|
||||||
|
<SheetContent class="overflow-y-auto px-4 py-12">
|
||||||
|
<SidebarMenu>
|
||||||
|
{
|
||||||
|
menus?.map((menu) => (
|
||||||
|
<SidebarMenuItem>
|
||||||
|
{menu.links && menu.links.length > 0 ? (
|
||||||
|
<Collapsible>
|
||||||
|
<CollapsibleTrigger>
|
||||||
|
<SidebarMenuButton class="h-10 rounded-md px-4 text-xl">
|
||||||
|
{menu.text}
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
<CollapsibleContent>
|
||||||
|
<SidebarMenuSub>
|
||||||
|
{menu.links?.map((link) => (
|
||||||
|
<SidebarMenuSubItem>
|
||||||
|
<SidebarMenuSubButton href={link.href}>
|
||||||
|
{link.text}
|
||||||
|
</SidebarMenuSubButton>
|
||||||
|
</SidebarMenuSubItem>
|
||||||
|
))}
|
||||||
|
</SidebarMenuSub>
|
||||||
|
</CollapsibleContent>
|
||||||
|
</Collapsible>
|
||||||
|
) : (
|
||||||
|
<SidebarMenuButton
|
||||||
|
class="h-10 w-full rounded-md px-4 text-xl has-[>svg]:px-4"
|
||||||
|
href={menu.href}
|
||||||
|
>
|
||||||
|
{menu.text}
|
||||||
|
</SidebarMenuButton>
|
||||||
|
)}
|
||||||
|
</SidebarMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SidebarMenu>
|
||||||
|
<HeaderActions class="flex flex-col gap-2">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === links.length - 1 ? "default" : "secondary"}
|
||||||
|
class="w-full"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</HeaderActions>
|
||||||
|
<HeaderActions>
|
||||||
|
{
|
||||||
|
socials?.map((social) => (
|
||||||
|
<Button variant="ghost" size="icon" href={social}>
|
||||||
|
<Icon href={social} />
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</HeaderActions>
|
||||||
|
</SheetContent>
|
||||||
|
</Sheet>
|
||||||
|
</Header>
|
||||||
67
ifttt-src/src/components/blocks/hero-1.astro
Normal file
67
ifttt-src/src/components/blocks/hero-1.astro
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
---
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
link?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
icon?: string
|
||||||
|
target?: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
icon?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, link, links, image } = Astro.props
|
||||||
|
|
||||||
|
const { icon: linkIcon, text: linkText, ...linkProps } = link || {}
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent class="items-center">
|
||||||
|
<Badge variant="secondary" {...linkProps}>
|
||||||
|
{linkText}
|
||||||
|
{linkProps.href && linkIcon && <Icon name={linkIcon} />}
|
||||||
|
</Badge>
|
||||||
|
<SectionProse class="text-center text-balance" size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions class="justify-center">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image sizes="(min-width: 1536px) 1536px, 100vw" priority {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
98
ifttt-src/src/components/blocks/hero-10.astro
Normal file
98
ifttt-src/src/components/blocks/hero-10.astro
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, item, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section
|
||||||
|
class={cn("-mt-(--header-height) justify-start", className)}
|
||||||
|
id={id}
|
||||||
|
size="lg"
|
||||||
|
>
|
||||||
|
<SectionSpread class="relative @5xl:items-center">
|
||||||
|
<SectionProse size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionContent class="shrink-0">
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
class="w-full"
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription>
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
</SectionSpread>
|
||||||
|
<SectionMedia
|
||||||
|
class="mask-y-to-black-100% absolute inset-0 size-full rounded-none bg-white mask-y-from-0% dark:bg-black"
|
||||||
|
>
|
||||||
|
<Image sizes="100vw" priority {...image} class="opacity-75" />
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
98
ifttt-src/src/components/blocks/hero-11.astro
Normal file
98
ifttt-src/src/components/blocks/hero-11.astro
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, item, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section
|
||||||
|
class={cn("justify-start pb-[72cqw] @5xl:pb-[36cqw]", className)}
|
||||||
|
id={id}
|
||||||
|
size="lg"
|
||||||
|
>
|
||||||
|
<SectionSpread class="relative @5xl:items-center">
|
||||||
|
<SectionProse size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionContent class="shrink-0">
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
class="w-full"
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription>
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
</SectionSpread>
|
||||||
|
<SectionMedia
|
||||||
|
class="mask-y-to-black-100% absolute inset-0 size-full rounded-none bg-white mask-y-from-0% dark:bg-black"
|
||||||
|
>
|
||||||
|
<Image class="opacity-75" sizes="100vw" priority {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
66
ifttt-src/src/components/blocks/hero-12.astro
Normal file
66
ifttt-src/src/components/blocks/hero-12.astro
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
class: className,
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
links,
|
||||||
|
image,
|
||||||
|
} = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("gap-8 pt-8", className)} id={id}>
|
||||||
|
<SectionContent class="border-y py-8">
|
||||||
|
<SectionSpread class="@5xl:items-end">
|
||||||
|
<SectionProse class="text-balance" size="sm">
|
||||||
|
{title && <h1>{title}</h1>}
|
||||||
|
</SectionProse>
|
||||||
|
<SectionProse class="text-muted-foreground text-balance" size="sm">
|
||||||
|
{description && <p>{description}</p>}
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions class="-my-2 -ml-3 flex-row flex-nowrap">
|
||||||
|
{
|
||||||
|
links?.map(({ href, text, ...link }) => (
|
||||||
|
<Button variant="link" href={href} {...link}>
|
||||||
|
{text}
|
||||||
|
{href && <Icon name="arrow-up-right" />}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionSpread>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image sizes="(min-width: 1536px) 1536px, 100vw" priority {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
63
ifttt-src/src/components/blocks/hero-13.astro
Normal file
63
ifttt-src/src/components/blocks/hero-13.astro
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
class: className,
|
||||||
|
id,
|
||||||
|
links,
|
||||||
|
image,
|
||||||
|
} = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("@5xl:pt-1", className)} id={id}>
|
||||||
|
<SectionSplit class="@5xl:grid-cols-[1fr_3fr] @5xl:items-start">
|
||||||
|
<SectionContent class="pt-(--section-py)">
|
||||||
|
<SectionProse class="text-balance" size="sm">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions class="-my-2 -ml-3">
|
||||||
|
{
|
||||||
|
links?.map(({ href, text, ...link }) => (
|
||||||
|
<Button variant="link" href={href} {...link}>
|
||||||
|
{text}
|
||||||
|
{href && <Icon name="arrow-up-right" />}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia class="relative z-100 -mr-5">
|
||||||
|
<Image
|
||||||
|
sizes="(min-width: 1536px) 1152px, (min-width: 1024px) 75vw, 100vw"
|
||||||
|
priority
|
||||||
|
{...image}
|
||||||
|
/>
|
||||||
|
</SectionMedia>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
70
ifttt-src/src/components/blocks/hero-14.astro
Normal file
70
ifttt-src/src/components/blocks/hero-14.astro
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
link?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
icon?: string
|
||||||
|
target?: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
icon?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, link, links, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent
|
||||||
|
class={cn(
|
||||||
|
"before:from-primary/10 relative items-center before:absolute before:bottom-full before:left-0 before:h-[200%] before:w-full before:animate-pulse before:rounded-full before:bg-gradient-to-t before:to-transparent before:blur-3xl"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Badge variant="secondary" {...link}>
|
||||||
|
{link?.text}
|
||||||
|
{link?.href && <Icon name={link?.icon} />}
|
||||||
|
</Badge>
|
||||||
|
<SectionProse class="text-center text-balance" size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions class="justify-center">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "outline"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image sizes="(min-width: 1536px) 1536px, 100vw" priority {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
87
ifttt-src/src/components/blocks/hero-2.astro
Normal file
87
ifttt-src/src/components/blocks/hero-2.astro
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
icon?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, item, links, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent class="items-center">
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription>
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
<SectionProse class="text-center text-balance" size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions class="justify-center">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image sizes="(min-width: 1536px) 1536px, 100vw" priority {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
59
ifttt-src/src/components/blocks/hero-3.astro
Normal file
59
ifttt-src/src/components/blocks/hero-3.astro
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
icon?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} size="lg">
|
||||||
|
<SectionContent class="items-center">
|
||||||
|
<SectionProse class="text-center text-balance" size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions class="justify-center">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia class="absolute inset-0 rounded-none bg-white dark:bg-black">
|
||||||
|
<Image
|
||||||
|
class="opacity-50"
|
||||||
|
sizes="(min-width: 1536px) 1536px, 100vw"
|
||||||
|
priority
|
||||||
|
{...image}
|
||||||
|
/>
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
64
ifttt-src/src/components/blocks/hero-4.astro
Normal file
64
ifttt-src/src/components/blocks/hero-4.astro
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
icon?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section
|
||||||
|
class={cn("justify-center py-[36cqw] @5xl:py-[18cqw]", className)}
|
||||||
|
id={id}
|
||||||
|
size="lg"
|
||||||
|
>
|
||||||
|
<SectionContent class="items-center">
|
||||||
|
<SectionProse class="text-center text-balance" size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions class="justify-center">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia class="absolute inset-0 rounded-none bg-white dark:bg-black">
|
||||||
|
<Image
|
||||||
|
class="opacity-50"
|
||||||
|
sizes="(min-width: 1536px) 1536px, 100vw"
|
||||||
|
priority
|
||||||
|
{...image}
|
||||||
|
/>
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
99
ifttt-src/src/components/blocks/hero-5.astro
Normal file
99
ifttt-src/src/components/blocks/hero-5.astro
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, list, links, item, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<List>
|
||||||
|
{
|
||||||
|
list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</List>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription>
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image sizes="(min-width: 1536px) 1536px, 100vw" priority {...image} />
|
||||||
|
</SectionMedia>
|
||||||
|
</Section>
|
||||||
106
ifttt-src/src/components/blocks/hero-6.astro
Normal file
106
ifttt-src/src/components/blocks/hero-6.astro
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, list, links, item, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit class="@5xl:items-center">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse class="text-balance" size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<List>
|
||||||
|
{
|
||||||
|
list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</List>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription>
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia>
|
||||||
|
<Image
|
||||||
|
sizes="(min-width: 1536px) 768px, (min-width: 1024px) 50vw, 100vw"
|
||||||
|
priority
|
||||||
|
{...image}
|
||||||
|
/>
|
||||||
|
</SectionMedia>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
108
ifttt-src/src/components/blocks/hero-7.astro
Normal file
108
ifttt-src/src/components/blocks/hero-7.astro
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, list, links, item, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} size="lg">
|
||||||
|
<SectionSplit class="@5xl:grid-cols-[2fr_3fr] @5xl:items-center">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse class="text-balance" size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<List>
|
||||||
|
{
|
||||||
|
list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</List>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription>
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia
|
||||||
|
class="-mr-(--section-px) rounded-r-none @5xl:-my-(--section-py)"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
sizes="(min-width: 1536px) 922px, (min-width: 1024px) 60vw, 100vw"
|
||||||
|
priority
|
||||||
|
{...image}
|
||||||
|
/>
|
||||||
|
</SectionMedia>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
72
ifttt-src/src/components/blocks/hero-8.astro
Normal file
72
ifttt-src/src/components/blocks/hero-8.astro
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} size="lg">
|
||||||
|
<SectionSplit class="@5xl:grid-cols-[1fr_3fr] @5xl:items-center">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse class="text-balance" size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia
|
||||||
|
class="-mr-(--section-px) rounded-r-none @5xl:-my-(--section-py)"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
sizes="(min-width: 1536px) 1152px, (min-width: 1024px) 75vw, 100vw"
|
||||||
|
priority
|
||||||
|
{...image}
|
||||||
|
/>
|
||||||
|
</SectionMedia>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
111
ifttt-src/src/components/blocks/hero-9.astro
Normal file
111
ifttt-src/src/components/blocks/hero-9.astro
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMedia,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
item?: {
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
title?: string
|
||||||
|
}[]
|
||||||
|
rating?: number
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, list, links, item, image } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("-mt-(--header-height)", className)} id={id}>
|
||||||
|
<SectionSplit>
|
||||||
|
<SectionContent class="relative z-10 pt-(--header-height) @5xl:self-center">
|
||||||
|
<SectionProse size="lg">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<List>
|
||||||
|
{
|
||||||
|
list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</List>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "secondary"}
|
||||||
|
size="lg"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia class="-space-x-5">
|
||||||
|
{
|
||||||
|
item?.images?.map((image) => (
|
||||||
|
<Avatar class="ring-background size-11 ring">
|
||||||
|
<AvatarImage {...image} />
|
||||||
|
</Avatar>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent class="mt-1">
|
||||||
|
<Rating rating={item?.rating} />
|
||||||
|
<ItemDescription>
|
||||||
|
{item?.description}
|
||||||
|
</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMedia
|
||||||
|
class="-mx-(--section-px) -my-(--section-py) rounded-none @max-5xl:mask-y-from-50% @5xl:-ml-[25%] @5xl:mask-b-from-50% @5xl:mask-l-from-0%"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
sizes="(min-width: 1536px) 768px, (min-width: 1024px) 50vw, 100vw"
|
||||||
|
priority
|
||||||
|
{...image}
|
||||||
|
/>
|
||||||
|
</SectionMedia>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
70
ifttt-src/src/components/blocks/images-1.astro
Normal file
70
ifttt-src/src/components/blocks/images-1.astro
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import { Tile, TileContent, TileMedia, TileTitle } from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
title?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("gap-12", className)} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid class="-mx-5 grid-cols-1 gap-1 @5xl:grid-cols-2">
|
||||||
|
{
|
||||||
|
items?.map(({ href, title, image }) => (
|
||||||
|
<Tile
|
||||||
|
href={href}
|
||||||
|
class="dark relative overflow-hidden bg-black! ring-0!"
|
||||||
|
>
|
||||||
|
<TileMedia class="w-full transition duration-500 ease-in-out group-hover/tile:scale-103">
|
||||||
|
<Image {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent class="absolute inset-0 z-10 size-full items-center justify-center p-6 text-center opacity-0 transition duration-500 ease-in-out group-hover/tile:opacity-100">
|
||||||
|
<TileTitle class="text-foreground">{title}</TileTitle>
|
||||||
|
</TileContent>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
62
ifttt-src/src/components/blocks/images-2.astro
Normal file
62
ifttt-src/src/components/blocks/images-2.astro
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, images, title, description } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section
|
||||||
|
class={cn("@5xl:pt-1 -mt-(--header-height) @5xl:gap-1", className)}
|
||||||
|
id={id}
|
||||||
|
>
|
||||||
|
<SectionSplit class="@5xl:grid-cols-[1fr_3fr] @5xl:items-start">
|
||||||
|
<SectionContent
|
||||||
|
class="@5xl:sticky @5xl:top-[calc(24px+var(--header-height,0px))]"
|
||||||
|
>
|
||||||
|
<SectionProse class="text-balance" size="sm">
|
||||||
|
{title && <h1>{title}</h1>}
|
||||||
|
{description && <p>{description}</p>}
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ href, text, ...link }) => (
|
||||||
|
<Button variant="link" class="h-auto p-0!" href={href} {...link}>
|
||||||
|
{text}
|
||||||
|
{href && <Icon name="arrow-up-right" />}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid class="-mx-5 grid-cols-1 gap-1 @5xl:grid-cols-2">
|
||||||
|
{images?.map(({ ...image }) => <Image {...image} />)}
|
||||||
|
</SectionGrid>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
46
ifttt-src/src/components/blocks/links-1.astro
Normal file
46
ifttt-src/src/components/blocks/links-1.astro
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid class="-mx-4" size="sm">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, href, target }) => (
|
||||||
|
<Button
|
||||||
|
class="text-foreground justify-start text-start text-base"
|
||||||
|
variant="link"
|
||||||
|
href={href}
|
||||||
|
target={target}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
49
ifttt-src/src/components/blocks/links-2.astro
Normal file
49
ifttt-src/src/components/blocks/links-2.astro
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("bg-muted/50 mt-16", className)} id={id}>
|
||||||
|
<SectionSplit class="gap-x-32 @5xl:grid-cols-[1fr_2fr]">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse class="max-w-sm">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid class="-mx-4" size="sm">
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }) => (
|
||||||
|
<Button
|
||||||
|
class="text-foreground justify-start text-start text-base"
|
||||||
|
variant="link"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
34
ifttt-src/src/components/blocks/logos-1.astro
Normal file
34
ifttt-src/src/components/blocks/logos-1.astro
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Logo, LogoImage, LogoText } from "@/components/ui/logo"
|
||||||
|
import { Section, SectionGrid, SectionProse } from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
logos?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, logos } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("gap-12", className)} id={id}>
|
||||||
|
<SectionProse size="sm">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionGrid size="sm">
|
||||||
|
{
|
||||||
|
logos?.map(({ src, alt, text, href }) => (
|
||||||
|
<Logo href={href}>
|
||||||
|
<LogoImage src={src} alt={alt} />
|
||||||
|
<LogoText>{text}</LogoText>
|
||||||
|
</Logo>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
41
ifttt-src/src/components/blocks/logos-2.astro
Normal file
41
ifttt-src/src/components/blocks/logos-2.astro
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Logo, LogoImage, LogoText } from "@/components/ui/logo"
|
||||||
|
import { Marquee, MarqueeContent } from "@/components/ui/marquee"
|
||||||
|
import { Section, SectionProse } from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
logos?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, logos } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section
|
||||||
|
class={cn("gap-12", className)}
|
||||||
|
id={id}
|
||||||
|
style={{ "--container": "768px" }}
|
||||||
|
>
|
||||||
|
<SectionProse class="mx-auto text-center" size="sm">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<Marquee class="mask-x-from-95%">
|
||||||
|
<MarqueeContent>
|
||||||
|
{
|
||||||
|
logos?.map(({ src, alt, text, href }) => (
|
||||||
|
<Logo href={href}>
|
||||||
|
<LogoImage src={src} alt={alt} />
|
||||||
|
<LogoText>{text}</LogoText>
|
||||||
|
</Logo>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</MarqueeContent>
|
||||||
|
</Marquee>
|
||||||
|
</Section>
|
||||||
33
ifttt-src/src/components/blocks/logos-3.astro
Normal file
33
ifttt-src/src/components/blocks/logos-3.astro
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
import { Logo, LogoImage, LogoText } from "@/components/ui/logo"
|
||||||
|
import { Section, SectionGrid, SectionProse } from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
logos?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, logos } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionProse class="mx-auto text-center" size="sm">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionGrid class="flex flex-wrap justify-center">
|
||||||
|
{
|
||||||
|
logos?.map(({ src, alt, text, href }) => (
|
||||||
|
<Logo href={href}>
|
||||||
|
<LogoImage src={src} alt={alt} />
|
||||||
|
<LogoText>{text}</LogoText>
|
||||||
|
</Logo>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
80
ifttt-src/src/components/blocks/pricings-1.astro
Normal file
80
ifttt-src/src/components/blocks/pricings-1.astro
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import { Price, PriceUnit, PriceValue } from "@/components/ui/price"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileActions,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
icon?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
price?: string | number
|
||||||
|
unit?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, links, list, price, unit }) => (
|
||||||
|
<Tile variant="floating" class="justify-between">
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle class="text-xl">{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
<Price>
|
||||||
|
<PriceValue price={price} />
|
||||||
|
<PriceUnit>{unit}</PriceUnit>
|
||||||
|
</Price>
|
||||||
|
<List class="mt-4 text-sm">
|
||||||
|
{list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon class="-mt-0.5" name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</TileContent>
|
||||||
|
<TileActions class="mt-auto w-full">
|
||||||
|
{links?.map(({ text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
class="w-full"
|
||||||
|
size="sm"
|
||||||
|
variant={i === 0 ? "default" : "outline"}
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</TileActions>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
83
ifttt-src/src/components/blocks/pricings-2.astro
Normal file
83
ifttt-src/src/components/blocks/pricings-2.astro
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import { Price, PriceUnit, PriceValue } from "@/components/ui/price"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileActions,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
icon?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
price?: string | number
|
||||||
|
unit?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionGrid class="grid-cols-1">
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, links, list, price, unit }) => (
|
||||||
|
<Tile variant="floating">
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
<Price>
|
||||||
|
<PriceValue price={price} />
|
||||||
|
<PriceUnit>{unit}</PriceUnit>
|
||||||
|
</Price>
|
||||||
|
<List class="mt-4 text-sm">
|
||||||
|
{list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon class="-mt-0.5" name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</TileContent>
|
||||||
|
<TileActions class="mt-auto w-full">
|
||||||
|
{links?.map(({ text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
class="w-full"
|
||||||
|
size="sm"
|
||||||
|
variant={i === 0 ? "default" : "outline"}
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</TileActions>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
80
ifttt-src/src/components/blocks/pricings-3.astro
Normal file
80
ifttt-src/src/components/blocks/pricings-3.astro
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import { Price, PriceUnit, PriceValue } from "@/components/ui/price"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileActions,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
icon?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
price?: string | number
|
||||||
|
unit?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionSpread>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, links, list, price, unit }) => (
|
||||||
|
<Tile variant="floating">
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
<Price>
|
||||||
|
<PriceValue class="text-3xl" price={price} />
|
||||||
|
<PriceUnit class="mt-3">{unit}</PriceUnit>
|
||||||
|
</Price>
|
||||||
|
<List class="mt-4 text-sm">
|
||||||
|
{list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon class="-mt-0.5" name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</TileContent>
|
||||||
|
<TileActions class="mt-auto w-full">
|
||||||
|
{links?.map(({ text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
class="w-full"
|
||||||
|
size="sm"
|
||||||
|
variant={i === 0 ? "default" : "outline"}
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</TileActions>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionSpread>
|
||||||
|
</Section>
|
||||||
103
ifttt-src/src/components/blocks/product-1.astro
Normal file
103
ifttt-src/src/components/blocks/product-1.astro
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import { List, ListItem } from "@/components/ui/list"
|
||||||
|
import {
|
||||||
|
NativeCarousel,
|
||||||
|
NativeCarouselContent,
|
||||||
|
NativeCarouselItem,
|
||||||
|
NativeCarouselNext,
|
||||||
|
NativeCarouselPrevious,
|
||||||
|
} from "@/components/ui/native-carousel"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
list?: string[]
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
class: className,
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
list,
|
||||||
|
links,
|
||||||
|
images,
|
||||||
|
} = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit class="items-start @5xl:gap-24">
|
||||||
|
<NativeCarousel>
|
||||||
|
<NativeCarouselContent>
|
||||||
|
{
|
||||||
|
images?.map((image) => (
|
||||||
|
<NativeCarouselItem>
|
||||||
|
<Image
|
||||||
|
class="object-contain"
|
||||||
|
sizes="(min-width: 1536px) 768px, (min-width: 1024px) 50vw, 100vw"
|
||||||
|
{...image}
|
||||||
|
/>
|
||||||
|
</NativeCarouselItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</NativeCarouselContent>
|
||||||
|
<NativeCarouselPrevious class="left-6" />
|
||||||
|
<NativeCarouselNext class="right-6" />
|
||||||
|
</NativeCarousel>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
{title && <h1>{title}</h1>}
|
||||||
|
{description && <p>{description}</p>}
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
<List>
|
||||||
|
{
|
||||||
|
list?.map((item) => (
|
||||||
|
<ListItem>
|
||||||
|
<Icon name="check" />
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</List>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
81
ifttt-src/src/components/blocks/products-1.astro
Normal file
81
ifttt-src/src/components/blocks/products-1.astro
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import { Price, PriceUnit, PriceValue } from "@/components/ui/price"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
price?: string | number
|
||||||
|
unit?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, image, href, price, unit }) => (
|
||||||
|
<Tile href={href}>
|
||||||
|
<TileMedia>
|
||||||
|
<Image class="aspect-video" sizes="600px" {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
<Price>
|
||||||
|
<PriceValue price={price} />
|
||||||
|
<PriceUnit>{unit}</PriceUnit>
|
||||||
|
</Price>
|
||||||
|
</TileContent>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
76
ifttt-src/src/components/blocks/products-2.astro
Normal file
76
ifttt-src/src/components/blocks/products-2.astro
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Price, PriceUnit, PriceValue } from "@/components/ui/price"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileSpread,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
icon?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
price?: string | number
|
||||||
|
unit?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSpread class="@5xl:items-center">
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "outline" : "ghost"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionSpread>
|
||||||
|
<SectionGrid size="lg">
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, price, unit }) => (
|
||||||
|
<Tile class="m-0 rounded-none border-t p-0 pt-6">
|
||||||
|
<TileSpread>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
<Price>
|
||||||
|
<PriceValue price={price} />
|
||||||
|
<PriceUnit>{unit}</PriceUnit>
|
||||||
|
</Price>
|
||||||
|
</TileSpread>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
81
ifttt-src/src/components/blocks/products-3.astro
Normal file
81
ifttt-src/src/components/blocks/products-3.astro
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileSpread,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
icon?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
price?: string
|
||||||
|
unit?: string
|
||||||
|
image?: {
|
||||||
|
src?: string
|
||||||
|
alt?: string
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items, ...props } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id} {...props}>
|
||||||
|
<SectionSplit
|
||||||
|
class="items-start @5xl:*:sticky @5xl:*:top-[calc(var(--section-py)+var(--header-height,0px))]"
|
||||||
|
>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid size="lg">
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, price }) => (
|
||||||
|
<Tile class="m-0 rounded-none border-t p-0 pt-6">
|
||||||
|
<TileSpread>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
<p>{price}</p>
|
||||||
|
</TileSpread>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
81
ifttt-src/src/components/blocks/products-4.astro
Normal file
81
ifttt-src/src/components/blocks/products-4.astro
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileSpread,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
icon?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
price?: string
|
||||||
|
unit?: string
|
||||||
|
image?: {
|
||||||
|
src?: string
|
||||||
|
alt?: string
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { links, items, ...props } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section {...props}>
|
||||||
|
<SectionSplit
|
||||||
|
class="items-start @5xl:*:sticky @5xl:*:top-[calc(var(--section-py)+var(--header-height,0px))]"
|
||||||
|
>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionGrid size="lg">
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, price }) => (
|
||||||
|
<Tile class="m-0 rounded-none border-t p-0 pt-6">
|
||||||
|
<TileSpread>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
<p>{price}</p>
|
||||||
|
</TileSpread>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "outline" : "ghost"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
89
ifttt-src/src/components/blocks/products-5.astro
Normal file
89
ifttt-src/src/components/blocks/products-5.astro
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import { Price, PriceUnit, PriceValue } from "@/components/ui/price"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
images?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}[]
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
price?: string | number
|
||||||
|
unit?: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, image, images, href, price, unit }) => (
|
||||||
|
<Tile href={href}>
|
||||||
|
<TileMedia>
|
||||||
|
<Image
|
||||||
|
class="bg-muted aspect-3/4 object-contain p-6"
|
||||||
|
sizes="600px"
|
||||||
|
{...(image || images?.[0])}
|
||||||
|
/>
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
<Price>
|
||||||
|
<PriceValue price={price} />
|
||||||
|
<PriceUnit>{unit}</PriceUnit>
|
||||||
|
</Price>
|
||||||
|
</TileContent>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
98
ifttt-src/src/components/blocks/reviews-1.astro
Normal file
98
ifttt-src/src/components/blocks/reviews-1.astro
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionMasonry,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
rating?: number
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
item?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionMasonry>
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, rating, item }) => (
|
||||||
|
<Tile class="shadow-none" variant="floating">
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia>
|
||||||
|
<Avatar class="size-10">
|
||||||
|
<AvatarImage {...item?.image} />
|
||||||
|
</Avatar>
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{item?.title}</ItemTitle>
|
||||||
|
<ItemDescription>{item?.description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
<Rating rating={rating} />
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionMasonry>
|
||||||
|
</Section>
|
||||||
101
ifttt-src/src/components/blocks/reviews-2.astro
Normal file
101
ifttt-src/src/components/blocks/reviews-2.astro
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
---
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
rating?: number
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
item?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid class="grid-cols-1">
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, rating, item }) => (
|
||||||
|
<Tile class="shadow-none" variant="floating">
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia>
|
||||||
|
<Avatar class="size-10">
|
||||||
|
<AvatarImage {...item?.image} />
|
||||||
|
</Avatar>
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{item?.title}</ItemTitle>
|
||||||
|
<ItemDescription>{item?.description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
<Rating rating={rating} />
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
102
ifttt-src/src/components/blocks/reviews-3.astro
Normal file
102
ifttt-src/src/components/blocks/reviews-3.astro
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import {
|
||||||
|
NativeCarousel,
|
||||||
|
NativeCarouselContent,
|
||||||
|
NativeCarouselItem,
|
||||||
|
NativeCarouselNext,
|
||||||
|
NativeCarouselPrevious,
|
||||||
|
} from "@/components/ui/native-carousel"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import { Tile, TileDescription } from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
rating?: number
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
item?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section
|
||||||
|
class={cn("items-center", className)}
|
||||||
|
id={id}
|
||||||
|
style={{ "--section-width": "var(--breakpoint-sm)" }}
|
||||||
|
>
|
||||||
|
<SectionContent class="items-center text-center">
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<NativeCarousel>
|
||||||
|
<NativeCarouselContent>
|
||||||
|
{
|
||||||
|
items?.map(({ description, rating, item }) => (
|
||||||
|
<NativeCarouselItem>
|
||||||
|
<Tile class="items-center bg-transparent! ring-transparent!">
|
||||||
|
<Rating rating={rating} />
|
||||||
|
<TileDescription class="text-center">
|
||||||
|
{description}
|
||||||
|
</TileDescription>
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemContent class="items-center text-center">
|
||||||
|
<ItemTitle>{item?.title}</ItemTitle>
|
||||||
|
<ItemDescription>{item?.description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
</Tile>
|
||||||
|
</NativeCarouselItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</NativeCarouselContent>
|
||||||
|
<NativeCarouselPrevious class="top-auto -bottom-2 left-6" />
|
||||||
|
<NativeCarouselNext class="top-auto right-6 -bottom-2" />
|
||||||
|
</NativeCarousel>
|
||||||
|
</Section>
|
||||||
103
ifttt-src/src/components/blocks/reviews-4.astro
Normal file
103
ifttt-src/src/components/blocks/reviews-4.astro
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Marquee, MarqueeContent } from "@/components/ui/marquee"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
rating?: number
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
item?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items = [] } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("gap-6", className)} id={id}>
|
||||||
|
<SectionContent class="mb-10">
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
{
|
||||||
|
(["left", "right"] as const).map((direction) => (
|
||||||
|
<Marquee class="-mx-(--section-px)">
|
||||||
|
<MarqueeContent direction={direction} pauseOnHover>
|
||||||
|
{[...items, ...items]?.map(({ title, description, rating, item }) => (
|
||||||
|
<Tile class="shadow-none" variant="floating">
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia>
|
||||||
|
<Avatar class="size-10">
|
||||||
|
<AvatarImage {...item?.image} />
|
||||||
|
</Avatar>
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{item?.title}</ItemTitle>
|
||||||
|
<ItemDescription>{item?.description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
<Rating rating={rating} />
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
</Tile>
|
||||||
|
))}
|
||||||
|
</MarqueeContent>
|
||||||
|
</Marquee>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Section>
|
||||||
103
ifttt-src/src/components/blocks/reviews-5.astro
Normal file
103
ifttt-src/src/components/blocks/reviews-5.astro
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
---
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Avatar, AvatarImage } from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@/components/ui/item"
|
||||||
|
import { Marquee, MarqueeContent } from "@/components/ui/marquee"
|
||||||
|
import { Rating } from "@/components/ui/rating"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
rating?: number
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
item?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items = [] } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={cn("gap-6", className)} id={id}>
|
||||||
|
<SectionContent class="mb-10 items-center text-center">
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ icon, text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
{
|
||||||
|
(["left", "right"] as const).map((direction) => (
|
||||||
|
<Marquee class="mask-x-from-95%">
|
||||||
|
<MarqueeContent direction={direction} pauseOnHover>
|
||||||
|
{[...items, ...items]?.map(({ title, description, rating, item }) => (
|
||||||
|
<Tile class="shadow-none" variant="floating">
|
||||||
|
<Item class="p-0">
|
||||||
|
<ItemMedia>
|
||||||
|
<Avatar class="size-10">
|
||||||
|
<AvatarImage {...item?.image} />
|
||||||
|
</Avatar>
|
||||||
|
</ItemMedia>
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle>{item?.title}</ItemTitle>
|
||||||
|
<ItemDescription>{item?.description}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
<Rating rating={rating} />
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
</Tile>
|
||||||
|
))}
|
||||||
|
</MarqueeContent>
|
||||||
|
</Marquee>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Section>
|
||||||
93
ifttt-src/src/components/blocks/services-1.astro
Normal file
93
ifttt-src/src/components/blocks/services-1.astro
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileSpread,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
tagline?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSpread class="@5xl:items-end">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionSpread>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, tagline, description, href, image }) => (
|
||||||
|
<Tile href={href}>
|
||||||
|
<TileMedia>
|
||||||
|
<Image sizes="600px" {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileSpread>
|
||||||
|
<TileContent>
|
||||||
|
<TileDescription class="text-primary text-xs font-medium">
|
||||||
|
{tagline}
|
||||||
|
</TileDescription>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
{href && (
|
||||||
|
<Icon
|
||||||
|
name="arrow-right"
|
||||||
|
class="mr-2 size-5 shrink-0 transition-transform group-hover/tile:translate-x-2"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</TileSpread>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
100
ifttt-src/src/components/blocks/services-2.astro
Normal file
100
ifttt-src/src/components/blocks/services-2.astro
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
icon?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ text, icon, href, target }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "outline"}
|
||||||
|
href={href}
|
||||||
|
target={target}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid size="lg">
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, image, links }) => (
|
||||||
|
<Tile
|
||||||
|
class="dark aspect-4/3 justify-end rounded-md border-0 bg-black"
|
||||||
|
variant="floating"
|
||||||
|
>
|
||||||
|
<TileMedia class="absolute inset-0 size-full mask-b-from-0% mask-b-to-black/50">
|
||||||
|
<Image sizes="620px" {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent class="w-full text-white">
|
||||||
|
<TileTitle class="text-foreground text-3xl">{title}</TileTitle>
|
||||||
|
<TileDescription class="text-foreground text-lg">
|
||||||
|
{description}
|
||||||
|
</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
<SectionActions>
|
||||||
|
{links?.map(({ text, icon, href, target }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "default" : "outline"}
|
||||||
|
href={href}
|
||||||
|
target={target}
|
||||||
|
>
|
||||||
|
{icon && <Icon name={icon} />}
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</SectionActions>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
98
ifttt-src/src/components/blocks/services-3.astro
Normal file
98
ifttt-src/src/components/blocks/services-3.astro
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileActions,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileSplit,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
tagline?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit
|
||||||
|
class="items-start @5xl:grid-cols-[2fr_3fr] @5xl:*:sticky @5xl:*:top-[calc(var(--section-py)+var(--header-height,0px))]"
|
||||||
|
>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid size="lg">
|
||||||
|
{
|
||||||
|
items?.map(({ title, tagline, description, image, links }) => (
|
||||||
|
<Tile>
|
||||||
|
<TileSplit>
|
||||||
|
<TileMedia>
|
||||||
|
<Image sizes="400px" {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileContent>
|
||||||
|
<TileDescription class="text-primary text-xs font-medium">
|
||||||
|
{tagline}
|
||||||
|
</TileDescription>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
<TileActions class="mt-2">
|
||||||
|
{links?.map(({ text, ...link }, i) => (
|
||||||
|
<Button
|
||||||
|
variant={i === 0 ? "outline" : "ghost"}
|
||||||
|
size="sm"
|
||||||
|
{...link}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</TileActions>
|
||||||
|
</TileContent>
|
||||||
|
</TileSplit>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
94
ifttt-src/src/components/blocks/services-4.astro
Normal file
94
ifttt-src/src/components/blocks/services-4.astro
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileSpread,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
tagline?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSpread class="@5xl:items-end">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionSpread>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, tagline, description, href, image }) => (
|
||||||
|
<Tile href={href} variant="floating">
|
||||||
|
<TileSpread class="py-3">
|
||||||
|
<TileContent>
|
||||||
|
<TileDescription class="text-primary text-xs font-medium">
|
||||||
|
{tagline}
|
||||||
|
</TileDescription>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
{href && (
|
||||||
|
<Icon
|
||||||
|
name="arrow-right"
|
||||||
|
class="mr-3 size-5 transition-transform group-hover/tile:translate-x-3"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</TileSpread>
|
||||||
|
|
||||||
|
<TileMedia class="-mr-6 rounded-r-none">
|
||||||
|
<Image sizes="600px" {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
96
ifttt-src/src/components/blocks/services-5.astro
Normal file
96
ifttt-src/src/components/blocks/services-5.astro
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileSpread,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
tagline?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit
|
||||||
|
class="items-start @5xl:grid-cols-[1fr_2fr] @5xl:*:sticky @5xl:*:top-[calc(var(--section-py)+var(--header-height,0px))]"
|
||||||
|
>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse class="text-balance!">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "outline" : "ghost"} {...link}>
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid class="@5xl:grid-cols-2">
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, href, image }) => (
|
||||||
|
<Tile
|
||||||
|
href={href}
|
||||||
|
class="dark aspect-[1/1] bg-black!"
|
||||||
|
variant="floating"
|
||||||
|
>
|
||||||
|
<TileMedia class="absolute inset-0 size-full bg-black mask-t-from-0% mask-t-to-black/10">
|
||||||
|
<Image sizes="600px" {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileSpread class="relative">
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription class="text-foreground">
|
||||||
|
{description}
|
||||||
|
</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
{href && (
|
||||||
|
<Icon
|
||||||
|
name="arrow-right"
|
||||||
|
class="size-5 shrink-0 transition-transform group-hover/tile:translate-x-2"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</TileSpread>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
87
ifttt-src/src/components/blocks/services-6.astro
Normal file
87
ifttt-src/src/components/blocks/services-6.astro
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSplit,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileSpread,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
tagline?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSplit
|
||||||
|
class="items-start @5xl:grid-cols-[1fr_2fr] @5xl:*:sticky @5xl:*:top-[calc(var(--section-py)+var(--header-height,0px))]"
|
||||||
|
>
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse class="text-balance!">
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "outline" : "ghost"} {...link}>
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionGrid class="@5xl:grid-cols-2">
|
||||||
|
{
|
||||||
|
items?.map(({ title, description, href }) => (
|
||||||
|
<Tile href={href} variant="floating">
|
||||||
|
<TileSpread>
|
||||||
|
<TileContent>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription class="text-foreground">
|
||||||
|
{description}
|
||||||
|
</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
{href && (
|
||||||
|
<Icon
|
||||||
|
name="arrow-right"
|
||||||
|
class="size-5 shrink-0 transition-transform group-hover/tile:translate-x-2"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</TileSpread>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</SectionSplit>
|
||||||
|
</Section>
|
||||||
93
ifttt-src/src/components/blocks/services-7.astro
Normal file
93
ifttt-src/src/components/blocks/services-7.astro
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
---
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Icon } from "@/components/ui/icon"
|
||||||
|
import { Image } from "@/components/ui/image"
|
||||||
|
import {
|
||||||
|
Section,
|
||||||
|
SectionActions,
|
||||||
|
SectionContent,
|
||||||
|
SectionGrid,
|
||||||
|
SectionProse,
|
||||||
|
SectionSpread,
|
||||||
|
} from "@/components/ui/section"
|
||||||
|
import {
|
||||||
|
Tile,
|
||||||
|
TileContent,
|
||||||
|
TileDescription,
|
||||||
|
TileMedia,
|
||||||
|
TileSpread,
|
||||||
|
TileTitle,
|
||||||
|
} from "@/components/ui/tile"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
class?: string
|
||||||
|
id?: string
|
||||||
|
links?: {
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
}[]
|
||||||
|
items?: {
|
||||||
|
href?: string
|
||||||
|
tagline?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
image?: {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
}
|
||||||
|
links?: {
|
||||||
|
icon?: string
|
||||||
|
text?: string
|
||||||
|
href?: string
|
||||||
|
target?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, id, links, items } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<Section class={className} id={id}>
|
||||||
|
<SectionSpread class="@5xl:items-end">
|
||||||
|
<SectionContent>
|
||||||
|
<SectionProse>
|
||||||
|
<slot />
|
||||||
|
</SectionProse>
|
||||||
|
</SectionContent>
|
||||||
|
<SectionActions>
|
||||||
|
{
|
||||||
|
links?.map(({ text, ...link }, i) => (
|
||||||
|
<Button variant={i === 0 ? "default" : "outline"} {...link}>
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionActions>
|
||||||
|
</SectionSpread>
|
||||||
|
<SectionGrid>
|
||||||
|
{
|
||||||
|
items?.map(({ title, tagline, description, href, image }) => (
|
||||||
|
<Tile href={href} variant="floating">
|
||||||
|
<TileMedia class="-mx-6 -mt-6 aspect-4/3">
|
||||||
|
<Image class="size-full! object-cover" sizes="600px" {...image} />
|
||||||
|
</TileMedia>
|
||||||
|
<TileSpread>
|
||||||
|
<TileContent>
|
||||||
|
<TileDescription class="text-primary text-xs font-medium">
|
||||||
|
{tagline}
|
||||||
|
</TileDescription>
|
||||||
|
<TileTitle>{title}</TileTitle>
|
||||||
|
<TileDescription>{description}</TileDescription>
|
||||||
|
</TileContent>
|
||||||
|
{href && (
|
||||||
|
<Icon
|
||||||
|
name="arrow-right"
|
||||||
|
class="size-5 shrink-0 transition-transform group-hover/tile:translate-x-2"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</TileSpread>
|
||||||
|
</Tile>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SectionGrid>
|
||||||
|
</Section>
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue