1 звезда на GitHub = 1 новый компонент.

Поставить звезду
Призывы к действию (CTA)

CTA App Download

Секция загрузки мобильного приложения с мокапом смартфона и кнопками магазинов приложений.

ctamobileapp-storedownloadmockup
Живое превью
Mobile Experience

Manage Your Astro Deployments On the Go

Download our native companion mobile application. Monitor real-time builds, latency metrics, and team notifications directly from your pocket.

⚡ Instant Push Alerts
📊 Real-Time Analytics
🔒 Biometric Security
Production Edge100% UP
✓ Build #402 deployed in 12s
⚡ TTFB latency: 14ms

Использование

Скопируйте и вставьте этот код в ваш React-компонент:

tsx
import { CtaAppDownload } from 'react-component-kit-ui/sections';

<CtaAppDownload />

Ручная установка

Если вы не используете пакет npm, создайте файл и вставьте следующий код: src/components/sections/CtaAppDownload.tsx + CtaAppDownload.css:

CtaAppDownload.tsx
'use client';

import './CtaAppDownload.css';

/**
 * CtaAppDownload — Full-page mobile app showcase and download CTA section with device mockup and store buttons.
 * 
 * @param {string} badge - Eyebrow badge text.
 * @param {string} title - Main headline.
 * @param {string} subtitle - Description text.
 */
export interface CtaAppDownloadProps {
  badge?: string;
  title?: string;
  subtitle?: string;
  className?: string;
}

export function CtaAppDownload({
  badge = "Mobile Experience",
  title = "Manage Your Astro Deployments On the Go",
  subtitle = "Download our native companion mobile application. Monitor real-time builds, latency metrics, and team notifications directly from your pocket.",
  className = ""
}: CtaAppDownloadProps) {
  return (
    <>
      <div className="cq-cta-app-download-cq" data-rk-68c50b="">
      <section className={`app-download-section ${className}`} aria-labelledby="app-title" data-rk-68c50b="">
        <div className="container" data-rk-68c50b="">
          <div className="app-card" data-rk-68c50b="">
            <div className="app-info" data-rk-68c50b="">
              {badge && <span className="app-badge" data-rk-68c50b="">{badge}</span>}
              <h2 id="app-title" className="app-title" data-rk-68c50b="">{title}</h2>
              <p className="app-subtitle" data-rk-68c50b="">{subtitle}</p>
      
              <div className="app-features-mini" data-rk-68c50b="">
                <div className="feat-pill" data-rk-68c50b="">⚡ Instant Push Alerts</div>
                <div className="feat-pill" data-rk-68c50b="">📊 Real-Time Analytics</div>
                <div className="feat-pill" data-rk-68c50b="">🔒 Biometric Security</div>
              </div>
      
              <div className="store-buttons" data-rk-68c50b="">
                <a href="#app-store" className="store-btn" data-rk-68c50b="">
                  <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" data-rk-68c50b=""><path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M15.97 6.85c.66-.8 1.11-1.92.99-3.04-.96.04-2.13.64-2.82 1.44-.6.7-.99 1.83-1.02 2.98.08.01.16.02.24.02.88 0 1.95-.58 2.61-1.4z" data-rk-68c50b="" /></svg>
                  <div className="store-btn__text" data-rk-68c50b="">
                    <span className="store-btn__sub" data-rk-68c50b="">Download on the</span>
                    <span className="store-btn__name" data-rk-68c50b="">App Store</span>
                  </div>
                </a>
      
                <a href="#google-play" className="store-btn" data-rk-68c50b="">
                  <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" data-rk-68c50b=""><path d="M3.609 1.814L13.792 12 3.61 22.186a2.227 2.227 0 0 1-.22-.968V2.782c0-.361.08-.696.22-.968zm11.24 11.24l2.128 2.129-12.03 6.946 9.902-9.075zm2.933-2.05l2.673 1.543c.876.505.876 1.332 0 1.837l-2.673 1.544-2.338-2.338 2.338-2.586zM4.947 1.87l12.031 6.947-2.128 2.128-9.903-9.075z" data-rk-68c50b="" /></svg>
                  <div className="store-btn__text" data-rk-68c50b="">
                    <span className="store-btn__sub" data-rk-68c50b="">GET IT ON</span>
                    <span className="store-btn__name" data-rk-68c50b="">Google Play</span>
                  </div>
                </a>
              </div>
            </div>
      
            <div className="app-visual" data-rk-68c50b="">
              <div className="phone-frame" data-rk-68c50b="">
                <div className="phone-notch" data-rk-68c50b=""></div>
                <div className="phone-screen" data-rk-68c50b="">
                  <div className="phone-header" data-rk-68c50b="">
                    <div className="phone-avatar" data-rk-68c50b=""></div>
                    <span data-rk-68c50b="">Production Edge</span>
                    <span className="phone-live" data-rk-68c50b="">100% UP</span>
                  </div>
                  <div className="phone-chart" data-rk-68c50b=""></div>
                  <div className="phone-card-mini" data-rk-68c50b="">✓ Build #402 deployed in 12s</div>
                  <div className="phone-card-mini" data-rk-68c50b="">⚡ TTFB latency: 14ms</div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>
      </div>
    </>
  );
}

export default CtaAppDownload;
CtaAppDownload.css
/* CtaAppDownload — ported from astro-component-kit (sections/CtaAppDownload.astro) */

.cq-cta-app-download-cq:where([data-rk-68c50b]) { container-type: inline-size; }
.app-download-section:where([data-rk-68c50b]) {
  padding: var(--sp-20, 5rem) var(--sp-6, 1.5rem);
  background: var(--c-bg-primary, #030712);
}

.container:where([data-rk-68c50b]) {
  max-width: 1200px;
  margin: 0 auto;
}

.app-card:where([data-rk-68c50b]) {
  background: linear-gradient(135deg, rgba(15, 23, 42, 0.8) 0%, rgba(10, 15, 30, 0.9) 100%);
  border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.1);
  border-radius: var(--r-2xl, 24px);
  padding: clamp(2rem, 5vw, 4rem);
  display: grid;
  grid-template-columns: 1.2fr 0.8fr;
  gap: 3rem;
  align-items: center;
}

.app-badge:where([data-rk-68c50b]) {
  display: inline-flex;
  padding: 0.35rem 0.9rem;
  border-radius: 9999px;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: color-mix(in srgb, var(--c-primary, #b8860b) 12%, transparent);
  color: #eab308;
  border: 1px solid rgba(234, 179, 8, 0.25);
  margin-bottom: var(--sp-4, 1rem);
}

.app-title:where([data-rk-68c50b]) {
  font-size: clamp(2rem, 4vw, 2.8rem);
  font-weight: 900;
  color: #fff;
  line-height: 1.2;
  letter-spacing: -0.02em;
  margin: 0 0 1rem;
}

.app-subtitle:where([data-rk-68c50b]) {
  font-size: 1.05rem;
  color: #94a3b8;
  line-height: 1.6;
  margin: 0 0 1.75rem;
}

.app-features-mini:where([data-rk-68c50b]) {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 2rem;
}

.feat-pill:where([data-rk-68c50b]) {
  padding: 0.4rem 0.85rem;
  background: rgb(var(--ink-rgb, 255 255 255) / 0.05);
  border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
  border-radius: 9999px;
  font-size: 0.82rem;
  color: #cbd5e1;
}

.store-buttons:where([data-rk-68c50b]) {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

.store-btn:where([data-rk-68c50b]) {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.65rem 1.25rem;
  background: rgba(0, 0, 0, 0.6);
  border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.15);
  border-radius: 12px;
  color: #fff;
  text-decoration: none;
  transition: all 0.2s ease;
}

.store-btn:hover:where([data-rk-68c50b]) {
  background: rgb(var(--ink-rgb, 255 255 255) / 0.1);
  border-color: rgb(var(--ink-rgb, 255 255 255) / 0.3);
}

.store-btn__text:where([data-rk-68c50b]) {
  display: flex;
  flex-direction: column;
  text-align: left;
}

.store-btn__sub:where([data-rk-68c50b]) {
  font-size: 0.65rem;
  color: #94a3b8;
  text-transform: uppercase;
}

.store-btn__name:where([data-rk-68c50b]) {
  font-size: 1rem;
  font-weight: 700;
}

/* Phone visual mockup */
.app-visual:where([data-rk-68c50b]) {
  display: flex;
  justify-content: center;
}

.phone-frame:where([data-rk-68c50b]) {
  width: 250px;
  height: 400px;
  background: #020617;
  border: 3px solid rgb(var(--ink-rgb, 255 255 255) / 0.2);
  border-radius: 36px;
  padding: 12px;
  box-shadow: 0 20px 50px -10px rgba(0, 0, 0, 0.8);
  display: flex;
  flex-direction: column;
}

.phone-notch:where([data-rk-68c50b]) {
  width: 70px;
  height: 12px;
  background: #0f172a;
  border-radius: 999px;
  margin: 0 auto 12px;
}

.phone-screen:where([data-rk-68c50b]) {
  flex: 1;
  background: rgba(15, 23, 42, 0.8);
  border-radius: 24px;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.phone-header:where([data-rk-68c50b]) {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 0.75rem;
  color: #fff;
  font-weight: 700;
}

.phone-live:where([data-rk-68c50b]) {
  font-size: 0.65rem;
  color: #10b981;
  background: rgba(16, 185, 129, 0.15);
  padding: 0.15rem 0.4rem;
  border-radius: 999px;
}

.phone-chart:where([data-rk-68c50b]) {
  height: 80px;
  background: linear-gradient(180deg, rgba(99, 102, 241, 0.3) 0%, transparent 100%);
  border-bottom: 2px solid #6366f1;
  border-radius: 8px;
}

.phone-card-mini:where([data-rk-68c50b]) {
  padding: 0.5rem;
  background: rgb(var(--ink-rgb, 255 255 255) / 0.05);
  border-radius: 8px;
  font-size: 0.72rem;
  color: #cbd5e1;
}

@container (max-width: 960px) {
  .app-card:where([data-rk-68c50b]) {
    grid-template-columns: 1fr;
  }
}