From 39ee6ea27fea223bc893b2be9cc473b1cf9cca4d Mon Sep 17 00:00:00 2001 From: Lisa Meyer <84317589+Lisa18289@users.noreply.github.com> Date: Thu, 10 Oct 2024 13:04:15 +0200 Subject: [PATCH] feat(List): add summary --- .../src/components/Action/Action.tsx | 4 +- .../ContextMenuTrigger/ContextMenuTrigger.tsx | 4 +- .../components/CounterBadge/CounterBadge.tsx | 22 +++---- .../src/components/List/List.module.css | 8 +++ .../components/src/components/List/List.tsx | 13 ++++- .../ListSummary/ListSummary.module.scss | 9 +++ .../components/ListSummary/ListSummary.tsx | 21 +++++++ .../List/components/ListSummary/index.ts | 4 ++ .../components/src/components/List/index.ts | 1 + .../List/stories/Default.stories.tsx | 42 +++++++++++++- .../PopoverTrigger/PopoverTrigger.tsx | 31 ++++------ .../src/components/Slider/Slider.tsx | 4 +- .../src/components/propTypes/index.ts | 3 + .../structure/list/examples/summary.tsx | 57 +++++++++++++++++++ .../03-components/structure/list/overview.mdx | 7 +++ 15 files changed, 186 insertions(+), 44 deletions(-) create mode 100644 packages/components/src/components/List/components/ListSummary/ListSummary.module.scss create mode 100644 packages/components/src/components/List/components/ListSummary/ListSummary.tsx create mode 100644 packages/components/src/components/List/components/ListSummary/index.ts create mode 100644 packages/docs/src/content/03-components/structure/list/examples/summary.tsx diff --git a/packages/components/src/components/Action/Action.tsx b/packages/components/src/components/Action/Action.tsx index 852c3f1b9..91ae1e780 100644 --- a/packages/components/src/components/Action/Action.tsx +++ b/packages/components/src/components/Action/Action.tsx @@ -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"; @@ -39,7 +37,7 @@ const actionButtonContext: ComponentPropsContext<"Button"> = { }), }; -export const Action: FC = flowComponent("Action", (props) => { +export const Action = flowComponent("Action", (props) => { const { children, actionModel: actionModelFromProps, ...actionProps } = props; const newActionModel = ActionModel.useNew(actionProps); const actionModel = actionModelFromProps ?? newActionModel; diff --git a/packages/components/src/components/ContextMenu/components/ContextMenuTrigger/ContextMenuTrigger.tsx b/packages/components/src/components/ContextMenu/components/ContextMenuTrigger/ContextMenuTrigger.tsx index 927d8f793..338e6cf21 100644 --- a/packages/components/src/components/ContextMenu/components/ContextMenuTrigger/ContextMenuTrigger.tsx +++ b/packages/components/src/components/ContextMenu/components/ContextMenuTrigger/ContextMenuTrigger.tsx @@ -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 = flowComponent( +export const ContextMenuTrigger = flowComponent( "ContextMenuTrigger", (props) => { const { children, ...triggerProps } = props; diff --git a/packages/components/src/components/CounterBadge/CounterBadge.tsx b/packages/components/src/components/CounterBadge/CounterBadge.tsx index 5355f0d34..ba02954ff 100644 --- a/packages/components/src/components/CounterBadge/CounterBadge.tsx +++ b/packages/components/src/components/CounterBadge/CounterBadge.tsx @@ -1,4 +1,3 @@ -import type { FC } from "react"; import React from "react"; import type { PropsWithElementType } from "@/lib/types/props"; import clsx from "clsx"; @@ -12,19 +11,16 @@ export interface CounterBadgeProps count?: number; } -export const CounterBadge: FC = 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 ( - - {count && count > 99 ? "99+" : count} - - ); - }, -); + return ( + + {count && count > 99 ? "99+" : count} + + ); +}); export default CounterBadge; diff --git a/packages/components/src/components/List/List.module.css b/packages/components/src/components/List/List.module.css index 8ee9aadbd..1ac14819f 100644 --- a/packages/components/src/components/List/List.module.css +++ b/packages/components/src/components/List/List.module.css @@ -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; + } + } } diff --git a/packages/components/src/components/List/List.tsx b/packages/components/src/components/List/List.tsx index 7bb52dfd9..26622ed19 100644 --- a/packages/components/src/components/List/List.tsx +++ b/packages/components/src/components/List/List.tsx @@ -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"; @@ -152,6 +152,9 @@ export const List = flowComponent("List", (props) => { tunnelId: "actions", ignoreBreakpoint: true, }, + ListSummary: { + tunnelId: "listSummary", + }, }; const hasActionGroup = !!deepFindOfType(children, ActionGroup); @@ -168,8 +171,12 @@ export const List = flowComponent("List", (props) => {
{children}
- {listModel.viewMode === "list" && } - {listModel.viewMode === "table" && } + +
+ + {listModel.viewMode === "list" && } + {listModel.viewMode === "table" &&
} +
diff --git a/packages/components/src/components/List/components/ListSummary/ListSummary.module.scss b/packages/components/src/components/List/components/ListSummary/ListSummary.module.scss new file mode 100644 index 000000000..c75c1908b --- /dev/null +++ b/packages/components/src/components/List/components/ListSummary/ListSummary.module.scss @@ -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); +} diff --git a/packages/components/src/components/List/components/ListSummary/ListSummary.tsx b/packages/components/src/components/List/components/ListSummary/ListSummary.tsx new file mode 100644 index 000000000..e8d65a534 --- /dev/null +++ b/packages/components/src/components/List/components/ListSummary/ListSummary.tsx @@ -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 ( +
+ {children} +
+ ); +}); + +export default ListSummary; diff --git a/packages/components/src/components/List/components/ListSummary/index.ts b/packages/components/src/components/List/components/ListSummary/index.ts new file mode 100644 index 000000000..27c2ed949 --- /dev/null +++ b/packages/components/src/components/List/components/ListSummary/index.ts @@ -0,0 +1,4 @@ +import { ListSummary } from "./ListSummary"; + +export { ListSummary } from "./ListSummary"; +export default ListSummary; diff --git a/packages/components/src/components/List/index.ts b/packages/components/src/components/List/index.ts index 3e5cbe0a4..58d2dd657 100644 --- a/packages/components/src/components/List/index.ts +++ b/packages/components/src/components/List/index.ts @@ -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"; diff --git a/packages/components/src/components/List/stories/Default.stories.tsx b/packages/components/src/components/List/stories/Default.stories.tsx index 0c45cdafa..7829c0821 100644 --- a/packages/components/src/components/List/stories/Default.stories.tsx +++ b/packages/components/src/components/List/stories/Default.stories.tsx @@ -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"; @@ -138,3 +138,43 @@ export default meta; type Story = StoryObj; export const Default: Story = {}; + +export const WithSummary: Story = { + render: () => { + const InvoiceList = typedList<{ + id: string; + date: string; + amount: string; + }>(); + + return ( +
+ Invoices + + + + total: 42,00 € + + + + + {(invoice) => ( + + {invoice.id} + + {invoice.date} - {invoice.amount} + + + )} + + +
+ ); + }, +}; diff --git a/packages/components/src/components/Popover/components/PopoverTrigger/PopoverTrigger.tsx b/packages/components/src/components/Popover/components/PopoverTrigger/PopoverTrigger.tsx index 76f99e79d..af9cdd553 100644 --- a/packages/components/src/components/Popover/components/PopoverTrigger/PopoverTrigger.tsx +++ b/packages/components/src/components/Popover/components/PopoverTrigger/PopoverTrigger.tsx @@ -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; - -export const PopoverTrigger: FC = flowComponent( - "PopoverTrigger", - (props) => { - const { children, ...triggerProps } = props; - return ( - - {children} - - ); - }, -); +export const PopoverTrigger = flowComponent("PopoverTrigger", (props) => { + const { children, ...triggerProps } = props; + return ( + + {children} + + ); +}); diff --git a/packages/components/src/components/Slider/Slider.tsx b/packages/components/src/components/Slider/Slider.tsx index 9ad5a361d..667aa2409 100644 --- a/packages/components/src/components/Slider/Slider.tsx +++ b/packages/components/src/components/Slider/Slider.tsx @@ -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"; @@ -19,7 +19,7 @@ export interface SliderProps showInitialMarker?: boolean; } -export const Slider: FC = flowComponent("Slider", (props) => { +export const Slider = flowComponent("Slider", (props) => { const { className, children, diff --git a/packages/components/src/components/propTypes/index.ts b/packages/components/src/components/propTypes/index.ts index b59b6600c..5f82889b9 100644 --- a/packages/components/src/components/propTypes/index.ts +++ b/packages/components/src/components/propTypes/index.ts @@ -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"; @@ -84,6 +85,7 @@ export interface FlowComponentPropsTypes { LayoutCard: LayoutCardProps; Link: LinkProps; List: ListProps; + ListSummary: ListSummaryProps; MenuItem: MenuItemProps; Modal: ModalProps; ModalTrigger: OverlayTriggerProps; @@ -142,6 +144,7 @@ const propsContextSupportingComponentsMap: Record< LayoutCard: true, Link: true, List: true, + ListSummary: true, MenuItem: true, Modal: true, ModalTrigger: true, diff --git a/packages/docs/src/content/03-components/structure/list/examples/summary.tsx b/packages/docs/src/content/03-components/structure/list/examples/summary.tsx new file mode 100644 index 000000000..c9d29acd1 --- /dev/null +++ b/packages/docs/src/content/03-components/structure/list/examples/summary.tsx @@ -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 ( + + + + Gesamt: 41,00 € + + + + + + {(invoice) => ( + + {invoice.id} + + {invoice.date} - {invoice.amount} + + + )} + + + ); +}; diff --git a/packages/docs/src/content/03-components/structure/list/overview.mdx b/packages/docs/src/content/03-components/structure/list/overview.mdx index 38cc5d22a..07a3c1899 100644 --- a/packages/docs/src/content/03-components/structure/list/overview.mdx +++ b/packages/docs/src/content/03-components/structure/list/overview.mdx @@ -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. + +## Summary + +Verwende eine `` um eine Zusammenfassung, wie beispielsweise die +Summe der Beträge, anzuzeigen. + +