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