Skip to content

Commit 7d93b4b

Browse files
Copilothotlong
andcommitted
feat: add mobile responsive improvements to core components
- DataTable: responsive toolbar (stack on mobile), touch-scroll wrapper, responsive pagination - DashboardRenderer: responsive grid (1→2→3→4 columns), responsive widget padding - KanbanImpl: responsive column width (w-72→w-80), responsive padding and gap - ObjectCalendar: responsive height calculation, responsive min-height - DetailView: responsive header (stack on mobile), responsive title size, wrapping actions - ListView: responsive toolbar padding, responsive search width, responsive filter/sort popovers - ObjectGrid: responsive error/loading padding - ObjectForm: responsive error/loading padding - TimelineRenderer: touch-scroll on horizontal and gantt variants Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 7e1c141 commit 7d93b4b

9 files changed

Lines changed: 33 additions & 29 deletions

File tree

packages/components/src/renderers/complex/data-table.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -510,13 +510,13 @@ const DataTableRenderer = ({ schema }: { schema: DataTableSchema }) => {
510510
const showToolbar = searchable || exportable || (selectable && selectedRowIds.size > 0) || hasPendingChanges;
511511

512512
return (
513-
<div className={`flex flex-col h-full gap-4 ${className || ''}`}>
513+
<div className={`flex flex-col h-full gap-2 sm:gap-4 ${className || ''}`}>
514514
{/* Toolbar */}
515515
{showToolbar && (
516-
<div className="flex items-center justify-between gap-4 flex-none">
516+
<div className="flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-2 sm:gap-4 flex-none">
517517
<div className="flex items-center gap-2 flex-1">
518518
{searchable && (
519-
<div className="relative max-w-sm flex-1">
519+
<div className="relative w-full sm:max-w-sm flex-1">
520520
<Search className="absolute left-2 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
521521
<Input
522522
placeholder="Search..."
@@ -531,7 +531,7 @@ const DataTableRenderer = ({ schema }: { schema: DataTableSchema }) => {
531531
)}
532532
</div>
533533

534-
<div className="flex items-center gap-2">
534+
<div className="flex flex-wrap items-center gap-2">
535535
{hasPendingChanges && (
536536
<>
537537
<div className="text-sm text-muted-foreground">
@@ -580,7 +580,7 @@ const DataTableRenderer = ({ schema }: { schema: DataTableSchema }) => {
580580
)}
581581

582582
{/* Table */}
583-
<div className="rounded-md border flex-1 min-h-0 overflow-auto relative bg-background">
583+
<div className="rounded-md border flex-1 min-h-0 overflow-auto relative bg-background [-webkit-overflow-scrolling:touch]">
584584
<Table>
585585
{caption && <TableCaption>{caption}</TableCaption>}
586586
<TableHeader className="sticky top-0 bg-background z-10 shadow-sm">
@@ -804,7 +804,7 @@ const DataTableRenderer = ({ schema }: { schema: DataTableSchema }) => {
804804

805805
{/* Pagination */}
806806
{pagination && sortedData.length > 0 && (
807-
<div className="flex items-center justify-between">
807+
<div className="flex flex-col sm:flex-row items-center justify-between gap-2">
808808
<div className="flex items-center gap-2">
809809
<span className="text-sm text-muted-foreground">Rows per page:</span>
810810
<Select

packages/plugin-calendar/src/ObjectCalendar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ export const ObjectCalendar: React.FC<ObjectCalendarProps> = ({
326326

327327
return (
328328
<div className={className}>
329-
<div className="border rounded-lg bg-background h-[calc(100vh-200px)] min-h-[600px]">
329+
<div className="border rounded-lg bg-background h-[calc(100vh-120px)] sm:h-[calc(100vh-160px)] md:h-[calc(100vh-200px)] min-h-[400px] sm:min-h-[600px]">
330330
<CalendarView
331331
events={events}
332332
currentDate={currentDate}

packages/plugin-dashboard/src/DashboardRenderer.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,13 @@ export const DashboardRenderer = forwardRef<HTMLDivElement, DashboardRendererPro
5656
return (
5757
<div
5858
ref={ref}
59-
className={cn("grid auto-rows-min", className)}
59+
className={cn(
60+
"grid auto-rows-min",
61+
"grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
62+
className
63+
)}
6064
style={{
61-
gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
65+
...(columns > 4 && { gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` }),
6266
gap: `${gap * 0.25}rem`
6367
}}
6468
{...props}
@@ -166,7 +170,7 @@ export const DashboardRenderer = forwardRef<HTMLDivElement, DashboardRendererPro
166170
</CardHeader>
167171
)}
168172
<CardContent className="p-0">
169-
<div className={cn("h-full w-full", !widget.title ? "p-4" : "p-4")}>
173+
<div className={cn("h-full w-full", "p-3 sm:p-4")}>
170174
<SchemaRenderer schema={componentSchema} />
171175
</div>
172176
</CardContent>

packages/plugin-detail/src/DetailView.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ export const DetailView: React.FC<DetailViewProps> = ({
182182
<TooltipProvider>
183183
<div className={cn('space-y-6', className)}>
184184
{/* Header - Airtable-inspired layout */}
185-
<div className="flex items-start justify-between gap-4 pb-4 border-b">
186-
<div className="flex items-start gap-3 flex-1 min-w-0">
185+
<div className="flex flex-col sm:flex-row items-start justify-between gap-3 sm:gap-4 pb-4 border-b">
186+
<div className="flex items-start gap-2 sm:gap-3 flex-1 min-w-0">
187187
{(schema.showBack ?? true) && (
188188
<Tooltip>
189189
<TooltipTrigger asChild>
@@ -196,7 +196,7 @@ export const DetailView: React.FC<DetailViewProps> = ({
196196
)}
197197
<div className="flex-1 min-w-0">
198198
<div className="flex items-center gap-2">
199-
<h1 className="text-2xl font-bold truncate">{schema.title || 'Details'}</h1>
199+
<h1 className="text-xl sm:text-2xl font-bold truncate">{schema.title || 'Details'}</h1>
200200
<Tooltip>
201201
<TooltipTrigger asChild>
202202
<Button
@@ -227,7 +227,7 @@ export const DetailView: React.FC<DetailViewProps> = ({
227227
</div>
228228
</div>
229229

230-
<div className="flex items-center gap-1.5 shrink-0">
230+
<div className="flex flex-wrap items-center gap-1.5 shrink-0">
231231
{schema.actions?.map((action, index) => (
232232
<SchemaRenderer key={index} schema={action} data={data} />
233233
))}

packages/plugin-form/src/ObjectForm.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ const SimpleObjectForm: React.FC<ObjectFormProps> = ({
511511
// Render error state
512512
if (error) {
513513
return (
514-
<div className="p-4 border border-red-300 bg-red-50 rounded-md">
514+
<div className="p-3 sm:p-4 border border-red-300 bg-red-50 rounded-md">
515515
<h3 className="text-red-800 font-semibold">Error loading form</h3>
516516
<p className="text-red-600 text-sm mt-1">{error.message}</p>
517517
</div>
@@ -521,7 +521,7 @@ const SimpleObjectForm: React.FC<ObjectFormProps> = ({
521521
// Render loading state
522522
if (loading) {
523523
return (
524-
<div className="p-8 text-center">
524+
<div className="p-4 sm:p-8 text-center">
525525
<div className="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"></div>
526526
<p className="mt-2 text-sm text-gray-600">Loading form...</p>
527527
</div>

packages/plugin-grid/src/ObjectGrid.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
465465

466466
if (error) {
467467
return (
468-
<div className="p-4 border border-red-300 bg-red-50 rounded-md">
468+
<div className="p-3 sm:p-4 border border-red-300 bg-red-50 rounded-md">
469469
<h3 className="text-red-800 font-semibold">Error loading grid</h3>
470470
<p className="text-red-600 text-sm mt-1">{error.message}</p>
471471
</div>
@@ -474,7 +474,7 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
474474

475475
if (loading && data.length === 0) {
476476
return (
477-
<div className="p-8 text-center">
477+
<div className="p-4 sm:p-8 text-center">
478478
<div className="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"></div>
479479
<p className="mt-2 text-sm text-gray-600">Loading grid...</p>
480480
</div>

packages/plugin-kanban/src/KanbanImpl.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ function KanbanColumn({
118118
role="group"
119119
aria-label={column.title}
120120
className={cn(
121-
"flex flex-col w-80 flex-shrink-0 rounded-lg border border-border bg-card/20 backdrop-blur-sm shadow-xl",
121+
"flex flex-col w-72 sm:w-80 flex-shrink-0 rounded-lg border border-border bg-card/20 backdrop-blur-sm shadow-xl",
122122
column.className
123123
)}
124124
>
125-
<div className="p-4 border-b border-border/50 bg-muted/20">
125+
<div className="p-3 sm:p-4 border-b border-border/50 bg-muted/20">
126126
<div className="flex items-center justify-between">
127127
<h3 id={`kanban-col-${column.id}`} className="font-mono text-sm font-semibold tracking-wider text-primary/90 uppercase">{column.title}</h3>
128128
<div className="flex items-center gap-2">
@@ -318,7 +318,7 @@ function KanbanBoardInner({ columns, onCardMove, className, dnd }: KanbanBoardPr
318318
onDragStart={handleDragStart}
319319
onDragEnd={handleDragEnd}
320320
>
321-
<div className={cn("flex gap-4 overflow-x-auto p-4", className)} role="region" aria-label="Kanban board">
321+
<div className={cn("flex gap-3 sm:gap-4 overflow-x-auto p-2 sm:p-4 [-webkit-overflow-scrolling:touch]", className)} role="region" aria-label="Kanban board">
322322
{boardColumns.map((column) => (
323323
<KanbanColumn
324324
key={column.id}

packages/plugin-list/src/ListView.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,8 @@ export const ListView: React.FC<ListViewProps> = ({
406406
)}
407407

408408
{/* Airtable-style Toolbar — Row 2: Tool buttons */}
409-
<div className="border-b px-4 py-1 flex items-center justify-between gap-2 bg-background">
410-
<div className="flex items-center gap-0.5 overflow-hidden">
409+
<div className="border-b px-2 sm:px-4 py-1 flex items-center justify-between gap-1 sm:gap-2 bg-background">
410+
<div className="flex items-center gap-0.5 overflow-hidden flex-1 min-w-0">
411411
{/* Hide Fields */}
412412
<Button
413413
variant="ghost"
@@ -439,7 +439,7 @@ export const ListView: React.FC<ListViewProps> = ({
439439
)}
440440
</Button>
441441
</PopoverTrigger>
442-
<PopoverContent align="start" className="w-[600px] p-4">
442+
<PopoverContent align="start" className="w-[calc(100vw-2rem)] sm:w-[600px] max-w-[600px] p-3 sm:p-4">
443443
<div className="space-y-4">
444444
<div className="flex items-center justify-between border-b pb-2">
445445
<h4 className="font-medium text-sm">Filter Records</h4>
@@ -487,7 +487,7 @@ export const ListView: React.FC<ListViewProps> = ({
487487
)}
488488
</Button>
489489
</PopoverTrigger>
490-
<PopoverContent align="start" className="w-[600px] p-4">
490+
<PopoverContent align="start" className="w-[calc(100vw-2rem)] sm:w-[600px] max-w-[600px] p-3 sm:p-4">
491491
<div className="space-y-4">
492492
<div className="flex items-center justify-between border-b pb-2">
493493
<h4 className="font-medium text-sm">Sort Records</h4>
@@ -530,7 +530,7 @@ export const ListView: React.FC<ListViewProps> = ({
530530
{/* Right: Search */}
531531
<div className="flex items-center gap-1">
532532
{searchExpanded ? (
533-
<div className="relative w-48 lg:w-64">
533+
<div className="relative w-36 sm:w-48 lg:w-64">
534534
<Search className="absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" />
535535
<Input
536536
placeholder="Find..."

packages/plugin-timeline/src/renderer.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
TimelineGanttBar,
2828
TimelineGanttBarContent,
2929
} from './index';
30-
import { renderChildren } from '@object-ui/components';
30+
import { renderChildren, cn } from '@object-ui/components';
3131

3232
// Constants
3333
const MILLISECONDS_PER_WEEK = 7 * 24 * 60 * 60 * 1000;
@@ -123,7 +123,7 @@ export const TimelineRenderer = ({ schema, className, ...props }: { schema: Time
123123
// Horizontal Timeline
124124
if (variant === 'horizontal') {
125125
return (
126-
<TimelineHorizontal className={className} {...props}>
126+
<TimelineHorizontal className={cn("overflow-x-auto [-webkit-overflow-scrolling:touch]", className)} {...props}>
127127
{items.map((item: any, index: number) => (
128128
<TimelineHorizontalItem key={index} className={item.className}>
129129
<div className="flex flex-col items-center">
@@ -208,7 +208,7 @@ export const TimelineRenderer = ({ schema, className, ...props }: { schema: Time
208208
const timeHeaders = generateTimeHeaders();
209209

210210
return (
211-
<TimelineGantt className={className} {...props}>
211+
<TimelineGantt className={cn("overflow-x-auto [-webkit-overflow-scrolling:touch]", className)} {...props}>
212212
{/* Header */}
213213
<TimelineGanttHeader>
214214
<TimelineGanttRowLabels className="flex items-center px-4 py-3">

0 commit comments

Comments
 (0)