From cd2a069310c6efca66af560cf5a0a4608c73a19b Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Mon, 21 Sep 2026 10:43:28 -0400 Subject: [PATCH 1/3] feat: add interactive hinge hero --- website/src/pages/index.jsx | 53 +++++++++++++------ website/src/pages/index.module.css | 85 +++++++++++++++++++++++++----- 2 files changed, 108 insertions(+), 30 deletions(-) diff --git a/website/src/pages/index.jsx b/website/src/pages/index.jsx index 9575f95..956f0af 100644 --- a/website/src/pages/index.jsx +++ b/website/src/pages/index.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import Layout from '@theme/Layout'; import Link from '@docusaurus/Link'; import CodeBlock from '@theme/CodeBlock'; @@ -15,41 +15,57 @@ for (const hinge of hinges) { }`; function HingePreview() { + const [angle, setAngle] = useState(Math.PI / 2); + const posture = angle < 0.35 ? 'closed' : angle > Math.PI - 0.35 ? 'fullyOpen' : 'partiallyOpen'; + const angleLabel = `${angle.toFixed(2)} rad`; + const fold = ((Math.PI - angle) / 2).toFixed(3); + return ( -
+
NATIVE HINGE STATE rad
-
- partiallyOpen -
-
+
+
+ {posture} +
-
+
-
-
- hinge -
-
- 1.57 rad +
+ hinge +
+
+ {angleLabel} +
+
+ + setAngle(Number(event.target.value))} + aria-valuetext={`${angleLabel}, ${posture}`} + /> + {angleLabel} +
Hierarchy @@ -60,7 +76,7 @@ function HingePreview() { Angle - Illustrative readings + Illustrative controls and readings
); @@ -94,6 +110,9 @@ export default function Home() {

react-native-hinges

+

+ Animate from native hinge snapshots with the Reanimated integration. +

diff --git a/website/src/pages/index.module.css b/website/src/pages/index.module.css index 582a5e2..e1d6855 100644 --- a/website/src/pages/index.module.css +++ b/website/src/pages/index.module.css @@ -51,6 +51,15 @@ color: var(--rr-muted); overflow-wrap: anywhere; } +.reanimatedNote { + max-width: 420px; + margin-top: 16px; + color: var(--rr-muted); + font-size: 0.88rem; +} +.reanimatedNote a { + font-weight: 600; +} .preview { margin: 0; min-width: 0; @@ -85,30 +94,48 @@ border-radius: 23px; background: var(--ifm-background-color); } +.hingeStage { + perspective: 900px; +} .provider { height: 262px; - border: 1.5px solid #527ef0; - border-radius: 12px; position: relative; - background-image: radial-gradient(var(--rr-border) 0.7px, transparent 0.7px); - background-size: 12px 12px; } .origin { position: absolute; top: 10px; left: 10px; + z-index: 2; + padding: 2px 4px; + background: var(--ifm-background-color); font: 0.61rem var(--ifm-font-family-monospace); color: var(--ifm-color-primary); } -.panes { +.foldPanel { position: absolute; - inset: 65px 18px 20px; - display: grid; - grid-template-columns: 1fr 1fr; - gap: 42px; -} -.pane { + top: 0; + bottom: 0; + width: calc(50% - 22px); min-width: 0; + padding: 65px 18px 20px; + border: 1.5px solid #527ef0; + background-color: var(--ifm-background-color); + background-image: radial-gradient(var(--rr-border) 0.7px, transparent 0.7px); + background-size: 12px 12px; + transition: transform 420ms cubic-bezier(0.2, 0.7, 0.2, 1); + will-change: transform; +} +.leftPanel { + left: 0; + border-radius: 12px 0 0 12px; + transform: rotateY(var(--hinge-left-fold)); + transform-origin: right center; +} +.rightPanel { + right: 0; + border-radius: 0 12px 12px 0; + transform: rotateY(var(--hinge-fold)); + transform-origin: left center; } .stubTitle { background: var(--rr-border); @@ -136,6 +163,7 @@ left: 50%; border-left: 2px solid #d57839; background: #d5783915; + z-index: 1; } .fold span { position: absolute; @@ -159,6 +187,28 @@ padding: 2px 7px; font: 0.62rem var(--ifm-font-family-monospace); color: #6936a7; + z-index: 2; +} +.previewControls { + display: grid; + grid-template-columns: auto 1fr auto; + gap: 12px; + align-items: center; + padding: 0 25px 18px; + color: var(--rr-muted); + font-size: 0.68rem; +} +.previewControls label, +.previewControls output { + font: 0.64rem var(--ifm-font-family-monospace); +} +.previewControls output { + color: #6936a7; +} +.previewControls input { + accent-color: var(--ifm-color-primary); + cursor: ew-resize; + min-width: 0; } .previewCaption { display: flex; @@ -357,10 +407,19 @@ .previewCaption { padding-left: 20px; } - .panes { - gap: 30px; + .previewControls { + grid-template-columns: 1fr auto; + } + .previewControls input { + grid-column: 1 / -1; + grid-row: 2; } .referenceLink { font-size: 0.76rem; } } +@media (prefers-reduced-motion: reduce) { + .foldPanel { + transition: none; + } +} From 38e57d088a1d301253e6af59e7cce506894cef6c Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Mon, 21 Sep 2026 10:54:37 -0400 Subject: [PATCH 2/3] fix: align hinge preview geometry --- website/src/pages/index.jsx | 5 ++++- website/src/pages/index.module.css | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/website/src/pages/index.jsx b/website/src/pages/index.jsx index 956f0af..da10a74 100644 --- a/website/src/pages/index.jsx +++ b/website/src/pages/index.jsx @@ -21,7 +21,10 @@ function HingePreview() { const fold = ((Math.PI - angle) / 2).toFixed(3); return ( -
+
NATIVE HINGE STATE diff --git a/website/src/pages/index.module.css b/website/src/pages/index.module.css index e1d6855..bdf402a 100644 --- a/website/src/pages/index.module.css +++ b/website/src/pages/index.module.css @@ -115,7 +115,7 @@ position: absolute; top: 0; bottom: 0; - width: calc(50% - 22px); + width: 50%; min-width: 0; padding: 65px 18px 20px; border: 1.5px solid #527ef0; From f3e83d9dac4e94113e8d588fdb512907d4565d3b Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Mon, 21 Sep 2026 11:35:17 -0400 Subject: [PATCH 3/3] fix: preserve hinge preview depth --- website/src/pages/index.module.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/src/pages/index.module.css b/website/src/pages/index.module.css index bdf402a..1ebf72e 100644 --- a/website/src/pages/index.module.css +++ b/website/src/pages/index.module.css @@ -100,6 +100,8 @@ .provider { height: 262px; position: relative; + perspective: 900px; + transform-style: preserve-3d; } .origin { position: absolute;