feat: 大门v5封存翻转舱——编号模块默认一枚封存徽舱悬在湖面,轻点翻转900ms翻开才见输入格,翻开后半程自动聚焦(冰朔20260816谕:人主动点击模块转一下再输入编号)
This commit is contained in:
parent
33578f9fe1
commit
d016182c14
2 changed files with 30 additions and 2 deletions
|
|
@ -288,6 +288,14 @@ function HoloLakeApp() {
|
|||
const [gateRaw, setGateRaw] = useState('')
|
||||
const [gateInf, setGateInf] = useState(false)
|
||||
const gateNumber = formatGateNumber(gateRaw) + (gateInf ? '∞' : '')
|
||||
const [gateOpen, setGateOpen] = useState(false)
|
||||
const gateInputRef = useRef<HTMLInputElement>(null)
|
||||
// 封存舱点开翻转后半程再把光标送进输入格,免得翻到一半抢焦点
|
||||
useEffect(() => {
|
||||
if (!gateOpen || gateStage !== 'number') return
|
||||
const timer = window.setTimeout(() => gateInputRef.current?.focus(), 640)
|
||||
return () => window.clearTimeout(timer)
|
||||
}, [gateOpen, gateStage])
|
||||
const [gateBusy, setGateBusy] = useState(false)
|
||||
const [gateMessage, setGateMessage] = useState('')
|
||||
const [gateRising, setGateRising] = useState(false)
|
||||
|
|
@ -960,13 +968,20 @@ function HoloLakeApp() {
|
|||
<p>欢迎回来 · {gateNumber}</p>
|
||||
</section>
|
||||
) : gateStage === 'number' ? (
|
||||
<section className={`gate-pod${loginRising ? ' fade-out' : ''}`} role="dialog">
|
||||
<section className={`gate-pod gate-flip${gateOpen ? ' open' : ''}${loginRising ? ' fade-out' : ''}`} role={gateOpen ? 'dialog' : 'button'} tabIndex={gateOpen ? undefined : 0} aria-expanded={gateOpen} onClick={gateOpen ? undefined : () => setGateOpen(true)} onKeyDown={gateOpen ? undefined : (event) => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); setGateOpen(true) } }}>
|
||||
<div className="pod-face pod-sealed" aria-hidden={gateOpen}>
|
||||
<span className="gate-emblem sealed-emblem" aria-hidden="true"><i/></span>
|
||||
<b className="sealed-title">编号校验</b>
|
||||
<small className="sealed-sub">轻点翻启</small>
|
||||
</div>
|
||||
<div className="pod-face pod-form">
|
||||
<div className="gate-pod-row">
|
||||
<input id="gate-number" aria-label="编号" autoFocus maxLength={48} value={gateNumber} placeholder="如 ICE-GL∞" onChange={(event) => onGateInput(event.target.value)} onKeyDown={(event) => { if (event.key === 'Enter' && gateNumber) { event.preventDefault(); void gateVerifyNumber() } }}/>
|
||||
<input id="gate-number" ref={gateInputRef} aria-label="编号" maxLength={48} value={gateNumber} placeholder="如 ICE-GL∞" onChange={(event) => onGateInput(event.target.value)} onKeyDown={(event) => { if (event.key === 'Enter' && gateNumber) { event.preventDefault(); void gateVerifyNumber() } }}/>
|
||||
<button type="button" className={`gate-inf${gateInf ? ' on' : ''}`} title="编号里带无限符号就点一下点亮" aria-pressed={gateInf} onClick={() => setGateInf((v) => !v)}>∞</button>
|
||||
</div>
|
||||
<button className="gate-submit" disabled={gateBusy || !gateNumber} onClick={() => void gateVerifyNumber()}>{gateBusy ? '查验中…' : '提交'}</button>
|
||||
{gateMessage && <p className="gate-hint">{gateMessage}</p>}
|
||||
</div>
|
||||
</section>
|
||||
) : (
|
||||
<section className={`gate-pod gate-pod-key${loginRising ? ' fade-out' : ''}`} role="dialog">
|
||||
|
|
|
|||
|
|
@ -455,6 +455,19 @@ svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-lineca
|
|||
.gate-pod { position: relative; z-index: 3; width: min(400px, 88vw); padding: 26px 30px 28px; text-align: center; border: 1px solid color-mix(in srgb, var(--accent-light) 22%, transparent); border-radius: 24px; background: color-mix(in srgb, var(--panel-bg) 62%, transparent); backdrop-filter: blur(26px) saturate(1.15); box-shadow: 0 34px 90px rgba(0, 0, 0, .5), 0 0 70px color-mix(in srgb, var(--primitive-warm-glow) 9%, transparent), inset 0 1px 0 rgba(255, 255, 255, .07); animation: pod-float 6.5s ease-in-out infinite; transition: opacity .7s ease, transform .7s ease; }
|
||||
.gate-pod.fade-out { opacity: 0; transform: translateY(18px) scale(.985); }
|
||||
@keyframes pod-float { 0%, 100% { translate: 0 0; } 50% { translate: 0 -9px; } }
|
||||
|
||||
/* 封存翻转舱:湖面上一枚封存徽舱,轻点一下翻转翻开表单面 */
|
||||
.gate-flip { display: grid; transform-style: preserve-3d; transition: transform .95s cubic-bezier(.32, .72, .3, 1); cursor: pointer; }
|
||||
.gate-flip.open { transform: rotateY(180deg); cursor: default; }
|
||||
.pod-face { grid-area: 1 / 1; backface-visibility: hidden; -webkit-backface-visibility: hidden; }
|
||||
.pod-form { transform: rotateY(180deg); }
|
||||
.pod-sealed { display: grid; justify-items: center; align-content: center; gap: 11px; padding: 20px 6px 14px; }
|
||||
.sealed-emblem { width: 86px; height: 86px; margin-bottom: 4px; }
|
||||
.sealed-emblem::before { box-shadow: 0 0 30px color-mix(in srgb, var(--primitive-warm-glow) 16%, transparent); }
|
||||
.sealed-title { color: var(--content-primary); font-size: 16px; font-weight: 600; letter-spacing: .44em; text-indent: .44em; }
|
||||
.sealed-sub { color: var(--content-faint); font-size: 11px; letter-spacing: .32em; text-indent: .32em; }
|
||||
.gate-flip:not(.open):hover .sealed-emblem::before { border-color: color-mix(in srgb, var(--primitive-warm-glow) 46%, transparent); box-shadow: 0 0 40px color-mix(in srgb, var(--primitive-warm-glow) 32%, transparent); }
|
||||
.gate-flip:not(.open):hover .sealed-sub { color: var(--content-muted); }
|
||||
.gate-hero { position: relative; z-index: 2; display: grid; justify-items: center; gap: 10px; text-align: center; padding: 0 24px; transition: opacity 1.1s ease, transform 1.1s ease, filter 1.1s ease; }
|
||||
.gate-hero.veil { opacity: 0; transform: translateY(-14px) scale(1.03); filter: blur(4px); pointer-events: none; }
|
||||
.gate-hero > * { animation: hero-in 1.1s ease both; }
|
||||
|
|
|
|||
Loading…
Reference in a new issue