diff --git a/input.css b/input.css index 0644b82..3b787ad 100644 --- a/input.css +++ b/input.css @@ -83,15 +83,19 @@ animation: popover-enter 150ms cubic-bezier(0.22, 1, 0.36, 1) both; } - /* 下拉选择面板入场(仅垂直微移,无水平居中变换;展开方向由 transform-origin 控制) */ + /* 下拉选择面板入场。面板的水平居中用 [transform:translateX(-50%)](不用 + -translate-x-1/2 utility:Tailwind v4 的 translate utility 走独立 translate + 属性,会与此处 transform 关键帧叠加成双倍位移),关键帧 fill 值须与面板 + 静态 transform 完全一致,否则动画结束时水平位置跳变;垂直仅微移,展开 + 方向由 transform-origin 控制。 */ @keyframes select-enter { 0% { opacity: 0; - transform: translateY(-4px) scale(0.98); + transform: translateX(-50%) translateY(-4px) scale(0.98); } 100% { opacity: 1; - transform: none; + transform: translateX(-50%); } } diff --git a/src/components/forms.rs b/src/components/forms.rs index fdfffd5..60a7a68 100644 --- a/src/components/forms.rs +++ b/src/components/forms.rs @@ -110,10 +110,14 @@ pub fn FormSelect( ) -> Element { // 面板与 POPOVER_PANEL_CLASS 同源(卡片化圆角 + 阴影)。宽度取 max(触发器, // 最长选项):紧凑触发器(如“手动”)下面板仍能完整展示长选项;上限防出屏。 + // 水平以触发器中心居中:面板宽于触发器时两侧对称探出,窄触发器不失衡。 + // 居中用 [transform:translateX(-50%)] 而非 -translate-x-1/2 utility:Tailwind + // v4 的 translate utility 走独立 translate 属性,会与 select-enter 关键帧的 + // transform 叠加造成双倍位移;关键帧的 fill 值与此处 transform 完全一致。 // 定义在函数体内:模块级私有常量若仅被 wasm 门控调用点引用,会在 server // 构建下触发 dead_code。 const TRIGGER_CLASS: &str = "w-full block cursor-pointer truncate select-none text-left pl-4 pr-10 py-2 border border-paper-border rounded-2xl bg-paper-entry text-paper-primary focus:outline-none focus:border-paper-accent focus:ring-1 focus:ring-paper-accent/30 transition-colors duration-200"; - const PANEL_CLASS: &str = "absolute left-0 z-50 w-max min-w-full max-w-[calc(100vw_-_2rem)] max-h-60 overflow-y-auto rounded-2xl border border-[var(--color-paper-border)] bg-[var(--color-paper-entry)] p-1.5 shadow-lg animate-select-enter"; + const PANEL_CLASS: &str = "absolute left-1/2 z-50 w-max min-w-full max-w-[calc(100vw_-_2rem)] [transform:translateX(-50%)] max-h-60 overflow-y-auto rounded-2xl border border-[var(--color-paper-border)] bg-[var(--color-paper-entry)] p-1.5 shadow-lg animate-select-enter"; let trigger_cls = trigger_class.unwrap_or(TRIGGER_CLASS);