@recursica/adapter-mui-v7 1.3.1 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +1 -1
  3. package/dist/adapter-mui-v7.cjs +16 -16
  4. package/dist/adapter-mui-v7.cjs.map +1 -1
  5. package/dist/adapter-mui-v7.css +1 -1
  6. package/dist/adapter-mui-v7.js +902 -880
  7. package/dist/adapter-mui-v7.js.map +1 -1
  8. package/dist/index.d.ts +8 -5
  9. package/docs/PHILOSOPHY.md +4 -0
  10. package/package.json +4 -8
  11. package/src/components/Heading/HEADING_IMPLEMENTATION_NOTES.md +10 -0
  12. package/src/components/Panel/PANEL_IMPLEMENTATION_NOTES.md +8 -0
  13. package/src/components/Panel/Panel.tsx +51 -9
  14. package/src/components/Slider/Slider.module.css +11 -0
  15. package/src/components/Text/TEXT_IMPLEMENTATION_NOTES.md +12 -0
  16. package/src/components/Text/Text.headings.dom.test.tsx +54 -0
  17. package/src/components/Text/Text.tsx +16 -0
  18. package/.storybook/commonArgTypes.ts +0 -148
  19. package/recursica_brand.json +0 -2610
  20. package/recursica_tokens.json +0 -769
  21. package/recursica_ui-kit.json +0 -9049
  22. package/recursica_variables_scoped.css +0 -6178
  23. package/src/Introduction.stories.tsx +0 -178
  24. package/src/components/Accordion/Accordion.stories.tsx +0 -198
  25. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +0 -68
  26. package/src/components/AutoComplete/AutoComplete.stories.tsx +0 -336
  27. package/src/components/Avatar/Avatar.stories.tsx +0 -92
  28. package/src/components/Badge/Badge.stories.tsx +0 -78
  29. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +0 -114
  30. package/src/components/Button/Button.stories.tsx +0 -196
  31. package/src/components/Card/Card.stories.tsx +0 -132
  32. package/src/components/Checkbox/Checkbox.stories.tsx +0 -97
  33. package/src/components/Checkbox/CheckboxGroup.stories.tsx +0 -139
  34. package/src/components/Chip/Chip.stories.tsx +0 -154
  35. package/src/components/Container/Container.stories.tsx +0 -118
  36. package/src/components/DatePicker/DatePicker.stories.tsx +0 -163
  37. package/src/components/Dropdown/Dropdown.stories.tsx +0 -252
  38. package/src/components/FileInput/FileInput.stories.tsx +0 -313
  39. package/src/components/FileUpload/FileUpload.stories.tsx +0 -362
  40. package/src/components/Flex/Flex.stories.tsx +0 -128
  41. package/src/components/FormControlLayout/FormControlLayout.stories.tsx +0 -118
  42. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +0 -129
  43. package/src/components/Group/Group.stories.tsx +0 -120
  44. package/src/components/Heading/Heading.stories.tsx +0 -112
  45. package/src/components/HoverCard/HoverCard.stories.tsx +0 -172
  46. package/src/components/Label/Label.stories.tsx +0 -131
  47. package/src/components/LayoutGrid/LayoutGrid.stories.tsx +0 -61
  48. package/src/components/Link/Link.stories.tsx +0 -58
  49. package/src/components/Loader/Loader.stories.tsx +0 -123
  50. package/src/components/Menu/Menu.stories.tsx +0 -402
  51. package/src/components/Modal/Modal.stories.tsx +0 -105
  52. package/src/components/NumberInput/NumberInput.stories.tsx +0 -96
  53. package/src/components/Pagination/Pagination.stories.tsx +0 -48
  54. package/src/components/Panel/Panel.stories.tsx +0 -227
  55. package/src/components/Popover/Popover.stories.tsx +0 -133
  56. package/src/components/Radio/Radio.stories.tsx +0 -93
  57. package/src/components/Radio/RadioGroup.stories.tsx +0 -117
  58. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +0 -163
  59. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +0 -106
  60. package/src/components/Slider/Slider.stories.tsx +0 -282
  61. package/src/components/Stack/Stack.stories.tsx +0 -108
  62. package/src/components/Stepper/Stepper.stories.tsx +0 -157
  63. package/src/components/Switch/Switch.stories.tsx +0 -114
  64. package/src/components/Switch/SwitchGroup.stories.tsx +0 -132
  65. package/src/components/Table/Table.stories.tsx +0 -154
  66. package/src/components/Tabs/Tabs.stories.tsx +0 -174
  67. package/src/components/Text/Text.stories.tsx +0 -123
  68. package/src/components/TextArea/TextArea.stories.tsx +0 -94
  69. package/src/components/TextField/TextField.stories.tsx +0 -162
  70. package/src/components/TimePicker/TimePicker.stories.tsx +0 -155
  71. package/src/components/Timeline/Timeline.stories.tsx +0 -128
  72. package/src/components/Toast/Toast.stories.tsx +0 -67
  73. package/src/components/Tooltip/Tooltip.stories.tsx +0 -165
  74. package/src/components/TransferList/TransferList.stories.tsx +0 -121
  75. package/src/components/Tree/Tree.stories.tsx +0 -104
@@ -1,157 +0,0 @@
1
- import React, { useState } from "react";
2
- import type { Meta, StoryObj } from "@storybook/react";
3
- import { Stepper, Step, StepLabel } from "./Stepper";
4
- import { Button } from "../Button/Button";
5
- import { Group } from "../Group/Group";
6
- import { Flex } from "../Flex/Flex";
7
-
8
- const meta: Meta<typeof Stepper> = {
9
- title: "UI-Kit/Stepper",
10
- component: Stepper,
11
- tags: ["autodocs"],
12
- parameters: {
13
- layout: "centered",
14
- },
15
- argTypes: {
16
- size: {
17
- control: "radio",
18
- options: ["small", "large"],
19
- },
20
- orientation: {
21
- control: "radio",
22
- options: ["horizontal", "vertical"],
23
- },
24
- },
25
- };
26
-
27
- export default meta;
28
- type Story = StoryObj<typeof Stepper>;
29
-
30
- const InteractiveStepper = (args: React.ComponentProps<typeof Stepper>) => {
31
- const [active, setActive] = useState(1);
32
- const nextStep = () =>
33
- setActive((current) => (current < 3 ? current + 1 : current));
34
- const prevStep = () =>
35
- setActive((current) => (current > 0 ? current - 1 : current));
36
-
37
- const steps = [
38
- {
39
- label: "First step",
40
- description: "Create an account and set up your billing profile",
41
- },
42
- {
43
- label: "Second step",
44
- description:
45
- "Verify email and ensure all notification preferences are correct",
46
- },
47
- { label: "Final step", description: "Get full access" },
48
- ];
49
-
50
- return (
51
- <Flex direction="column" style={{ width: 600 }}>
52
- <Stepper {...args} activeStep={active}>
53
- {steps.map((step, index) => (
54
- <Step key={index} completed={active > index}>
55
- <StepLabel description={step.description}>{step.label}</StepLabel>
56
- </Step>
57
- ))}
58
- </Stepper>
59
-
60
- {active === steps.length && (
61
- <div style={{ marginTop: 24, textAlign: "center" }}>
62
- Completed, click back button to get to previous step
63
- </div>
64
- )}
65
-
66
- <Group mt={24} justify="center" gap={8}>
67
- <Button variant="outline" onClick={prevStep} disabled={active === 0}>
68
- Previous step
69
- </Button>
70
- <Button variant="outline" onClick={nextStep} disabled={active === 3}>
71
- Next step
72
- </Button>
73
- </Group>
74
- </Flex>
75
- );
76
- };
77
-
78
- export const Default: Story = {
79
- render: (args) => <InteractiveStepper {...args} />,
80
- args: {
81
- size: "large",
82
- orientation: "horizontal",
83
- },
84
- };
85
-
86
- export const Small: Story = {
87
- render: (args) => <InteractiveStepper {...args} />,
88
- args: {
89
- size: "small",
90
- orientation: "horizontal",
91
- },
92
- };
93
-
94
- export const Vertical: Story = {
95
- render: (args) => <InteractiveStepper {...args} />,
96
- args: {
97
- size: "large",
98
- orientation: "vertical",
99
- },
100
- };
101
-
102
- const StressTestStepper = (args: React.ComponentProps<typeof Stepper>) => {
103
- const [active, setActive] = useState(1);
104
- const nextStep = () =>
105
- setActive((current) => (current < 3 ? current + 1 : current));
106
- const prevStep = () =>
107
- setActive((current) => (current > 0 ? current - 1 : current));
108
-
109
- const steps = [
110
- {
111
- label:
112
- "This is an extremely long step title designed to test how the layout handles multiline text wrapping and constraints",
113
- description: "Create an account and set up your billing profile",
114
- },
115
- {
116
- label: "Second step",
117
- description:
118
- "Verify email and ensure all notification preferences are correct",
119
- },
120
- { label: "Final step", description: undefined },
121
- ];
122
-
123
- return (
124
- <Flex direction="column" style={{ width: 600 }}>
125
- <Stepper {...args} activeStep={active}>
126
- {steps.map((step, index) => (
127
- <Step key={index} completed={active > index}>
128
- <StepLabel description={step.description}>{step.label}</StepLabel>
129
- </Step>
130
- ))}
131
- </Stepper>
132
-
133
- {active === steps.length && (
134
- <div style={{ marginTop: 24, textAlign: "center" }}>
135
- Completed, click back button to get to previous step
136
- </div>
137
- )}
138
-
139
- <Group mt={24} justify="center" gap={8}>
140
- <Button variant="outline" onClick={prevStep} disabled={active === 0}>
141
- Previous step
142
- </Button>
143
- <Button variant="outline" onClick={nextStep} disabled={active === 3}>
144
- Next step
145
- </Button>
146
- </Group>
147
- </Flex>
148
- );
149
- };
150
-
151
- export const LayoutStressTest: Story = {
152
- render: (args) => <StressTestStepper {...args} />,
153
- args: {
154
- size: "large",
155
- orientation: "horizontal",
156
- },
157
- };
@@ -1,114 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/react";
2
- import { Switch } from "./Switch";
3
- import { Stack } from "../Stack/Stack";
4
-
5
- const meta: Meta<typeof Switch> = {
6
- title: "UI-Kit/Switch",
7
- component: Switch,
8
- tags: ["autodocs"],
9
- parameters: {
10
- docs: {
11
- description: {
12
- component: `
13
- The \`Switch\` component is an atomic form primitive representing boolean states, natively aligned to the Recursica design system.
14
-
15
- > [!IMPORTANT]
16
- > Unlike \`Checkbox\`, the \`Switch\` is typically used for standalone settings toggles. It fully supports the universal \`ReadOnlyField\` boundaries when passed the \`readOnly\` attribute.
17
-
18
- ### Usage
19
- To render a standard switch:
20
- \`\`\`tsx
21
- <Switch label="Enable Notifications" defaultChecked />
22
- \`\`\`
23
- `,
24
- },
25
- },
26
- },
27
- argTypes: {
28
- checked: {
29
- control: "boolean",
30
- },
31
- disabled: {
32
- control: "boolean",
33
- },
34
- required: {
35
- control: "boolean",
36
- },
37
- error: {
38
- control: "boolean",
39
- },
40
- defaultChecked: {
41
- control: "boolean",
42
- },
43
- readOnly: {
44
- control: "boolean",
45
- description:
46
- "Toggles structural read-only data presentation bypassing interaction boundaries completely.",
47
- },
48
- controlMaxWidth: { table: { disable: true } },
49
- controlMinWidth: { table: { disable: true } },
50
- emptyValueComponent: { table: { disable: true } },
51
- },
52
- };
53
-
54
- export default meta;
55
-
56
- type Story = StoryObj<typeof Switch>;
57
-
58
- export const Default: Story = {
59
- args: {
60
- disabled: false,
61
- label: "Standard Switch",
62
- },
63
- // We explicitly destructure global Storybook injected arguments so they do not leak into the DOM natively.
64
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
65
- render: ({ withLayer, layer, ...args }: any) => <Switch {...args} />,
66
- };
67
-
68
- export const SideBySideLayout: Story = {
69
- args: {
70
- label: "Opt-in form alignment",
71
- formLayout: "side-by-side",
72
- },
73
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
74
- render: ({ withLayer, layer, ...args }: any) => <Switch {...args} />,
75
- };
76
-
77
- export const StaticVariations: Story = {
78
- args: {},
79
- render: () => (
80
- <Stack spacing="rec-xl">
81
- <Switch label="Default Unchecked State" />
82
- <Switch label="Checked State" defaultChecked />
83
- <Switch label="Disabled Unchecked" disabled />
84
- <Switch label="Disabled Checked" defaultChecked disabled />
85
- </Stack>
86
- ),
87
- };
88
-
89
- export const ReadOnly: Story = {
90
- args: {
91
- ...Default.args,
92
- readOnly: true,
93
- },
94
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
95
- render: ({ withLayer, layer, ...args }: any) => <Switch {...args} />,
96
- };
97
-
98
- export const CustomReadOnly: Story = {
99
- args: {
100
- ...Default.args,
101
- readOnly: true,
102
- },
103
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
104
- render: ({ withLayer, layer, ...args }: any) => (
105
- <Switch
106
- {...args}
107
- readOnlyComponent={({ checked, label }) => (
108
- <span style={{ fontWeight: "bold", color: checked ? "green" : "red" }}>
109
- {label} {checked ? "ENABLED" : "DISABLED"}
110
- </span>
111
- )}
112
- />
113
- ),
114
- };
@@ -1,132 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/react";
2
- import { Switch } from "./Switch";
3
- import { SwitchGroup } from "./SwitchGroup";
4
- import { useState } from "react";
5
- import { formControlArgTypes } from "../../../.storybook/commonArgTypes";
6
-
7
- const meta: Meta<typeof SwitchGroup> = {
8
- title: "UI-Kit/SwitchGroup",
9
- component: SwitchGroup,
10
- tags: ["autodocs"],
11
- parameters: {
12
- docs: {
13
- description: {
14
- component: `
15
- The \`SwitchGroup\` component is the mandatory organizational wrapper for orchestrating \`Switch\` primitives into macro form layouts. It inherently leverages the \`FormControlWrapper\`, granting native access to structural alignments, assistive descriptions, and strict flex arrays.
16
-
17
- ### Supported Layout Vectors
18
- - **\`formLayout="stacked"\`**: Top-to-bottom layout cascading the Label bounding box down vertically into a standard stacked switch array.
19
- - **\`formLayout="side-by-side"\`**: Flow architecture pulling the grouping Label dynamically to the left while structurally organizing the internal switches cleanly alongside it horizontally.
20
-
21
- > [!IMPORTANT]
22
- > If you require a solitary \`Switch\` field to natively accept an overarching form label, assistive text, or align with other side-by-side components in a form column, you must wrap it inside a \`Switch.Group\` to trigger the \`FormControlWrapper\` mapping.
23
- `,
24
- },
25
- },
26
- },
27
- argTypes: {
28
- ...formControlArgTypes,
29
- readOnly: {
30
- control: "boolean",
31
- description:
32
- "Passes read-only lock natively down mapping inner switches into explicitly disabled states.",
33
- },
34
- },
35
- };
36
-
37
- export default meta;
38
-
39
- type Story = StoryObj<typeof SwitchGroup>;
40
-
41
- export const Default: Story = {
42
- args: {
43
- formLayout: "stacked",
44
- label: "Standard Group",
45
- },
46
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
47
- render: function StoryRender({ withLayer, layer, ...args }: any) {
48
- const [value, setValue] = useState<string[]>([]);
49
- return (
50
- <SwitchGroup {...args} value={value} onChange={setValue}>
51
- <Switch value="1" label="Option 1" />
52
- <Switch value="2" label="Option 2" />
53
- </SwitchGroup>
54
- );
55
- },
56
- };
57
-
58
- export const StackedLayout: Story = {
59
- args: {
60
- formLayout: "stacked",
61
- label: "Notification Settings",
62
- description: "Manage your preferences.",
63
- assistiveText: "We recommend turning these on.",
64
- error: "",
65
- required: true,
66
- },
67
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
68
- render: function StoryRender({ withLayer, layer, ...args }: any) {
69
- const [value, setValue] = useState<string[]>(["email"]);
70
- return (
71
- <SwitchGroup {...args} value={value} onChange={setValue}>
72
- <Switch value="email" label="Email Alerts" />
73
- <Switch value="push" label="Push Notifications" />
74
- <Switch value="sms" label="SMS Messages" />
75
- </SwitchGroup>
76
- );
77
- },
78
- };
79
-
80
- export const SideBySideLayout: Story = {
81
- args: {
82
- ...StackedLayout.args,
83
- formLayout: "side-by-side",
84
- labelSize: "default",
85
- labelAlignment: "left",
86
- },
87
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
88
- render: function StoryRender({ withLayer, layer, ...args }: any) {
89
- const [value, setValue] = useState<string[]>([]);
90
- return (
91
- <SwitchGroup {...args} value={value} onChange={setValue}>
92
- <Switch value="weekly" label="Weekly Digest" />
93
- <Switch value="marketing" label="Marketing Emails" />
94
- </SwitchGroup>
95
- );
96
- },
97
- };
98
-
99
- export const SolitaryFormControl: Story = {
100
- args: {
101
- formLayout: "side-by-side",
102
- label: "Enable Backups",
103
- description: "Automatically back up your data nightly.",
104
- },
105
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
106
- render: function StoryRender({ withLayer, layer, ...args }: any) {
107
- const [value, setValue] = useState<string[]>(["auto"]);
108
- return (
109
- <SwitchGroup {...args} value={value} onChange={setValue}>
110
- <Switch value="auto" label="Auto-backup" />
111
- </SwitchGroup>
112
- );
113
- },
114
- };
115
-
116
- export const ReadOnly: Story = {
117
- args: {
118
- ...StackedLayout.args,
119
- readOnly: true,
120
- },
121
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
122
- render: function StoryRender({ withLayer, layer, ...args }: any) {
123
- const [value, setValue] = useState<string[]>(["email", "sms"]);
124
- return (
125
- <SwitchGroup {...args} value={value} onChange={setValue}>
126
- <Switch value="email" label="Email Alerts" />
127
- <Switch value="push" label="Push Notifications" />
128
- <Switch value="sms" label="SMS Messages" />
129
- </SwitchGroup>
130
- );
131
- },
132
- };
@@ -1,154 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/react";
2
- import { Table } from "./Table";
3
-
4
- const meta: Meta<typeof Table> = {
5
- title: "UI-Kit/Table",
6
- component: Table,
7
- tags: ["autodocs"],
8
- };
9
-
10
- export default meta;
11
-
12
- type Story = StoryObj<typeof Table>;
13
-
14
- const elements = [
15
- { position: 6, mass: 12.011, symbol: "C", name: "Carbon" },
16
- { position: 7, mass: 14.007, symbol: "N", name: "Nitrogen" },
17
- { position: 8, mass: 15.999, symbol: "O", name: "Oxygen" },
18
- { position: 9, mass: 18.998, symbol: "F", name: "Fluorine" },
19
- { position: 10, mass: 20.18, symbol: "Ne", name: "Neon" },
20
- ];
21
-
22
- export const Default: Story = {
23
- render: () => {
24
- const rows = elements.map((element) => (
25
- <Table.Row key={element.name}>
26
- <Table.Cell>{element.position}</Table.Cell>
27
- <Table.Cell>{element.name}</Table.Cell>
28
- <Table.Cell>{element.symbol}</Table.Cell>
29
- <Table.Cell>{element.mass}</Table.Cell>
30
- </Table.Row>
31
- ));
32
-
33
- return (
34
- <Table.Container>
35
- <Table>
36
- <Table.Head>
37
- <Table.Row>
38
- <Table.Cell>Element position</Table.Cell>
39
- <Table.Cell>Element name</Table.Cell>
40
- <Table.Cell>Symbol</Table.Cell>
41
- <Table.Cell>Atomic mass</Table.Cell>
42
- </Table.Row>
43
- </Table.Head>
44
- <Table.Body>{rows}</Table.Body>
45
- </Table>
46
- </Table.Container>
47
- );
48
- },
49
- };
50
-
51
- export const SortedColumn: Story = {
52
- render: () => {
53
- const sorted = [...elements].sort((a, b) => a.mass - b.mass);
54
- const rows = sorted.map((element) => (
55
- <Table.Row key={element.name}>
56
- <Table.Cell>{element.position}</Table.Cell>
57
- <Table.Cell>{element.name}</Table.Cell>
58
- <Table.Cell>{element.symbol}</Table.Cell>
59
- <Table.Cell>{element.mass}</Table.Cell>
60
- </Table.Row>
61
- ));
62
-
63
- return (
64
- <Table.Container>
65
- <Table>
66
- <Table.Head>
67
- <Table.Row>
68
- <Table.Cell>Element position</Table.Cell>
69
- <Table.Cell>Element name</Table.Cell>
70
- <Table.Cell>Symbol</Table.Cell>
71
- <Table.Cell sorted="asc">
72
- <Table.SortLabel active direction="asc">
73
- Atomic mass
74
- </Table.SortLabel>
75
- </Table.Cell>
76
- </Table.Row>
77
- </Table.Head>
78
- <Table.Body>{rows}</Table.Body>
79
- </Table>
80
- </Table.Container>
81
- );
82
- },
83
- };
84
-
85
- export const SelectedAndDisabledRows: Story = {
86
- render: () => (
87
- <Table.Container>
88
- <Table>
89
- <Table.Head>
90
- <Table.Row>
91
- <Table.Cell>Element position</Table.Cell>
92
- <Table.Cell>Element name</Table.Cell>
93
- <Table.Cell>Symbol</Table.Cell>
94
- <Table.Cell>Atomic mass</Table.Cell>
95
- </Table.Row>
96
- </Table.Head>
97
- <Table.Body>
98
- {elements.map((element, index) => (
99
- <Table.Row
100
- key={element.name}
101
- selected={index === 0}
102
- disabled={index === elements.length - 1}
103
- >
104
- <Table.Cell>{element.position}</Table.Cell>
105
- <Table.Cell>{element.name}</Table.Cell>
106
- <Table.Cell>{element.symbol}</Table.Cell>
107
- <Table.Cell>{element.mass}</Table.Cell>
108
- </Table.Row>
109
- ))}
110
- </Table.Body>
111
- </Table>
112
- </Table.Container>
113
- ),
114
- };
115
-
116
- export const CurrencyColumnWithFooter: Story = {
117
- render: () => {
118
- const prices = [
119
- { item: "Widget", price: 19.99 },
120
- { item: "Gadget", price: 49.5 },
121
- { item: "Gizmo", price: 9.25 },
122
- ];
123
- const total = prices.reduce((sum, row) => sum + row.price, 0);
124
-
125
- return (
126
- <Table.Container>
127
- <Table>
128
- <Table.Head>
129
- <Table.Row>
130
- <Table.Cell>Item</Table.Cell>
131
- <Table.Cell variant="currency">Price</Table.Cell>
132
- </Table.Row>
133
- </Table.Head>
134
- <Table.Body>
135
- {prices.map((row) => (
136
- <Table.Row key={row.item}>
137
- <Table.Cell>{row.item}</Table.Cell>
138
- <Table.Cell variant="currency">
139
- ${row.price.toFixed(2)}
140
- </Table.Cell>
141
- </Table.Row>
142
- ))}
143
- </Table.Body>
144
- <Table.Footer>
145
- <Table.Row>
146
- <Table.Cell>Total</Table.Cell>
147
- <Table.Cell variant="currency">${total.toFixed(2)}</Table.Cell>
148
- </Table.Row>
149
- </Table.Footer>
150
- </Table>
151
- </Table.Container>
152
- );
153
- },
154
- };