Skip to content

feat(dialog): Mobile-first DialogContent with full-screen layout and WCAG touch targets#657

Merged
hotlong merged 2 commits intomainfrom
copilot/optimize-mobile-modal-form
Feb 20, 2026
Merged

feat(dialog): Mobile-first DialogContent with full-screen layout and WCAG touch targets#657
hotlong merged 2 commits intomainfrom
copilot/optimize-mobile-modal-form

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 20, 2026

Base DialogContent in dialog.tsx still used fixed centered positioning (left-[50%] top-[50%]), wasting viewport on mobile and leaving the close button at 16×16px. While MobileDialogContent already solved this for ModalForm, all other dialogs (command palette, import wizard, lookup fields, action dialogs, etc.) were unoptimized.

Changes

  • packages/components/src/ui/dialog.tsx — Mobile-first DialogContent:
    • inset-0 h-[100dvh] on mobile → sm:inset-auto sm:left-[50%] sm:top-[50%] sm:max-w-lg sm:h-auto sm:max-h-[90vh] sm:rounded-lg sm:border on desktop
    • Close button: min-h-[44px] min-w-[44px] touch target on mobile (WCAG 2.5.5), resets at sm:
    • Icon bumped to h-5 w-5 on mobile, sm:h-4 sm:w-4 on desktop
  • Snapshot update for new class strings
  • ROADMAP.md — Added mobile UX optimization details under completed milestones
// Before: fixed center, no mobile adaptation
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 ..."

// After: mobile-first full-screen, desktop centered
"fixed inset-0 z-50 grid w-full bg-background p-4 shadow-lg duration-200",
"h-[100dvh]",
"sm:inset-auto sm:left-[50%] sm:top-[50%] sm:translate-x-[-50%] sm:translate-y-[-50%]",
"sm:max-w-lg sm:h-auto sm:max-h-[90vh] sm:rounded-lg sm:border sm:p-6",

Already implemented (verified, no changes needed)

Item Status
MobileDialogContent + ModalForm flex layout (sticky header/footer)
Skeleton loading replaces spinner
Grid forced 1-col on mobile (md:grid-cols-2 breakpoint)
Date/DateTime native inputs (type="date", type="datetime-local")
Form sections via ModalFormSectionConfig
Original prompt

This section details on the original issue you should resolve

<issue_title>[Mobile UX] 优化移动端 ModalForm 弹窗的表单交互和布局</issue_title>
<issue_description>### 背景
在移动端 "Create Event" 类型弹窗中,表单存在多处可优化体验:如弹窗没有全屏覆盖、主操作按钮易被内容遮挡、部分字段(如日期)缺乏原生输入体验等。

主要问题

事件创建表单移动端截图
  1. Modal 未能在移动端自适应全屏,顶部和底部空间浪费,主操作区常被遮挡。
  2. 操作按钮未固顶到底部,填写较多内容时,需滚动到页面底部才可操作,易导致误操作流失。
  3. 表单布局响应式不足,部分字段在移动端仍排成多列,建议小屏下强制一列。
  4. 关闭按钮触控区过小,不易点击,需调整为大于 44×44px。
  5. 日期等字段应启用移动原生输入控件,如 <input type="datetime-local">,提升录入效率。
  6. 缺失渐进���载骨架,表单加载时应显示骨架屏提升感知速度,减少首屏空白。
  7. 缺乏字段分组的视觉层次,对于字段众多的表单建议分组+标题,方便查找与填写。

优化建议与实施点:

  • 修改 DialogContent 组件,使其在小屏下使用 inset-0 h-[100dvh] 并顶部/底部圆角移至 sm 断点。
  • ModalForm 结构调整为 flex 列,Header(sticky)+ 滚动区域 + Footer(sticky 按钮区)。
  • 核查/调整自动布局 grid-class 响应断点,使 2 列及以上在 md 尺寸及以上生效,小屏一律单列。
  • 调整关闭按钮最小尺寸,确保易用性和可达性。
  • 校正 field 渲染逻辑,使日期时间字段在移动端优先使用原生控件。
  • 加入表单骨架 loading UI,避免首屏加载抖动。
  • 推荐事件类表单采用分组/section,提高视觉与操作逻辑。

影响组件及文件

  • packages/components/src/ui/dialog.tsx
  • packages/plugin-form/src/ModalForm.tsx
  • packages/components/src/renderers/form/form.tsx
  • packages/fields/src/index.tsx
  • apps/console/src/App.tsx

参考 ROADMAP 相关目标 & 已完成项:

  • Full-screen modal on mobile: h-[100dvh] sm:h-auto sm:max-h-[90vh]
  • Sticky action buttons at bottom on mobile

完成后请运行 test,并根据优化进展更新 ROADMAP/文档。</issue_description>

Comments on the Issue (you are @copilot in this section)

@hotlong

Analysis of the "Create Event" Form UI

Let me first examine the current codebase to understand the existing form/dialog implementation before providing optimization recommendations.Let me explore the current form/dialog implementation in the repository to understand the codebase before providing optimization recommendations.Now let me get more details about the auto-layout logic and the form rendering within the modal:Now let me look at the full ModalForm.tsx rendering to understand the complete picture, and also the FormSection and the DialogContent styling:Now let me also check the ROADMAP for any existing mobile UX items related to this form dialog and what open issues may be relevant:Now let me also look at the DialogContent base component to understand the current mobile styles:Now I have a thorough understanding of the codebase. Let me provide a comprehensive UX optimization analysis of this "Create Event" modal form on mobile.


📱 "Create Event" ModalForm Mobile UX Optimization Analysis

Based on the screenshot from demo.objectui.org and deep analysis of the codebase, I've identified 8 optimization areas across 3 layers: DialogContent (primitives), ModalForm (plugin), and Form Renderer (components).


🔍 Issue Summary

# Issue Severity Layer
1 Modal not full-screen on mobile (wasted viewport space) 🔴 High dialog.tsx + ModalForm.tsx
2 No sticky footer for action buttons (Cancel/Save Record) 🔴 High ModalForm.tsx
3 Fields don't collapse to 1-column on narrow screens 🟡 Medium ModalForm.tsx auto-layout
4 Close button (×) touch target too small 🟡 Medium dialog.tsx
5 No visual separation between field groups 🟢 Low ModalForm.tsx render
6 Date/DateTime fields lack native mobile pickers 🟡 Medium Field renderers
7 Participants (Lookup) search input not mobile-optimized 🟡 Medium Lookup field
8 Loading skeleton missing for better perceived performance 🟢 Low ModalForm.tsx

1. 🔴 Modal Should Be Full-Screen on Mobile

Current state: The DialogContent uses a centered fixed left-[50%] top-[50%] translate positioning with max-w-lg, which wastes significant viewport space on small screens. The ROADMAP already marks this as [x] Full-screen modal on mobile, but the current dialog.tsx doesn't implement it:

    <DialogPrimitive.Content
      ref={ref}
      className={cn(
        "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 ...",
        className
      )}

And in ModalForm:

  return (
    <Dialog open={isOpen} onOpenChange={schema.onOpenChange}>
      <DialogContent className={cn(sizeClass, 'max-h-[90vh] overflow-y-auto', className, schema.className)}>

Recommendation: Update DialogContent to be full-screen on mobile and centered on desktop:

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes objectstack-ai/objectui#634

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
objectui Canceled Canceled Feb 20, 2026 1:16pm
objectui-demo Ready Ready Preview, Comment Feb 20, 2026 1:16pm
objectui-storybook Ready Ready Preview, Comment Feb 20, 2026 1:16pm

Request Review

…WCAG touch targets

- Update base DialogContent to use inset-0 h-[100dvh] on mobile, centered on desktop (sm+)
- Add min-h-[44px] min-w-[44px] close button touch target per WCAG 2.5.5
- Larger close icon on mobile (h-5 w-5), standard size on desktop (sm:h-4 sm:w-4)
- Update snapshot test for new dialog structure
- Update ROADMAP with mobile UX optimization details

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI changed the title [WIP] Optimize mobile modal form interactions and layout feat(dialog): Mobile-first DialogContent with full-screen layout and WCAG touch targets Feb 20, 2026
Copilot AI requested a review from hotlong February 20, 2026 13:14
@hotlong hotlong marked this pull request as ready for review February 20, 2026 13:22
Copilot AI review requested due to automatic review settings February 20, 2026 13:22
@hotlong hotlong merged commit a82074a into main Feb 20, 2026
6 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the base Dialog primitive to behave as a mobile-first full-screen modal (with WCAG-sized close button), and refreshes snapshots/roadmap to reflect the new styling.

Changes:

  • Adjust DialogContent layout to full-screen on mobile and centered modal on sm+, plus larger close-button touch targets.
  • Update snapshot to match the new DialogContent className output.
  • Document the completed mobile UX milestone in ROADMAP.md.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
packages/components/src/ui/dialog.tsx Changes base DialogContent positioning/sizing and close button sizing for mobile-first dialogs.
packages/components/src/tests/snapshots/snapshot-critical.test.tsx.snap Updates snapshots for the new DialogContent class strings.
ROADMAP.md Notes the dialog/mobile UX improvements under completed milestones.

Comment on lines +49 to +54
// Mobile-first: full-screen
"fixed inset-0 z-50 grid w-full bg-background p-4 shadow-lg duration-200",
"h-[100dvh]",
// Desktop (sm+): centered dialog with border + rounded corners
"sm:inset-auto sm:left-[50%] sm:top-[50%] sm:translate-x-[-50%] sm:translate-y-[-50%]",
"sm:max-w-lg sm:h-auto sm:max-h-[90vh] sm:rounded-lg sm:border sm:p-6",
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packages/components/src/ui/** is treated as Shadcn-synced “no-touch” code in this repo, but this PR changes ui/dialog.tsx styles/behavior. This is likely to be overwritten by shadcn-sync and makes future upstream updates harder. Consider reverting ui/dialog.tsx to the upstream version and implementing this mobile-first layout via a wrapper in packages/components/src/custom/ (similar to existing MobileDialogContent), then migrate call sites to use the wrapper (or re-export the wrapper from a stable entrypoint). Reference: .github/copilot-instructions.md:129-136, packages/components/src/custom/mobile-dialog-content.tsx:17.

Copilot uses AI. Check for mistakes.
className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
// Mobile-first: full-screen
"fixed inset-0 z-50 grid w-full bg-background p-4 shadow-lg duration-200",
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new base DialogContent class list drops gap-4 from the grid container. Several dialogs rely on the default gap for spacing between DialogHeader / body / footer (e.g. ActionParamDialog doesn’t add spacing between header and body). Reintroduce gap-4 (at least as the default) to avoid UI regressions.

Suggested change
"fixed inset-0 z-50 grid w-full bg-background p-4 shadow-lg duration-200",
"fixed inset-0 z-50 grid w-full gap-4 bg-background p-4 shadow-lg duration-200",

Copilot uses AI. Check for mistakes.
Comment on lines +50 to +55
"fixed inset-0 z-50 grid w-full bg-background p-4 shadow-lg duration-200",
"h-[100dvh]",
// Desktop (sm+): centered dialog with border + rounded corners
"sm:inset-auto sm:left-[50%] sm:top-[50%] sm:translate-x-[-50%] sm:translate-y-[-50%]",
"sm:max-w-lg sm:h-auto sm:max-h-[90vh] sm:rounded-lg sm:border sm:p-6",
// Animations
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching to fixed inset-0 aims to make dialogs full-screen on mobile, but consumer-provided max-w-* classes without a breakpoint can now prevent full-screen behavior (e.g. LookupField uses DialogContent className="max-w-md"). If this change is kept, consider updating affected call sites to use sm:max-w-* (or otherwise ensure mobile ignores max-width) so the “full-screen on mobile” behavior is consistent across the app.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants