From af903351b6e1b15f78c27df17e85f755295e11c0 Mon Sep 17 00:00:00 2001 From: Alexandra Vedeler Date: Tue, 28 Nov 2023 10:27:59 +0100 Subject: [PATCH] New local list component as a wrapper for the Designsystem List (#627) * created new local List component as a wrapper for the Designsystem List * PR fixes --- .../BorderedList/BorderedList.module.css | 16 +++++++++ src/components/BorderedList/BorderedList.tsx | 30 +++++++++++++++++ .../BorderedListItem.module.css | 15 +++++++++ .../BorderedListItem/BorderedListItem.tsx | 31 +++++++++++++++++ src/components/BorderedList/index.ts | 15 +++++++++ .../CompactDeletableListItem.module.css | 2 ++ .../CompactDeletableListItem.tsx | 8 +++-- .../DeletableListItem.test.cy.tsx | 23 +++++++------ .../DeletableListItem/DeletableListItem.tsx | 7 ++-- src/components/index.ts | 1 + .../OrgDelegationActionBar.module.css | 2 +- .../OrgDelegationActionBar.tsx | 6 ++-- .../offered/ChooseApiPage/ChooseApiPage.tsx | 7 ++-- .../ConfirmationPage.module.css | 3 +- .../ConfirmationPage/ConfirmationPage.tsx | 31 +++++++++-------- .../ReceiptPage/ReceiptPage.module.css | 4 +-- .../offered/ReceiptPage/ReceiptPage.tsx | 33 +++++++++---------- .../SearchSection/SearchSection.tsx | 2 +- 18 files changed, 176 insertions(+), 60 deletions(-) create mode 100644 src/components/BorderedList/BorderedList.module.css create mode 100644 src/components/BorderedList/BorderedList.tsx create mode 100644 src/components/BorderedList/BorderedListItem/BorderedListItem.module.css create mode 100644 src/components/BorderedList/BorderedListItem/BorderedListItem.tsx create mode 100644 src/components/BorderedList/index.ts diff --git a/src/components/BorderedList/BorderedList.module.css b/src/components/BorderedList/BorderedList.module.css new file mode 100644 index 000000000..c2ad8660a --- /dev/null +++ b/src/components/BorderedList/BorderedList.module.css @@ -0,0 +1,16 @@ +.borderedList { + --borderStyle: dashed; + margin-bottom: 0.5rem; + padding-left: 0; + border-top-color: #bcc7cc; + border-top-width: 1px; + border-top-style: var(--borderStyle); +} + +.dashed { + --borderStyle: dashed; +} + +.solid { + --borderStyle: solid; +} diff --git a/src/components/BorderedList/BorderedList.tsx b/src/components/BorderedList/BorderedList.tsx new file mode 100644 index 000000000..3f759d088 --- /dev/null +++ b/src/components/BorderedList/BorderedList.tsx @@ -0,0 +1,30 @@ +import type { ListProps } from '@digdir/design-system-react'; +import { List } from '@digdir/design-system-react'; +import cn from 'classnames'; +import * as React from 'react'; + +import classes from './BorderedList.module.css'; + +export type BorderedListProps = { + /** + * Style of the border separating the items + */ + borderStyle?: 'solid' | 'dashed'; +} & ListProps; + +export const BorderedList = ({ + borderStyle = 'dashed', + children, + className, + ...rest +}: BorderedListProps) => { + return ( + + {children} + + ); +}; diff --git a/src/components/BorderedList/BorderedListItem/BorderedListItem.module.css b/src/components/BorderedList/BorderedListItem/BorderedListItem.module.css new file mode 100644 index 000000000..c73c14054 --- /dev/null +++ b/src/components/BorderedList/BorderedListItem/BorderedListItem.module.css @@ -0,0 +1,15 @@ +.borderedListItem { + --borderStyle: dashed; + border-bottom-color: #bcc7cc; + border-bottom-width: 1px; + border-bottom-style: var(--borderStyle); + list-style: none; +} + +.dashed { + --borderStyle: dashed; +} + +.solid { + --borderStyle: solid; +} diff --git a/src/components/BorderedList/BorderedListItem/BorderedListItem.tsx b/src/components/BorderedList/BorderedListItem/BorderedListItem.tsx new file mode 100644 index 000000000..e2c075478 --- /dev/null +++ b/src/components/BorderedList/BorderedListItem/BorderedListItem.tsx @@ -0,0 +1,31 @@ +import type { ListItemProps } from '@digdir/design-system-react'; +import { List } from '@digdir/design-system-react'; +import cn from 'classnames'; +import * as React from 'react'; + +import classes from './BorderedListItem.module.css'; + +export type BorderedListItemProps = { + /** + * Style of the border separating the items + */ + borderStyle?: 'solid' | 'dashed'; +} & ListItemProps; + +export const BorderedListItem = ({ + borderStyle = 'dashed', + children, + ...rest +}: BorderedListItemProps) => { + return ( + + {children} + + ); +}; + +BorderedListItem.displayName = 'BorderedList.Item'; diff --git a/src/components/BorderedList/index.ts b/src/components/BorderedList/index.ts new file mode 100644 index 000000000..9feb8d87b --- /dev/null +++ b/src/components/BorderedList/index.ts @@ -0,0 +1,15 @@ +import { BorderedList as BorderedListRoot } from './BorderedList'; +import { BorderedListItem } from './BorderedListItem/BorderedListItem'; + +export type { BorderedListProps } from './BorderedList'; +export type { BorderedListItemProps } from './BorderedListItem/BorderedListItem'; + +type BorderedListComponent = typeof BorderedListRoot & { + Item: typeof BorderedListItem; +}; + +const BorderedList = BorderedListRoot as BorderedListComponent; + +BorderedList.Item = BorderedListItem; + +export { BorderedList, BorderedListItem }; diff --git a/src/components/CompactDeletableListItem/CompactDeletableListItem.module.css b/src/components/CompactDeletableListItem/CompactDeletableListItem.module.css index 1d2e9a4fd..bf9c22562 100644 --- a/src/components/CompactDeletableListItem/CompactDeletableListItem.module.css +++ b/src/components/CompactDeletableListItem/CompactDeletableListItem.module.css @@ -57,6 +57,8 @@ .listItemIcon { margin-right: 10px; + display: flex; + justify-content: center; } .middleText { diff --git a/src/components/CompactDeletableListItem/CompactDeletableListItem.tsx b/src/components/CompactDeletableListItem/CompactDeletableListItem.tsx index 97a327a61..36f8268a6 100644 --- a/src/components/CompactDeletableListItem/CompactDeletableListItem.tsx +++ b/src/components/CompactDeletableListItem/CompactDeletableListItem.tsx @@ -1,11 +1,13 @@ /* eslint-disable @typescript-eslint/restrict-plus-operands */ -import { Button, ListItem } from '@digdir/design-system-react'; +import { Button } from '@digdir/design-system-react'; import { SvgIcon } from '@altinn/altinn-design-system'; import { useTranslation } from 'react-i18next'; import cn from 'classnames'; import * as React from 'react'; import { MinusCircleIcon } from '@navikt/aksel-icons'; +import { BorderedList } from '../BorderedList'; + import classes from './CompactDeletableListItem.module.css'; export enum ListTextColor { @@ -30,7 +32,7 @@ export const CompactDeletableListItem = ({ const { t } = useTranslation('common'); return ( - +
-
+ ); }; diff --git a/src/components/DeletableListItem/DeletableListItem.test.cy.tsx b/src/components/DeletableListItem/DeletableListItem.test.cy.tsx index 6484c0aa7..d5ea11ce7 100644 --- a/src/components/DeletableListItem/DeletableListItem.test.cy.tsx +++ b/src/components/DeletableListItem/DeletableListItem.test.cy.tsx @@ -1,11 +1,10 @@ import { Provider } from 'react-redux'; import { mount } from 'cypress/react18'; -import { List } from '@digdir/design-system-react'; import * as React from 'react'; import type { OverviewOrg } from '@/rtk/features/apiDelegation/overviewOrg/overviewOrgSlice'; import store from '@/rtk/app/store'; -import { DeletableListItem } from '@/components'; +import { DeletableListItem, BorderedList } from '@/components'; Cypress.Commands.add('mount', (component, options = {}) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -36,14 +35,14 @@ describe('DeletableListItem', () => { }; cy.mount( - + null} softRestoreCallback={() => null} item={overviewOrg.apiList[0]} isEditable={true} /> - , + , ); cy.findByRole('button', { name: /delete/i }).should('exist'); }); @@ -67,14 +66,14 @@ describe('DeletableListItem', () => { }; cy.mount( - + null} softRestoreCallback={() => null} item={overviewOrg.apiList[0]} isEditable={false} /> - , + , ); cy.findByRole('button', { name: /delete/i }).should('not.exist'); }); @@ -98,14 +97,14 @@ describe('DeletableListItem', () => { }; cy.mount( - + null} softRestoreCallback={() => null} item={overviewOrg.apiList[0]} isEditable={true} /> - , + , ); cy.get('[data-testid="list-item-texts"]').should( @@ -141,14 +140,14 @@ describe('DeletableListItem', () => { const softDeleteSpy = cy.spy(softDelete).as('softDeleteSpy'); cy.mount( - + null} item={overviewOrg.apiList[0]} isEditable={true} /> - , + , ); cy.findByRole('button', { name: /delete/i }).click(); @@ -180,14 +179,14 @@ describe('DeletableListItem', () => { const softRestoreSpy = cy.spy(softRestore).as('softRestoreSpy'); cy.mount( - + null} softRestoreCallback={softRestoreSpy} item={overviewOrg.apiList[0]} isEditable={true} /> - , + , ); cy.findByRole('button', { name: /undo/i }).click(); diff --git a/src/components/DeletableListItem/DeletableListItem.tsx b/src/components/DeletableListItem/DeletableListItem.tsx index 6d83b5ed7..6d3326a2e 100644 --- a/src/components/DeletableListItem/DeletableListItem.tsx +++ b/src/components/DeletableListItem/DeletableListItem.tsx @@ -1,4 +1,4 @@ -import { Button, ListItem } from '@digdir/design-system-react'; +import { Button } from '@digdir/design-system-react'; import cn from 'classnames'; import { useTranslation } from 'react-i18next'; import * as React from 'react'; @@ -7,6 +7,7 @@ import { MinusCircleIcon, ArrowUndoIcon } from '@navikt/aksel-icons'; import type { ApiListItem } from '@/rtk/features/apiDelegation/overviewOrg/overviewOrgSlice'; import { useMediaQuery } from '@/resources/hooks'; +import { BorderedList } from '../BorderedList'; import ScopeList from '../ScopeList/ScopeList'; import classes from './DeletableListItem.module.css'; @@ -58,7 +59,7 @@ export const DeletableListItem = ({ ); return ( - +
{isEditable && isEditableActions}
- + ); }; diff --git a/src/components/index.ts b/src/components/index.ts index 4fbf0e7df..ce758b22b 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -13,3 +13,4 @@ export { Dialog, DialogContent, type DialogProps } from './Dialog'; export { ProgressModal } from './ProgressModal/ProgressModal'; export { GroupElements } from './GroupElements/GroupElements'; export { RestartPrompter } from './RestartPrompter/RestartPrompter'; +export * from './BorderedList'; diff --git a/src/features/apiDelegation/components/OverviewPageContent/OrgDelegationActionBar/OrgDelegationActionBar.module.css b/src/features/apiDelegation/components/OverviewPageContent/OrgDelegationActionBar/OrgDelegationActionBar.module.css index 22f923e97..1aaa4ae5f 100644 --- a/src/features/apiDelegation/components/OverviewPageContent/OrgDelegationActionBar/OrgDelegationActionBar.module.css +++ b/src/features/apiDelegation/components/OverviewPageContent/OrgDelegationActionBar/OrgDelegationActionBar.module.css @@ -15,7 +15,7 @@ } .actionBarContent { - padding-right: 10px; + padding: 10px 0 10px 10px; } .actionBarText__softDelete { diff --git a/src/features/apiDelegation/components/OverviewPageContent/OrgDelegationActionBar/OrgDelegationActionBar.tsx b/src/features/apiDelegation/components/OverviewPageContent/OrgDelegationActionBar/OrgDelegationActionBar.tsx index 8a3e36f6b..ca4c749af 100644 --- a/src/features/apiDelegation/components/OverviewPageContent/OrgDelegationActionBar/OrgDelegationActionBar.tsx +++ b/src/features/apiDelegation/components/OverviewPageContent/OrgDelegationActionBar/OrgDelegationActionBar.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Button, List } from '@digdir/design-system-react'; +import { Button } from '@digdir/design-system-react'; import cn from 'classnames'; import { useTranslation } from 'react-i18next'; import * as React from 'react'; @@ -8,7 +8,7 @@ import { MinusCircleIcon, ArrowUndoIcon, PlusCircleIcon } from '@navikt/aksel-ic import type { OverviewOrg } from '@/rtk/features/apiDelegation/overviewOrg/overviewOrgSlice'; import { softDelete, softRestore } from '@/rtk/features/apiDelegation/overviewOrg/overviewOrgSlice'; import { useAppDispatch } from '@/rtk/app/hooks'; -import { DeletableListItem, ActionBar } from '@/components'; +import { DeletableListItem, ActionBar, BorderedList } from '@/components'; import { useMediaQuery } from '@/resources/hooks'; import classes from './OrgDelegationActionBar.module.css'; @@ -135,7 +135,7 @@ export const OrgDelegationActionBar = ({ } >
- {listItems} + {listItems}
); diff --git a/src/features/apiDelegation/offered/ChooseApiPage/ChooseApiPage.tsx b/src/features/apiDelegation/offered/ChooseApiPage/ChooseApiPage.tsx index 4d5031edf..6ab1147cc 100644 --- a/src/features/apiDelegation/offered/ChooseApiPage/ChooseApiPage.tsx +++ b/src/features/apiDelegation/offered/ChooseApiPage/ChooseApiPage.tsx @@ -1,5 +1,5 @@ import { SearchField } from '@altinn/altinn-design-system'; -import { Button, List, Spinner } from '@digdir/design-system-react'; +import { Button, Spinner } from '@digdir/design-system-react'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { FilterIcon, Buldings3Icon } from '@navikt/aksel-icons'; @@ -14,6 +14,8 @@ import { ErrorPanel, GroupElements, RestartPrompter, + DelegationActionBar, + BorderedList, } from '@/components'; import { useAppDispatch, useAppSelector } from '@/rtk/app/hooks'; import { ApiDelegationPath } from '@/routes/paths'; @@ -32,7 +34,6 @@ import { } from '@/rtk/features/apiDelegation/delegableApi/delegableApiSlice'; import type { DelegableApi } from '@/rtk/features/apiDelegation/delegableApi/delegableApiSlice'; import { Filter, type FilterOption } from '@/components/Filter'; -import { DelegationActionBar } from '@/components/DelegationActionBar'; import classes from './ChooseApiPage.module.css'; @@ -167,7 +168,7 @@ export const ChooseApiPage = () => { ) : (

{t('api_delegation.chosen_orgs')}:

- {chosenDelegableOrgs} + {chosenDelegableOrgs}
)}

diff --git a/src/features/apiDelegation/offered/ConfirmationPage/ConfirmationPage.module.css b/src/features/apiDelegation/offered/ConfirmationPage/ConfirmationPage.module.css index ccac36d85..af6c239c2 100644 --- a/src/features/apiDelegation/offered/ConfirmationPage/ConfirmationPage.module.css +++ b/src/features/apiDelegation/offered/ConfirmationPage/ConfirmationPage.module.css @@ -52,5 +52,6 @@ } .listContainer { - margin-bottom: 40px; + margin-top: 15px; + margin-bottom: 30px; } diff --git a/src/features/apiDelegation/offered/ConfirmationPage/ConfirmationPage.tsx b/src/features/apiDelegation/offered/ConfirmationPage/ConfirmationPage.tsx index c4c0560e4..ac8124d10 100644 --- a/src/features/apiDelegation/offered/ConfirmationPage/ConfirmationPage.tsx +++ b/src/features/apiDelegation/offered/ConfirmationPage/ConfirmationPage.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import type { Key } from 'react'; import { useEffect, useState } from 'react'; import { Buldings3Icon, CogIcon } from '@navikt/aksel-icons'; -import { Button, Heading, List, Paragraph, Spinner } from '@digdir/design-system-react'; +import { Button, Heading, Paragraph, Spinner } from '@digdir/design-system-react'; import { useAppDispatch, useAppSelector } from '@/rtk/app/hooks'; import { ApiDelegationPath } from '@/routes/paths'; @@ -17,6 +17,7 @@ import { PageContent, PageHeader, RestartPrompter, + BorderedList, } from '@/components'; import type { ApiDelegation, @@ -70,7 +71,7 @@ export const ConfirmationPage = () => { const delegableApiList = () => { return (
- + {chosenApis?.map((api: DelegableApi | ApiDelegation, index: Key) => ( { middleText={api.orgName} > ))} - +
); }; const delegableOrgList = () => { return ( - - {chosenOrgs?.map((org: DelegableOrg, index: Key | null | undefined) => ( - } - removeCallback={chosenOrgs.length > 1 ? () => dispatch(softRemoveOrg(org)) : null} - leftText={org.orgName} - middleText={t('api_delegation.org_nr') + ' ' + org.orgNr} - > - ))} - +
+ + {chosenOrgs?.map((org: DelegableOrg, index: Key | null | undefined) => ( + } + removeCallback={chosenOrgs.length > 1 ? () => dispatch(softRemoveOrg(org)) : null} + leftText={org.orgName} + middleText={t('api_delegation.org_nr') + ' ' + org.orgNr} + > + ))} + +
); }; diff --git a/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.module.css b/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.module.css index 73baf98dd..769e39bcc 100644 --- a/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.module.css +++ b/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.module.css @@ -1,3 +1,3 @@ -.listContainer { - margin-bottom: 40px; +.list { + margin-bottom: 40px !important; } diff --git a/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.tsx b/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.tsx index 0aaaaca38..4c975309a 100644 --- a/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.tsx +++ b/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.tsx @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; import type { Key } from 'react'; import * as React from 'react'; -import { Button, Heading, List, Paragraph } from '@digdir/design-system-react'; +import { Button, Heading, Paragraph } from '@digdir/design-system-react'; import { useNavigate } from 'react-router-dom'; import { useAppDispatch, useAppSelector } from '@/rtk/app/hooks'; @@ -15,6 +15,7 @@ import { PageContent, CompactDeletableListItem, RestartPrompter, + BorderedList, } from '@/components'; import { ListTextColor } from '@/components/CompactDeletableListItem/CompactDeletableListItem'; import type { ApiDelegation } from '@/rtk/features/apiDelegation/delegationRequest/delegationRequestSlice'; @@ -44,20 +45,18 @@ export const ReceiptPage = () => { > {t('api_delegation.failed_delegations')} -
- - {failedApiDelegations?.map( - (apiDelegation: ApiDelegation, index: Key | null | undefined) => ( - - ), - )} - -
+ + {failedApiDelegations?.map( + (apiDelegation: ApiDelegation, index: Key | null | undefined) => ( + + ), + )} + ); }; @@ -72,7 +71,7 @@ export const ReceiptPage = () => { > {t('api_delegation.succesful_delegations')} - + {successfulApiDelegations?.map( (apiDelegation: ApiDelegation, index: Key | null | undefined) => ( { > ), )} - + ); }; diff --git a/src/features/singleRight/components/SearchSection/SearchSection.tsx b/src/features/singleRight/components/SearchSection/SearchSection.tsx index 7a4372d2b..eea14061a 100644 --- a/src/features/singleRight/components/SearchSection/SearchSection.tsx +++ b/src/features/singleRight/components/SearchSection/SearchSection.tsx @@ -105,7 +105,7 @@ export const SearchSection = ({ onAdd, onUndo }: SearchSectionParams) => {