I implemented the ShadTable into a prototype project and experiencing an weird behaviour with the "RemainingTableSpanExtent".
On mobile the middle column of the table expands perfectly fine.
import 'package:prototype_app/components/appbar.dart';
import 'package:prototype_app/components/timesheet_card.dart';
import 'package:prototype_app/theme.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
var timesheets = [
(
date: DateTime.now(),
startTime: "7:00",
endTime: "16:00",
timeBreak: "1:00",
),
(
date: DateTime.now(),
startTime: "7:00",
endTime: "16:00",
timeBreak: "1:00",
),
(
date: DateTime.now(),
startTime: "7:00",
endTime: "16:00",
timeBreak: "1:00",
),
(
date: DateTime.now(),
startTime: "7:00",
endTime: "16:00",
timeBreak: "1:00",
),
];
final months = {
'jan': 'Januar',
'feb': 'Februrar',
'mar': 'März',
'apr': 'April',
'may': 'Mai',
'jun': 'Juni',
'jul': 'July',
'aug': 'August',
'sep': 'September',
'okt': 'Oktober',
'nov': 'November',
'dez': 'Dezember',
};
final years = {
2024,
2023,
2022,
};
class TimesheetOverview extends StatelessWidget {
const TimesheetOverview({super.key});
@override
Widget build(BuildContext context) {
final theme = ShadTheme.of(context);
return Scaffold(
appBar: AppBar(context, false),
body: Padding(
padding: const EdgeInsets.only(
top: 20,
left: 20,
right: 20,
),
child: SafeArea(
child: Wrap(
runSpacing: 15,
children: [
const TimesheetCard(
overviewMode: false,
),
Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(right: 8.0),
child: ShadCard(
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Überstunden",
style: theme.textTheme.large,
),
Text(
"3:54",
style: theme.textTheme.h2,
),
Text(
"2024",
style: theme.textTheme.p,
),
],
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 8.0),
child: ShadCard(
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Vertrag",
style: theme.textTheme.large,
),
Text(
"40:00",
style: theme.textTheme.h2,
),
Text(
"Noch 13:00",
style: theme.textTheme.p,
),
],
),
),
),
),
],
),
Padding(
padding: const EdgeInsets.only(top: 12),
child: Text("Bereits erfasst", style: theme.textTheme.h3),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: ShadSelect<String>(
placeholder: const Text('Monat'),
options: [
Padding(
padding: const EdgeInsets.fromLTRB(32, 6, 6, 6),
child: Text(
'Monate',
style: theme.textTheme.muted.copyWith(
fontWeight: FontWeight.w600,
color: theme.colorScheme.popoverForeground,
),
textAlign: TextAlign.start,
),
),
...months.entries.map((e) =>
ShadOption(value: e.key, child: Text(e.value))),
],
selectedOptionBuilder: (context, value) =>
Text(months[value]!),
),
),
Expanded(
child: ShadSelect<String>(
placeholder: const Text('Jahr'),
options: [
Padding(
padding: const EdgeInsets.fromLTRB(32, 6, 6, 6),
child: Text(
'Jahre',
style: theme.textTheme.muted.copyWith(
fontWeight: FontWeight.w600,
color: theme.colorScheme.popoverForeground,
),
textAlign: TextAlign.start,
),
),
...years.map((e) => ShadOption(
value: e.toString(), child: Text(e.toString()))),
],
selectedOptionBuilder: (context, value) => Text(value),
),
),
],
),
Center(
child: ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 600,
// added just to center the table vertically
maxHeight: 700,
),
child: ShadTable.list(
columnSpanExtent: (index) {
if (index == 0) return const FixedTableSpanExtent(80);
if (index == 1) {
return const MinTableSpanExtent(
FixedTableSpanExtent(150),
RemainingTableSpanExtent(),
);
}
return const FixedTableSpanExtent(130);
},
rowSpanExtent: (row) {
return const FixedTableSpanExtent(60);
},
children: timesheets.map(
(timesheet) => [
ShadTableCell(
alignment: Alignment.center,
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
direction: Axis.vertical,
children: [
Text(
"${timesheet.date.day}",
textAlign: TextAlign.center,
style: theme.textTheme.large,
),
Text(
DateFormat('EE', 'de_DE')
.format(timesheet.date)
.replaceAll(".", ""),
textAlign: TextAlign.center,
style: theme.textTheme.p
.copyWith(color: primaryColor),
),
],
),
),
ShadTableCell(
child: Wrap(
direction: Axis.vertical,
children: [
Text(
"${timesheet.startTime} - ${timesheet.endTime}",
style: theme.textTheme.large,
),
Text(
"Pause: ${timesheet.timeBreak}",
style: theme.textTheme.p,
),
],
),
),
const ShadTableCell(
alignment: Alignment.center,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ShadButton.secondary(
padding: EdgeInsets.symmetric(horizontal: 8),
icon: Icon(Icons.edit),
),
ShadButton.destructive(
padding: EdgeInsets.symmetric(horizontal: 8),
icon: Icon(Icons.delete),
),
],
)),
],
),
),
),
),
],
),
),
),
);
}
}