Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add list summary #835

Merged
merged 10 commits into from
Oct 10, 2024
4 changes: 1 addition & 3 deletions packages/components/src/components/Action/Action.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import type { FC } from "react";
import React from "react";
import { ActionModel as ActionModel } from "@/components/Action/models/ActionModel";
import type { PropsContext } from "@/lib/propsContext";
import { dynamic, PropsContextProvider } from "@/lib/propsContext";
import type { ActionProps } from "@/components/Action/types";
import { ActionContextProvider } from "@/components/Action/context";
import { useActionStateContext } from "@/components/Action/models/ActionStateContext";
import { useConfirmationModalButtonSlot } from "@/components/Action/hooks/useConfirmationModalButtonSlot";
Expand Down Expand Up @@ -39,7 +37,7 @@ const actionButtonContext: ComponentPropsContext<"Button"> = {
}),
};

export const Action: FC<ActionProps> = flowComponent("Action", (props) => {
export const Action = flowComponent("Action", (props) => {
const { children, actionModel: actionModelFromProps, ...actionProps } = props;
const newActionModel = ActionModel.useNew(actionProps);
const actionModel = actionModelFromProps ?? newActionModel;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import * as Aria from "react-aria-components";
import type { FC } from "react";
import React from "react";
import type { OverlayTriggerProps } from "@/components/OverlayTrigger";
import { OverlayTrigger } from "@/components/OverlayTrigger";
import { flowComponent } from "@/lib/componentFactory/flowComponent";

export const ContextMenuTrigger: FC<OverlayTriggerProps> = flowComponent(
export const ContextMenuTrigger = flowComponent(
"ContextMenuTrigger",
(props) => {
const { children, ...triggerProps } = props;
Expand Down
22 changes: 9 additions & 13 deletions packages/components/src/components/CounterBadge/CounterBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { FC } from "react";
import React from "react";
import type { PropsWithElementType } from "@/lib/types/props";
import clsx from "clsx";
Expand All @@ -12,19 +11,16 @@ export interface CounterBadgeProps
count?: number;
}

export const CounterBadge: FC<CounterBadgeProps> = flowComponent(
"CounterBadge",
(props) => {
const { className, count, refProp: ref, ...rest } = props;
export const CounterBadge = flowComponent("CounterBadge", (props) => {
const { className, count, refProp: ref, ...rest } = props;

const rootClassName = clsx(styles.counterBadge, className);
const rootClassName = clsx(styles.counterBadge, className);

return (
<span className={rootClassName} {...rest} aria-hidden ref={ref}>
{count && count > 99 ? "99+" : count}
</span>
);
},
);
return (
<span className={rootClassName} {...rest} aria-hidden ref={ref}>
{count && count > 99 ? "99+" : count}
</span>
);
});

export default CounterBadge;
8 changes: 8 additions & 0 deletions packages/components/src/components/List/List.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,12 @@
flex-direction: column;
row-gap: var(--list--block-to-block-spacing);
container-type: inline-size;

:has(:global(.flow--list--list-summary)) {
:global(.flow--list--items),
:global(.flow--list--table) {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
}
13 changes: 10 additions & 3 deletions packages/components/src/components/List/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { Table } from "@/components/List/components/Table";
import { Table as TableSetupComponent } from "@/components/List/setupComponents/Table";
import { TableHeader } from "@/components/List/setupComponents/TableHeader";
import { TableBody } from "@/components/List/setupComponents/TableBody";
import { TunnelProvider } from "@mittwald/react-tunnel";
import { TunnelExit, TunnelProvider } from "@mittwald/react-tunnel";
import { type PropsContext, PropsContextProvider } from "@/lib/propsContext";
import headerStyles from "./components/Header/Header.module.css";
import { ActionGroup } from "@/components/ActionGroup";
Expand Down Expand Up @@ -152,6 +152,9 @@ export const List = flowComponent("List", (props) => {
tunnelId: "actions",
ignoreBreakpoint: true,
},
ListSummary: {
tunnelId: "listSummary",
},
};

const hasActionGroup = !!deepFindOfType(children, ActionGroup);
Expand All @@ -168,8 +171,12 @@ export const List = flowComponent("List", (props) => {
<div className={styles.list} ref={ref}>
{children}
<Header hasActionGroup={hasActionGroup} />
{listModel.viewMode === "list" && <Items />}
{listModel.viewMode === "table" && <Table />}

<div>
<TunnelExit id="listSummary" />
{listModel.viewMode === "list" && <Items />}
{listModel.viewMode === "table" && <Table />}
</div>
<Footer />
</div>
</listContext.Provider>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.listSummary {
border-width: var(--list-item--border-width);
border-bottom-width: 0;
border-style: var(--list-item--border-style);
border-color: var(--list-item--border-color);
padding: var(--list-item--padding);
border-top-left-radius: var(--list-item--corner-radius);
border-top-right-radius: var(--list-item--corner-radius);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { PropsWithChildren } from "react";
import React from "react";
import styles from "./ListSummary.module.scss";
import type { FlowComponentProps } from "@/lib/componentFactory/flowComponent";
import { flowComponent } from "@/lib/componentFactory/flowComponent";

export interface ListSummaryProps
extends FlowComponentProps,
PropsWithChildren {}

export const ListSummary = flowComponent("ListSummary", (props) => {
const { children } = props;

return (
<header className={styles.listSummary} {...props}>
{children}
</header>
);
});

export default ListSummary;
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { ListSummary } from "./ListSummary";

export { ListSummary } from "./ListSummary";
export default ListSummary;
1 change: 1 addition & 0 deletions packages/components/src/components/List/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export type {
} from "@/components/List/model/loading/types";
export type { RenderItemFn } from "@/components/List/model/item/types";
export { View as ListItemView } from "./components/Items/components/Item/components/View";
export * from "./components/ListSummary";
export * from "./List";
export * from "./setupComponents/ListFilter";
export * from "./setupComponents/ListSorting";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import AlertBadge from "@/components/AlertBadge";
import type { Domain } from "../testData/domainApi";
import { getDomains, getTypes } from "../testData/domainApi";
import { Section } from "@/components/Section";
import { typedList } from "@/components/List";
import { ListItemView, ListSummary, typedList } from "@/components/List";
import { Button } from "@/components/Button";
import IconDownload from "@/components/Icon/components/icons/IconDownload";
import { ActionGroup } from "@/components/ActionGroup";
Expand Down Expand Up @@ -138,3 +138,43 @@ export default meta;
type Story = StoryObj<typeof List>;

export const Default: Story = {};

export const WithSummary: Story = {
render: () => {
const InvoiceList = typedList<{
id: string;
date: string;
amount: string;
}>();

return (
<Section>
<Heading>Invoices</Heading>
<InvoiceList.List batchSize={5} aria-label="Invoices">
<ListSummary>
<Text style={{ display: "block", textAlign: "right" }}>
<b>total: 42,00 €</b>
</Text>
</ListSummary>
<InvoiceList.StaticData
data={[
{ id: "RG100000", date: "1.9.2024", amount: "25,00 €" },
{ id: "RG100001", date: "12.9.2024", amount: "12,00 €" },
{ id: "RG100002", date: "3.10.2024", amount: "4,00 €" },
]}
/>
<InvoiceList.Item>
{(invoice) => (
<ListItemView>
<Heading>{invoice.id}</Heading>
<Text>
{invoice.date} - {invoice.amount}
</Text>
</ListItemView>
)}
</InvoiceList.Item>
</InvoiceList.List>
</Section>
);
},
};
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
import * as Aria from "react-aria-components";
import type { FC } from "react";
import React from "react";
import type { OverlayTriggerProps } from "@/components/OverlayTrigger";
import { OverlayTrigger } from "@/components/OverlayTrigger";
import { flowComponent } from "@/lib/componentFactory/flowComponent";

type Props = Omit<OverlayTriggerProps, "overlayType">;

export const PopoverTrigger: FC<Props> = flowComponent(
"PopoverTrigger",
(props) => {
const { children, ...triggerProps } = props;
return (
<OverlayTrigger
overlayType="Popover"
{...triggerProps}
component={Aria.DialogTrigger}
>
{children}
</OverlayTrigger>
);
},
);
export const PopoverTrigger = flowComponent("PopoverTrigger", (props) => {
const { children, ...triggerProps } = props;
return (
<OverlayTrigger
overlayType="Popover"
{...triggerProps}
component={Aria.DialogTrigger}
>
{children}
</OverlayTrigger>
);
});
4 changes: 2 additions & 2 deletions packages/components/src/components/Slider/Slider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { FC, PropsWithChildren } from "react";
import type { PropsWithChildren } from "react";
import React from "react";
import type { FlowComponentProps } from "@/lib/componentFactory/flowComponent";
import { flowComponent } from "@/lib/componentFactory/flowComponent";
Expand All @@ -19,7 +19,7 @@ export interface SliderProps
showInitialMarker?: boolean;
}

export const Slider: FC<SliderProps> = flowComponent("Slider", (props) => {
export const Slider = flowComponent("Slider", (props) => {
const {
className,
children,
Expand Down
3 changes: 3 additions & 0 deletions packages/components/src/components/propTypes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import type * as Aria from "react-aria-components";
import type { DateRangePickerProps } from "@/components/DateRangePicker";
import type { TimeFieldProps } from "@/components/TimeField";
import type { AlertIconProps } from "@/components/AlertIcon";
import type { ListSummaryProps } from "@/components/List/components/ListSummary/ListSummary";

export * from "./types";

Expand Down Expand Up @@ -84,6 +85,7 @@ export interface FlowComponentPropsTypes {
LayoutCard: LayoutCardProps;
Link: LinkProps;
List: ListProps<never>;
ListSummary: ListSummaryProps;
MenuItem: MenuItemProps;
Modal: ModalProps;
ModalTrigger: OverlayTriggerProps;
Expand Down Expand Up @@ -142,6 +144,7 @@ const propsContextSupportingComponentsMap: Record<
LayoutCard: true,
Link: true,
List: true,
ListSummary: true,
MenuItem: true,
Modal: true,
ModalTrigger: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {
ListItemView,
ListSummary,
typedList,
} from "@mittwald/flow-react-components/List";
import Heading from "@mittwald/flow-react-components/Heading";
import Text from "@mittwald/flow-react-components/Text";

export default () => {
const InvoiceList = typedList<{
id: string;
date: string;
amount: string;
}>();

return (
<InvoiceList.List batchSize={5} aria-label="Invoices">
<ListSummary>
<Text
style={{ display: "block", textAlign: "right" }}
>
<b>Gesamt: 41,00 €</b>
</Text>
</ListSummary>
<InvoiceList.StaticData
data={[
{
id: "RG100000",
date: "1.9.2024",
amount: "25,00 €",
},
{
id: "RG100001",
date: "12.9.2024",
amount: "12,00 €",
},
{
id: "RG100002",
date: "3.10.2024",
amount: "4,00 €",
},
]}
/>

<InvoiceList.Item>
{(invoice) => (
<ListItemView>
<Heading>{invoice.id}</Heading>
<Text>
{invoice.date} - {invoice.amount}
</Text>
</ListItemView>
)}
</InvoiceList.Item>
</InvoiceList.List>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,10 @@ Standard 10 Einträge an und lädt über einen Klick auf "Mehr anzeigen" jeweils
Einträge nach. Diese Werte lassen sich über die `batchSize` Property anpassen.

<LiveCodeEditor example="pagination" editorCollapsed />

## Summary

Verwende eine `<ListSummary/>` um eine Zusammenfassung, wie beispielsweise die
Summe der Beträge, anzuzeigen.

<LiveCodeEditor example="summary" editorCollapsed />