Commit 4206d7fd by CaIon

feat(data-table): enhance mobile card view handling and improve layout logic

parent 50b8f2a2
......@@ -64,4 +64,4 @@ export const DISABLED_ROW_DESKTOP =
'[--data-table-card-bg:var(--table-disabled)] hover:[--data-table-card-bg:var(--table-disabled-hover)] [background-color:var(--table-disabled)] hover:[background-color:var(--table-disabled-hover)] [&>td:first-child]:[border-left-color:var(--table-disabled-border)] [&>td:first-child]:border-l-4 [&>td:first-child]:pl-1'
export const DISABLED_ROW_MOBILE =
'[--data-table-card-bg:var(--table-disabled)] [background-color:var(--table-disabled)] border-l-4 [border-left-color:var(--table-disabled-border)]'
'[--data-table-card-bg:var(--table-disabled)] [background-color:var(--table-disabled)]'
......@@ -134,17 +134,6 @@ export type DataTablePageProps<TData> = {
hideMobile?: boolean
/**
* Render the card view on mobile instead of the default {@link MobileCardList}.
* When enabled, the mobile layout reuses the same {@link DataTableCardGrid}
* (and therefore `renderCard` / `cardGridClassName`) as the desktop card view,
* stacked in a single column. Falls back to the generic card content when no
* `renderCard` is provided. Ignored when a custom `mobile` slot is supplied.
*
* Defaults to `false`, so existing pages keep the list-style mobile layout.
*/
mobileCardView?: boolean
/**
* Row className resolver — applied to both desktop `TableRow` and mobile card.
* Composes with the default `data-state="selected"` styling on desktop.
* The `ctx.isMobile` flag is provided so consumers can return the
......@@ -235,9 +224,8 @@ export type DataTablePageProps<TData> = {
* pages render the table only and behave exactly as before. When enabled, a
* {@link DataTableViewModeToggle} is injected into the default toolbar
* (requires `toolbarProps`; ignored when a fully custom `toolbar` is used)
* and the desktop view switches between the table and a card grid.
*
* The mobile layout is unaffected — it always renders the mobile list.
* and the view switches between the table and a card grid on desktop and
* mobile. Mobile card mode reuses the same card renderer in a single column.
*/
enableCardView?: boolean
......@@ -323,7 +311,7 @@ export function DataTablePage<TData>(props: DataTablePageProps<TData>) {
) : undefined
const toolbarNode = renderToolbar(props, viewToggle)
const mobileNode = renderMobile(props, showMobile)
const mobileNode = renderMobile(props, showMobile, cardViewActive, viewMode)
const desktopNode = renderDesktop(props, showMobile, cardViewActive, viewMode)
const paginationNode = renderPagination(props)
......@@ -393,12 +381,15 @@ function renderPagination<TData>(
function renderMobile<TData>(
props: DataTablePageProps<TData>,
showMobile: boolean
showMobile: boolean,
cardViewActive: boolean,
viewMode: DataTableViewMode
): React.ReactNode {
if (!showMobile) {
return null
}
const isFetchingOnly = props.isFetching && !props.isLoading
const ownGetRowClassName = props.getRowClassName
const mobileGetRowClassName =
props.mobileProps?.getRowClassName ??
......@@ -408,29 +399,61 @@ function renderMobile<TData>(
let mobileContent = props.mobile
if (mobileContent === undefined) {
mobileContent = props.mobileCardView ? (
<DataTableCardGrid
table={props.table}
isLoading={props.isLoading}
emptyTitle={props.emptyTitle}
emptyDescription={props.emptyDescription}
emptyIcon={props.emptyIcon}
renderCard={props.renderCard}
gridClassName={props.cardGridClassName ?? 'grid grid-cols-1 gap-3'}
skeletonKeyPrefix={props.skeletonKeyPrefix}
getRowKey={props.mobileProps?.getRowKey}
getRowClassName={mobileGetRowClassName}
/>
) : (
<MobileCardList
table={props.table}
isLoading={props.isLoading}
emptyTitle={props.emptyTitle}
emptyDescription={props.emptyDescription}
getRowKey={props.mobileProps?.getRowKey}
getRowClassName={mobileGetRowClassName}
/>
)
if (cardViewActive && viewMode === DATA_TABLE_VIEW_MODES.TABLE) {
mobileContent = (
<DataTableView
table={props.table}
isLoading={props.isLoading}
emptyTitle={props.emptyTitle}
emptyDescription={props.emptyDescription}
emptyIcon={props.emptyIcon}
emptyAction={props.emptyAction}
skeletonKeyPrefix={props.skeletonKeyPrefix}
renderRow={props.renderRow}
applyHeaderSize={props.applyHeaderSize}
tableHeaderClassName={cn(
'[background-color:var(--table-header)]',
props.tableHeaderClassName
)}
getColumnClassName={props.getColumnClassName}
pinnedColumns={props.pinnedColumns}
containerClassName={cn(
'transition-opacity duration-150',
isFetchingOnly && 'pointer-events-none opacity-60',
props.tableClassName
)}
getRowClassName={(row) =>
props.getRowClassName?.(row, { isMobile: false })
}
/>
)
} else if (cardViewActive) {
mobileContent = (
<DataTableCardGrid
table={props.table}
isLoading={props.isLoading}
emptyTitle={props.emptyTitle}
emptyDescription={props.emptyDescription}
emptyIcon={props.emptyIcon}
renderCard={props.renderCard}
gridClassName={props.cardGridClassName ?? 'grid grid-cols-1 gap-3'}
skeletonKeyPrefix={props.skeletonKeyPrefix}
getRowKey={props.mobileProps?.getRowKey}
getRowClassName={mobileGetRowClassName}
/>
)
} else {
mobileContent = (
<MobileCardList
table={props.table}
isLoading={props.isLoading}
emptyTitle={props.emptyTitle}
emptyDescription={props.emptyDescription}
getRowKey={props.mobileProps?.getRowKey}
getRowClassName={mobileGetRowClassName}
/>
)
}
}
return <div className='min-h-0 flex-1 overflow-y-auto'>{mobileContent}</div>
......
......@@ -361,7 +361,6 @@ export function ChannelsTable() {
viewModeStorageKey={CHANNELS_VIEW_MODE_STORAGE_KEY}
renderCard={(row) => <ChannelCard row={row} />}
cardGridClassName='grid grid-cols-1 gap-3 sm:gap-4 lg:grid-cols-2 2xl:grid-cols-3'
mobileCardView
applyHeaderSize
toolbarProps={{
searchPlaceholder: t('Filter by name, ID, or key...'),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment