Skip to content

Commit 1ea8c33

Browse files
authored
Merge pull request #889 from buildo/bento-887
[Table] allow to specify align and other params on single cells
2 parents adc33f1 + 0f6db77 commit 1ea8c33

File tree

3 files changed

+80
-27
lines changed

3 files changed

+80
-27
lines changed

packages/bento-design-system/src/Table/cells.tsx

+32-11
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,37 @@ export function ButtonLinkCell({
6363
);
6464
}
6565

66+
type TextCellValue =
67+
| LocalizedString
68+
| ({ text: LocalizedString } & Partial<Pick<BodyProps, "size" | "weight" | "color" | "align">>);
6669
export function TextCell({
6770
value,
68-
column: { align },
71+
column,
6972
options,
70-
}: CellProps<any, LocalizedString> & {
73+
}: CellProps<any, TextCellValue> & {
7174
options: Partial<Pick<BodyProps, "size" | "weight" | "color">>;
7275
}) {
7376
const config = useBentoConfig().table;
7477
const padding = config.padding.textCell ?? config.padding.defaultCell;
75-
const { size, weight, color } = mergeProps(config.defaultCellOptions.textCell, options);
78+
const cellOptions: Omit<TextCellValue, "text"> = typeof value === "string" ? {} : value;
79+
80+
const { size, weight, color, align } = mergeProps(
81+
column,
82+
config.defaultCellOptions.textCell,
83+
options,
84+
cellOptions
85+
);
7686
return (
7787
<Box {...padding} textAlign={align}>
7888
<Body size={size} weight={weight} color={color}>
79-
{value}
89+
{typeof value === "string" ? value : value.text}
8090
</Body>
8191
</Box>
8292
);
8393
}
8494

8595
export function TextWithIconCell({
86-
value: { icon, iconPosition, text, tooltipContent },
96+
value: { icon, iconPosition, text, tooltipContent, ...cellOptions },
8797
column: { align },
8898
options,
8999
}: CellProps<
@@ -93,7 +103,7 @@ export function TextWithIconCell({
93103
iconPosition: "left" | "right";
94104
text: LocalizedString;
95105
tooltipContent?: Children;
96-
}
106+
} & Partial<Pick<BodyProps, "size" | "weight" | "color">>
97107
> & {
98108
options: Partial<Pick<BodyProps, "size" | "weight" | "color">> & {
99109
iconSize?: IconProps["size"];
@@ -103,7 +113,8 @@ export function TextWithIconCell({
103113
const config = useBentoConfig().table;
104114
const { size, weight, color, iconSize, iconColor } = mergeProps(
105115
config.defaultCellOptions.textWithIconCell,
106-
options
116+
options,
117+
cellOptions
107118
);
108119
const padding = config.padding.textWithIconCell ?? config.padding.defaultCell;
109120
const icon_ = icon && icon({ size: iconSize, color: iconColor });
@@ -144,20 +155,30 @@ export function ChipCell({ value: chipProps, column: { align } }: CellProps<any,
144155
);
145156
}
146157

158+
type LabelCellValue =
159+
| LocalizedString
160+
| ({ text: LocalizedString } & Partial<Pick<LabelProps, "size" | "color" | "align">>);
147161
export function LabelCell({
148162
value,
149-
column: { align },
163+
column,
150164
options,
151-
}: CellProps<any, LocalizedString> & {
165+
}: CellProps<any, LabelCellValue> & {
152166
options: Partial<Pick<LabelProps, "size" | "color">>;
153167
}) {
154168
const config = useBentoConfig().table;
155169
const padding = config.padding.labelCell ?? config.padding.defaultCell;
156-
const { size, color } = mergeProps(config.defaultCellOptions.labelCell, options);
170+
const cellOptions = typeof value === "string" ? {} : value;
171+
172+
const { size, color, align } = mergeProps(
173+
column,
174+
config.defaultCellOptions.labelCell,
175+
options,
176+
cellOptions
177+
);
157178
return (
158179
<Box {...padding} textAlign={align}>
159180
<Label size={size} color={color}>
160-
{value}
181+
{typeof value === "string" ? value : value.text}
161182
</Label>
162183
</Box>
163184
);

packages/bento-design-system/src/Table/tableColumn.tsx

+24-10
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export function textWithIcon<A extends string>({
151151
icon: ((props: IconProps) => Children) | null;
152152
text: LocalizedString;
153153
tooltipContent?: Children;
154-
}
154+
} & Partial<Pick<BodyProps, "size" | "weight" | "color">>
155155
>) => {
156156
const value = { ..._value, iconPosition };
157157
const textWithIconCellProps = {
@@ -166,6 +166,9 @@ export function textWithIcon<A extends string>({
166166
});
167167
}
168168

169+
type NumberCellValue =
170+
| number
171+
| ({ numericValue: number } & Partial<Pick<BodyProps, "size" | "weight" | "color" | "align">>);
169172
export function number<A extends string>({
170173
valueFormatter,
171174
size,
@@ -177,17 +180,27 @@ export function number<A extends string>({
177180
} & Partial<Pick<BodyProps, "size" | "weight" | "color">>) {
178181
return custom({
179182
...options,
180-
Cell: ({ value: numericValue, ...props }: CellProps<any, number>) => {
181-
const value = valueFormatter(numericValue);
183+
Cell: ({ value, ...props }: CellProps<any, NumberCellValue>) => {
184+
const numericValue = typeof value === "number" ? value : value.numericValue;
185+
const formattedValue = valueFormatter(numericValue);
182186
const textCellProps = {
183187
...props,
184-
value,
185-
cell: { ...props.cell, value },
186-
options: { size, weight, color },
188+
value: formattedValue,
189+
cell: { ...props.cell, value: formattedValue },
190+
options: {
191+
size,
192+
weight,
193+
color,
194+
align: typeof value === "number" ? undefined : value.align,
195+
},
187196
};
188197
return <TextCell {...textCellProps} />;
189198
},
190-
sortType: (a = 0, b = 0) => a - b,
199+
sortType: (a = 0, b = 0) => {
200+
const aValue = typeof a === "number" ? a : a.numericValue;
201+
const bValue = typeof b === "number" ? b : b.numericValue;
202+
return aValue - bValue;
203+
},
191204
});
192205
}
193206

@@ -203,21 +216,22 @@ export function numberWithIcon<A extends string>({
203216
return custom({
204217
...options,
205218
Cell: ({
206-
value: { numericValue, icon, tooltipContent },
219+
value: { numericValue, icon, tooltipContent, ...cellOptions },
207220
...props
208221
}: CellProps<
209222
any,
210223
{
211224
icon: ((props: IconProps) => Children) | null;
212225
numericValue: number;
213226
tooltipContent?: Children;
214-
}
227+
} & Partial<Pick<BodyProps, "size" | "weight" | "color">>
215228
>) => {
216229
const value = {
217230
text: valueFormatter(numericValue),
218231
icon,
219232
iconPosition: "right" as const,
220233
tooltipContent,
234+
...cellOptions,
221235
};
222236
const textCellProps = {
223237
...props,
@@ -242,7 +256,7 @@ export function label<A extends string>({
242256
}: ColumnOptionsBase<A> & Partial<Pick<LabelProps, "size" | "color">>) {
243257
return custom({
244258
...options,
245-
Cell: (props: Omit<ComponentProps<typeof TextCell>, "options">) => (
259+
Cell: (props: Omit<ComponentProps<typeof LabelCell>, "options">) => (
246260
<LabelCell {...{ ...props, options: { size, color } }} />
247261
),
248262
});

packages/bento-design-system/stories/Components/Table.stories.tsx

+24-6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const exampleColumns = [
3434
headerLabel: "Extended complete address",
3535
accessor: "address",
3636
width: { custom: 200 },
37+
align: "center",
3738
}),
3839
tableColumn.textWithIcon({
3940
headerLabel: "Country",
@@ -113,7 +114,14 @@ const exampleColumnsWithFooter = [
113114
hint: { onPress: action("hint") },
114115
footer: ({ rows }) =>
115116
Intl.NumberFormat("en").format(
116-
rows.reduce((acc, row) => acc + (row.values.applications ?? 0), 0)
117+
rows.reduce(
118+
(acc, row) =>
119+
acc +
120+
(typeof row.values.applications === "number"
121+
? row.values.applications ?? 0
122+
: row.values.applications?.numericValue ?? 0),
123+
0
124+
)
117125
),
118126
}),
119127
tableColumn.numberWithIcon({
@@ -192,7 +200,14 @@ const exampleGroupedColumns = [
192200
hint: { onPress: action("hint") },
193201
footer: ({ rows }) =>
194202
Intl.NumberFormat("en").format(
195-
rows.reduce((acc, row) => acc + (row.values.applications ?? 0), 0)
203+
rows.reduce(
204+
(acc, row) =>
205+
acc +
206+
(typeof row.values.applications === "number"
207+
? row.values.applications ?? 0
208+
: row.values.applications?.numericValue ?? 0),
209+
0
210+
)
196211
),
197212
}),
198213
tableColumn.numberWithIcon({
@@ -317,7 +332,10 @@ const deleteAction = {
317332
const exampleData = [
318333
{
319334
name: "Amazon",
320-
address: "Theodore Lowe Ap #867-859 Sit Rd. Azusa New York 39531",
335+
address: {
336+
text: "Theodore Lowe Ap #867-859 Sit Rd. Azusa New York 39531",
337+
weight: "strong",
338+
},
321339
country: {
322340
icon: IconInfoSolid,
323341
text: "US",
@@ -334,7 +352,7 @@ const exampleData = [
334352
numericValue: 100,
335353
icon: IconInfoSolid,
336354
},
337-
type: "Private",
355+
type: { text: "Private", color: "secondary", align: "right" },
338356
website: { href: "http://www.amazon.com", label: "Link" },
339357
alerts: { icon: IconWarningSolid, label: "Warning" },
340358
group: "Group 1",
@@ -379,7 +397,7 @@ const exampleData = [
379397
hierarchy: "primary",
380398
onPress: () => {},
381399
} as const,
382-
applications: 1_000,
400+
applications: { numericValue: 1_000, align: "left" },
383401
status: { label: "Pending", color: "yellow" } as const,
384402
value: {
385403
numericValue: 120,
@@ -436,7 +454,7 @@ const exampleData = [
436454
group: "Group 1",
437455
deleteAction,
438456
},
439-
];
457+
] as const;
440458

441459
const meta = {
442460
component: Table,

0 commit comments

Comments
 (0)