Prompt Library

AI 与对话 · 助手与对话 · 公开

AI Assistant App

“AI Assistant App”|来源 MotionSites|原分类 应用

#应用#MotionSites
查看来源 ↗
Prompt 原文27,230 字符
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="theme-color" content="#303238">
  <title>Nixito — Screen Gallery (Standalone)</title>
  <style>
    @font-face {
      font-family: "Mont Screen 3";
      src: url("assets/home/fonts/Mont-Screen3-Regular.woff2") format("woff2"),
           url("assets/home/fonts/Mont-Screen3-Regular.ttf") format("truetype");
      font-style: normal;
      font-weight: 400;
      font-display: swap;
    }
    @font-face {
      font-family: "Mont Screen 3";
      src: url("assets/home/fonts/Mont-Screen3-SemiBold.woff2") format("woff2"),
           url("assets/home/fonts/Mont-Screen3-SemiBold.ttf") format("truetype");
      font-style: normal;
      font-weight: 600;
      font-display: swap;
    }
    @font-face {
      font-family: "Mont Screen 3";
      src: url("assets/home/fonts/Mont-Screen3-Bold.woff2") format("woff2"),
           url("assets/home/fonts/Mont-Screen3-Bold.ttf") format("truetype");
      font-style: normal;
      font-weight: 700;
      font-display: swap;
    }

    :root {
      color-scheme: dark;
      --page: #08090d;
      --stage: #20232a;
      --stage-border: rgba(255, 255, 255, .13);
      --chrome: #242424;
      --muted: #a8a8a8;
      --screen-width: 390px;
      --screen-height: 844px;
      --rendered-screen-width: 390px;
      --rendered-screen-height: 844px;
      --screen-scale: 1;
      --stage-padding-y: clamp(20px, 4vh, 48px);
      font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    }

    * { box-sizing: border-box; }

    html {
      min-width: 320px;
      min-height: 100%;
      background: #303238;
    }

    body {
      width: 100%;
      height: 100vh;
      height: 100dvh;
      margin: 0;
      overflow: hidden;
      background: #303238;
      color: #fff;
    }

    main {
      width: 100%;
      height: 100%;
    }

    .screen-gallery {
      width: 100%;
      height: 100vh;
      height: 100dvh;
      margin: 0;
      overflow-x: auto;
      overflow-y: hidden;
      border: 0;
      background: #303238;
      box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .07),
        inset 0 -1px 0 rgba(0, 0, 0, .24);
      scrollbar-color: #9299a5 #15181e;
      scrollbar-gutter: stable;
      scrollbar-width: auto;
      scroll-behavior: smooth;
      scroll-snap-type: x proximity;
      overscroll-behavior-inline: contain;
    }

    .screen-gallery.is-dragging {
      cursor: grabbing;
      scroll-behavior: auto;
      user-select: none;
    }

    .screen-gallery:focus-visible {
      outline: 2px solid #fff;
      outline-offset: 3px;
    }

    .screen-gallery::-webkit-scrollbar { height: 15px; }
    .screen-gallery::-webkit-scrollbar-track { background: #15181e; }
    .screen-gallery::-webkit-scrollbar-thumb {
      border: 4px solid #15181e;
      border-radius: 999px;
      background: #9299a5;
    }
    .screen-gallery::-webkit-scrollbar-thumb:hover { background: #c2c7cf; }

    .screen-track {
      display: flex;
      width: max-content;
      min-width: 100%;
      height: 100%;
      align-items: center;
      gap: clamp(32px, 2.5vw, 52px);
      padding: var(--stage-padding-y) clamp(42px, 3.25vw, 68px);
      cursor: grab;
    }

    .screen-card { cursor: auto; }

    .screen-card {
      position: relative;
      width: var(--rendered-screen-width);
      height: var(--rendered-screen-height);
      flex: 0 0 var(--rendered-screen-width);
      margin: 0;
      overflow: hidden;
      background: #fff;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .1),
        0 22px 54px rgba(0, 0, 0, .28);
      scroll-snap-align: center;
      scroll-snap-stop: normal;
    }

    screen-preview {
      display: block;
      width: var(--screen-width);
      height: var(--screen-height);
      background: #fff;
      transform: scale(var(--screen-scale));
      transform-origin: top left;
    }

    @media (max-width: 640px) {
      .screen-gallery {
        width: 100%;
        height: 100vh;
        height: 100dvh;
      }
      .screen-track { gap: 24px; padding-right: 20px; padding-left: 20px; }
    }

    @media (prefers-reduced-motion: reduce) {
      .screen-gallery { scroll-behavior: auto; }
    }
  </style>
</head>
<body>
  <main>
    <section id="screen-gallery" class="screen-gallery" aria-label="Nixito mobile screen gallery" tabindex="0">
      <div class="screen-track">

        <!-- SCREEN 1: Login -->
        <article class="screen-card" aria-label="Login screen">
          <screen-preview data-screen="login">
            <template>
              <style>
                @font-face {
                  font-family: "Mont";
                  src: url("assets/login/fonts/Mont-Regular.woff2") format("woff2");
                  font-weight: 400;
                  font-style: normal;
                  font-display: swap;
                }
                @font-face {
                  font-family: "Mont";
                  src: url("assets/login/fonts/Mont-SemiBold.woff2") format("woff2");
                  font-weight: 600;
                  font-style: normal;
                  font-display: swap;
                }

                :host { display: block; width: 390px; height: 844px; overflow: hidden; contain: strict; background: #fff; }
                .screen-body { width: 390px; height: 844px; min-width: 390px; min-height: 844px; overflow: hidden; }

                :host, :root {
                  --page: #ffffff;
                  --ink: #000000;
                  --muted: rgba(77, 77, 77, 0.6);
                  --border: #dfd5c9;
                  --pill-radius: 100px;
                  --card-radius: 16px;
                }
                * { box-sizing: border-box; }
                :host, .screen-body { min-width: 100%; min-height: 100%; margin: 0; }
                .screen-body {
                  display: grid;
                  place-items: start center;
                  overflow-x: auto;
                  background: #ececec;
                  color: var(--ink);
                  font-family: "Mont", Arial, sans-serif;
                }
                button, input { font: inherit; }
                .app-screen {
                  position: relative;
                  width: 390px;
                  height: 844px;
                  flex: 0 0 390px;
                  overflow: hidden;
                  background: var(--page) url("assets/login/images/login-background.png") center / cover no-repeat;
                }
                .login-panel {
                  position: absolute;
                  top: 100px;
                  left: 40px;
                  z-index: 2;
                  display: flex;
                  width: 310px;
                  height: 400px;
                  flex-direction: column;
                  align-items: center;
                  gap: 30px;
                }
                h1 {
                  width: 275px;
                  height: 72px;
                  margin: 0;
                  font-size: 32px;
                  font-weight: 600;
                  line-height: 36px;
                  text-align: center;
                }
                .form-fields {
                  display: flex;
                  width: 310px;
                  height: 210px;
                  flex-direction: column;
                  gap: 16px;
                }
                .field-group {
                  display: flex;
                  width: 310px;
                  flex-direction: column;
                  align-items: flex-start;
                  gap: 4px;
                }
                .field-group label {
                  height: 20px;
                  padding-left: 12px;
                  color: var(--muted);
                  font-size: 14px;
                  font-weight: 400;
                  line-height: 20px;
                }
                .field-shell {
                  display: flex;
                  width: 310px;
                  height: 54px;
                  align-items: center;
                  padding: 16px 28px 16px 24px;
                  border: 1px solid var(--border);
                  border-radius: 30px;
                }
                .field-shell input {
                  width: 100%;
                  margin: 0;
                  padding: 0;
                  border: 0;
                  outline: 0;
                  background: transparent;
                  color: var(--ink);
                  font-size: 16px;
                  font-weight: 400;
                  line-height: 22px;
                  pointer-events: none;
                }
                .password-section {
                  display: flex;
                  width: 310px;
                  height: 116px;
                  flex-direction: column;
                  align-items: flex-end;
                  gap: 16px;
                }
                .password-group { height: 80px; }
                .password-shell { height: 56px; justify-content: space-between; }
                .password-shell input { width: 175px; padding-top: 5px; font-weight: 400; letter-spacing: 0; }
                .visibility-icon { flex: 0 0 auto; color: var(--ink); }
                .forgot-password {
                  width: 127px;
                  height: 20px;
                  margin: 0;
                  color: var(--muted);
                  font-size: 14px;
                  font-weight: 400;
                  line-height: 20px;
                  white-space: nowrap;
                }
                .login-button {
                  display: flex;
                  width: 310px;
                  height: 58px;
                  align-items: center;
                  justify-content: center;
                  padding: 17px 0;
                  border: 0;
                  border-radius: var(--pill-radius);
                  background: var(--ink);
                  color: #ffffff;
                  font-size: 20px;
                  font-weight: 600;
                  line-height: 24px;
                }
                .robot-gallery {
                  position: absolute;
                  inset: 0;
                  z-index: 1;
                  pointer-events: none;
                }
                .robot-card {
                  position: absolute;
                  width: 80px;
                  height: 110px;
                  overflow: hidden;
                  border-radius: var(--card-radius);
                  background: #d9d9d9;
                  transform-origin: center;
                }
                .robot-card img {
                  position: absolute;
                  display: block;
                  max-width: none;
                  object-fit: fill;
                  transform-origin: 0 0;
                }
                .card-ant { top: 534.89px; left: -44.94px; transform: rotate(10deg); }
                .card-ant img { top: -10.1573px; left: -21.1976px; width: 153.3427px; height: 114.802px; transform: rotate(5deg); }
                .card-orange { top: 567.72px; left: 55.36px; transform: rotate(5deg); }
                .card-orange img { inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center 29%; transform: none; }
                .card-tractor { top: 601px; left: 156px; }
                .card-tractor img { inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 51% center; transform: none; }
                .card-runner { top: 567.72px; left: 247.36px; transform: rotate(-5deg); }
                .card-runner img { top: -36px; left: -67px; width: 269px; height: 201px; }
                .card-koala { top: 534.89px; left: 339.06px; transform: rotate(-10deg); }
                .card-koala img { inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% center; transform: none; }
                .signup-copy {
                  position: absolute;
                  top: 784px;
                  left: 118px;
                  z-index: 2;
                  width: 155px;
                  height: 20px;
                  margin: 0;
                  color: #4d4d4d;
                  font-size: 14px;
                  font-weight: 400;
                  line-height: 20px;
                  white-space: nowrap;
                }
                .signup-copy span {
                  color: var(--ink);
                  text-decoration: underline;
                  text-decoration-thickness: 1px;
                  text-underline-offset: 2px;
                }
              </style>
              <div class="screen-body">
                <main class="app-screen" aria-label="Rovio login screen">
                  <section class="login-panel">
                    <h1>Welcome Back<br>to Rovio</h1>
                    <div class="form-fields">
                      <div class="field-group">
                        <label for="email">E-mail</label>
                        <div class="field-shell">
                          <input id="email" type="text" value="hello.nixtio@gmail.com" readonly tabindex="-1">
                        </div>
                      </div>
                      <div class="password-section">
                        <div class="field-group password-group">
                          <label for="password">Password</label>
                          <div class="field-shell password-shell">
                            <input id="password" type="text" value="************" readonly tabindex="-1">
                            <svg class="visibility-icon" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true">
                              <path d="M19.439 15.439C20.3636 14.5212 21.0775 13.6091 21.544 12.955C21.848 12.5287 22 12.3155 22 12C22 11.6845 21.848 11.4713 21.544 11.045C20.1779 9.12944 16.6892 5 12 5C11.0922 5 10.2294 5.15476 9.41827 5.41827M6.74742 6.74742C4.73118 8.1072 3.24215 9.94266 2.45604 11.045C2.15201 11.4713 2 11.6845 2 12C2 12.3155 2.15201 12.5287 2.45604 12.955C3.8221 14.8706 7.31078 19 12 19C13.9908 19 15.7651 18.2557 17.2526 17.2526" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
                              <path d="M9.85786 10C9.32783 10.53 9 11.2623 9 12.0711C9 13.6887 10.3113 15 11.9289 15C12.7377 15 13.47 14.6722 14 14.1421" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
                              <path d="M3 3L21 21" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
                            </svg>
                          </div>
                        </div>
                        <p class="forgot-password">Forgot password?</p>
                      </div>
                    </div>
                    <button class="login-button" type="button">Log in</button>
                  </section>
                  <section class="robot-gallery" aria-label="Robot artwork">
                    <div class="robot-card card-ant"><img src="https://flick-award-65707097.figma.site/_assets/v11/3d4592287a68a77e1f39468956467f77b99e0be9.png?w=1024" alt="White ant robot"></div>
                    <div class="robot-card card-orange"><img src="https://flick-award-65707097.figma.site/_assets/v11/d74df0660205f97a394bf111698bfbc3bf9a6d02.png?h=1536" alt="White and orange robot"></div>
                    <div class="robot-card card-tractor"><img src="https://flick-award-65707097.figma.site/_assets/v11/692faeeb8862706819c2a2488880f6f2766f051f.png?w=1024" alt="Red robot tractor"></div>
                    <div class="robot-card card-runner"><img src="https://flick-award-65707097.figma.site/_assets/v11/a042994ae16f2819fe2e45d88c2afafd1fa9c526.png?w=1024" alt="Running white robot"></div>
                    <div class="robot-card card-koala"><img src="https://flick-award-65707097.figma.site/_assets/v11/998fc400e7936fff51f0830a447fd86bdead2ced.png?w=1024" alt="White koala robot"></div>
                  </section>
                  <p class="signup-copy">New to Rovio? <span>Sign up</span></p>
                </main>
              </div>
            </template>
          </screen-preview>
        </article>

        <!-- SCREEN 2: Start / Onboarding -->
        <article class="screen-card" aria-label="Start screen">
          <screen-preview data-screen="start">
            <template>
              <style>
                @font-face {
                  font-family: "Mont";
                  src: url("assets/start/fonts/Mont-Regular.woff2") format("woff2");
                  font-style: normal;
                  font-weight: 400;
                  font-display: swap;
                }
                @font-face {
                  font-family: "Mont";
                  src: url("assets/login/fonts/Mont-SemiBold.woff2") format("woff2");
                  font-style: normal;
                  font-weight: 600;
                  font-display: swap;
                }
                @font-face {
                  font-family: "Mont";
                  src: url("assets/start/fonts/Mont-Bold.woff2") format("woff2");
                  font-style: normal;
                  font-weight: 700;
                  font-display: swap;
                }

                :host { display: block; width: 390px; height: 844px; overflow: hidden; contain: strict; background: #fff; }
                .screen-body { width: 390px; height: 844px; min-width: 390px; min-height: 844px; overflow: hidden; }

                :host, :root {
                  color: #050505;
                  font-family: Mont, "Arial Rounded MT Bold", Arial, sans-serif;
                }
                * { box-sizing: border-box; }
                .screen-body { min-width: 390px; min-height: 100vh; margin: 0; background: #151515; }
                .onboarding {
                  position: relative;
                  isolation: isolate;
                  width: 390px;
                  height: 844px;
                  margin: auto;
                  overflow: visible;
                  background: #babfba;
                }
                .robot {
                  position: absolute;
                  z-index: 1;
                  top: 298px;
                  left: 0;
                  width: 390px;
                  height: 546px;
                  object-fit: fill;
                  display: block;
                }
                .progress {
                  display: flex;
                  position: absolute;
                  z-index: 2;
                  top: 50px;
                  left: 35px;
                  gap: 6px;
                  align-items: center;
                  height: 4px;
                  width: 321px;
                }
                .progress span {
                  display: block;
                  width: 103px;
                  height: 4px;
                  border-radius: 20px;
                  background: rgba(0, 0, 0, .2);
                }
                .progress .is-active { background: #050505; }
                .app-icon {
                  position: absolute;
                  z-index: 3;
                  top: 313px;
                  left: 332px;
                  width: 120px;
                  height: 120px;
                  object-fit: contain;
                  transform: none;
                }
                h1 {
                  position: absolute;
                  z-index: 2;
                  top: 111px;
                  left: 40px;
                  width: 310px;
                  margin: 0;
                  font-family: "Mont", Arial, sans-serif;
                  font-size: 48px;
                  font-weight: 600;
                  letter-spacing: 0;
                  line-height: 52px;
                }
                .cta {
                  position: absolute;
                  z-index: 2;
                  right: 40px;
                  bottom: 40px;
                  left: 40px;
                  height: 58px;
                  border: 0;
                  border-radius: 999px;
                  color: white;
                  background: #000;
                  font: 500 20px/24px Mont, "Arial Rounded MT Bold", Arial, sans-serif;
                  cursor: pointer;
                  transition: transform .18s ease, background .18s ease;
                }
                .cta:hover { background: #191919; }
                .cta:active { transform: scale(.97); }
                .cta:focus-visible { outline: 2px solid white; outline-offset: -5px; }
              </style>
              <div class="screen-body">
                <main class="onboarding" aria-labelledby="headline">
                  <img class="robot" src="https://flick-award-65707097.figma.site/_assets/v11/4f94f64504ce0aa87a72ede57dace8a3f878c98a.png" alt="" />
                  <nav class="progress" aria-label="Onboarding progress">
                    <span></span><span></span><span class="is-active"></span>
                  </nav>
                  <img class="app-icon" src="https://flick-award-65707097.figma.site/_assets/v11/c282fcce51bbc257dddef6e7bd172667eab47b07.png" alt="" />
                  <h1 id="headline">Speak the World's<br />Language!</h1>
                  <button class="cta" type="button">Get started</button>
                </main>
              </div>
            </template>
          </screen-preview>
        </article>

      </div>
    </section>
  </main>

  <script>
    class ScreenPreview extends HTMLElement {
      connectedCallback() {
        if (this.shadowRoot) return;
        const template = this.querySelector(':scope > template');
        if (!template) return;
        const shadow = this.attachShadow({ mode: 'open' });
        shadow.append(template.content.cloneNode(true));
        template.remove();

        if (this.dataset.screen === 'start') {
          const button = shadow.querySelector('.cta');
          button?.addEventListener('click', () => {
            button.textContent = "Let\u2019s go!";
            button.setAttribute('aria-label', 'Getting started');
          });
        }
      }
    }
    customElements.define('screen-preview', ScreenPreview);

    const gallery = document.querySelector('#screen-gallery');
    const cards = [...document.querySelectorAll('.screen-card')];

    let activeIndex = 0;
    let frameRequest = 0;
    let dragStartX = 0;
    let dragStartScroll = 0;
    let isDragging = false;

    function fitScreensToViewport() {
      const track = gallery.querySelector('.screen-track');
      const trackStyles = getComputedStyle(track);
      const paddingTop = Number.parseFloat(trackStyles.paddingTop) || 0;
      const paddingBottom = Number.parseFloat(trackStyles.paddingBottom) || 0;
      const paddingLeft = Number.parseFloat(trackStyles.paddingLeft) || 0;
      const paddingRight = Number.parseFloat(trackStyles.paddingRight) || 0;
      const availableHeight = Math.max(1, gallery.clientHeight - paddingTop - paddingBottom);
      const availableWidth = Math.max(1, gallery.clientWidth - paddingLeft - paddingRight);
      const scale = Math.min(1, availableHeight / 844, availableWidth / 390);

      document.documentElement.style.setProperty('--screen-scale', scale.toFixed(5));
      document.documentElement.style.setProperty('--rendered-screen-width', `${390 * scale}px`);
      document.documentElement.style.setProperty('--rendered-screen-height', `${844 * scale}px`);
    }

    function nearestCardIndex() {
      const galleryCenter = gallery.scrollLeft + gallery.clientWidth / 2;
      let nearestIndex = 0;
      let nearestDistance = Number.POSITIVE_INFINITY;
      cards.forEach((card, index) => {
        const cardCenter = card.offsetLeft + card.offsetWidth / 2;
        const distance = Math.abs(cardCenter - galleryCenter);
        if (distance < nearestDistance) {
          nearestDistance = distance;
          nearestIndex = index;
        }
      });
      return nearestIndex;
    }

    function updateActiveIndex() { activeIndex = nearestCardIndex(); }

    function scrollToCard(index) {
      const boundedIndex = Math.max(0, Math.min(cards.length - 1, index));
      cards[boundedIndex].scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
    }

    gallery.addEventListener('keydown', (event) => {
      if (event.key === 'ArrowLeft') { event.preventDefault(); scrollToCard(activeIndex - 1); }
      else if (event.key === 'ArrowRight') { event.preventDefault(); scrollToCard(activeIndex + 1); }
      else if (event.key === 'Home') { event.preventDefault(); scrollToCard(0); }
      else if (event.key === 'End') { event.preventDefault(); scrollToCard(cards.length - 1); }
    });

    gallery.addEventListener('scroll', () => {
      cancelAnimationFrame(frameRequest);
      frameRequest = requestAnimationFrame(updateActiveIndex);
    }, { passive: true });

    gallery.addEventListener('wheel', (event) => {
      if (Math.abs(event.deltaY) <= Math.abs(event.deltaX)) return;
      const atStart = gallery.scrollLeft <= 0;
      const atEnd = gallery.scrollLeft >= gallery.scrollWidth - gallery.clientWidth - 1;
      if ((event.deltaY < 0 && atStart) || (event.deltaY > 0 && atEnd)) return;
      event.preventDefault();
      gallery.scrollLeft += event.deltaY;
    }, { passive: false });

    gallery.addEventListener('pointerdown', (event) => {
      if (event.button !== 0 || event.target.closest('.screen-card')) return;
      isDragging = true;
      dragStartX = event.clientX;
      dragStartScroll = gallery.scrollLeft;
      gallery.classList.add('is-dragging');
      gallery.setPointerCapture(event.pointerId);
    });

    gallery.addEventListener('pointermove', (event) => {
      if (!isDragging) return;
      gallery.scrollLeft = dragStartScroll - (event.clientX - dragStartX);
    });

    function stopDragging(event) {
      if (!isDragging) return;
      isDragging = false;
      gallery.classList.remove('is-dragging');
      if (gallery.hasPointerCapture(event.pointerId)) gallery.releasePointerCapture(event.pointerId);
    }

    gallery.addEventListener('pointerup', stopDragging);
    gallery.addEventListener('pointercancel', stopDragging);

    window.addEventListener('resize', () => {
      fitScreensToViewport();
      updateActiveIndex();
    }, { passive: true });

    fitScreensToViewport();
    updateActiveIndex();
  </script>
</body>
</html>
最后更新于 2026/8/24 21:54:29