From 506c5148996df0beb50970319c2f5aebe1bb4b98 Mon Sep 17 00:00:00 2001 From: Peter Hellstrand Date: Wed, 11 Sep 2024 15:31:44 +0200 Subject: [PATCH] docs(ffe-tables-react): storybook example tables --- .../ffe-tables-react/src/Table.stories.tsx | 384 ++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 packages/ffe-tables-react/src/Table.stories.tsx diff --git a/packages/ffe-tables-react/src/Table.stories.tsx b/packages/ffe-tables-react/src/Table.stories.tsx new file mode 100644 index 0000000000..14465e9695 --- /dev/null +++ b/packages/ffe-tables-react/src/Table.stories.tsx @@ -0,0 +1,384 @@ +import React from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; +import { Table } from './Table'; +import { TableHead } from './TableHead'; +import { TableBody } from './TableBody'; +import { TableHeaderCell } from './TableHeaderCell'; +import { TableRow } from './TableRow'; +import { TableDataCell } from './TableDataCell'; +import { TableCaption } from './TableCaption'; +import { TableFoot } from './TableFoot'; +import { TableRowExpandable } from './TableRowExpandable'; +import { formatNumber } from '@sb1/ffe-formatters'; +import { TertiaryButton } from '@sb1/ffe-buttons-react'; + +const meta: Meta = { + title: 'components/table/Table', + component: Table, + tags: ['autodocs'], +}; +export default meta; + +type Story = StoryObj; + +export const Standard: Story = { + args: {}, + render: () => { + const data = [ + { name: 'Anders', age: 32 }, + { name: 'Erik', age: 25 }, + { name: 'Gunn', age: 29 }, + { name: 'Safi', age: 42 }, + { name: 'Sandra', age: 42 }, + ]; + + const navnHeader = 'Navn'; + const alderHeader = 'Alder'; + const gjenomsnittsalderHeader = ' Gjenomsnittsalder'; + + return ( +
+ + Utviklere + + + + {navnHeader} + + + {alderHeader} + + + + + {data.map(it => ( + + + {it.name} + + + {it.age} + + + ))} + + + + + {gjenomsnittsalderHeader} + + + {data.reduce((sum, curr) => sum + curr.age, 0) / + data.length} + + + +
+
+ ); + }, +}; + +export const Expandable: Story = { + args: {}, + render: () => { + const data = [ + { + name: 'Ola Normann', + email: 'ola@normann.no', + expand: 'Info: mer spennende info om Ola', + }, + { + name: 'Sivert Svensk', + email: 'sivert@svenska.se', + expand: 'Info: mer spennende info om Sivert', + }, + { + name: 'Daniel Dansk', + email: 'daniel@dansk.dk', + expand: 'Info: mer spennende info om Daniel', + }, + ]; + const navnHeader = 'Navn'; + const epostHeader = 'E-post'; + return ( +
+ + Tabel utvidbare rader + + + + {navnHeader} + + + {epostHeader} + + + + + {data.map((it, index) => ( + + + {it.name} + + + {it.email} + + + ))} + +
+
+ ); + }, +}; + +export const Sortable: Story = { + args: {}, + render: () => { + type Data = { + name: string; + email: string; + age: number; + fortune: number; + button: React.ReactNode; + expand?: React.ReactNode; + }; + + const button = ( + { + e.preventDefault(); + e.stopPropagation(); + }} + > + poke + + ); + + const data: Data[] = [ + { + name: 'Ola Normann', + email: 'ola@normann.no', + age: 23, + fortune: 12693005.93, + button, + expand: 'Info: mer spennende info om Ola', + }, + { + name: 'Sivert Svensk', + email: 'sivert@svenska.se', + age: 45, + fortune: 9005.93, + button, + }, + { + name: 'Daniel Dansk', + email: 'daniel@dansk.dk', + age: 39, + fortune: 8693005.93, + button, + }, + { + name: 'Lille Ole', + email: 'lilleole@gmail.com', + age: 9, + fortune: 23.12, + button, + }, + ]; + + function compareStringAsc( + getField: (item: Item) => string | null | undefined, + ) { + return (itemA: Item, itemB: Item) => { + const a = getField(itemA); + const b = getField(itemB); + if (!a) return 1; + if (!b) return -1; + if (a === b) return 0; + return a.localeCompare(b); + }; + } + + function compareStringDesc( + getField: (item: Item) => string | null | undefined, + ) { + return (itemA: Item, itemB: Item) => { + const a = getField(itemA); + const b = getField(itemB); + if (!a) return 1; + if (!b) return -1; + if (a === b) return 0; + return b.localeCompare(a); + }; + } + + function compareNumberAsc( + getField: (item: Item) => number | null | undefined, + ) { + return (itemA: Item, itemB: Item) => { + const a = getField(itemA); + const b = getField(itemB); + return (a != null ? a : Infinity) - (b != null ? b : Infinity); + }; + } + + function compareNumberDesc( + getField: (item: Item) => number | null | undefined, + ) { + return (itemA: Item, itemB: Item) => { + const a = getField(itemA); + const b = getField(itemB); + return ( + (b != null ? b : -Infinity) - (a != null ? a : -Infinity) + ); + }; + } + + const sortFunctions = { + name: { + ascending: compareStringAsc(it => it.name), + descending: compareStringDesc(it => it.name), + none: null, + }, + email: { + ascending: compareStringAsc(it => it.email), + descending: compareStringDesc(it => it.email), + none: null, + }, + age: { + ascending: compareNumberAsc(it => it.age), + descending: compareNumberDesc(it => it.age), + none: null, + }, + fortune: { + ascending: compareNumberAsc(it => it.fortune), + descending: compareNumberDesc(it => it.fortune), + none: null, + }, + }; + + return ( +
+ + {({ activeSortKey, activeSortOrder }) => { + const sortFunc = + activeSortKey && activeSortOrder + ? sortFunctions[ + activeSortKey as keyof typeof sortFunctions + ][activeSortOrder] + : null; + + const sortedData = sortFunc + ? [...data.sort(sortFunc)] + : data; + + const navnHeader = 'Navn'; + const epostHeader = 'E-post'; + const alderHeader = 'Alder'; + const formueHeader = 'Formue'; + const pokeHeader = 'Poke'; + + return ( + <> + + Masse spennende data + + + + + {navnHeader} + + + {epostHeader} + + + {alderHeader} + + + {formueHeader} + + + {pokeHeader} + + + + + {sortedData.map(it => { + const rowContent = ( + <> + + {it.name} + + + {it.email} + + + {it.age} + + + {formatNumber(it.fortune, { + decimals: 2, + })} + + + {it.button} + + + ); + + return it.expand ? ( + + {rowContent} + + ) : ( + + {rowContent} + + ); + })} + + + ); + }} +
+
+ ); + }, +};