From e6f16f5f782739df9423f0f52cc2a2ffaef046ce Mon Sep 17 00:00:00 2001 From: Inge Fossland Date: Mon, 16 Dec 2024 14:45:55 +0100 Subject: [PATCH] feat: timeline + dialog fixes (#135) - Fefactor History to generic Timeline components. - Replace DialogHeadings with a generic Byline compoent. - Rename SectionBase to Section, ArticleBase to Article and align most generic components to make it easier to build generic pages and concepts. - Replace spesific dialog components with more generic concepts that are easier to adjust. - Visual alignment and tuning. - Stories for dialogs. --- lib/components/Attachment/index.ts | 1 - lib/components/Bookmarks/BookmarksSection.tsx | 10 +- lib/components/Bookmarks/index.ts | 1 + lib/components/Button/ButtonBase.tsx | 2 +- lib/components/Button/buttonBase.module.css | 4 + lib/components/Button/buttonIcon.module.css | 4 + lib/components/Button/buttonLabel.module.css | 5 + lib/components/Byline/Byline.stories.tsx | 50 ++ lib/components/Byline/Byline.tsx | 33 ++ lib/components/Byline/byline.module.css | 30 ++ lib/components/Byline/index.ts | 1 + lib/components/ContextMenu/ContextMenu.tsx | 10 +- lib/components/Dialog/Dialog.stories.tsx | 461 ++---------------- lib/components/Dialog/Dialog.tsx | 132 +++-- .../Dialog/DialogActions.stories.ts | 2 +- lib/components/Dialog/DialogArticleBase.tsx | 10 - .../DialogAttachments.stories.ts} | 8 +- .../DialogAttachments.tsx} | 4 +- lib/components/Dialog/DialogBase.tsx | 13 - lib/components/Dialog/DialogBodyBase.tsx | 17 - lib/components/Dialog/DialogByline.tsx | 37 ++ .../Dialog/DialogBylline.stories.ts | 29 ++ .../Dialog/DialogContent.stories.ts | 20 - .../Dialog/DialogContent.stories.tsx | 43 ++ lib/components/Dialog/DialogContent.tsx | 42 +- lib/components/Dialog/DialogFooter.tsx | 15 - lib/components/Dialog/DialogHeader.stories.ts | 27 - lib/components/Dialog/DialogHeader.tsx | 23 - lib/components/Dialog/DialogHeaderBase.tsx | 16 - .../{DialogTitle.tsx => DialogHeading.tsx} | 16 +- .../Dialog/DialogHeadings.stories.ts | 35 -- lib/components/Dialog/DialogHeadings.tsx | 79 --- .../Dialog/DialogHistory.stories.ts | 73 +-- lib/components/Dialog/DialogHistory.tsx | 48 +- .../Dialog/DialogHistoryDetails.tsx | 42 ++ lib/components/Dialog/DialogHistoryItem.tsx | 48 ++ lib/components/Dialog/DialogLabel.tsx | 5 +- lib/components/Dialog/DialogList.stories.ts | 46 +- lib/components/Dialog/DialogList.tsx | 17 +- .../{DialogGroup.tsx => DialogListGroup.tsx} | 12 +- .../Dialog/DialogListItem.stories.tsx | 52 +- lib/components/Dialog/DialogListItem.tsx | 119 +++-- .../Dialog/DialogMetadata.stories.ts | 2 +- lib/components/Dialog/DialogMetadata.tsx | 48 +- lib/components/Dialog/DialogNav.stories.ts | 89 ---- lib/components/Dialog/DialogNav.tsx | 56 --- lib/components/Dialog/DialogSection.tsx | 20 + lib/components/Dialog/DialogSectionBase.tsx | 20 - .../Dialog/DialogSeenBy.stories.tsx | 2 +- lib/components/Dialog/DialogStatus.stories.ts | 2 +- lib/components/Dialog/DialogTimeline.tsx | 19 + lib/components/Dialog/DialogTimelineItem.tsx | 28 ++ .../Dialog/DialogTouchedBy.stories.tsx | 2 +- .../DialogTransmissions.stories.tsx} | 8 +- .../DialogTransmissions.tsx} | 4 +- lib/components/Dialog/DraftDialog.stories.tsx | 160 ++++++ lib/components/Dialog/DraftDialog.tsx | 91 ++++ .../Dialog/dialogArticleBase.module.css | 5 - .../Dialog/dialogBodyBase.module.css | 13 - lib/components/Dialog/dialogBorder.module.css | 1 + lib/components/Dialog/dialogGroup.module.css | 35 -- .../Dialog/dialogHeaderBase.module.css | 14 - ...le.module.css => dialogHeading.module.css} | 24 +- .../Dialog/dialogHeadings.module.css | 37 -- .../Dialog/dialogListItem.module.css | 93 ++-- lib/components/Dialog/dialogNav.module.css | 12 - .../Dialog/dialogSectionBase.module.css | 11 - lib/components/Dialog/index.ts | 30 +- lib/components/Dropdown/Backdrop.tsx | 7 +- lib/components/Dropdown/backdrop.module.css | 4 + lib/components/Footer/Footer.stories.ts | 2 +- lib/components/GlobalMenu/BackButton.tsx | 6 +- lib/components/Header/Header.stories.tsx | 2 +- lib/components/Header/HeaderButton.stories.ts | 2 +- lib/components/Header/HeaderLogo.stories.ts | 2 +- lib/components/History/HistoryBorder.tsx | 17 - lib/components/History/HistoryItem.stories.ts | 107 ---- lib/components/History/HistoryItem.tsx | 54 -- .../History/HistoryItemBase.stories.ts | 57 --- lib/components/History/HistoryItemBase.tsx | 45 -- lib/components/History/HistoryItemMedia.tsx | 21 - lib/components/History/HistoryList.stories.ts | 174 ------- lib/components/History/HistoryList.tsx | 26 - lib/components/History/HistoryMetadata.tsx | 46 -- .../History/historyBorder.module.css | 8 - lib/components/History/historyItem.module.css | 19 - .../History/historyItemBase.module.css | 26 - .../History/historyItemMedia.module.css | 21 - lib/components/History/index.ts | 3 - lib/components/List/ListItem.stories.tsx | 2 +- lib/components/List/ListItem.tsx | 4 +- lib/components/List/ListItemBase.tsx | 9 +- lib/components/List/ListItemMedia.tsx | 4 +- lib/components/List/listItemBase.module.css | 19 +- lib/components/List/listItemHeader.module.css | 7 +- lib/components/List/listItemLabel.module.css | 35 +- lib/components/List/listItemSelect.module.css | 1 + lib/components/Menu/MenuItems.tsx | 3 +- lib/components/Meta/MetaBase.tsx | 10 +- lib/components/Meta/MetaItem.tsx | 13 +- lib/components/Meta/MetaItemBase.tsx | 4 +- .../{meta.module.css => metaBase.module.css} | 2 +- lib/components/Meta/metaItemBase.module.css | 12 +- lib/components/Meta/metaItemLabel.module.css | 2 +- lib/components/Page/Article.tsx | 14 + lib/components/Page/PageBase.stories.tsx | 84 ++++ lib/components/Page/PageBase.tsx | 8 +- lib/components/Page/PageHeader.stories.tsx | 100 ++++ lib/components/Page/PageHeader.tsx | 38 +- lib/components/Page/PageHeaderMedia.tsx | 25 - lib/components/Page/PageNav.stories.tsx | 35 ++ lib/components/Page/PageNav.tsx | 29 +- lib/components/Page/Section.tsx | 72 +++ lib/components/Page/SectionBase.tsx | 52 -- lib/components/Page/SectionHeader.tsx | 18 +- lib/components/Page/index.ts | 6 +- lib/components/Page/pageNav.module.css | 3 +- ...tionBase.module.css => section.module.css} | 101 +++- lib/components/Page/sectionHeader.module.css | 9 - lib/components/Timeline/Timeline.stories.tsx | 63 +++ lib/components/Timeline/Timeline.tsx | 19 + lib/components/Timeline/TimelineBase.tsx | 12 + lib/components/Timeline/TimelineSection.tsx | 49 ++ lib/components/Timeline/index.ts | 3 + .../timelineBase.module.css} | 7 +- .../Timeline/timelineSection.module.css | 61 +++ .../Transmission/TransmissionItem.tsx | 28 +- .../Transmission/TransmissionList.stories.ts | 53 +- .../Transmission/TransmissionType.tsx | 37 ++ lib/components/Transmission/index.ts | 1 - lib/components/Typography/Heading.tsx | 6 +- lib/components/Typography/Typography.tsx | 13 +- lib/components/Typography/heading.module.css | 18 +- .../Typography/typography.module.css | 45 +- lib/components/index.ts | 4 +- lib/css/theme-article.css | 4 +- lib/examples/avatar/brreg-logo.png | Bin 0 -> 5342 bytes lib/examples/avatar/brreg.ts | 8 + lib/examples/avatar/index.ts | 5 + lib/examples/avatar/nav-logo.png | Bin 0 -> 2567 bytes lib/examples/avatar/nav.ts | 8 + lib/examples/avatar/oslo-logo.png | Bin 0 -> 12114 bytes lib/examples/avatar/oslo.ts | 8 + lib/examples/avatar/skatt-logo.png | Bin 0 -> 2088 bytes lib/examples/avatar/skatt.ts | 8 + lib/examples/avatar/ssb-logo.png | Bin 0 -> 6622 bytes lib/examples/avatar/ssb.ts | 7 + lib/examples/dialog/dialogContextMenu.ts | 37 ++ lib/examples/dialog/dialogHistoryItems.ts | 32 ++ lib/examples/dialog/dialogListItems.ts | 30 ++ lib/examples/dialog/extendedLetterDialog.tsx | 83 ++++ lib/examples/dialog/index.ts | 18 + lib/examples/dialog/metadataDialog.tsx | 91 ++++ .../dialog/reportingCompletedDialog.tsx | 32 ++ lib/examples/dialog/reportingDialog.tsx | 45 ++ lib/examples/dialog/reportingDraftDialog.tsx | 40 ++ lib/examples/dialog/reportingHistoryItems.tsx | 54 ++ .../dialog/reportingInProgressDialog.tsx | 43 ++ lib/examples/dialog/simpleLetterDialog.tsx | 43 ++ lib/examples/dialog/transmissionList.ts | 97 ++++ .../dialog/transmissionsCompletedDialog.tsx | 42 ++ lib/examples/dialog/transmissionsDialog.tsx | 31 ++ .../dialog/transmissionsHistoryItems.ts | 202 ++++++++ .../dialog/transmissionsInProgressDialog.tsx | 45 ++ lib/examples/dialog/transmissionsTimeline.ts | 24 + lib/examples/index.ts | 2 + lib/stories/Inbox/BookmarksPage.tsx | 6 +- lib/stories/Inbox/ProfilePage.tsx | 2 +- lib/stories/Inbox/SettingsPage.tsx | 2 +- package.json | 10 +- tsconfig.json | 2 +- 171 files changed, 3082 insertions(+), 2236 deletions(-) create mode 100644 lib/components/Byline/Byline.stories.tsx create mode 100644 lib/components/Byline/Byline.tsx create mode 100644 lib/components/Byline/byline.module.css create mode 100644 lib/components/Byline/index.ts delete mode 100644 lib/components/Dialog/DialogArticleBase.tsx rename lib/components/{Attachment/AttachmentSection.stories.ts => Dialog/DialogAttachments.stories.ts} (65%) rename lib/components/{Attachment/AttachmentSection.tsx => Dialog/DialogAttachments.tsx} (73%) delete mode 100644 lib/components/Dialog/DialogBase.tsx delete mode 100644 lib/components/Dialog/DialogBodyBase.tsx create mode 100644 lib/components/Dialog/DialogByline.tsx create mode 100644 lib/components/Dialog/DialogBylline.stories.ts delete mode 100644 lib/components/Dialog/DialogContent.stories.ts create mode 100644 lib/components/Dialog/DialogContent.stories.tsx delete mode 100644 lib/components/Dialog/DialogFooter.tsx delete mode 100644 lib/components/Dialog/DialogHeader.stories.ts delete mode 100644 lib/components/Dialog/DialogHeader.tsx delete mode 100644 lib/components/Dialog/DialogHeaderBase.tsx rename lib/components/Dialog/{DialogTitle.tsx => DialogHeading.tsx} (58%) delete mode 100644 lib/components/Dialog/DialogHeadings.stories.ts delete mode 100644 lib/components/Dialog/DialogHeadings.tsx create mode 100644 lib/components/Dialog/DialogHistoryDetails.tsx create mode 100644 lib/components/Dialog/DialogHistoryItem.tsx rename lib/components/Dialog/{DialogGroup.tsx => DialogListGroup.tsx} (59%) delete mode 100644 lib/components/Dialog/DialogNav.stories.ts delete mode 100644 lib/components/Dialog/DialogNav.tsx create mode 100644 lib/components/Dialog/DialogSection.tsx delete mode 100644 lib/components/Dialog/DialogSectionBase.tsx create mode 100644 lib/components/Dialog/DialogTimeline.tsx create mode 100644 lib/components/Dialog/DialogTimelineItem.tsx rename lib/components/{Transmission/TransmissionSection.stories.tsx => Dialog/DialogTransmissions.stories.tsx} (96%) rename lib/components/{Transmission/TransmissionSection.tsx => Dialog/DialogTransmissions.tsx} (76%) create mode 100644 lib/components/Dialog/DraftDialog.stories.tsx create mode 100644 lib/components/Dialog/DraftDialog.tsx delete mode 100644 lib/components/Dialog/dialogArticleBase.module.css delete mode 100644 lib/components/Dialog/dialogBodyBase.module.css delete mode 100644 lib/components/Dialog/dialogGroup.module.css delete mode 100644 lib/components/Dialog/dialogHeaderBase.module.css rename lib/components/Dialog/{dialogTitle.module.css => dialogHeading.module.css} (80%) delete mode 100644 lib/components/Dialog/dialogHeadings.module.css delete mode 100644 lib/components/Dialog/dialogNav.module.css delete mode 100644 lib/components/Dialog/dialogSectionBase.module.css delete mode 100644 lib/components/History/HistoryBorder.tsx delete mode 100644 lib/components/History/HistoryItem.stories.ts delete mode 100644 lib/components/History/HistoryItem.tsx delete mode 100644 lib/components/History/HistoryItemBase.stories.ts delete mode 100644 lib/components/History/HistoryItemBase.tsx delete mode 100644 lib/components/History/HistoryItemMedia.tsx delete mode 100644 lib/components/History/HistoryList.stories.ts delete mode 100644 lib/components/History/HistoryList.tsx delete mode 100644 lib/components/History/HistoryMetadata.tsx delete mode 100644 lib/components/History/historyBorder.module.css delete mode 100644 lib/components/History/historyItem.module.css delete mode 100644 lib/components/History/historyItemBase.module.css delete mode 100644 lib/components/History/historyItemMedia.module.css delete mode 100644 lib/components/History/index.ts rename lib/components/Meta/{meta.module.css => metaBase.module.css} (75%) create mode 100644 lib/components/Page/Article.tsx create mode 100644 lib/components/Page/PageBase.stories.tsx create mode 100644 lib/components/Page/PageHeader.stories.tsx delete mode 100644 lib/components/Page/PageHeaderMedia.tsx create mode 100644 lib/components/Page/PageNav.stories.tsx create mode 100644 lib/components/Page/Section.tsx delete mode 100644 lib/components/Page/SectionBase.tsx rename lib/components/Page/{sectionBase.module.css => section.module.css} (51%) delete mode 100644 lib/components/Page/sectionHeader.module.css create mode 100644 lib/components/Timeline/Timeline.stories.tsx create mode 100644 lib/components/Timeline/Timeline.tsx create mode 100644 lib/components/Timeline/TimelineBase.tsx create mode 100644 lib/components/Timeline/TimelineSection.tsx create mode 100644 lib/components/Timeline/index.ts rename lib/components/{History/historyList.module.css => Timeline/timelineBase.module.css} (63%) create mode 100644 lib/components/Timeline/timelineSection.module.css create mode 100644 lib/components/Transmission/TransmissionType.tsx create mode 100644 lib/examples/avatar/brreg-logo.png create mode 100644 lib/examples/avatar/brreg.ts create mode 100644 lib/examples/avatar/index.ts create mode 100644 lib/examples/avatar/nav-logo.png create mode 100644 lib/examples/avatar/nav.ts create mode 100644 lib/examples/avatar/oslo-logo.png create mode 100644 lib/examples/avatar/oslo.ts create mode 100644 lib/examples/avatar/skatt-logo.png create mode 100644 lib/examples/avatar/skatt.ts create mode 100644 lib/examples/avatar/ssb-logo.png create mode 100644 lib/examples/avatar/ssb.ts create mode 100644 lib/examples/dialog/dialogContextMenu.ts create mode 100644 lib/examples/dialog/dialogHistoryItems.ts create mode 100644 lib/examples/dialog/dialogListItems.ts create mode 100644 lib/examples/dialog/extendedLetterDialog.tsx create mode 100644 lib/examples/dialog/index.ts create mode 100644 lib/examples/dialog/metadataDialog.tsx create mode 100644 lib/examples/dialog/reportingCompletedDialog.tsx create mode 100644 lib/examples/dialog/reportingDialog.tsx create mode 100644 lib/examples/dialog/reportingDraftDialog.tsx create mode 100644 lib/examples/dialog/reportingHistoryItems.tsx create mode 100644 lib/examples/dialog/reportingInProgressDialog.tsx create mode 100644 lib/examples/dialog/simpleLetterDialog.tsx create mode 100644 lib/examples/dialog/transmissionList.ts create mode 100644 lib/examples/dialog/transmissionsCompletedDialog.tsx create mode 100644 lib/examples/dialog/transmissionsDialog.tsx create mode 100644 lib/examples/dialog/transmissionsHistoryItems.ts create mode 100644 lib/examples/dialog/transmissionsInProgressDialog.tsx create mode 100644 lib/examples/dialog/transmissionsTimeline.ts diff --git a/lib/components/Attachment/index.ts b/lib/components/Attachment/index.ts index ced4448f..b661c858 100644 --- a/lib/components/Attachment/index.ts +++ b/lib/components/Attachment/index.ts @@ -1,3 +1,2 @@ export * from './AttachmentLink'; export * from './AttachmentList'; -export * from './AttachmentSection'; diff --git a/lib/components/Bookmarks/BookmarksSection.tsx b/lib/components/Bookmarks/BookmarksSection.tsx index 82da8c57..351974a7 100644 --- a/lib/components/Bookmarks/BookmarksSection.tsx +++ b/lib/components/Bookmarks/BookmarksSection.tsx @@ -1,4 +1,4 @@ -import { BookmarksList, Heading, MetaItem, SectionBase, SectionFooter, SectionHeader } from '../'; +import { BookmarksList, Heading, MetaItem, Section, SectionFooter, SectionHeader } from '../'; import type { BookmarksListItemProps } from '../'; export interface BookmarksSectionProps { @@ -7,16 +7,16 @@ export interface BookmarksSectionProps { updatedAtLabel?: string; } -export const BookmarksSection = ({ title, items, updatedAtLabel }) => { +export const BookmarksSection = ({ title, items, updatedAtLabel }: BookmarksSectionProps) => { return ( - +
{title} - + {updatedAtLabel} - +
); }; diff --git a/lib/components/Bookmarks/index.ts b/lib/components/Bookmarks/index.ts index 71503c54..0703b5df 100644 --- a/lib/components/Bookmarks/index.ts +++ b/lib/components/Bookmarks/index.ts @@ -1,3 +1,4 @@ export * from './BookmarksList'; export * from './BookmarksListItem'; export * from './QueryLabel'; +export * from './BookmarksSection'; diff --git a/lib/components/Button/ButtonBase.tsx b/lib/components/Button/ButtonBase.tsx index 5bc216d0..14b2379d 100644 --- a/lib/components/Button/ButtonBase.tsx +++ b/lib/components/Button/ButtonBase.tsx @@ -4,7 +4,7 @@ import type { ElementType, ReactNode } from 'react'; import styles from './buttonBase.module.css'; export type ButtonVariant = 'solid' | 'outline' | 'dotted' | 'text'; -export type ButtonSize = 'sm' | 'md' | 'lg' | 'custom'; +export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'custom'; export type ButtonColor = 'primary' | 'secondary'; export interface ButtonBaseProps extends React.HTMLAttributes { diff --git a/lib/components/Button/buttonBase.module.css b/lib/components/Button/buttonBase.module.css index 017bae94..481aec9b 100644 --- a/lib/components/Button/buttonBase.module.css +++ b/lib/components/Button/buttonBase.module.css @@ -46,6 +46,10 @@ border-color: var(--theme-base-active); } +.button[data-size="xs"] { + height: 1.5rem; /* sm 24 */ +} + .button[data-size="sm"] { height: 2.25rem; /* sm 36 */ } diff --git a/lib/components/Button/buttonIcon.module.css b/lib/components/Button/buttonIcon.module.css index 1e2dd5a1..0a583e75 100644 --- a/lib/components/Button/buttonIcon.module.css +++ b/lib/components/Button/buttonIcon.module.css @@ -4,6 +4,10 @@ justify-content: center; } +.icon[data-size="xs"] { + font-size: 1rem; +} + .icon[data-size="sm"] { font-size: 1.25rem; } diff --git a/lib/components/Button/buttonLabel.module.css b/lib/components/Button/buttonLabel.module.css index 58ecc6a8..733d52b0 100644 --- a/lib/components/Button/buttonLabel.module.css +++ b/lib/components/Button/buttonLabel.module.css @@ -4,6 +4,11 @@ padding: 0 .25em; } +.label[data-size="xs"] { + font-size: 0.75rem; + padding: 0 .5em; +} + .label[data-size="sm"] { font-size: 0.875rem; } diff --git a/lib/components/Byline/Byline.stories.tsx b/lib/components/Byline/Byline.stories.tsx new file mode 100644 index 00000000..5d856ce7 --- /dev/null +++ b/lib/components/Byline/Byline.stories.tsx @@ -0,0 +1,50 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { Byline } from './Byline'; + +const meta = { + title: 'Byline/Byline', + component: Byline, + tags: ['autodocs'], + parameters: {}, + args: { + datetime: '2024-12-12 11:15', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + children: '12. desember 2024 kl 11.15', + }, +}; + +export const Avatar: Story = { + args: { + avatar: { + type: 'person', + name: 'Per Person', + }, + children: ( + <> + Per Person, 12. desember 2024 + + ), + }, +}; + +export const LargeAvatar: Story = { + args: { + size: 'lg', + avatar: { + type: 'person', + name: 'Per Person', + }, + children: ( + <> + Skatteetaten til Per Person + + ), + }, +}; diff --git a/lib/components/Byline/Byline.tsx b/lib/components/Byline/Byline.tsx new file mode 100644 index 00000000..20a20e2d --- /dev/null +++ b/lib/components/Byline/Byline.tsx @@ -0,0 +1,33 @@ +import type { ReactNode } from 'react'; +import { Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Skeleton } from '..'; +import styles from './byline.module.css'; + +export type BylineSize = 'xs' | 'sm' | 'lg'; + +export interface BylineProps { + size?: BylineSize; + avatar?: AvatarProps; + avatarGroup?: AvatarGroupProps; + datetime?: string; + loading?: boolean; + children?: ReactNode; +} + +/** Byline, possible avatar/avatarGroup, name and more info */ + +export const Byline = ({ loading, size = 'xs', avatar, avatarGroup, datetime, children }: BylineProps) => { + return ( +
+ + {avatarGroup ? ( + + ) : ( + avatar && + )} + + +
+ ); +}; diff --git a/lib/components/Byline/byline.module.css b/lib/components/Byline/byline.module.css new file mode 100644 index 00000000..7e3fe826 --- /dev/null +++ b/lib/components/Byline/byline.module.css @@ -0,0 +1,30 @@ +.byline { + display: inline-flex; + align-items: center; + column-gap: 0.5em; +} + +.label { + display: inline-flex; + flex-wrap: wrap; + column-gap: 0.25em; + color: var(--theme-text-subtle); +} + +.label[data-size="xs"], +.label[data-size="sm"] { + font-size: 14px; + line-height: 1.125rem; + padding: 0.1875rem 0; +} + +.label[data-size="md"], +.label[data-size="lg"] { + font-size: 16px; + line-height: 1.25rem; +} + +.label > strong { + font-weight: 500; + color: var(--theme-text-default); +} diff --git a/lib/components/Byline/index.ts b/lib/components/Byline/index.ts new file mode 100644 index 00000000..ecde6547 --- /dev/null +++ b/lib/components/Byline/index.ts @@ -0,0 +1 @@ +export * from './Byline'; diff --git a/lib/components/ContextMenu/ContextMenu.tsx b/lib/components/ContextMenu/ContextMenu.tsx index 4ce2f816..d1ef9c63 100644 --- a/lib/components/ContextMenu/ContextMenu.tsx +++ b/lib/components/ContextMenu/ContextMenu.tsx @@ -1,7 +1,9 @@ 'use client'; import cx from 'classnames'; +import { useRef } from 'react'; import { DropdownBase, type DropdownPlacement, IconButton, type MenuItemProps } from '../'; import { type MenuItemGroups, MenuItems } from '../'; +import { useClickOutside } from '../../hooks'; import { useRootContext } from '../RootProvider'; import styles from './contextMenu.module.css'; @@ -25,9 +27,13 @@ export const ContextMenu = ({ items, }: ContextMenuProps) => { const { currentId, toggleId, closeAll } = useRootContext(); + const ref = useRef(null); + useClickOutside(ref, () => closeAll()); const onToggle = () => toggleId(id); + const expanded = currentId === id; + return ( -
+
- +
diff --git a/lib/components/Dialog/Dialog.stories.tsx b/lib/components/Dialog/Dialog.stories.tsx index 2ca5eb6f..9ae2ecd7 100644 --- a/lib/components/Dialog/Dialog.stories.tsx +++ b/lib/components/Dialog/Dialog.stories.tsx @@ -1,5 +1,18 @@ import { withThemeByDataAttribute } from '@storybook/addon-themes'; import type { Meta, StoryObj } from '@storybook/react'; +import { + dialogContextMenu, + extendedLetterDialog, + metadataDialog, + reportingCompletedDialog, + reportingDialog, + reportingDraftDialog, + reportingInProgressDialog, + simpleLetterDialog, + transmissionsCompletedDialog, + transmissionsDialog, + transmissionsInProgressDialog, +} from '../../examples'; import { Dialog } from './Dialog'; const meta = { @@ -18,6 +31,17 @@ const meta = { ], argTypes: { body: { control: 'text' } }, args: { + sender: { + type: 'company', + name: 'Skatteetaten', + imageUrl: + 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', + }, + recipientLabel: 'til', + recipient: { + type: 'person', + name: 'Roar Recipient', + }, seenBy: { as: 'a', href: '#', @@ -30,41 +54,10 @@ const meta = { href: '#', label: 'Aktivitetslogg', }, - menu: { - id: 'context-menu', - items: [ - { - groupId: '1', - id: '1', - icon: 'arrow-redo', - title: 'Del og gi tilgang', - }, - { - groupId: '1', - id: '2', - icon: 'eye', - title: 'Marker som lest', - }, - { - groupId: '2', - id: '3', - icon: 'archive', - title: 'Flytt til arkiv', - }, - { - groupId: '2', - id: '4', - icon: 'trash', - title: 'Flytt til papirkurv', - }, - { - groupId: '3', - id: '4', - icon: 'clock-dashed', - title: 'Aktivitetslogg', - }, - ], + backButton: { + label: 'Tilbake', }, + menu: dialogContextMenu, updatedAt: '2024-11-25 15:30', updatedAtLabel: '25. november 1999 kl 15.30', title: 'Title', @@ -75,398 +68,42 @@ const meta = { export default meta; type Story = StoryObj; -export const Body: Story = { - args: { - body: ( - <> -

Heading 2

-

Body can be displayed using HTML.

-
    -
  • List item 1
  • -
  • List item 2
  • -
  • List item 3
  • -
- - ), - }, +export const SimpleLetter: Story = { + args: simpleLetterDialog, }; -export const Attachments: Story = { - args: { - attachments: { - title: '2 vedlegg', - items: [ - { - label: 'Dokument 1.pdf', - href: '', - }, - { - label: 'Dokument 2.pdf', - href: '', - }, - ], - }, - }, +export const ExtendedLetter: Story = { + args: extendedLetterDialog, }; -export const Transmissions: Story = { - args: { - sender: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - title: 'Tredjepartsopplysninger for boligselskap', - summary: - 'Her finner du alle innsendinger og tilbakemeldinger for tredjepartsopplysninger for boligselskap 2023. Frist for å levere er 20. januar 2024.', - actions: [ - { - label: 'Lever tredjepartsopplysninger', - }, - ], - additionalInfo: ( -

- Sameier med 9 eller flere boligseksjoner skal levere opplysninger om sameiers andel av felles inntekter, - utgifter, formue og gjeld. Mer informasjon. -

- ), - history: { - title: 'Hva har skjedd?', - items: [ - { - createdAtLabel: '15. februar 2024 kl. 08.45', - createdBy: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - summary: 'Skjemaet er lukket for rapportering og korreksjoner.', - }, - { - createdAtLabel: '2. januar 2024 kl 08.00', - createdBy: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - summary: 'Du kan nå levere tredjepartsopplysninger.', - }, - { - createdAtLabel: '15. oktober 2023 kl 08.00', - createdBy: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - summary: 'Du må levere tredjepartsopplysninger for boligselskap.', - attachments: [ - { - label: 'Rapportering av tredjepartsopplysninger for boligselskap.pdf', - }, - ], - }, - ], - }, - transmissions: { - title: '6 forsendelser', - items: [ - { - createdAt: '1999-01-01', - createdAtLabel: 'Skatteetaten, 1. mars 2024', - sender: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - badge: { - label: 'Godkjent, med feil', - }, - title: 'Leveransen er godkjent, men inneholder feil', - summary: - 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', - attachments: { - title: '2 vedlegg', - items: [ - { - label: 'Dokument 1.pdf', - href: '', - }, - { - label: 'Dokument 2.pdf', - href: '', - }, - ], - }, - }, - { - sender: { - name: 'Per Olav Olsen', - }, - title: 'Tredjepartsopplysninger ble levert', - createdAtLabel: '1. mars 2024', - summary: - 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', - }, - { - createdAt: '1999-01-01', - createdAtLabel: 'Skatteetaten, 1. mars 2024', - sender: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - badge: { - label: 'Godkjent', - }, - title: 'Leveransen er godkjent', - summary: - 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', - attachments: { - title: '2 vedlegg', - items: [ - { - label: 'Dokument 1.pdf', - href: '', - }, - { - label: 'Dokument 2.pdf', - href: '', - }, - ], - }, - }, - { - sender: { - name: 'Kari Susanne Pettersen', - }, - title: 'Tredjepartsopplysninger ble levert', - createdAtLabel: '1. mars 2024', - summary: - 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', - }, - - { - createdAt: '1999-01-01', - createdAtLabel: 'Skatteetaten, 1. mars 2024', - sender: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - badge: { - label: 'Avvist', - }, - title: 'Leveransen er avvist', - summary: - 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', - attachments: { - title: '2 vedlegg', - items: [ - { - label: 'Dokument 1.pdf', - href: '', - }, - { - label: 'Dokument 2.pdf', - href: '', - }, - ], - }, - }, - { - sender: { - name: 'Siren Søftebø', - }, - title: 'Tredjepartsopplysninger ble levert', - createdAtLabel: '1. mars 2024', - summary: - 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', - }, - ], - }, - }, +export const TypographyMetadata: Story = { + args: metadataDialog, }; -export const Actions: Story = { - args: { - actions: [ - { - id: '1', - priority: 'primary', - label: 'Primary', - }, - { - id: '2', - priority: 'secondary', - label: 'Secondary', - }, - ], - }, +export const ReportingRequired: Story = { + args: reportingDialog, }; -export const RequiresAttention: Story = { - args: { - status: { label: 'Krever handling', value: 'requires-attention' }, - sender: { - name: 'Statistisk sentralbyrå', - imageUrl: 'https://digdir-proto-proto.vercel.app/_next/static/media/SSB.0ca4474e.png', - }, - recipient: { - name: 'Bergen Bar', - }, - title: 'Rapportering av bedriftsdata', - summary: 'Du må levere bedriftsdata innen 1. januar.', - additionalInfo: ( -

- Din bedrift er en av 8.000 virksomheter som har opplysningsplikt i 2024. Statistikken er viktig for samfunnet og - det er ikke valgfritt å delta. Hvis dere ikke sender opplysningene innen fristen, vil foretaket kunne få - tvangsmulkt. Les mer på SSB.no -

- ), - actions: [ - { - id: '1', - priority: 'primary', - label: 'Rapporter bedriftsdata', - }, - ], - dueAt: '2025-01-01', - dueAtLabel: 'Frist: 1. januar 2025', - attachments: { - title: '1 vedlegg', - items: [ - { - label: 'Vedtak om innlevering av bedriftsdata.pdf', - href: '', - }, - ], - }, - }, +export const ReportingDraft: Story = { + args: reportingDraftDialog, }; -export const InProgress: Story = { - args: { - ...RequiresAttention.args, - status: { value: 'in-progress', label: 'Under arbeid' }, - - dueAt: null, - dueAtLabel: null, - updatedAtLabel: '27. november 2024 kl 10.30', - - summary: 'Saken er sendt til manuell behandling. Forventet behandlingstid: 2 uker.', - body: ( - <> -

Hva skjer nå?

-

Saken din har fått saksbehandler og blir behandlet manuelt.

-
    -
  • - Din saksbehandler: Siri Saksbehander -
  • -
  • - Ditt saksnummer: XRT0987 -
  • -
-

Oppgi saksnummer ved kontakt.

- - ), - actions: null, - attachments: {}, - additionalInfo: ( -

- Din bedrift er en av 8.000 virksomheter som har opplysningsplikt i 2024. Statistikken er viktig for samfunnet og - det er ikke valgfritt å delta. Hvis dere ikke sender opplysningene innen fristen, vil foretaket kunne få - tvangsmulkt. Les mer på SSB.no -

- ), - - history: { - title: 'Hva har skjedd?', - items: [ - { - createdBy: { - type: 'person', - name: 'Ola Nordmann', - }, - createdAtLabel: '27. november 2024 kl 10.24', - summary: 'Bedriftsdata ble levert.', - }, - { - createdBy: { - type: 'company', - name: 'Statistisk sentralbyrå', - imageUrl: 'https://digdir-proto-proto.vercel.app/_next/static/media/SSB.0ca4474e.png', - }, - createdAtLabel: '24. november 2024 kl 15.30', - summary: 'Du må levere bedriftsdata innen 1. januar.', - attachments: { - title: '1 vedlegg', - items: [ - { - label: 'Vedtak om innlevering av bedriftsdata.pdf', - href: '', - }, - ], - }, - }, - ], - }, - }, +export const ReportingInProgress: Story = { + args: reportingInProgressDialog, }; -export const Draft: Story = { - args: { - status: { value: 'draft', label: 'Utkast' }, - - sender: { - name: 'Statistisk sentralbyrå', - imageUrl: 'https://digdir-proto-proto.vercel.app/_next/static/media/SSB.0ca4474e.png', - }, - - recipient: { - name: 'Bergen Bar', - }, - - title: 'Registrere enkeltmannsforetak', - summary: 'Skjema er opprettet.', +export const ReportingCompleted: Story = { + args: reportingCompletedDialog, +}; - actions: [ - { - id: '1', - priority: 'primary', - label: 'Gå til skjema', - }, - { - id: '2', - priority: 'secondary', - label: 'Forkast', - }, - ], +export const Transmissions: Story = { + args: transmissionsDialog, +}; - attachments: {}, - }, +export const TransmissionsInProgress: Story = { + args: transmissionsInProgressDialog, }; -export const Sent: Story = { - args: { - ...Draft.args, - status: { value: 'sent', label: 'Sendt' }, - actions: null, - summary: 'Skjema er sendt inn.', - attachments: { - title: '1 vedlegg', - items: [ - { - href: '#', - label: 'Kvittering på innsendt skjema.pdf', - }, - ], - }, - }, +export const TransmissionsCompleted: Story = { + args: transmissionsCompletedDialog, }; diff --git a/lib/components/Dialog/Dialog.tsx b/lib/components/Dialog/Dialog.tsx index 90b3d279..269b0d1e 100644 --- a/lib/components/Dialog/Dialog.tsx +++ b/lib/components/Dialog/Dialog.tsx @@ -1,29 +1,42 @@ import type { ReactNode } from 'react'; -import { AttachmentSection, type AttachmentSectionProps } from '../Attachment'; -import type { ContextMenuProps } from '../ContextMenu/'; -import { MetaBase } from '../Meta'; -import { TransmissionSection, type TransmissionSectionProps } from '../Transmission'; -import { type DialogActionButtonProps, DialogActions } from './DialogActions.tsx'; -import { DialogActivityLog, type DialogActivityLogProps } from './DialogActivityLog'; -import { DialogArticleBase } from './DialogArticleBase'; -import { DialogBase } from './DialogBase'; -import { DialogBodyBase } from './DialogBodyBase'; -import { DialogContent } from './DialogContent'; -import { DialogFooter } from './DialogFooter'; -import { DialogHeader } from './DialogHeader'; -import type { DialogRecipientProps, DialogSenderProps } from './DialogHeadings.tsx'; -import { DialogHistory, type DialogHistoryProps } from './DialogHistory'; -import { type DialogBackButtonProps, DialogNav } from './DialogNav'; -import { DialogSeenBy, type DialogSeenByProps } from './DialogSeenBy'; -import type { DialogStatusProps } from './DialogStatus'; +import { + Article, + type AvatarProps, + type BackButtonProps, + type ContextMenuProps, + type DialogActionButtonProps, + DialogActions, + type DialogActivityLogProps, + DialogAttachments, + type DialogAttachmentsProps, + DialogByline, + DialogContent, + DialogHistory, + type DialogHistoryProps, + DialogMetadata, + DialogSection, + type DialogSectionProps, + type DialogSeenByProps, + type DialogStatusProps, + DialogTimeline, + type DialogTimelineProps, + Heading, + PageBase, + PageNav, + Typography, +} from '..'; export interface DialogProps { /** Dialog id */ id: string; /** Title */ title: string; + /** Sender */ + sender: AvatarProps; + /** Recipient */ + recipient?: AvatarProps; /** Back button */ - backButton?: DialogBackButtonProps; + backButton?: BackButtonProps; /** Context menu */ menu?: ContextMenuProps; /** Dialog status */ @@ -36,10 +49,10 @@ export interface DialogProps { dueAt?: string; /** Due at label */ dueAtLabel?: string; - /** Sender */ - sender?: DialogSenderProps; - /** Recipient */ - recipient?: DialogRecipientProps; + /** Recipient label (prefix) */ + recipientLabel?: string; + /** Group recipient, show both sender and recipient avatars */ + recipientGroup?: boolean; /** Summary */ summary?: string; /** Body (should be an output markdown/html rendered to React / HTML) */ @@ -50,14 +63,16 @@ export interface DialogProps { seenBy?: DialogSeenByProps; /** Activity Log */ activityLog?: DialogActivityLogProps; - /** More information about the dialog, process, etc. */ - additionalInfo?: ReactNode; /** Dialog attachments */ - attachments?: AttachmentSectionProps; - /** Dialog transmissions */ - transmissions?: TransmissionSectionProps; - /** History */ + attachments?: DialogAttachmentsProps; + /** Dialog history */ history?: DialogHistoryProps; + /** Dialog timeline */ + timeline?: DialogTimelineProps; + /** More information about the dialog, process, etc. */ + additionalInfo?: DialogSectionProps; + /** Contact information. */ + contactInfo?: DialogSectionProps; } /** @@ -75,34 +90,57 @@ export const Dialog = ({ title, sender, recipient, + recipientLabel = 'to', + recipientGroup, summary = 'Summary.', body, actions = [], attachments, - history, seenBy, activityLog, + history, + timeline, additionalInfo, - transmissions, + contactInfo, }: DialogProps) => { return ( - - - - - - - {attachments && } + + + + +
+ {title} + {history && } + + + + +

{summary}

+ {body} + {attachments && } {actions?.length > 0 && } - {transmissions && } - - {seenBy && } - {activityLog && } - - - {additionalInfo && } - {history && } - - +
+ + {timeline && } + + {additionalInfo && ( + + {additionalInfo?.children} + + )} + + {contactInfo && ( + + {contactInfo?.children} + + )} +
+
); }; diff --git a/lib/components/Dialog/DialogActions.stories.ts b/lib/components/Dialog/DialogActions.stories.ts index b2e275ec..367f2768 100644 --- a/lib/components/Dialog/DialogActions.stories.ts +++ b/lib/components/Dialog/DialogActions.stories.ts @@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { DialogActions } from './DialogActions'; const meta = { - title: 'Dialog/Sections/DialogActions', + title: 'Dialog/DialogActions', component: DialogActions, tags: ['autodocs'], args: { diff --git a/lib/components/Dialog/DialogArticleBase.tsx b/lib/components/Dialog/DialogArticleBase.tsx deleted file mode 100644 index 65ae5d2d..00000000 --- a/lib/components/Dialog/DialogArticleBase.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import type { ReactNode } from 'react'; -import styles from './dialogArticleBase.module.css'; - -interface ArticleBaseProps { - children?: ReactNode; -} - -export const DialogArticleBase = ({ children }: ArticleBaseProps) => { - return
{children}
; -}; diff --git a/lib/components/Attachment/AttachmentSection.stories.ts b/lib/components/Dialog/DialogAttachments.stories.ts similarity index 65% rename from lib/components/Attachment/AttachmentSection.stories.ts rename to lib/components/Dialog/DialogAttachments.stories.ts index 599d9f59..4251e70f 100644 --- a/lib/components/Attachment/AttachmentSection.stories.ts +++ b/lib/components/Dialog/DialogAttachments.stories.ts @@ -1,16 +1,16 @@ import type { Meta, StoryObj } from '@storybook/react'; import { attachments } from '../../examples/attachments.ts'; -import { AttachmentSection } from './AttachmentSection'; +import { DialogAttachments } from './DialogAttachments'; const meta = { - title: 'Attachment/AttachmentSection', - component: AttachmentSection, + title: 'Dialog/DialogAttachments', + component: DialogAttachments, tags: ['autodocs'], args: { title: '6 vedlegg', items: attachments, }, -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/lib/components/Attachment/AttachmentSection.tsx b/lib/components/Dialog/DialogAttachments.tsx similarity index 73% rename from lib/components/Attachment/AttachmentSection.tsx rename to lib/components/Dialog/DialogAttachments.tsx index 3c84e62f..e22024f2 100644 --- a/lib/components/Attachment/AttachmentSection.tsx +++ b/lib/components/Dialog/DialogAttachments.tsx @@ -1,12 +1,12 @@ import { type AttachmentLinkProps, AttachmentList } from '../Attachment'; import { Heading } from '../Typography'; -export interface AttachmentSectionProps { +export interface DialogAttachmentsProps { title?: string; items?: AttachmentLinkProps[]; } -export const AttachmentSection = ({ title = 'Attachments', items }: AttachmentSectionProps) => { +export const DialogAttachments = ({ title = 'Attachments', items }: DialogAttachmentsProps) => { if (!items?.length) { return null; } diff --git a/lib/components/Dialog/DialogBase.tsx b/lib/components/Dialog/DialogBase.tsx deleted file mode 100644 index 971b82e4..00000000 --- a/lib/components/Dialog/DialogBase.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import type { ReactNode } from 'react'; -import styles from './dialog.module.css'; - -export type DialogSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; -export type DialogVariant = 'neutral' | 'draft' | 'trashed' | 'archived'; - -export interface DialogBaseProps { - children?: ReactNode; -} - -export const DialogBase = ({ children }: DialogBaseProps) => { - return
{children}
; -}; diff --git a/lib/components/Dialog/DialogBodyBase.tsx b/lib/components/Dialog/DialogBodyBase.tsx deleted file mode 100644 index cfa6a619..00000000 --- a/lib/components/Dialog/DialogBodyBase.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import type { ReactNode } from 'react'; -import { DialogBorder } from './DialogBorder'; -import styles from './dialogBodyBase.module.css'; - -export interface DialogBodyProps { - children?: ReactNode; -} - -export const DialogBodyBase = ({ children }: DialogBodyProps) => { - return ( - -
- {children} -
-
- ); -}; diff --git a/lib/components/Dialog/DialogByline.tsx b/lib/components/Dialog/DialogByline.tsx new file mode 100644 index 00000000..1be07aad --- /dev/null +++ b/lib/components/Dialog/DialogByline.tsx @@ -0,0 +1,37 @@ +import { type AvatarProps, Byline, type BylineSize } from '..'; + +export interface DialogBylineProps { + sender: AvatarProps; + recipient?: AvatarProps; + recipientLabel?: string; + recipientGroup?: boolean; + loading?: boolean; + size?: BylineSize; +} + +/** Dialog byline */ +export const DialogByline = ({ + sender, + recipient, + recipientLabel = 'to', + recipientGroup = false, + loading, + size = 'xs', +}: DialogBylineProps) => { + if (!sender && !recipient) { + return null; + } + + const avatarGroup = + recipientGroup && sender && recipient + ? { + items: [sender, recipient], + } + : undefined; + + return ( + + {sender?.name} {recipientLabel + ' ' + recipient?.name} + + ); +}; diff --git a/lib/components/Dialog/DialogBylline.stories.ts b/lib/components/Dialog/DialogBylline.stories.ts new file mode 100644 index 00000000..383a3994 --- /dev/null +++ b/lib/components/Dialog/DialogBylline.stories.ts @@ -0,0 +1,29 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { skatt } from '../../examples/avatar'; +import { DialogByline } from './DialogByline'; + +const meta = { + title: 'Dialog/DialogByline', + component: DialogByline, + tags: ['autodocs'], + args: { + sender: skatt, + recipient: { + type: 'person', + name: 'Per Person', + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: {}, +}; + +export const Large: Story = { + args: { + size: 'lg', + }, +}; diff --git a/lib/components/Dialog/DialogContent.stories.ts b/lib/components/Dialog/DialogContent.stories.ts deleted file mode 100644 index ac06ef82..00000000 --- a/lib/components/Dialog/DialogContent.stories.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { DialogContent } from './DialogContent'; - -const meta = { - title: 'Dialog/Sections/DialogContent', - component: DialogContent, - tags: ['autodocs'], - args: { - updatedAt: '1999-05-26 22:59:00', - summary: 'Summary', - body: 'Body', - }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: {}, -}; diff --git a/lib/components/Dialog/DialogContent.stories.tsx b/lib/components/Dialog/DialogContent.stories.tsx new file mode 100644 index 00000000..1640c176 --- /dev/null +++ b/lib/components/Dialog/DialogContent.stories.tsx @@ -0,0 +1,43 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { DialogContent } from './DialogContent'; + +const meta = { + title: 'Dialog/DialogContent', + component: DialogContent, + tags: ['autodocs'], + args: { + updatedAt: '1999-05-26 22:59:00', + updatedAtLabel: '25. mai 1999 kl 22.59', + children: 'Body', + seenBy: { + seenByEndUser: true, + label: 'Sett av deg', + }, + activityLog: { + label: 'Aktivitetslogg', + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: {}, +}; + +export const ExtendedContent: Story = { + args: { + children: ( + <> +

+ Sander Svendsen er sykmeldt i 4 dager fra 2. juli–5. juli 2024. Du må oppgi nærmeste leder. +

+
Ansvarlig lege
+

Mark Medisin + 47 23369090

+
Nærmeste leder
+

Ikke oppgitt.

+ + ), + }, +}; diff --git a/lib/components/Dialog/DialogContent.tsx b/lib/components/Dialog/DialogContent.tsx index c0154bd1..bad24f8b 100644 --- a/lib/components/Dialog/DialogContent.tsx +++ b/lib/components/Dialog/DialogContent.tsx @@ -1,23 +1,39 @@ import type { ReactNode } from 'react'; -import { Typography } from '../Typography'; -import { DialogMetadata } from './DialogMetadata'; +import { + Byline, + DialogActivityLog, + type DialogActivityLogProps, + DialogSeenBy, + type DialogSeenByProps, + MetaBase, + Section, + TimelineSection, + Typography, +} from '..'; export interface DialogContentProps { updatedAt?: string; updatedAtLabel?: string; - summary?: string; - body?: ReactNode; + seenBy?: DialogSeenByProps; + activityLog?: DialogActivityLogProps; + children?: ReactNode; } -/** Main textual content of a dialog, including summary, body and a timestamp */ -export const DialogContent = ({ updatedAt, updatedAtLabel, summary, body }: DialogContentProps) => { +/** Main content of a dialog */ + +export const DialogContent = ({ updatedAt, updatedAtLabel, seenBy, activityLog, children }: DialogContentProps) => { return ( -
- - -

{summary}

- {body} -
-
+ +
+
+ {updatedAtLabel} + {children} +
+ + {seenBy && } + {activityLog && } + +
+
); }; diff --git a/lib/components/Dialog/DialogFooter.tsx b/lib/components/Dialog/DialogFooter.tsx deleted file mode 100644 index cdbabb46..00000000 --- a/lib/components/Dialog/DialogFooter.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import type { ReactNode } from 'react'; -import { Typography } from '../Typography'; -import { DialogSectionBase } from './DialogSectionBase'; - -export interface DialogFooterProps { - additionalInfo?: ReactNode; -} - -export const DialogFooter = ({ additionalInfo }: DialogFooterProps) => { - return ( - - {additionalInfo} - - ); -}; diff --git a/lib/components/Dialog/DialogHeader.stories.ts b/lib/components/Dialog/DialogHeader.stories.ts deleted file mode 100644 index b8f5f177..00000000 --- a/lib/components/Dialog/DialogHeader.stories.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { DialogHeader } from './DialogHeader'; - -const meta = { - title: 'Dialog/Sections/DialogHeader', - component: DialogHeader, - tags: ['autodocs'], - args: { - title: 'Title', - variant: 'neutral', - sender: { - name: 'Sender', - type: 'company', - }, - recipient: { - name: 'Recipient', - type: 'person', - }, - }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: {}, -}; diff --git a/lib/components/Dialog/DialogHeader.tsx b/lib/components/Dialog/DialogHeader.tsx deleted file mode 100644 index 040ba6c7..00000000 --- a/lib/components/Dialog/DialogHeader.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { DialogHeaderBase } from './DialogHeaderBase'; -import { DialogHeadings, type DialogRecipientProps, type DialogSenderProps } from './DialogHeadings'; -import type { DialogListItemVariant } from './DialogListItem.tsx'; -import { DialogTitle } from './DialogTitle'; - -export interface DialogHeaderProps { - title: string; - variant: DialogListItemVariant; - sender?: DialogSenderProps; - seen?: boolean; - recipient?: DialogRecipientProps; -} - -export const DialogHeader = ({ title, sender, recipient, seen = false, variant }: DialogHeaderProps) => { - return ( - - - {title} - - {sender && recipient && } - - ); -}; diff --git a/lib/components/Dialog/DialogHeaderBase.tsx b/lib/components/Dialog/DialogHeaderBase.tsx deleted file mode 100644 index 071c9fa0..00000000 --- a/lib/components/Dialog/DialogHeaderBase.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import type { ReactNode } from 'react'; -import type { DialogSize } from './DialogBase'; -import styles from './dialogHeaderBase.module.css'; - -export interface DialogHeaderBaseProps { - size?: DialogSize; - children?: ReactNode; -} - -export const DialogHeaderBase = ({ size, children }: DialogHeaderBaseProps) => { - return ( -
- {children} -
- ); -}; diff --git a/lib/components/Dialog/DialogTitle.tsx b/lib/components/Dialog/DialogHeading.tsx similarity index 58% rename from lib/components/Dialog/DialogTitle.tsx rename to lib/components/Dialog/DialogHeading.tsx index 9d72f78b..840eee60 100644 --- a/lib/components/Dialog/DialogTitle.tsx +++ b/lib/components/Dialog/DialogHeading.tsx @@ -1,15 +1,13 @@ import type { ReactNode } from 'react'; -import { Skeleton } from '../Skeleton'; -import type { DialogSize, DialogVariant } from './DialogBase'; -import { DialogLabel } from './DialogLabel'; -import styles from './dialogTitle.module.css'; +import { DialogLabel, type DialogListItemSize, type DialogListItemVariant, Skeleton } from '..'; +import styles from './dialogHeading.module.css'; -export type DialogTitleProps = { +export type DialogHeadingProps = { loading?: boolean; /** Size */ - size?: DialogSize; + size?: DialogListItemSize; /** Variant */ - variant?: DialogVariant; + variant?: DialogListItemVariant; /** Label */ label?: string; /** Variant */ @@ -19,9 +17,9 @@ export type DialogTitleProps = { }; /** - * Dialog title + * Dialog heading */ -export const DialogTitle = ({ loading, size = 'sm', seen = false, variant, label, children }: DialogTitleProps) => { +export const DialogHeading = ({ loading, size = 'sm', seen = false, variant, label, children }: DialogHeadingProps) => { return (

diff --git a/lib/components/Dialog/DialogHeadings.stories.ts b/lib/components/Dialog/DialogHeadings.stories.ts deleted file mode 100644 index 6f37b8c1..00000000 --- a/lib/components/Dialog/DialogHeadings.stories.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { DialogHeadings } from './DialogHeadings'; - -const meta = { - title: 'Dialog/Sections/DialogHeadings', - component: DialogHeadings, - tags: ['autodocs'], - parameters: {}, - args: { - sender: { - name: 'Sender', - }, - recipient: { - type: 'person', - name: 'Recipient', - }, - }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const Default: Story = {}; - -export const Company: Story = { - args: { - grouped: true, - }, -}; - -export const Grouped: Story = { - args: { - grouped: true, - }, -}; diff --git a/lib/components/Dialog/DialogHeadings.tsx b/lib/components/Dialog/DialogHeadings.tsx deleted file mode 100644 index acf9c5b2..00000000 --- a/lib/components/Dialog/DialogHeadings.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { Avatar, AvatarGroup, type AvatarSize } from '../Avatar'; -import { Skeleton } from '../Skeleton'; -import type { DialogSize } from './DialogBase'; -import styles from './dialogHeadings.module.css'; - -export type DialogSenderType = 'company' | 'person'; -export type DialogRecipientType = 'company' | 'person'; - -export interface DialogSenderProps { - type?: DialogSenderType; - name: string; - imageUrl?: string; -} - -export interface DialogRecipientProps { - type?: DialogRecipientType; - name: string; -} - -const sizeMap = { - avatar: { - xs: 'xs', - sm: 'xs', - md: 'xs', - lg: 'xs', - xl: 'lg', - }, -}; - -export interface DialogHeadingsProps { - /** Sender */ - sender: DialogSenderProps; - /** Recipient */ - recipient: DialogRecipientProps; - size?: DialogSize; - /** Group sender and recipient avatars */ - grouped?: boolean; - loading?: boolean; -} - -/** Dialog headings for sender and recipient. Should present an avatar for the sender. */ - -export const DialogHeadings = ({ loading, grouped, size = 'lg', sender, recipient }: DialogHeadingsProps) => { - return ( -
- - {grouped ? ( - - ) : ( - - )} - - - - {' '} - {sender.name} - - {recipient?.name && ( - - - {'til'} - {recipient.name} - - - )} - -
- ); -}; diff --git a/lib/components/Dialog/DialogHistory.stories.ts b/lib/components/Dialog/DialogHistory.stories.ts index 48dfdba7..c5497553 100644 --- a/lib/components/Dialog/DialogHistory.stories.ts +++ b/lib/components/Dialog/DialogHistory.stories.ts @@ -1,73 +1,14 @@ import type { Meta, StoryObj } from '@storybook/react'; +import { dialogHistoryItems } from '../../examples'; import { DialogHistory } from './DialogHistory'; const meta = { - title: 'Dialog/Sections/DialogHistory', + title: 'Dialog/DialogHistory', component: DialogHistory, tags: ['autodocs'], parameters: {}, args: { - items: [ - { - createdBy: { - name: 'Kari Nordmann', - }, - createdAt: '2023-03-11 08:00', - summary: 'Skattemeldingen ble levert.', - attachments: { - title: 'Vedlegg', - items: [ - { - label: 'Kvittering på innsendt skattemelding.pdf', - href: 'kvittering.pdf', - }, - ], - }, - }, - { - createdBy: { - type: 'company', - name: 'Skatteetaten', - imageUrl: 'https://digdir-proto-proto.vercel.app/_next/static/media/Skatteetaten.636ef817.png', - }, - createdAt: '2023-03-11 08:00', - summary: 'Vi har mottatt nye opplysninger og oppdatert skattemeldingen din.', - attachments: { - title: 'Vedlegg', - items: [ - { - label: 'Oppdatert skattemelding', - href: 'kvittering_oppdatert.pdf', - }, - ], - }, - }, - { - createdBy: { - name: 'Kari Nordmann', - }, - createdAt: '2023-03-11 08:00', - summary: 'Skattemeldingen ble levert.', - attachments: { - title: 'Vedlegg', - items: [ - { - label: 'Kvittering på innsendt skattemelding.pdf', - href: 'kvittering.pdf', - }, - ], - }, - }, - { - createdBy: { - type: 'company', - name: 'Skatteetaten', - imageUrl: 'https://digdir-proto-proto.vercel.app/_next/static/media/Skatteetaten.636ef817.png', - }, - createdAt: '2023-03-11 08:00', - summary: 'Skattemeldingen din for 2022 er tilgjengelig.', - }, - ], + items: dialogHistoryItems, }, } satisfies Meta; @@ -77,3 +18,11 @@ type Story = StoryObj; export const Default: Story = { args: {}, }; + +export const Collapsible: Story = { + args: { + collapsible: true, + expandLabel: 'Vis historikk', + collapseLabel: 'Skjul historikk', + }, +}; diff --git a/lib/components/Dialog/DialogHistory.tsx b/lib/components/Dialog/DialogHistory.tsx index 84b2e217..2d72e900 100644 --- a/lib/components/Dialog/DialogHistory.tsx +++ b/lib/components/Dialog/DialogHistory.tsx @@ -1,19 +1,51 @@ -import { type HistoryItemProps, HistoryList } from '../History/'; -import { DialogSectionBase } from './DialogSectionBase'; +'use client'; +import { useState } from 'react'; +import { MetaItem, TimelineBase } from '../'; +import { DialogHistoryItem, type DialogHistoryItemProps } from './DialogHistoryItem'; export interface DialogHistoryProps { - title?: string; - items?: HistoryItemProps[]; + items?: DialogHistoryItemProps[]; + summary?: string; + updatedAt?: string; + updatedAtLabel?: string; + expandLabel?: string; + collapseLabel?: string; + collapsible?: boolean; } -export const DialogHistory = ({ title = 'History', items }: DialogHistoryProps) => { +export const DialogHistory = ({ + items, + summary = 'History summary', + updatedAt, + updatedAtLabel, + collapsible = false, + expandLabel = 'Expand history', + collapseLabel = 'Collapse history', +}: DialogHistoryProps) => { + const [expanded, setExpanded] = useState(false); + + const onToggle = () => { + setExpanded((prevState) => !prevState); + }; + if (!items) { return null; } return ( - - - + + {((expanded || !collapsible) && + items.map((item, index) => { + return ; + })) || } + + {collapsible && ( +
+ + {expanded ? collapseLabel : expandLabel} + +
+ )} +
); }; diff --git a/lib/components/Dialog/DialogHistoryDetails.tsx b/lib/components/Dialog/DialogHistoryDetails.tsx new file mode 100644 index 00000000..873bb3d2 --- /dev/null +++ b/lib/components/Dialog/DialogHistoryDetails.tsx @@ -0,0 +1,42 @@ +'use client'; +import { useState } from 'react'; +import { + DialogAttachments, + type DialogAttachmentsProps, + DialogMetadata, + DialogTransmissions, + type DialogTransmissionsProps, +} from '../'; + +export interface DialogHistoryDetailsProps { + attachments?: DialogAttachmentsProps; + transmissions?: DialogTransmissionsProps; +} + +export const DialogHistoryDetails = ({ attachments, transmissions }: DialogHistoryDetailsProps) => { + const attachmentsLabel = attachments?.title; + const transmissionsLabel = transmissions?.title; + + const [expanded, setExpanded] = useState(false); + + const onExpand = () => { + setExpanded(true); + }; + + if (!attachments && !transmissions) { + return false; + } + + if (expanded) { + return ( + <> + {attachments && } + {transmissions && } + + ); + } + + return ( + + ); +}; diff --git a/lib/components/Dialog/DialogHistoryItem.tsx b/lib/components/Dialog/DialogHistoryItem.tsx new file mode 100644 index 00000000..08248b4b --- /dev/null +++ b/lib/components/Dialog/DialogHistoryItem.tsx @@ -0,0 +1,48 @@ +'use client'; +import type { ReactNode } from 'react'; +import { + type AvatarProps, + type DialogAttachmentsProps, + type DialogTransmissionsProps, + TimelineSection, + Typography, +} from '../'; + +import { DialogHistoryDetails } from './DialogHistoryDetails'; + +export interface DialogHistoryItemProps { + createdAt?: string; + createdAtLabel?: string; + createdBy?: AvatarProps; + summary?: string; + attachments?: DialogAttachmentsProps; + transmissions?: DialogTransmissionsProps; + collapsed?: boolean; + children?: ReactNode; +} + +export const DialogHistoryItem = ({ + createdBy, + createdAt, + createdAtLabel, + summary, + attachments, + transmissions, + children, +}: DialogHistoryItemProps) => { + return ( + + + {summary &&

{summary}

} + + {children} +
+
+ ); +}; diff --git a/lib/components/Dialog/DialogLabel.tsx b/lib/components/Dialog/DialogLabel.tsx index 0f02df94..246c663c 100644 --- a/lib/components/Dialog/DialogLabel.tsx +++ b/lib/components/Dialog/DialogLabel.tsx @@ -1,10 +1,11 @@ import type { ReactNode } from 'react'; import { MetaItem, type MetaItemSize } from '../Meta'; -import type { DialogVariant } from './DialogBase'; + +export type DialogLabelVariant = 'normal' | 'trashed' | 'archived'; export interface DialogLabelProps { size?: MetaItemSize; - variant?: DialogVariant; + variant?: DialogLabelVariant; label?: string; children?: ReactNode; } diff --git a/lib/components/Dialog/DialogList.stories.ts b/lib/components/Dialog/DialogList.stories.ts index 5d38542a..2c30f822 100644 --- a/lib/components/Dialog/DialogList.stories.ts +++ b/lib/components/Dialog/DialogList.stories.ts @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; +import { dialogListItems } from '../../examples'; import { DialogList } from './DialogList'; - const meta = { title: 'Dialog/DialogList', component: DialogList, @@ -9,38 +9,7 @@ const meta = { layout: 'fullscreen', }, args: { - items: [ - { - title: 'Støtte til utbygging av solceller', - summary: 'Din støtte er innvilget', - status: { value: 'draft' }, - groupId: '2024-01', - }, - { - title: 'Støtte til utbygging av solceller', - summary: 'Din støtte er innvilget', - status: { value: 'sent' }, - groupId: '2024-02', - }, - { - title: 'Støtte til utbygging av solceller', - summary: 'Din støtte er innvilget', - status: { value: 'requires-attention' }, - groupId: '2024-01', - }, - { - title: 'Støtte til utbygging av solceller', - summary: 'Din støtte er innvilget', - status: { value: 'in-progress' }, - groupId: '2024-02', - }, - { - title: 'Støtte til utbygging av solceller', - summary: 'Din støtte er innvilget.', - status: { value: 'completed' }, - groupId: '2024-01', - }, - ], + items: dialogListItems, }, } satisfies Meta; @@ -54,11 +23,14 @@ export const Default: Story = { export const Grouped: Story = { args: { groups: { - '2024-01': { - title: 'Januar 2024', + '2023-01': { + title: 'Januar 2023', + }, + '2023-02': { + title: 'Februar 2023', }, - '2024-02': { - title: 'Februar 2024', + '2023-10': { + title: 'Oktober 2023', }, }, }, diff --git a/lib/components/Dialog/DialogList.tsx b/lib/components/Dialog/DialogList.tsx index 7aed210b..9d1c2b09 100644 --- a/lib/components/Dialog/DialogList.tsx +++ b/lib/components/Dialog/DialogList.tsx @@ -1,15 +1,14 @@ -import { SectionBase } from '../'; +import { Section } from '../'; +import { DialogListGroup, type DialogListGroupProps, DialogListItem, type DialogListItemProps } from '../'; import { useMenu } from '../../hooks'; -import { DialogGroup, type DialogGroupProps } from './DialogGroup'; -import { DialogListItem, type DialogListItemProps } from './DialogListItem'; export interface DialogListProps { items: DialogListItemProps[]; - groups?: Record; + groups?: Record; } export const DialogList = ({ items, groups = {} }: DialogListProps) => { - const { menu } = useMenu({ + const { menu } = useMenu({ items, groups, groupByKey: 'groupId', @@ -17,19 +16,19 @@ export const DialogList = ({ items, groups = {} }: DialogListProps) => { }); return ( - +
{menu?.map((group, groupIndex) => { const groupProps = group.props || {}; return ( - + {group?.items.map((item, index) => { const itemProps = item.props || {}; return ; })} - + ); })} - +
); }; diff --git a/lib/components/Dialog/DialogGroup.tsx b/lib/components/Dialog/DialogListGroup.tsx similarity index 59% rename from lib/components/Dialog/DialogGroup.tsx rename to lib/components/Dialog/DialogListGroup.tsx index 63e3c8e1..81b14903 100644 --- a/lib/components/Dialog/DialogGroup.tsx +++ b/lib/components/Dialog/DialogListGroup.tsx @@ -1,17 +1,17 @@ import type { ReactNode } from 'react'; -import { Heading, ListBase, SectionBase, SectionHeader } from '../'; +import { Heading, ListBase, Section, SectionHeader } from '../'; import { Button } from '../Button'; -export interface DialogGroupProps { +export interface DialogListGroupProps { title?: string; children?: ReactNode; } -export const DialogGroup = ({ title, children }: DialogGroupProps) => { +export const DialogListGroup = ({ title, children }: DialogListGroupProps) => { return ( - +
{title && ( - + {title}
); }; diff --git a/lib/components/Dialog/DialogListItem.stories.tsx b/lib/components/Dialog/DialogListItem.stories.tsx index 1d0db58b..2007027c 100644 --- a/lib/components/Dialog/DialogListItem.stories.tsx +++ b/lib/components/Dialog/DialogListItem.stories.tsx @@ -1,14 +1,14 @@ import { withThemeByDataAttribute } from '@storybook/addon-themes'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta } from '@storybook/react'; import { Fragment, useState } from 'react'; -import { DialogListItem } from './DialogListItem'; +import { DialogListItem, type DialogListItemProps, type DialogListItemSize } from './DialogListItem'; import { DialogStatusEnum } from './DialogStatus'; import { ListBase } from '../List'; import { MetaItem } from '../Meta'; -const getStatusLabel = (value) => { +const getStatusLabel = (value: string) => { switch (value) { case 'draft': return 'Utkast'; @@ -25,7 +25,7 @@ const getStatusLabel = (value) => { } }; -const sizes = ['lg', 'md', 'sm', 'xs']; +const sizes = ['xl', 'lg', 'md', 'sm', 'xs'] as DialogListItemSize[]; const statuslist = Object.keys(DialogStatusEnum)?.map((value) => { return { value, @@ -65,14 +65,13 @@ const meta = { } satisfies Meta; export default meta; -type Story = StoryObj; -export const Statuses = (args) => { +export const Statuses = (args: DialogListItemProps) => { return ( - {statuslist?.map((status) => { + {statuslist.map((status) => { return ( - + {status?.value} @@ -82,10 +81,10 @@ export const Statuses = (args) => { ); }; -export const Loading = (args) => { +export const Loading = (args: DialogListItemProps) => { return ( - + Loading Loaded @@ -93,7 +92,7 @@ export const Loading = (args) => { ); }; -export const Variants = (args) => { +export const Variants = (args: DialogListItemProps) => { return ( @@ -107,7 +106,6 @@ export const Variants = (args) => { Dialog has been seen { Dialog has been moved to archive { ); }; -export const DueAt = (args) => { +export const DueAt = (args: DialogListItemProps) => { return ( { ); }; -export const SeenBy = (args) => { +export const SeenBy = (args: DialogListItemProps) => { return ( @@ -187,7 +184,7 @@ export const TouchedBy = (args) => { ); }; -export const TextLength = (args) => { +export const TextLength = (args: DialogListItemProps) => { return ( { ); }; -export const Selectable = (args) => { - const [items, setItems] = useState({ - 1: { +interface SelectableItem { + id: string; + title: string; + selected: boolean; +} +export const Selectable = (args: DialogListItemProps) => { + const [items, setItems] = useState>({ + '1': { id: '1', title: 'Item 1', selected: true, }, - 2: { + '2': { id: '2', title: 'Item 2', selected: false, }, - 3: { + '3': { id: '3', title: 'Item 2', selected: false, }, }); - const onSelect = ({ id }) => { - setItems((prevState) => { + const onSelect = ({ id }: { id: string }) => { + setItems((prevState: Record) => { return { ...prevState, [id]: { @@ -243,7 +245,7 @@ export const Selectable = (args) => { onSelect(item) : null} + onClick={item.selected ? () => onSelect(item) : undefined} selected={item.selected} select={{ checked: item?.selected, onChange: () => onSelect(item) }} /> @@ -255,7 +257,7 @@ export const Selectable = (args) => { ); }; -export const Sizes = (args) => { +export const Sizes = (args: DialogListItemProps) => { return ( {sizes?.map((size) => { diff --git a/lib/components/Dialog/DialogListItem.tsx b/lib/components/Dialog/DialogListItem.tsx index 9b696ec4..24d08b69 100644 --- a/lib/components/Dialog/DialogListItem.tsx +++ b/lib/components/Dialog/DialogListItem.tsx @@ -1,25 +1,32 @@ import type { ElementType } from 'react'; -import { ListItemBase, type ListItemColor, ListItemHeader, ListItemLabel } from '../List'; -import { DialogBorder } from './DialogBorder'; -import { DialogDescription } from './DialogDescription'; -import { DialogHeaderBase } from './DialogHeaderBase'; -import { DialogHeadings } from './DialogHeadings'; -import type { DialogRecipientProps, DialogSenderProps } from './DialogHeadings'; -import { DialogMetadata } from './DialogMetadata'; -import type { DialogSeenByProps } from './DialogSeenBy'; -import { DialogSelect, type DialogSelectProps } from './DialogSelect'; -import type { DialogStatusProps } from './DialogStatus'; -import { DialogTitle } from './DialogTitle'; -import { DialogTouchedBy, type DialogTouchedByActor } from './DialogTouchedBy'; +import { + type AvatarProps, + DialogBorder, + DialogByline, + DialogHeading, + DialogMetadata, + type DialogSeenByProps, + DialogSelect, + type DialogSelectProps, + type DialogStatusProps, + type DialogTouchedByActor, + ListItemBase, + type ListItemColor, + ListItemHeader, + ListItemLabel, + Skeleton, +} from '..'; export type DialogListItemSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; -export type DialogListItemVariant = 'neutral' | 'draft' | 'trashed' | 'archived'; +export type DialogListItemVariant = 'normal' | 'trashed' | 'archived'; import styles from './dialogListItem.module.css'; export interface DialogListItemProps { /** Dialog title */ title: string; + /** Dialog sender */ + sender: AvatarProps; /** Dialog description */ description?: string; /** Dialog summary (will override description) */ @@ -42,12 +49,12 @@ export interface DialogListItemProps { selected?: boolean; /** Dialog status */ status?: DialogStatusProps; - /** Dialog sender */ - sender?: DialogSenderProps; /** Dialog Recipient */ - recipient?: DialogRecipientProps; - /** Group view, show avatar for recipient */ - grouped?: boolean; + recipient?: AvatarProps; + /** Dialog Recipient */ + recipientLabel?: string; + /** Group recipient, show both sender and recipient avatars */ + recipientGroup?: boolean; /** Updated datetime */ updatedAt?: string; /** Updated at label */ @@ -68,7 +75,7 @@ export interface DialogListItemProps { tabIndex?: number; /** Custom label */ label?: string; - /** *Custom background color */ + /** Custom color */ color?: ListItemColor; /** Dialog has been seen */ seen?: boolean; @@ -89,14 +96,15 @@ export interface DialogListItemProps { */ export const DialogListItem = ({ - size = 'lg', - variant = 'neutral', + size = 'xl', + variant = 'normal', loading, select, status, sender, recipient, - grouped, + recipientLabel = 'to', + recipientGroup = false, updatedAt, updatedAtLabel, archivedAt, @@ -117,13 +125,13 @@ export const DialogListItem = ({ }: DialogListItemProps) => { const applicableVariant = trashedAt ? 'trashed' : archivedAt ? 'archived' : variant; - if (size === 'xs' || size === 'sm') { + if (size === 'xs' || size === 'sm' || size === 'md') { return ( - + - + @@ -131,7 +139,7 @@ export const DialogListItem = ({ } return ( - + } > - - +
+ {title} - - {sender && recipient && ( - - )} - - - {summary || description} - -
- + - {touchedBy && ( - - )} -
+

+ {summary || description} +

+
+
diff --git a/lib/components/Dialog/DialogMetadata.stories.ts b/lib/components/Dialog/DialogMetadata.stories.ts index f62c5e86..b347ec17 100644 --- a/lib/components/Dialog/DialogMetadata.stories.ts +++ b/lib/components/Dialog/DialogMetadata.stories.ts @@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { DialogMetadata } from './DialogMetadata'; const meta = { - title: 'Dialog/Sections/DialogMetadata', + title: 'Dialog/DialogMetadata', component: DialogMetadata, tags: ['autodocs'], parameters: {}, diff --git a/lib/components/Dialog/DialogMetadata.tsx b/lib/components/Dialog/DialogMetadata.tsx index 83c261b2..8d9f70a0 100644 --- a/lib/components/Dialog/DialogMetadata.tsx +++ b/lib/components/Dialog/DialogMetadata.tsx @@ -1,12 +1,24 @@ -import { MetaBase, MetaItem, MetaTimestamp } from '../Meta'; -import { DialogSeenBy, type DialogSeenByProps } from './DialogSeenBy'; -import { DialogStatus, type DialogStatusProps } from './DialogStatus'; +import { + type AvatarProps, + DialogSeenBy, + type DialogSeenByProps, + DialogStatus, + type DialogStatusProps, + DialogTouchedBy, + type DialogTouchedByProps, + MetaBase, + MetaItem, + MetaTimestamp, +} from '..'; export type DialogMetadataProps = { + className?: string; /** Metadata is loading */ loading?: boolean; /** Dialog status */ status?: DialogStatusProps; + /** Sender */ + sender?: AvatarProps; /** Updated datetime */ updatedAt?: string; /** Updated label */ @@ -25,8 +37,16 @@ export type DialogMetadataProps = { trashedAtLabel?: string; /** Who have seen the dialog after latest update */ seenBy?: DialogSeenByProps; + /** Who have seen the dialog after latest update */ + touchedBy?: DialogTouchedByProps; /** Number of attachments */ attachmentsCount?: number; + /** Attachments label */ + attachmentsLabel?: string; + /** Transmissions label */ + transmissionsLabel?: string; + /** Clickable items */ + onClick?: () => void; }; /** @@ -34,8 +54,10 @@ export type DialogMetadataProps = { */ export const DialogMetadata = ({ + className, loading, status, + sender, updatedAt, updatedAtLabel, dueAt, @@ -45,13 +67,18 @@ export const DialogMetadata = ({ archivedAt, archivedAtLabel, seenBy, + touchedBy, attachmentsCount = 0, + attachmentsLabel, + transmissionsLabel, + onClick, }: DialogMetadataProps) => { return ( - + {status && } {updatedAt && ( + {sender && sender.name + ', '} {updatedAtLabel} )} @@ -60,9 +87,14 @@ export const DialogMetadata = ({ {dueAtLabel} )} - {attachmentsCount > 0 && ( - - {attachmentsCount} + {(attachmentsLabel || attachmentsCount > 0) && ( + + {attachmentsLabel || attachmentsCount} + + )} + {transmissionsLabel && ( + + {transmissionsLabel} )} {(trashedAt && trashedAtLabel && ( @@ -76,6 +108,8 @@ export const DialogMetadata = ({ )) || (!loading && seenBy && )} + + {touchedBy && } ); }; diff --git a/lib/components/Dialog/DialogNav.stories.ts b/lib/components/Dialog/DialogNav.stories.ts deleted file mode 100644 index bcfa977c..00000000 --- a/lib/components/Dialog/DialogNav.stories.ts +++ /dev/null @@ -1,89 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { DialogNav } from './DialogNav'; - -const meta = { - title: 'Dialog/Sections/DialogNav', - component: DialogNav, - tags: ['autodocs'], - parameters: {}, - args: {}, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const Draft: Story = { - args: { - status: { - value: 'draft', - label: 'Utkast', - }, - }, -}; - -export const Sent: Story = { - args: { - status: { - value: 'draft', - label: 'Utkast', - }, - }, -}; - -export const RequiresAttention: Story = { - args: { - status: { - value: 'requires-attention', - label: 'Utkast', - }, - }, -}; - -export const InProgress: Story = { - args: { - status: { - value: 'in-progress', - label: 'Utkast', - }, - }, -}; - -export const ContextMenu: Story = { - args: { - menu: { - id: 'context-menu-1', - items: [ - { - id: '1', - groupId: '1', - icon: 'arrow-redo', - label: 'Del og gi tilgang', - }, - { - id: '2', - groupId: '1', - icon: 'eye-closed', - label: 'Marker som ny', - }, - { - id: '3', - groupId: '2', - icon: 'archive', - label: 'Flytt til arkiv', - }, - { - id: '4', - groupId: '2', - icon: 'trash', - label: 'Flytt til papirkurv', - }, - { - id: '5', - groupId: '3', - icon: 'clock-dashed', - label: 'Aktivitetslogg', - }, - ], - }, - }, -}; diff --git a/lib/components/Dialog/DialogNav.tsx b/lib/components/Dialog/DialogNav.tsx deleted file mode 100644 index c4e00754..00000000 --- a/lib/components/Dialog/DialogNav.tsx +++ /dev/null @@ -1,56 +0,0 @@ -'use client'; -import type { ElementType } from 'react'; -import { Button } from '../Button'; -import { ContextMenu, type ContextMenuProps } from '../ContextMenu'; -import { MetaTimestamp } from '../Meta'; -import { DialogStatus, type DialogStatusProps } from './DialogStatus'; -import { DialogTouchedBy, type DialogTouchedByActor } from './DialogTouchedBy'; -import styles from './dialogNav.module.css'; - -export interface DialogBackButtonProps { - as?: ElementType; - href?: string; - label?: string; -} - -export interface DialogNavProps { - status?: DialogStatusProps; - dueAt?: string; - dueAtLabel?: string; - touchedBy?: DialogTouchedByActor[]; - backButton?: DialogBackButtonProps; - menu?: ContextMenuProps; -} - -/** - * Dialog navigation bar with Back button and possibly a context menu. - */ -export const DialogNav = ({ - backButton = { - as: 'a', - label: 'Back', - }, - status, - dueAt, - dueAtLabel, - touchedBy, - menu, -}: DialogNavProps) => { - return ( - - ); -}; diff --git a/lib/components/Dialog/DialogSection.tsx b/lib/components/Dialog/DialogSection.tsx new file mode 100644 index 00000000..9e43a195 --- /dev/null +++ b/lib/components/Dialog/DialogSection.tsx @@ -0,0 +1,20 @@ +import type { ReactNode } from 'react'; +import { Heading, Section } from '..'; + +export interface DialogSectionProps { + title?: string; + children?: ReactNode; +} + +export const DialogSection = ({ title, children }: DialogSectionProps) => { + if (!children) { + return null; + } + + return ( +
+ {title && {title}} + {children} +
+ ); +}; diff --git a/lib/components/Dialog/DialogSectionBase.tsx b/lib/components/Dialog/DialogSectionBase.tsx deleted file mode 100644 index b8efdc99..00000000 --- a/lib/components/Dialog/DialogSectionBase.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import type { ReactNode } from 'react'; -import styles from './dialogSectionBase.module.css'; - -export interface DialogSectionBaseProps { - title?: string; - children?: ReactNode; -} - -export const DialogSectionBase = ({ title, children }: DialogSectionBaseProps) => { - if (!children) { - return null; - } - - return ( -
- {title &&

{title}

} - {children} -
- ); -}; diff --git a/lib/components/Dialog/DialogSeenBy.stories.tsx b/lib/components/Dialog/DialogSeenBy.stories.tsx index a37587e7..76c58f72 100644 --- a/lib/components/Dialog/DialogSeenBy.stories.tsx +++ b/lib/components/Dialog/DialogSeenBy.stories.tsx @@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { DialogSeenBy } from './DialogSeenBy'; const meta = { - title: 'Dialog/Sections/DialogSeenBy', + title: 'Dialog/DialogSeenBy', component: DialogSeenBy, tags: ['autodocs'], parameters: {}, diff --git a/lib/components/Dialog/DialogStatus.stories.ts b/lib/components/Dialog/DialogStatus.stories.ts index f0cce56c..05d0b80b 100644 --- a/lib/components/Dialog/DialogStatus.stories.ts +++ b/lib/components/Dialog/DialogStatus.stories.ts @@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { DialogStatus, DialogStatusEnum } from './DialogStatus'; const meta = { - title: 'Dialog/Sections/DialogStatus', + title: 'Dialog/DialogStatus', component: DialogStatus, tags: ['autodocs'], parameters: { diff --git a/lib/components/Dialog/DialogTimeline.tsx b/lib/components/Dialog/DialogTimeline.tsx new file mode 100644 index 00000000..9c43b622 --- /dev/null +++ b/lib/components/Dialog/DialogTimeline.tsx @@ -0,0 +1,19 @@ +'use client'; +import { Heading, TimelineBase } from '../'; +import { DialogTimelineItem, type DialogTimelineItemProps } from './DialogTimelineItem'; + +export interface DialogTimelineProps { + title?: string; + items?: DialogTimelineItemProps[]; +} + +export const DialogTimeline = ({ title, items = [] }: DialogTimelineProps) => { + return ( + + {title} + {items.map((item, index) => { + return ; + })} + + ); +}; diff --git a/lib/components/Dialog/DialogTimelineItem.tsx b/lib/components/Dialog/DialogTimelineItem.tsx new file mode 100644 index 00000000..2e43b36c --- /dev/null +++ b/lib/components/Dialog/DialogTimelineItem.tsx @@ -0,0 +1,28 @@ +'use client'; +import type { ReactNode } from 'react'; +import { ListBase, TimelineSection, TransmissionItem, type TransmissionItemProps, Typography } from '../'; + +export interface DialogTimelineItemProps { + updatedAt: string; + updatedAtLabel: string; + summary?: string; + items?: TransmissionItemProps[]; + children?: ReactNode; +} + +export const DialogTimelineItem = ({ updatedAt, updatedAtLabel, summary, items }: DialogTimelineItemProps) => { + return ( + + + {summary &&

{summary}

} + {items && ( + + {items.map((item, index) => ( + + ))} + + )} +
+
+ ); +}; diff --git a/lib/components/Dialog/DialogTouchedBy.stories.tsx b/lib/components/Dialog/DialogTouchedBy.stories.tsx index 6d71c341..1c201d23 100644 --- a/lib/components/Dialog/DialogTouchedBy.stories.tsx +++ b/lib/components/Dialog/DialogTouchedBy.stories.tsx @@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { DialogTouchedBy } from './DialogTouchedBy'; const meta = { - title: 'Dialog/Sections/DialogTouchedBy', + title: 'Dialog/DialogTouchedBy', component: DialogTouchedBy, tags: ['autodocs'], parameters: {}, diff --git a/lib/components/Transmission/TransmissionSection.stories.tsx b/lib/components/Dialog/DialogTransmissions.stories.tsx similarity index 96% rename from lib/components/Transmission/TransmissionSection.stories.tsx rename to lib/components/Dialog/DialogTransmissions.stories.tsx index 23d863f1..2a4d6d2c 100644 --- a/lib/components/Transmission/TransmissionSection.stories.tsx +++ b/lib/components/Dialog/DialogTransmissions.stories.tsx @@ -1,9 +1,9 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { TransmissionSection } from './TransmissionSection'; +import { DialogTransmissions } from './DialogTransmissions'; const meta = { - title: 'Transmission/TransmissionSection', - component: TransmissionSection, + title: 'Dialog/DialogTransmissions', + component: DialogTransmissions, tags: ['autodocs'], parameters: {}, args: { @@ -126,7 +126,7 @@ const meta = { }, ], }, -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/lib/components/Transmission/TransmissionSection.tsx b/lib/components/Dialog/DialogTransmissions.tsx similarity index 76% rename from lib/components/Transmission/TransmissionSection.tsx rename to lib/components/Dialog/DialogTransmissions.tsx index 8318a689..69390e7d 100644 --- a/lib/components/Transmission/TransmissionSection.tsx +++ b/lib/components/Dialog/DialogTransmissions.tsx @@ -2,13 +2,13 @@ import { Toolbar, type ToolbarProps } from '../Toolbar'; import { type TransmissionItemProps, TransmissionList } from '../Transmission'; import { Heading } from '../Typography'; -export interface TransmissionSectionProps { +export interface DialogTransmissionsProps { title?: string; items?: TransmissionItemProps[]; toolbar?: ToolbarProps; } -export const TransmissionSection = ({ title = 'Transmissions', items, toolbar }: TransmissionSectionProps) => { +export const DialogTransmissions = ({ title = 'Transmissions', items, toolbar }: DialogTransmissionsProps) => { if (!items?.length) { return null; } diff --git a/lib/components/Dialog/DraftDialog.stories.tsx b/lib/components/Dialog/DraftDialog.stories.tsx new file mode 100644 index 00000000..02049a8f --- /dev/null +++ b/lib/components/Dialog/DraftDialog.stories.tsx @@ -0,0 +1,160 @@ +import { withThemeByDataAttribute } from '@storybook/addon-themes'; +import type { Meta, StoryObj } from '@storybook/react'; +import { + dialogContextMenu, + extendedLetterDialog, + metadataDialog, + reportingCompletedDialog, + reportingDialog, + reportingDraftDialog, + reportingInProgressDialog, + simpleLetterDialog, + transmissionsCompletedDialog, + transmissionsDialog, + transmissionsInProgressDialog, +} from '../../examples'; +import { DraftDialog } from './DraftDialog'; + +const meta = { + title: 'Dialog/DraftDialog', + component: DraftDialog, + tags: ['autodocs'], + parameters: {}, + decorators: [ + withThemeByDataAttribute({ + themes: { + company: 'company', + person: 'person', + }, + defaultTheme: 'company', + }), + ], + argTypes: { body: { control: 'text' } }, + args: { + sender: { + type: 'company', + name: 'Skatteetaten', + imageUrl: + 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', + }, + recipientLabel: 'til', + recipient: { + type: 'person', + name: 'Roar Recipient', + }, + seenBy: { + as: 'a', + href: '#', + label: 'Sett av deg + 2', + seenByEndUser: true, + seenByOthersCount: 24, + }, + activityLog: { + as: 'a', + href: '#', + label: 'Aktivitetslogg', + }, + backButton: { + label: 'Tilbake', + }, + menu: dialogContextMenu, + updatedAt: '2024-11-25 15:30', + updatedAtLabel: '25. november 1999 kl 15.30', + title: 'Title', + summary: 'Summary', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const SimpleLetter: Story = { + args: simpleLetterDialog, +}; + +export const ExtendedLetter: Story = { + args: extendedLetterDialog, +}; + +export const TypographyMetadata: Story = { + args: metadataDialog, +}; + +export const ReportingRequired: Story = { + args: reportingDialog, +}; + +export const ReportingDraft: Story = { + args: reportingDraftDialog, +}; + +export const ReportingInProgress: Story = { + args: reportingInProgressDialog, +}; + +export const ReportingCompleted: Story = { + args: reportingCompletedDialog, +}; + +export const Transmissions: Story = { + args: transmissionsDialog, +}; + +export const TransmissionsInProgress: Story = { + args: transmissionsInProgressDialog, +}; + +export const TransmissionsCompleted: Story = { + args: transmissionsCompletedDialog, +}; + +export const Draft: Story = { + args: { + status: { value: 'draft', label: 'Utkast' }, + + sender: { + name: 'Statistisk sentralbyrå', + imageUrl: 'https://digdir-proto-proto.vercel.app/_next/static/media/SSB.0ca4474e.png', + }, + + recipient: { + name: 'Bergen Bar', + }, + + title: 'Registrere enkeltmannsforetak', + summary: 'Skjema er opprettet.', + + actions: [ + { + id: '1', + priority: 'primary', + label: 'Gå til skjema', + }, + { + id: '2', + priority: 'secondary', + label: 'Forkast', + }, + ], + + attachments: {}, + }, +}; + +export const Sent: Story = { + args: { + ...Draft.args, + status: { value: 'sent', label: 'Sendt' }, + actions: undefined, + summary: 'Skjema er sendt inn.', + attachments: { + title: '1 vedlegg', + items: [ + { + href: '#', + label: 'Kvittering på innsendt skjema.pdf', + }, + ], + }, + }, +}; diff --git a/lib/components/Dialog/DraftDialog.tsx b/lib/components/Dialog/DraftDialog.tsx new file mode 100644 index 00000000..73d687d0 --- /dev/null +++ b/lib/components/Dialog/DraftDialog.tsx @@ -0,0 +1,91 @@ +import type { ReactNode } from 'react'; +import { + Article, + Avatar, + Byline, + DialogActions, + DialogAttachments, + DialogByline, + DialogContent, + DialogHistory, + DialogMetadata, + type DialogProps, + DialogSection, + DialogTimeline, + Heading, + PageBase, + PageNav, + Section, + Typography, +} from '..'; + +/** + * Draft dialog variant, + */ + +export const DraftDialog = ({ + backButton, + menu, + updatedAt, + updatedAtLabel, + dueAt, + dueAtLabel, + status, + title, + sender, + recipient, + recipientLabel = 'to', + recipientGroup, + summary = 'Summary.', + body, + actions = [], + attachments, + seenBy, + activityLog, + history, + timeline, + additionalInfo, + contactInfo, +}: DialogProps) => { + return ( + + + + +
+
+
+ + {title} +
+ + {recipient?.name} + {recipientLabel + ' ' + sender?.name + ', '} + {updatedAtLabel} + +
+ +
+ +

{summary}

+ {body} + {attachments && } + {actions?.length > 0 && } +
+
+ + {additionalInfo && ( + + {additionalInfo?.children} + + )} + + {contactInfo && ( + + {contactInfo?.children} + + )} +
+
+ ); +}; diff --git a/lib/components/Dialog/dialogArticleBase.module.css b/lib/components/Dialog/dialogArticleBase.module.css deleted file mode 100644 index 7ab349ee..00000000 --- a/lib/components/Dialog/dialogArticleBase.module.css +++ /dev/null @@ -1,5 +0,0 @@ -.article { - display: flex; - flex-direction: column; - padding: 0 1.5rem; -} diff --git a/lib/components/Dialog/dialogBodyBase.module.css b/lib/components/Dialog/dialogBodyBase.module.css deleted file mode 100644 index 20b4b992..00000000 --- a/lib/components/Dialog/dialogBodyBase.module.css +++ /dev/null @@ -1,13 +0,0 @@ -.border { - padding-left: 1.5rem; - padding-top: 0; - margin-left: 1rem; - row-gap: 1.5rem; - margin-bottom: 1.5rem; -} - -.body { - display: flex; - flex-direction: column; - row-gap: 1.5em; -} diff --git a/lib/components/Dialog/dialogBorder.module.css b/lib/components/Dialog/dialogBorder.module.css index 66514eb2..9b4a8698 100644 --- a/lib/components/Dialog/dialogBorder.module.css +++ b/lib/components/Dialog/dialogBorder.module.css @@ -1,4 +1,5 @@ .border { + position: relative; border-left: 0.25rem solid; border-color: var(--theme-surface-active); diff --git a/lib/components/Dialog/dialogGroup.module.css b/lib/components/Dialog/dialogGroup.module.css deleted file mode 100644 index 6b853bb2..00000000 --- a/lib/components/Dialog/dialogGroup.module.css +++ /dev/null @@ -1,35 +0,0 @@ -.section { - display: flex; - flex-direction: column; - row-gap: 0.5rem; - margin: 0.5rem 0; -} - -.header { - display: flex; - justify-content: space-between; - margin: 0.5rem 0; -} - -.title { - font-size: 1.25rem; - font-weight: 500; - line-height: 1.5rem; - margin: 0.375rem 0; -} - -.title { - padding: 0 1rem; -} - -@media (min-width: 1024px) { - .title { - padding: 0; - } -} - -.list { - display: flex; - flex-direction: column; - row-gap: 0.5rem; -} diff --git a/lib/components/Dialog/dialogHeaderBase.module.css b/lib/components/Dialog/dialogHeaderBase.module.css deleted file mode 100644 index 39d72b19..00000000 --- a/lib/components/Dialog/dialogHeaderBase.module.css +++ /dev/null @@ -1,14 +0,0 @@ -.header { - display: flex; - flex-direction: column; -} - -.header[data-size="xl"] { - row-gap: 1.5em; - margin-bottom: 1.5rem; -} - -.header[data-size="md"], -.header[data-size="lg"] { - row-gap: 0.5rem; -} diff --git a/lib/components/Dialog/dialogTitle.module.css b/lib/components/Dialog/dialogHeading.module.css similarity index 80% rename from lib/components/Dialog/dialogTitle.module.css rename to lib/components/Dialog/dialogHeading.module.css index a75816cf..5d73dbdc 100644 --- a/lib/components/Dialog/dialogTitle.module.css +++ b/lib/components/Dialog/dialogHeading.module.css @@ -1,12 +1,23 @@ .heading { padding-right: 1.25rem; display: inline-flex; - column-gap: 0.5rem; + column-gap: 0.5em; } .title { + line-height: 1.25; font-weight: 600; margin: 0; +} + +.title[data-size="xs"], +.title[data-size="sm"] { + font-size: 1rem; +} + +.title[data-size="md"], +.title[data-size="lg"], +.title[data-size="xl"] { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; @@ -15,22 +26,17 @@ text-overflow: ellipsis; } -.title[data-size="xs"] { - font-size: 1rem; -} - -.title[data-size="sm"] { +.title[data-size="md"] { font-size: 1rem; } -.title[data-size="md"], .title[data-size="lg"] { - font-size: 1.25rem; + font-size: 1.125rem; line-height: 1.5rem; } .title[data-size="xl"] { - font-size: 1.5rem; + font-size: 1.25rem; line-height: 1.25; } diff --git a/lib/components/Dialog/dialogHeadings.module.css b/lib/components/Dialog/dialogHeadings.module.css deleted file mode 100644 index 9642e7f3..00000000 --- a/lib/components/Dialog/dialogHeadings.module.css +++ /dev/null @@ -1,37 +0,0 @@ -.headings { - display: inline-flex; - column-gap: 0.5em; - align-items: center; -} - -.headings[data-size="xs"], -.headings[data-size="sm"] { - font-size: 12px; -} - -.headings[data-size="md"], -.headings[data-size="lg"] { - font-size: 14px; -} - -.headings[data-size="xl"] { - font-size: 16px; -} - -.text { - display: inline-flex; - flex-wrap: wrap; - column-gap: 0.25em; - color: var(--neutral-text-subtle); -} - -.sender { - font-weight: 500; - color: var(--neutral-text-default); -} - -.recipient { - display: inline-flex; - column-gap: 0.25em; - white-space: nowrap; -} diff --git a/lib/components/Dialog/dialogListItem.module.css b/lib/components/Dialog/dialogListItem.module.css index fac687b1..196b6a42 100644 --- a/lib/components/Dialog/dialogListItem.module.css +++ b/lib/components/Dialog/dialogListItem.module.css @@ -1,7 +1,41 @@ -.item[data-size="lg"], -.item[data-size="md"] { +/*.item[data-size="md"] { + padding: 0.75em; +} + +.item[data-size="lg"] { + padding: 0.875em; +} + +.item[data-size="xl"] { padding: 1em; } +*/ + +.border[data-size="xs"], +.border[data-size="sm"] { + width: 100%; + flex-direction: row; + align-items: center; + padding-left: 0.75rem; +} + +.border[data-size="md"] { + margin: 0.25rem 0; + padding-left: 0.75rem; + row-gap: 0.5rem; +} + +.border[data-size="lg"] { + margin: 0.25rem 0; + padding-left: 0.875rem; + row-gap: 0.875rem; +} + +.border[data-size="xl"] { + margin: 0.25rem 0; + padding-left: 1rem; + row-gap: 1rem; +} .select { position: absolute; @@ -10,33 +44,48 @@ margin: 0.375rem; } +.header { + display: flex; + flex-direction: column; + row-gap: 0.25rem; +} + +.header[data-size="xs"], +.header[data-size="sm"] { + display: flex; + flex-direction: row; +} + .summary { font-size: 1rem; - line-height: 1.35; - margin: 0; font-weight: 400; -} - -.summary[data-size="lg"] { + line-height: 1.25; + color: var(--theme-text-subtle); display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; - margin-top: 0.5rem; + margin: 0; } +.summary[data-size="xs"], +.summary[data-size="sm"], .summary[data-size="md"] { - display: none; + font-size: 0.875rem; +} + +.summary[data-size="lg"] { + font-size: 1rem; +} + +.summary[data-size="xl"] { + font-size: 1rem; } .footer { width: 100%; - margin-top: 1rem; - display: flex; - flex-direction: column; - row-gap: 1rem; } .touchedBy { @@ -45,21 +94,3 @@ bottom: 0; margin: 8px; } - -/* sizes */ - -.border[data-size="lg"] { - padding-left: 1rem; -} - -.border[data-size="md"] { - padding-left: 1rem; -} - -.border[data-size="xs"], -.border[data-size="sm"] { - width: 100%; - flex-direction: row; - align-items: center; - padding-left: 0.75rem; -} diff --git a/lib/components/Dialog/dialogNav.module.css b/lib/components/Dialog/dialogNav.module.css deleted file mode 100644 index 984e41fe..00000000 --- a/lib/components/Dialog/dialogNav.module.css +++ /dev/null @@ -1,12 +0,0 @@ -.nav { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0.5rem; -} - -.action { - display: flex; - align-items: center; - column-gap: .5rem; -} diff --git a/lib/components/Dialog/dialogSectionBase.module.css b/lib/components/Dialog/dialogSectionBase.module.css deleted file mode 100644 index 34e4949b..00000000 --- a/lib/components/Dialog/dialogSectionBase.module.css +++ /dev/null @@ -1,11 +0,0 @@ -.section { - display: flex; - flex-direction: column; - margin-bottom: 1.5rem; -} - -.title { - font-size: 1.25rem; - font-weight: 600; - margin: 1em 0; -} diff --git a/lib/components/Dialog/index.ts b/lib/components/Dialog/index.ts index d180eda8..8b14e360 100644 --- a/lib/components/Dialog/index.ts +++ b/lib/components/Dialog/index.ts @@ -1,24 +1,28 @@ export * from './Dialog'; export * from './DialogList'; -export * from './DialogMetadata'; +export * from './DialogListGroup'; export * from './DialogListItem'; -export * from './DialogActions.tsx'; + +export * from './DialogMetadata'; +export * from './DialogByline'; + +export * from './DialogActions'; export * from './DialogActivityLog'; -export * from './DialogArticleBase'; -export * from './DialogBase'; -export * from './DialogBodyBase'; export * from './DialogBorder'; export * from './DialogContent'; -export * from './DialogFooter'; -export * from './DialogHeader'; -export * from './DialogHeaderBase'; -export * from './DialogHeadings'; -export * from './DialogHistory'; -export * from './DialogNav'; -export * from './DialogSectionBase'; +export * from './DialogSection'; export * from './DialogSeenBy'; export * from './DialogSelect'; export * from './DialogStatus'; -export * from './DialogTitle'; +export * from './DialogHeading'; export * from './DialogTouchedBy'; export * from './DialogLabel'; + +export * from './DialogAttachments'; +export * from './DialogTransmissions'; + +export * from './DialogTimeline'; +export * from './DialogTimelineItem'; + +export * from './DialogHistory'; +export * from './DialogHistoryItem'; diff --git a/lib/components/Dropdown/Backdrop.tsx b/lib/components/Dropdown/Backdrop.tsx index 6c836923..053112ce 100644 --- a/lib/components/Dropdown/Backdrop.tsx +++ b/lib/components/Dropdown/Backdrop.tsx @@ -2,11 +2,14 @@ import cx from 'classnames'; import type { MouseEventHandler } from 'react'; import styles from './backdrop.module.css'; +export type BackdropColor = 'transparent' | 'theme'; + export interface BackdropProps { className?: string; + color?: BackdropColor; onClick?: MouseEventHandler; } -export const Backdrop = ({ className, onClick }: BackdropProps) => { - return
; +export const Backdrop = ({ className, color, onClick }: BackdropProps) => { + return
; }; diff --git a/lib/components/Dropdown/backdrop.module.css b/lib/components/Dropdown/backdrop.module.css index 8392c899..6afc29d8 100644 --- a/lib/components/Dropdown/backdrop.module.css +++ b/lib/components/Dropdown/backdrop.module.css @@ -9,3 +9,7 @@ width: 100%; height: 100%; } + +.backdrop[data-color="transparent"] { + background-color: transparent; +} diff --git a/lib/components/Footer/Footer.stories.ts b/lib/components/Footer/Footer.stories.ts index 8847f3a8..af243db7 100644 --- a/lib/components/Footer/Footer.stories.ts +++ b/lib/components/Footer/Footer.stories.ts @@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Footer } from './Footer'; const meta = { - title: 'Footer/Footer', + title: 'Layout/Footer', component: Footer, tags: ['autodocs'], parameters: { diff --git a/lib/components/GlobalMenu/BackButton.tsx b/lib/components/GlobalMenu/BackButton.tsx index 3b40630e..f866990e 100644 --- a/lib/components/GlobalMenu/BackButton.tsx +++ b/lib/components/GlobalMenu/BackButton.tsx @@ -1,10 +1,12 @@ +import type { ElementType } from 'react'; import { MenuItem } from '../Menu'; export interface BackButtonProps { label: string; onClick?: () => void; + as?: ElementType; } -export const BackButton = ({ label, onClick }: BackButtonProps) => { - return ; +export const BackButton = ({ label, onClick, as }: BackButtonProps) => { + return ; }; diff --git a/lib/components/Header/Header.stories.tsx b/lib/components/Header/Header.stories.tsx index b6c8cf39..f7202586 100644 --- a/lib/components/Header/Header.stories.tsx +++ b/lib/components/Header/Header.stories.tsx @@ -3,7 +3,7 @@ import { header, useAccountMenu, useInboxSearch } from '../../examples'; import { Header } from './Header'; const meta = { - title: 'Header/Header', + title: 'Layout/Header', component: Header, tags: ['autodocs'], parameters: { diff --git a/lib/components/Header/HeaderButton.stories.ts b/lib/components/Header/HeaderButton.stories.ts index e61ae52e..4d6c6714 100644 --- a/lib/components/Header/HeaderButton.stories.ts +++ b/lib/components/Header/HeaderButton.stories.ts @@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { HeaderButton } from './HeaderButton'; const meta = { - title: 'Header/HeaderButton', + title: 'Layout/HeaderButton', component: HeaderButton, tags: ['autodocs'], parameters: { diff --git a/lib/components/Header/HeaderLogo.stories.ts b/lib/components/Header/HeaderLogo.stories.ts index 77a0bfb9..80c65d71 100644 --- a/lib/components/Header/HeaderLogo.stories.ts +++ b/lib/components/Header/HeaderLogo.stories.ts @@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { HeaderLogo } from './HeaderLogo'; const meta = { - title: 'Header/HeaderLogo', + title: 'Layout/HeaderLogo', component: HeaderLogo, tags: ['autodocs'], parameters: {}, diff --git a/lib/components/History/HistoryBorder.tsx b/lib/components/History/HistoryBorder.tsx deleted file mode 100644 index ef8daa74..00000000 --- a/lib/components/History/HistoryBorder.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import cx from 'classnames'; -import type { ReactNode } from 'react'; -import styles from './historyBorder.module.css'; - -export interface HistoryBorderProps { - seen?: boolean; - className?: string; - children?: ReactNode; -} - -export const HistoryBorder = ({ seen = true, className, children }: HistoryBorderProps) => { - return ( -
- {children} -
- ); -}; diff --git a/lib/components/History/HistoryItem.stories.ts b/lib/components/History/HistoryItem.stories.ts deleted file mode 100644 index c01c8ec5..00000000 --- a/lib/components/History/HistoryItem.stories.ts +++ /dev/null @@ -1,107 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { HistoryItem } from './HistoryItem'; - -const meta = { - title: 'History/HistoryItem', - component: HistoryItem, - tags: ['autodocs'], - parameters: {}, - args: { - createdAt: '2024-09-22 13:34', - createdAtLabel: '22. september 2024 kl 13.34', - createdBy: { - name: 'Eirik Horneland', - }, - summary: 'Brann slo Glimt 4-1 på Stadion.', - }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: {}, -}; - -export const Attachments: Story = { - args: { - attachments: { - title: '6 vedlegg', - items: [ - { - href: '#', - label: '1-0 Castro.pdf', - }, - { - href: '#', - label: '2-0 Kornvig.pdf', - }, - { - href: '#', - label: '3-0 Kartum.pdf', - }, - { - href: '#', - label: '3-1 Zinkernagel.pdf', - }, - { - href: '#', - label: '4-1 Castro.pdf', - }, - ], - }, - }, -}; - -export const Transmissions: Story = { - args: { - size: 'sm', - summary: 'Leveransen er godkjent', - transmissions: { - title: '2 forsendelser', - items: [ - { - sender: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - title: 'Leveransen er godkjent', - badge: { - label: 'Godkjent', - }, - attachments: { - title: '1 vedlegg', - items: [ - { - href: '#', - label: 'Godkjent leveranse.pdf', - }, - ], - }, - }, - { - title: 'Tredjepartsopplysninger ble levert', - sender: { - type: 'person', - name: 'Hassan El Fakiri', - }, - attachments: { - title: '2 vedlegg', - items: [ - { - href: '#', - label: '1-0 Castro.pdf', - }, - { - href: '#', - label: '2-0 Kornvig.pdf', - }, - ], - }, - }, - ], - }, - }, -}; diff --git a/lib/components/History/HistoryItem.tsx b/lib/components/History/HistoryItem.tsx deleted file mode 100644 index 42fdcec8..00000000 --- a/lib/components/History/HistoryItem.tsx +++ /dev/null @@ -1,54 +0,0 @@ -'use client'; -import { useState } from 'react'; -import { AttachmentSection, type AttachmentSectionProps } from '../Attachment'; -import type { AvatarProps } from '../Avatar/'; -import { TransmissionSection, type TransmissionSectionProps } from '../Transmission'; -import type { TypographySize } from '../Typography'; -import { HistoryItemBase } from './HistoryItemBase'; -import { HistoryMetadata } from './HistoryMetadata'; - -export interface HistoryItemProps { - size?: TypographySize; - createdBy?: AvatarProps; - createdAt: string; - createdAtLabel?: string; - summary?: string; - attachments?: AttachmentSectionProps; - transmissions?: TransmissionSectionProps; -} - -export const HistoryItem = ({ - createdBy, - createdAt, - createdAtLabel, - summary, - attachments, - transmissions, -}: HistoryItemProps) => { - const attachmentsLabel = attachments?.title; - const transmissionsLabel = transmissions?.title; - - const [expanded, setExpanded] = useState(false); - - const onExpand = () => { - setExpanded(true); - }; - - return ( - - {summary &&

{summary}

} - {expanded ? ( - <> - {attachments && } - {transmissions && } - - ) : ( - - )} -
- ); -}; diff --git a/lib/components/History/HistoryItemBase.stories.ts b/lib/components/History/HistoryItemBase.stories.ts deleted file mode 100644 index ff4f02ba..00000000 --- a/lib/components/History/HistoryItemBase.stories.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import { HistoryItemBase } from './HistoryItemBase'; - -const meta = { - title: 'History/HistoryItemBase', - component: HistoryItemBase, - tags: ['autodocs'], - parameters: {}, - args: { - createdAt: '2024-09-22 13:34', - createdAtLabel: '22. september 2024 kl 13.34', - children: 'Children', - }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: {}, -}; - -export const Person: Story = { - args: { - createdBy: { - type: 'person', - name: 'Eirik Horneland', - }, - }, -}; - -export const Company: Story = { - args: { - createdBy: { - type: 'company', - name: 'Bergen Bar', - }, - }, -}; - -export const Logo: Story = { - args: { - createdBy: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - }, -}; - -export const Icon: Story = { - args: { - icon: 'pencil-line', - }, -}; diff --git a/lib/components/History/HistoryItemBase.tsx b/lib/components/History/HistoryItemBase.tsx deleted file mode 100644 index 7e4158b6..00000000 --- a/lib/components/History/HistoryItemBase.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import type { ReactNode } from 'react'; -import type { AvatarProps } from '../Avatar/'; -import type { IconName } from '../Icon/'; -import { MetaTimestamp } from '../Meta/'; -import { Typography } from '../Typography'; -import { HistoryBorder } from './HistoryBorder'; -import { HistoryItemMedia } from './HistoryItemMedia'; -import styles from './historyItemBase.module.css'; - -export interface HistoryItemBaseProps { - loading?: boolean; - /** Keep ISO 8601 format for consistency */ - createdAt: string; - createdAtLabel?: string; - createdBy?: AvatarProps; - icon?: IconName; - children: ReactNode; -} - -export const HistoryItemBase = ({ - loading, - icon, - createdAt, - createdAtLabel, - createdBy, - children, -}: HistoryItemBaseProps) => { - return ( -
- -
- - {createdBy && {createdBy.name + ', '}} - {createdAtLabel} - - - {children} - -
-
- ); -}; diff --git a/lib/components/History/HistoryItemMedia.tsx b/lib/components/History/HistoryItemMedia.tsx deleted file mode 100644 index 3d0e6ae0..00000000 --- a/lib/components/History/HistoryItemMedia.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Avatar, type AvatarProps } from '../Avatar'; -import { Icon, type IconName } from '../Icon'; -import { Skeleton } from '../Skeleton'; -import styles from './historyItemMedia.module.css'; - -interface HistoryItemMediaProps { - loading?: boolean; - icon?: IconName; - avatar?: AvatarProps; -} - -export const HistoryItemMedia = ({ loading, icon, avatar }: HistoryItemMediaProps) => { - return ( -
- - {(icon && ) || - (avatar && ) ||
} - -
- ); -}; diff --git a/lib/components/History/HistoryList.stories.ts b/lib/components/History/HistoryList.stories.ts deleted file mode 100644 index 6bdce390..00000000 --- a/lib/components/History/HistoryList.stories.ts +++ /dev/null @@ -1,174 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { HistoryList } from './HistoryList'; - -const meta = { - title: 'History/HistoryList', - component: HistoryList, - tags: ['autodocs'], - parameters: {}, - args: { - items: [ - { - createdAt: '2004-02-15 08:00', - createdAtLabel: '15. februar 2024 kl 08.00', - createdBy: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - summary: 'Skjemaet er lukket for ordinær rapportering og korreksjoner.', - }, - { - createdAt: '2004-01-31 08:00', - createdAtLabel: '31. januar 2024 kl 08.00', - createdBy: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - summary: 'Skjemaet er lukket for ordinær rapportering. Du kan gjøre korreksjoner tom. 15. februar.', - }, - { - size: 'sm', - createdAt: '2024-01-17 15:12', - createdAtLabel: '17. januar 2024 kl 15.12', - summary: 'Tredjepartsopplysninger er godkjent.', - transmissions: { - title: '2 forsendelser', - items: [ - { - title: 'Forseendelse 1', - sender: { - type: 'person', - name: 'Eirik Horneland', - }, - }, - { - title: 'Svar på forsendelse 1', - sender: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - }, - ], - }, - }, - { - size: 'sm', - createdAt: '2024-01-04 12:15', - createdAtLabel: '4. januar 2024 kl 12.15', - summary: 'Tredjepartsopplysninger ble levert.', - transmissions: { - title: '1 forsendelse', - items: [ - { - title: 'Forseendelse 1', - sender: { - type: 'person', - name: 'Eirik Horneland', - }, - }, - ], - }, - }, - { - createdAt: '2004-01-02 08:00', - createdAtLabel: '2. januar 2024 kl 08.00', - createdBy: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - summary: 'Skjemaet er åpent. Du kan nå levere tredjepartsopplysninger.', - }, - { - createdAt: '2003-10-15 08:00', - createdAtLabel: '15. oktober 2023 kl 08.00', - createdBy: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - summary: 'Du må levere tredjepartsopplysninger for boligselskap.', - attachments: { - title: '1 vedlegg', - items: [ - { - href: '#', - label: 'Rapportering av tredjepartsopplysninger for boligselskap.pdf', - }, - ], - }, - }, - ], - }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: {}, -}; - -export const ActivityLog: Story = { - args: { - items: [ - { - createdAt: '2004-01-02 08:00', - createdAtLabel: '2. januar 2024 kl 08.00', - summary: 'Dialogen ble flyttet til papirkurven.', - }, - { - createdAt: '2003-10-15 08:00', - createdAtLabel: '15. oktober 2023 kl 08.00', - createdBy: { - type: 'company', - name: 'Skatteetaten', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - summary: 'Du må levere tredjepartsopplysninger for boligselskap.', - attachments: { - title: '1 vedlegg', - items: [ - { - href: '#', - label: 'Rapportering av tredjepartsopplysninger for boligselskap.pdf', - }, - ], - }, - }, - { - size: 'xs', - createdAt: '2004-01-02 08:00', - createdAtLabel: '2. januar 2024 kl 08.00', - summary: 'Utkast lagret.', - }, - { - size: 'xs', - createdAt: '2004-01-02 08:00', - createdAtLabel: '2. januar 2024 kl 08.00', - summary: 'Skjema opprettet.', - }, - { - size: 'xs', - createdAt: '2004-01-02 08:00', - createdAtLabel: '2. januar 2024 kl 08.00', - summary: 'Dialogen ble flyttet til arkivet.', - }, - { - size: 'xs', - createdAt: '2004-01-02 08:00', - createdAtLabel: '2. januar 2024 kl 08.00', - summary: 'Dialogen ble opprettet.', - }, - ], - }, -}; diff --git a/lib/components/History/HistoryList.tsx b/lib/components/History/HistoryList.tsx deleted file mode 100644 index 068ddcd5..00000000 --- a/lib/components/History/HistoryList.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import cx from 'classnames'; -import { HistoryItem, type HistoryItemProps } from './HistoryItem'; -import styles from './historyList.module.css'; - -export interface HistoryProps { - items: HistoryItemProps[]; - className?: string; -} - -export const HistoryList = ({ items, className }: HistoryProps) => { - if (!items.length) { - return null; - } - - return ( -
    - {items.map((item, index) => { - return ( -
  • - -
  • - ); - })} -
- ); -}; diff --git a/lib/components/History/HistoryMetadata.tsx b/lib/components/History/HistoryMetadata.tsx deleted file mode 100644 index be9a447a..00000000 --- a/lib/components/History/HistoryMetadata.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { MetaBase, MetaItem } from '../Meta'; - -export type HistoryMetadataProps = { - /** Metadata is loading */ - loading?: boolean; - transmissionsLabel?: string; - attachmentsLabel?: string; - onClick: () => void; -}; - -/** - * Metadata for a history items. - */ - -export const HistoryMetadata = ({ loading, transmissionsLabel, attachmentsLabel, onClick }: HistoryMetadataProps) => { - if (!transmissionsLabel && !attachmentsLabel) { - return null; - } - - return ( - - {attachmentsLabel && ( - - {attachmentsLabel} - - )} - {transmissionsLabel && ( - - {transmissionsLabel} - - )} - - ); -}; diff --git a/lib/components/History/historyBorder.module.css b/lib/components/History/historyBorder.module.css deleted file mode 100644 index c621b686..00000000 --- a/lib/components/History/historyBorder.module.css +++ /dev/null @@ -1,8 +0,0 @@ -.border { - border-left: 0.25rem solid; - border-color: var(--theme-surface-active); -} - -.border[data-seen="true"] { - border-color: var(--neutral-surface-default); -} diff --git a/lib/components/History/historyItem.module.css b/lib/components/History/historyItem.module.css deleted file mode 100644 index bcdc6f91..00000000 --- a/lib/components/History/historyItem.module.css +++ /dev/null @@ -1,19 +0,0 @@ -.item { - display: flex; - flex-direction: column; -} - -.header { - margin: 0.375em; -} - -.border { - padding-left: 1.5rem; - padding-top: 0; - margin-left: 1rem; - padding-bottom: 1.5rem; -} - -.body { - margin-top: -1.875rem; -} diff --git a/lib/components/History/historyItemBase.module.css b/lib/components/History/historyItemBase.module.css deleted file mode 100644 index 2da9eff4..00000000 --- a/lib/components/History/historyItemBase.module.css +++ /dev/null @@ -1,26 +0,0 @@ -.item { - display: flex; -} - -.sidebar { - flex-shrink: 0; - display: flex; - flex-direction: column; -} - -.border { - flex-grow: 1; - padding-left: 1.5rem; - padding-top: 0; - margin-left: 1rem; - padding-bottom: 1.5rem; -} - -.content { - flex-grow: 1; - padding: 0.375rem 0; -} - -.body { - margin: 0; -} diff --git a/lib/components/History/historyItemMedia.module.css b/lib/components/History/historyItemMedia.module.css deleted file mode 100644 index 1cc76360..00000000 --- a/lib/components/History/historyItemMedia.module.css +++ /dev/null @@ -1,21 +0,0 @@ -/* media */ - -.media { - flex-shrink: 0; - width: 2.25rem; - height: 2.25rem; - display: inline-flex; - align-items: center; - justify-content: center; -} - -.icon { - font-size: 1.5rem; -} - -.dot { - background-color: var(--theme-surface-active); - width: .875rem; - height: .875rem; - border-radius: 50%; -} diff --git a/lib/components/History/index.ts b/lib/components/History/index.ts deleted file mode 100644 index 9103f79f..00000000 --- a/lib/components/History/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './HistoryList'; -export * from './HistoryItem'; -export * from './HistoryItemBase'; diff --git a/lib/components/List/ListItem.stories.tsx b/lib/components/List/ListItem.stories.tsx index d881e9cf..ef2fe296 100644 --- a/lib/components/List/ListItem.stories.tsx +++ b/lib/components/List/ListItem.stories.tsx @@ -3,7 +3,7 @@ import { Fragment, useState } from 'react'; import { Button, List, ListBase, ListItem, ListItemBase, ListItemHeader, MetaItem } from '../'; -const sizes = ['lg', 'md', 'sm', 'xs']; +const sizes = ['xl', 'lg', 'md', 'sm', 'xs']; const meta = { title: 'List/ListItem', diff --git a/lib/components/List/ListItem.tsx b/lib/components/List/ListItem.tsx index f2d88606..dcea316f 100644 --- a/lib/components/List/ListItem.tsx +++ b/lib/components/List/ListItem.tsx @@ -3,10 +3,10 @@ import type { AvatarGroupProps, AvatarProps } from '../Avatar'; import type { BadgeProps } from '../Badge'; import type { ContextMenuProps } from '../ContextMenu'; import type { IconName } from '../Icon'; -import { ListItemBase } from './ListItemBase'; +import { ListItemBase, type ListItemBaseProps } from './ListItemBase'; import { ListItemHeader, type ListItemHeaderProps } from './ListItemHeader'; -export interface ListItemProps extends ListItemHeaderProps { +export interface ListItemProps extends ListItemBaseProps, ListItemHeaderProps { /** Custom className */ className?: string; /** Element is loading, display a placeholder */ diff --git a/lib/components/List/ListItemBase.tsx b/lib/components/List/ListItemBase.tsx index e9d531b1..b929b72b 100644 --- a/lib/components/List/ListItemBase.tsx +++ b/lib/components/List/ListItemBase.tsx @@ -2,11 +2,13 @@ import type { ReactNode } from 'react'; import styles from './listItemBase.module.css'; export type ListItemSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; -export type ListItemColor = 'default' | 'accent' | 'transparent'; +export type ListItemVariant = 'solid' | 'dotted'; +export type ListItemColor = 'subtle' | 'accent' | 'transparent'; export type ListItemShadow = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; export interface ListItemBaseProps { color?: ListItemColor; + variant?: ListItemVariant; size?: ListItemSize; shadow?: ListItemShadow; className?: string; @@ -16,13 +18,13 @@ export interface ListItemBaseProps { active?: boolean; selected?: boolean; expanded?: boolean; - controls?: ReactNode; children?: ReactNode; } export const ListItemBase = ({ size, - color = 'default', + variant = 'solid', + color = 'subtle', shadow = 'xs', loading, disabled, @@ -35,6 +37,7 @@ export const ListItemBase = ({ return (
{/** Render a separator if this is a new group or a new level */} - - {(level ?? groupIndex) > 0 && divider ? : ''} + {(level > 0 || groupIndex) && divider ? : ''} {title && ( diff --git a/lib/components/Meta/MetaBase.tsx b/lib/components/Meta/MetaBase.tsx index d5bee2a7..17c8f03e 100644 --- a/lib/components/Meta/MetaBase.tsx +++ b/lib/components/Meta/MetaBase.tsx @@ -1,15 +1,17 @@ +import cx from 'classnames'; import type { ReactNode } from 'react'; import type { MetaItemSize } from './MetaItemBase'; -import styles from './meta.module.css'; +import styles from './metaBase.module.css'; export interface MetaBaseProps { size?: MetaItemSize; + className?: string; children?: ReactNode; } -export const MetaBase = ({ size = 'xs', children }: MetaBaseProps) => { +export const MetaBase = ({ size = 'xs', className, children }: MetaBaseProps) => { return ( -
+
{children} -
+ ); }; diff --git a/lib/components/Meta/MetaItem.tsx b/lib/components/Meta/MetaItem.tsx index a7bae991..90ad1691 100644 --- a/lib/components/Meta/MetaItem.tsx +++ b/lib/components/Meta/MetaItem.tsx @@ -7,6 +7,7 @@ import { MetaItemMedia } from './MetaItemMedia'; export interface MetaItemProps { loading?: boolean; + reverse?: boolean; /** Render as element */ as?: ElementType; /** Meta size */ @@ -23,9 +24,17 @@ export interface MetaItemProps { onClick?: () => void; } -export const MetaItem = ({ loading, size = 'xs', variant = 'text', icon, children, ...rest }: MetaItemProps) => { +export const MetaItem = ({ + loading, + reverse, + size = 'xs', + variant = 'text', + icon, + children, + ...rest +}: MetaItemProps) => { return ( - + {!loading && icon && } diff --git a/lib/components/Meta/MetaItemBase.tsx b/lib/components/Meta/MetaItemBase.tsx index 405869f7..6c8e595a 100644 --- a/lib/components/Meta/MetaItemBase.tsx +++ b/lib/components/Meta/MetaItemBase.tsx @@ -8,6 +8,7 @@ export type MetaItemColor = 'subtle'; export interface MetaItemBaseProps { as?: ElementType; + reverse?: boolean; variant?: MetaItemVariant; size?: MetaItemSize; color?: MetaItemColor; @@ -19,6 +20,7 @@ export interface MetaItemBaseProps { export const MetaItemBase = ({ as, + reverse, variant = 'text', size, color, @@ -37,7 +39,7 @@ export const MetaItemBase = ({ data-variant={variant} data-progress={progress} dateTime={datetime} - className={cx(styles.item, className)} + className={cx(styles.item, { [styles.reverse]: reverse }, className)} {...rest} > {children} diff --git a/lib/components/Meta/meta.module.css b/lib/components/Meta/metaBase.module.css similarity index 75% rename from lib/components/Meta/meta.module.css rename to lib/components/Meta/metaBase.module.css index e536a4aa..81083da3 100644 --- a/lib/components/Meta/meta.module.css +++ b/lib/components/Meta/metaBase.module.css @@ -1,5 +1,5 @@ .meta { - display: inline-flex; + display: flex; align-items: center; flex-wrap: wrap; column-gap: 0.5rem; diff --git a/lib/components/Meta/metaItemBase.module.css b/lib/components/Meta/metaItemBase.module.css index 0e0fbd10..722e86a0 100644 --- a/lib/components/Meta/metaItemBase.module.css +++ b/lib/components/Meta/metaItemBase.module.css @@ -16,7 +16,7 @@ .item { border: 1px; border-radius: 2px; - color: var(--neutral-text-subtle); + color: var(--theme-text-subtle); display: inline-flex; align-items: center; column-gap: 0.25em; @@ -24,13 +24,19 @@ text-decoration: none; } +.reverse { + flex-direction: row-reverse; +} + .item strong { font-weight: 500; - color: var(--neutral-text-default); + color: var(--theme-text-default); } button.item:hover, -a.item:hover { +a.item:hover, +button.item:hover strong, +a.item:hover strong { color: var(--theme-base-hover); cursor: pointer; } diff --git a/lib/components/Meta/metaItemLabel.module.css b/lib/components/Meta/metaItemLabel.module.css index 148dcbcc..d2977084 100644 --- a/lib/components/Meta/metaItemLabel.module.css +++ b/lib/components/Meta/metaItemLabel.module.css @@ -19,7 +19,7 @@ .label[data-variant="outline"], .label[data-variant="dotted"], .label[data-variant="solid"] { - font-size: 0.875em; + font-size: 0.75rem; font-weight: 500; padding: 0 0.25em; } diff --git a/lib/components/Page/Article.tsx b/lib/components/Page/Article.tsx new file mode 100644 index 00000000..471e50d5 --- /dev/null +++ b/lib/components/Page/Article.tsx @@ -0,0 +1,14 @@ +import type { ReactNode } from 'react'; +import { Section, type SectionProps } from './Section'; + +export interface ArticleProps extends SectionProps { + children?: ReactNode; +} + +export const Article = ({ theme = 'article', children, ...props }: ArticleProps) => { + return ( +
+ {children} +
+ ); +}; diff --git a/lib/components/Page/PageBase.stories.tsx b/lib/components/Page/PageBase.stories.tsx new file mode 100644 index 00000000..0c470196 --- /dev/null +++ b/lib/components/Page/PageBase.stories.tsx @@ -0,0 +1,84 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { Article, Button, Byline, Heading, PageBase, PageHeader, PageNav, Section, Typography } from '..'; +import { nav, skatt } from '../../examples/avatar'; + +const meta = { + title: 'Page/PageBase', + component: PageBase, + tags: ['autodocs'], + parameters: {}, + args: {}, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const DialogPage = () => { + return ( + + +
+ + +

Some text

+
+
+
+
+ ); +}; + +export const ProfilePage = () => { + return ( + +
+ + + Tabs? + +
+
+ +

Lorem ipsum dolor sit amet

+
+
+
+ ); +}; + +export const ArticlePage = ({ args }) => { + return ( + + +
+ + Når du har unger som ikke gjør som du sier kan du bruke dette skjemaet. + + NAV, 14. oktober 2024 + +
+ +
+
+ +
+ +

+ Barneoppdragelse i hjemmet handler om å skape en balanse mellom kjærlighet, grenser og respekt. Det er + viktig å vise barna ubetinget kjærlighet og støtte, samtidig som man setter tydelige og konsistente + grenser som hjelper dem å forstå hva som er akseptabel oppførsel. +

+

Nøkkelen

+

+ Kommunikasjon er nøkkelen: lytte til barnas tanker og følelser, og gi dem mulighet til å uttrykke seg, + samtidig som man forklarer hvorfor regler og forventninger finnes. Positiv forsterkning, som ros og + anerkjennelse av gode handlinger, fremmer ønsket adferd, mens konstruktiv veiledning bør erstatte streng + straff. Ved å være en god rollemodell og skape et trygt, strukturert og kjærlig miljø, gir man barna de + beste forutsetninger for å utvikle seg til trygge, ansvarlige og empatiske individer. +

+
+
+
+
+ ); +}; diff --git a/lib/components/Page/PageBase.tsx b/lib/components/Page/PageBase.tsx index 9c167243..59cc3601 100644 --- a/lib/components/Page/PageBase.tsx +++ b/lib/components/Page/PageBase.tsx @@ -1,14 +1,14 @@ import type { ReactNode } from 'react'; -import { SectionBase, type SectionBaseProps } from './SectionBase'; +import { Section, type SectionProps } from './Section'; -export interface PageBaseProps extends SectionBaseProps { +export interface PageBaseProps extends SectionProps { children?: ReactNode; } export const PageBase = ({ children, ...props }: PageBaseProps) => { return ( - +
{children} - +
); }; diff --git a/lib/components/Page/PageHeader.stories.tsx b/lib/components/Page/PageHeader.stories.tsx new file mode 100644 index 00000000..e010820a --- /dev/null +++ b/lib/components/Page/PageHeader.stories.tsx @@ -0,0 +1,100 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { PageHeader } from './PageHeader'; + +const meta = { + title: 'Page/PageHeader', + component: PageHeader, + tags: ['autodocs'], + parameters: {}, + args: { + title: 'Page title', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: {}, +}; + +export const Company: Story = { + args: { + avatar: { + type: 'company', + name: 'Zero Zulu', + }, + title: 'Zero Zulu', + }, +}; + +export const Person: Story = { + args: { + avatar: { + name: 'Zero Zulu', + }, + title: 'Zero Zulu', + }, +}; + +export const Icon: Story = { + args: { + icon: 'teddy-bear', + title: 'Zero Zulu', + }, +}; + +export const People: Story = { + args: { + avatarGroup: { + defaultType: 'person', + items: [ + { + name: 'Albert Åberg', + }, + { + name: 'Birger Meling', + }, + { + name: 'Celine Dion', + }, + ], + }, + }, +}; + +export const Companies: Story = { + args: { + avatarGroup: { + defaultType: 'company', + items: [ + { + name: 'Albert Åberg', + }, + { + name: 'Birger Meling', + }, + { + name: 'Celine Dion', + }, + ], + }, + }, +}; + +export const CompanyAndPerson: Story = { + args: { + avatarGroup: { + items: [ + { + type: 'company', + name: 'Albert Åberg', + }, + { + type: 'person', + name: 'Birger Meling', + }, + ], + }, + }, +}; diff --git a/lib/components/Page/PageHeader.tsx b/lib/components/Page/PageHeader.tsx index 0d4263f3..492c0549 100644 --- a/lib/components/Page/PageHeader.tsx +++ b/lib/components/Page/PageHeader.tsx @@ -1,25 +1,29 @@ -import { Heading } from '../'; -import { PageHeaderMedia, type PageHeaderMediaProps } from './PageHeaderMedia'; -import { PageNav } from './PageNav'; -import { SectionBase, type SectionBaseProps } from './SectionBase'; -import styles from './pageHeader.module.css'; +import { + type AvatarGroupProps, + type AvatarProps, + Heading, + type IconName, + ListItemMedia, + Section, + type SectionProps, +} from '..'; -export interface PageHeaderProps extends SectionBaseProps, PageHeaderMediaProps { +export interface PageHeaderProps extends SectionProps { title?: string; description?: string; + icon?: IconName; + avatar?: AvatarProps; + avatarGroup?: AvatarGroupProps; } -export const PageHeader = ({ title, description, icon, avatar, avatarGroup, children, ...props }: PageHeaderProps) => { +export const PageHeader = ({ title, icon, avatar, avatarGroup, children, ...rest }: PageHeaderProps) => { return ( - - -
- -
- {title} -
{description}
-
-
-
+
+
+ + {title} +
+ {children} +
); }; diff --git a/lib/components/Page/PageHeaderMedia.tsx b/lib/components/Page/PageHeaderMedia.tsx deleted file mode 100644 index 5f4f227e..00000000 --- a/lib/components/Page/PageHeaderMedia.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import type { ReactNode } from 'react'; -import { Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps } from '../Avatar'; -import { Icon, type IconName } from '../Icon'; -import styles from './pageHeader.module.css'; - -export interface PageHeaderMediaProps { - icon?: IconName; - avatar?: AvatarProps; - avatarGroup?: AvatarGroupProps; - children?: ReactNode; -} - -export const PageHeaderMedia = ({ icon, avatar, avatarGroup }: PageHeaderMediaProps) => { - if (!icon && !avatar && !avatarGroup) { - return false; - } - - return ( -
- {(icon && ) || - (avatar && ) || - (avatarGroup && )} -
- ); -}; diff --git a/lib/components/Page/PageNav.stories.tsx b/lib/components/Page/PageNav.stories.tsx new file mode 100644 index 00000000..bd3f7677 --- /dev/null +++ b/lib/components/Page/PageNav.stories.tsx @@ -0,0 +1,35 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { dialogContextMenu } from '../../examples'; +import { PageNav } from './PageNav'; + +const meta = { + title: 'Page/PageNav', + component: PageNav, + tags: ['autodocs'], + parameters: {}, + args: { + backButton: { + label: 'Tilbake', + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const BackButton: Story = { + args: { + backButton: { + label: 'Tilbake', + }, + }, +}; + +export const BackAndContextMenu: Story = { + args: { + backButton: { + label: 'Tilbake', + }, + menu: dialogContextMenu, + }, +}; diff --git a/lib/components/Page/PageNav.tsx b/lib/components/Page/PageNav.tsx index ef73d5a0..6863eb3e 100644 --- a/lib/components/Page/PageNav.tsx +++ b/lib/components/Page/PageNav.tsx @@ -1,34 +1,37 @@ -import type { ElementType, ReactNode } from 'react'; -import { Button } from '../Button'; +import type { ReactNode } from 'react'; +import { type BackButtonProps, Button, ContextMenu, type ContextMenuProps, Section, type SectionProps } from '../'; import styles from './pageNav.module.css'; -export interface PageBackButtonProps { - as?: ElementType; - href?: string; - label?: string; -} +export type PageNavPadding = 'none' | 'sm'; -export interface PageNavProps { - backButton?: PageBackButtonProps; +export interface PageNavProps extends SectionProps { + padding?: PageNavPadding; + backButton?: BackButtonProps; + menu?: ContextMenuProps; children?: ReactNode; } /** - * Page navigation bar with back button or breadcrumbs. + * Page navigation bar with Back button and controls. */ export const PageNav = ({ + padding = 'none', backButton = { as: 'a', label: 'Back', }, + menu, children, }: PageNavProps) => { return ( - +
+ {children} + {menu && } +
+ ); }; diff --git a/lib/components/Page/Section.tsx b/lib/components/Page/Section.tsx new file mode 100644 index 00000000..b1fafdb2 --- /dev/null +++ b/lib/components/Page/Section.tsx @@ -0,0 +1,72 @@ +import cx from 'classnames'; +import type { CSSProperties, ReactNode } from 'react'; +import styles from './section.module.css'; + +export type SectionTheme = 'inherit' | 'global' | 'neutral' | 'article'; +export type SectionColor = 'transparent' | 'subtle' | 'surface' | 'accent'; +export type SectionElement = 'section' | 'article' | 'header' | 'footer' | 'div'; +export type SectionSpacing = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; +export type SectionPadding = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; +export type SectionMargin = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; +export type SectionShadow = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; +export type SectionFlex = 'col' | 'row'; +export type SectionAlign = 'initial' | 'start' | 'end' | 'center' | 'stretch'; +export type SectionJustify = 'initial' | 'start' | 'end' | 'center' | 'between'; + +export interface SectionProps { + as?: SectionElement; + theme?: SectionTheme; + color?: SectionColor; + flex?: SectionFlex; + align?: SectionAlign; + justify?: SectionJustify; + reverse?: boolean; + padding?: SectionPadding; + spacing?: SectionSpacing; + margin?: SectionMargin; + shadow?: SectionShadow; + inset?: boolean; + children?: ReactNode; + className?: string; + style?: CSSProperties; +} + +export const Section = ({ + as = 'section', + theme = 'inherit', + color = 'transparent', + flex = 'col', + reverse = false, + align = 'initial', + justify = 'initial', + padding = 'none', + spacing = 'none', + margin = 'none', + shadow = 'none', + inset = false, + className, + style, + children, +}: SectionProps) => { + const Component = as; + + return ( + + {children} + + ); +}; diff --git a/lib/components/Page/SectionBase.tsx b/lib/components/Page/SectionBase.tsx deleted file mode 100644 index ccd9bfda..00000000 --- a/lib/components/Page/SectionBase.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import cx from 'classnames'; -import type { CSSProperties, ReactNode } from 'react'; -import styles from './sectionBase.module.css'; - -export type SectionElement = 'section' | 'main' | 'header' | 'footer' | 'div'; -export type SectionColor = 'transparent' | 'white' | 'subtle' | 'accent'; -export type SectionSpacing = 'none' | 'sm' | 'md' | 'lg'; -export type SectionMargin = 'none' | 'sm' | 'md' | 'lg'; -export type SectionShadow = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; - -export interface SectionBaseProps { - as?: SectionElement; - color?: SectionColor; - padding?: boolean; - spacing?: SectionSpacing; - margin?: SectionMargin; - shadow?: SectionShadow; - inset?: boolean; - children?: ReactNode; - className?: string; - style?: CSSProperties; -} - -export const SectionBase = ({ - as = 'section', - color = 'transparent', - padding = false, - spacing = 'none', - margin = 'none', - shadow = 'none', - inset = false, - className, - style, - children, -}: SectionBaseProps) => { - const Component = as; - - return ( - - {children} - - ); -}; diff --git a/lib/components/Page/SectionHeader.tsx b/lib/components/Page/SectionHeader.tsx index 1fa880c3..89fd86c3 100644 --- a/lib/components/Page/SectionHeader.tsx +++ b/lib/components/Page/SectionHeader.tsx @@ -1,16 +1,20 @@ import type { ReactNode } from 'react'; -import styles from './sectionHeader.module.css'; +import { Section, type SectionProps } from './Section'; -export interface SectionHeaderProps { - padding?: boolean; - margin?: boolean; +export interface SectionHeaderProps extends SectionProps { children?: ReactNode; } -export const SectionHeader = ({ margin = false, children }: SectionHeaderProps) => { +export const SectionHeader = ({ + flex = 'row', + align = 'center', + justify = 'between', + children, + ...rest +}: SectionHeaderProps) => { return ( -
+
{children} -
+ ); }; diff --git a/lib/components/Page/index.ts b/lib/components/Page/index.ts index 01c59629..06f3055d 100644 --- a/lib/components/Page/index.ts +++ b/lib/components/Page/index.ts @@ -1,5 +1,9 @@ export * from './PageBase'; +export * from './PageNav'; export * from './PageHeader'; -export * from './SectionBase'; + export * from './SectionHeader'; export * from './SectionFooter'; + +export * from './Article'; +export * from './Section'; diff --git a/lib/components/Page/pageNav.module.css b/lib/components/Page/pageNav.module.css index 984e41fe..8948a31c 100644 --- a/lib/components/Page/pageNav.module.css +++ b/lib/components/Page/pageNav.module.css @@ -2,10 +2,9 @@ display: flex; align-items: center; justify-content: space-between; - padding: 0.5rem; } -.action { +.controls { display: flex; align-items: center; column-gap: .5rem; diff --git a/lib/components/Page/sectionBase.module.css b/lib/components/Page/section.module.css similarity index 51% rename from lib/components/Page/sectionBase.module.css rename to lib/components/Page/section.module.css index 461503d0..45cbc700 100644 --- a/lib/components/Page/sectionBase.module.css +++ b/lib/components/Page/section.module.css @@ -1,8 +1,43 @@ .section { display: flex; +} + +.section[data-flex="col"] { flex-direction: column; } +.section[data-flex="row"] { + flex-direction: row; +} + +.section[data-align="center"] { + align-items: center; +} + +.section[data-align="start"] { + align-items: flex-start; +} + +.section[data-align="end"] { + align-items: flex-end; +} + +.section[data-justify="start"] { + justify-content: flex-start; +} + +.section[data-justify="end"] { + justify-content: flex-end; +} + +.section[data-justify="center"] { + justify-content: center; +} + +.section[data-justify="between"] { + justify-content: space-between; +} + /* inset on small screens */ @media (max-width: 1024px) { @@ -12,57 +47,85 @@ } } +/* padding */ + +.section[data-padding="xs"] { + padding: 0.25rem; +} + +.section[data-padding="sm"] { + padding: 0.5rem; +} + +.section[data-padding="md"] { + padding: 0.75rem; +} + +.section[data-padding="lg"] { + padding: 1rem; +} + +.section[data-padding="xl"] { + padding: 1.5rem; +} + +@media (max-width: 1024px) { + .section[data-padding="xl"] { + padding: 1.5rem 1rem; + } +} + /* spacing */ +.section[data-spacing="xs"] { + gap: 0.25rem; +} + .section[data-spacing="sm"] { - row-gap: 0.25rem; + gap: 0.5rem; } .section[data-spacing="md"] { - row-gap: 0.5rem; + gap: 0.75rem; } .section[data-spacing="lg"] { - row-gap: 1rem; + gap: 1rem; } .section[data-spacing="xl"] { - row-gap: 1.5rem; + gap: 1.5rem; } /* margin */ -.section[data-margin="sm"] { +.section[data-margin="xs"] { margin: 0.25rem 0; } -.section[data-margin="md"] { +.section[data-margin="sm"] { margin: 0.5rem 0; } -.section[data-margin="lg"] { - margin: 1rem 0; +.section[data-margin="md"] { + margin: 0.75rem 0; } -/* padding */ - -.section[data-padding="true"] { - padding: 1.5rem; +.section[data-margin="lg"] { + margin: 1rem 0; } -@media (max-width: 1024px) { - .section[data-padding="true"] { - padding: 1.5rem 1rem; - } +.section[data-margin="lg"] { + margin: 1.5rem 0; } /* color */ -.section[data-color="white"] { - background-color: #fff; +.section[data-color="subtle"] { + background-color: var(--theme-background-default); } -.section[data-color="subtle"] { +.section[data-color="surface"] { background-color: var(--theme-surface-default); } diff --git a/lib/components/Page/sectionHeader.module.css b/lib/components/Page/sectionHeader.module.css deleted file mode 100644 index 1015c984..00000000 --- a/lib/components/Page/sectionHeader.module.css +++ /dev/null @@ -1,9 +0,0 @@ -.header { - display: flex; - align-items: center; - justify-content: space-between; -} - -.header[data-margin="true"] { - margin: 0.5rem 0; -} diff --git a/lib/components/Timeline/Timeline.stories.tsx b/lib/components/Timeline/Timeline.stories.tsx new file mode 100644 index 00000000..8589c379 --- /dev/null +++ b/lib/components/Timeline/Timeline.stories.tsx @@ -0,0 +1,63 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { Timeline } from './'; + +const meta = { + title: 'Timeline/Timeline', + component: Timeline, + tags: ['autodocs'], + parameters: {}, + args: { + items: [ + { + children: 'Timeline section', + }, + { + datetime: '2024-12-12 11:15', + dateline: '12. desember 2024', + children: 'With byline', + }, + { + size: 'xs', + avatar: { + name: 'Per Person', + }, + datetime: '2024-12-12 11:15', + dateline: '12. desember 2024', + children: 'XS avatar and byline', + }, + { + size: 'sm', + avatar: { + name: 'Per Person', + }, + datetime: '2024-12-12 11:15', + dateline: '12. desember 2024', + children: 'Small avatar and byline', + }, + { + size: 'lg', + avatar: { + type: 'company', + name: 'Bergen bar', + }, + byline: 'Bergen bar', + datetime: '2024-12-12 11:15', + dateline: '12. desember 2024', + children: 'Large avatar and byline', + }, + ], + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: {}, +}; + +export const ActivityLog: Story = { + args: { + items: [{}], + }, +}; diff --git a/lib/components/Timeline/Timeline.tsx b/lib/components/Timeline/Timeline.tsx new file mode 100644 index 00000000..fb010b3f --- /dev/null +++ b/lib/components/Timeline/Timeline.tsx @@ -0,0 +1,19 @@ +import { TimelineBase, TimelineSection, type TimelineSectionProps } from '.'; + +export interface TimelineProps { + items: TimelineSectionProps[]; +} + +export const Timeline = ({ items }: TimelineProps) => { + return ( + + {items?.map((item, index) => { + return ( + + {item.children} + + ); + })} + + ); +}; diff --git a/lib/components/Timeline/TimelineBase.tsx b/lib/components/Timeline/TimelineBase.tsx new file mode 100644 index 00000000..57d37b99 --- /dev/null +++ b/lib/components/Timeline/TimelineBase.tsx @@ -0,0 +1,12 @@ +import cx from 'classnames'; +import type { ReactNode } from 'react'; +import styles from './timelineBase.module.css'; + +export interface TimelineBaseProps { + children: ReactNode; + className?: string; +} + +export const TimelineBase = ({ className, children }: TimelineBaseProps) => { + return
{children}
; +}; diff --git a/lib/components/Timeline/TimelineSection.tsx b/lib/components/Timeline/TimelineSection.tsx new file mode 100644 index 00000000..583bb854 --- /dev/null +++ b/lib/components/Timeline/TimelineSection.tsx @@ -0,0 +1,49 @@ +import type { ReactNode } from 'react'; +import { Avatar, type AvatarProps, Byline, type BylineSize, type IconName } from '..'; + +import styles from './timelineSection.module.css'; + +export interface TimelineSectionProps { + loading?: boolean; + seen?: boolean; + size?: BylineSize; + datetime?: string; + dateline?: string; + byline?: ReactNode; + avatar?: AvatarProps; + icon?: IconName; + children?: ReactNode; +} + +export const TimelineSection = ({ + loading, + size = 'xs', + seen = true, + datetime, + dateline, + byline, + avatar, + children, +}: TimelineSectionProps) => { + return ( +
+ +
+ {(byline || dateline) && ( + + {byline && {byline && dateline ? byline + ', ' : byline}} + {dateline && {dateline}} + + )} + {children} +
+
+ ); +}; diff --git a/lib/components/Timeline/index.ts b/lib/components/Timeline/index.ts new file mode 100644 index 00000000..2e1c12b8 --- /dev/null +++ b/lib/components/Timeline/index.ts @@ -0,0 +1,3 @@ +export * from './TimelineBase'; +export * from './TimelineSection'; +export * from './Timeline'; diff --git a/lib/components/History/historyList.module.css b/lib/components/Timeline/timelineBase.module.css similarity index 63% rename from lib/components/History/historyList.module.css rename to lib/components/Timeline/timelineBase.module.css index d77c055d..8b038911 100644 --- a/lib/components/History/historyList.module.css +++ b/lib/components/Timeline/timelineBase.module.css @@ -1,12 +1,7 @@ -.list { - list-style: none; +.timeline { display: flex; flex-direction: column; row-gap: 1rem; padding: 0; margin: 0; } - -.item { - margin: 0; -} diff --git a/lib/components/Timeline/timelineSection.module.css b/lib/components/Timeline/timelineSection.module.css new file mode 100644 index 00000000..509d042b --- /dev/null +++ b/lib/components/Timeline/timelineSection.module.css @@ -0,0 +1,61 @@ +.section { + display: flex; + column-gap: 0.5rem; +} + +.sidebar { + flex-shrink: 0; + display: flex; + flex-direction: column; + align-items: center; + row-gap: 0.375rem; + width: 2.25rem; +} + +.sidebar[data-size="xs"] { + margin-top: 0.125rem; +} + +.media[data-size="xs"] { + min-height: 20px; + display: flex; + align-items: center; + justify-content: center; +} + +.dot { + background-color: var(--theme-surface-active); + width: .875rem; + height: .875rem; + border-radius: 50%; +} + +.dot[data-seen="true"] { + background-color: var(--theme-surface-hover); +} + +.border { + flex-grow: 1; + padding-top: 0; + padding-bottom: 1.5rem; +} + +.border { + width: 0.25rem; + background-color: var(--theme-surface-active); +} + +.border[data-seen="true"] { + background-color: var(--neutral-surface-default); +} + +.content { + flex-grow: 1; + display: flex; + flex-direction: column; +} + +.content[data-size="lg"] { + padding: 0.5rem 0; + row-gap: 1rem; +} diff --git a/lib/components/Transmission/TransmissionItem.tsx b/lib/components/Transmission/TransmissionItem.tsx index c3f69734..e0225d70 100644 --- a/lib/components/Transmission/TransmissionItem.tsx +++ b/lib/components/Transmission/TransmissionItem.tsx @@ -1,13 +1,15 @@ import { useState } from 'react'; -import { AttachmentSection, type AttachmentSectionProps } from '../Attachment'; import type { AvatarProps } from '../Avatar'; import type { BadgeProps } from '../Badge'; +import { DialogAttachments, type DialogAttachmentsProps } from '../Dialog'; import { ListItem } from '../List'; import { MetaTimestamp } from '../Meta'; import { Typography } from '../Typography'; +import type { TransmissionTypeProps } from './TransmissionType'; import styles from './transmissionItem.module.css'; export interface TransmissionItemProps { + type?: TransmissionTypeProps; loading?: boolean; expanded?: boolean; sender: AvatarProps; @@ -17,15 +19,15 @@ export interface TransmissionItemProps { title?: string; description?: string | undefined; summary?: string; - attachments?: AttachmentSectionProps; + attachments?: DialogAttachmentsProps; } export const TransmissionItem = ({ + type, loading, sender, createdAt, createdAtLabel, - badge, title, description, summary, @@ -37,6 +39,22 @@ export const TransmissionItem = ({ setExpanded((prevState) => !prevState); }; + if (type?.value === 'draft') { + return ( + + ); + } + return ( {expanded && ( @@ -63,7 +81,7 @@ export const TransmissionItem = ({ )}

{summary}

- {attachments && } + {attachments && }
)} diff --git a/lib/components/Transmission/TransmissionList.stories.ts b/lib/components/Transmission/TransmissionList.stories.ts index e902c78b..239171a5 100644 --- a/lib/components/Transmission/TransmissionList.stories.ts +++ b/lib/components/Transmission/TransmissionList.stories.ts @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react'; - +import { transmissionList } from '../../examples'; import { TransmissionList } from './TransmissionList'; const meta = { @@ -8,56 +8,7 @@ const meta = { tags: ['autodocs'], parameters: {}, args: { - items: [ - { - createdAt: '2024-09-22 13:34', - createdAtLabel: '22. september 2024 kl 13.34', - badge: { - label: 'Godkjent, med feil', - }, - sender: { - name: 'Skatteetaten', - type: 'company', - imageUrl: - 'https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96', - }, - title: 'Leveransen er godkjent, men inneholder feil', - description: '22. sept 11.10', - summary: - 'Leveransen er godkjent, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding og feilliste under.', - attachments: { - title: '6 vedlegg', - items: [ - { - href: '#', - label: 'Feilliste.pdf', - }, - ], - }, - }, - { - createdAt: '2004-09-09 11:05', - createdAtLabel: '22. september 2024 kl 11.05', - sender: { - name: 'Eirik Horneland', - }, - badge: { - label: 'Sendt inn', - }, - title: 'Tredjepartsopplysninger ble sendt inn', - description: '22. sept 11.05', - summary: 'Dere får tilbakemelding om en kort stund.', - attachments: { - title: '1 vedlegg', - items: [ - { - href: '#', - label: 'Innsendte opplysninger.pdf', - }, - ], - }, - }, - ], + items: transmissionList, }, } satisfies Meta; diff --git a/lib/components/Transmission/TransmissionType.tsx b/lib/components/Transmission/TransmissionType.tsx new file mode 100644 index 00000000..74b66dee --- /dev/null +++ b/lib/components/Transmission/TransmissionType.tsx @@ -0,0 +1,37 @@ +import { Badge, type BadgeSize } from '../Badge'; + +export enum TransmissionTypeEnum { + /** Used to indicate a user-initiated transmission not yet sent. */ + draft = 'draft', + /** Transmissions submitted by an end user. */ + submission = 'submission', + /** User submitted correction. */ + correction = 'correction', + /** The transmission has been accepted. */ + acceptance = 'acceptance', + /** The transmission has been rejected. */ + rejection = 'Rejection', + /** The transmission is an elert. */ + alert = 'Alert', +} + +export type TransmissionTypeValue = keyof typeof TransmissionTypeEnum; + +export interface TransmissionTypeProps { + loading?: boolean; + size?: BadgeSize; + value?: TransmissionTypeValue; + label?: string; +} + +/** + * Transmission type. + */ + +export const TransmissionType = ({ loading, size = 'sm', label }: TransmissionTypeProps) => { + if (loading) { + return null; + } + + return {label}; +}; diff --git a/lib/components/Transmission/index.ts b/lib/components/Transmission/index.ts index b5bb1374..d16ad81b 100644 --- a/lib/components/Transmission/index.ts +++ b/lib/components/Transmission/index.ts @@ -1,3 +1,2 @@ export * from './TransmissionItem'; export * from './TransmissionList'; -export * from './TransmissionSection'; diff --git a/lib/components/Typography/Heading.tsx b/lib/components/Typography/Heading.tsx index 59e332d0..a724f078 100644 --- a/lib/components/Typography/Heading.tsx +++ b/lib/components/Typography/Heading.tsx @@ -3,20 +3,22 @@ import type { ReactNode } from 'react'; import styles from './heading.module.css'; export type HeadingSize = 'xs' | 'sm' | 'md' | 'lg'; +export type HeadingWeight = 'normal' | 'medium' | 'bold'; export type HeadingComponent = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; export interface HeadingProps { as?: HeadingComponent; size?: HeadingSize; + weight?: HeadingWeight; className?: string; children?: ReactNode; } -export const Heading = ({ as = 'h2', size = 'md', className, children }: HeadingProps) => { +export const Heading = ({ as = 'h2', size = 'md', weight = 'medium', className, children }: HeadingProps) => { const H = as; return ( - + {children} ); diff --git a/lib/components/Typography/Typography.tsx b/lib/components/Typography/Typography.tsx index 3a4d7f8f..a53325e9 100644 --- a/lib/components/Typography/Typography.tsx +++ b/lib/components/Typography/Typography.tsx @@ -1,20 +1,27 @@ import cx from 'classnames'; import type { ElementType, ReactNode } from 'react'; -import type { LayoutTheme } from '../Layout'; import styles from './typography.module.css'; +export type TypographyTheme = 'inherit' | 'neutral' | 'company' | 'person' | 'article'; export type TypographySize = 'xs' | 'sm' | 'md' | 'lg'; export interface TypographyProps { as?: ElementType; size?: TypographySize; - theme?: LayoutTheme; + theme?: TypographyTheme; className?: string; children?: ReactNode; href?: string; } -export const Typography = ({ as = 'div', size = 'md', theme, className, children, ...restProps }: TypographyProps) => { +export const Typography = ({ + as = 'div', + size = 'md', + theme = 'inherit', + className, + children, + ...restProps +}: TypographyProps) => { const Component = as; return ( diff --git a/lib/components/Typography/heading.module.css b/lib/components/Typography/heading.module.css index 32833490..30078c14 100644 --- a/lib/components/Typography/heading.module.css +++ b/lib/components/Typography/heading.module.css @@ -2,17 +2,25 @@ margin: 0; } +.heading[data-weight="normal"] { + font-weight: 400; +} + +.heading[data-weight="medium"] { + font-weight: 500; +} + +.heading[data-weight="bold"] { + font-weight: 600; +} + .heading[data-size="xs"] { font-size: 0.875rem; - font-weight: 400; line-height: 1.5rem; - color: var(--theme-text-subtle); - margin-bottom: 0.375rem; } .heading[data-size="sm"] { font-size: 1.125rem; - font-weight: 500; line-height: 1.5rem; } @@ -25,5 +33,5 @@ .heading[data-size="lg"] { font-size: 1.5rem; font-weight: 500; - line-height: 1.5rem; + line-height: 1.25; } diff --git a/lib/components/Typography/typography.module.css b/lib/components/Typography/typography.module.css index 955ee9de..45c79c8d 100644 --- a/lib/components/Typography/typography.module.css +++ b/lib/components/Typography/typography.module.css @@ -24,36 +24,61 @@ margin-bottom: 0; } -.typography h2 { +.typography strong { + font-weight: 500; +} + +.typography a { + color: var(--theme-base-default); +} + +.typography > p { + font-size: 1em; + margin: 1em 0; +} + +.typography > h2 { font-size: 1.25rem; font-weight: 600; margin-top: 1.5em; margin-bottom: 0; } -.typography h3 { +.typography > h3 { font-size: 1em; font-weight: 600; margin: 1em 0; } -.typography h4 { +.typography > h4 { font-size: 1em; font-weight: 600; margin: 1em 0 0; } -.typography p { - font-size: 1em; - margin: 1em 0; +.typography > h5, +.typography > h6 { + font-size: 0.875rem; + margin: 1em 0 0; } -.typography strong { - font-weight: 600; +.typography > h6 { + font-weight: 500; + color: var(--theme-text-subtle); } -.typography a { - color: var(--link-base-default); +.typography > h6 { + font-weight: 400; + color: var(--theme-text-subtle); +} + +.typography > h5 + *, +.typography > h6 + * { + margin-top: 0; +} + +.typography > section { + margin: 1em 0; } .typography ul:not([class]), diff --git a/lib/components/index.ts b/lib/components/index.ts index 9ba344f1..3698574b 100644 --- a/lib/components/index.ts +++ b/lib/components/index.ts @@ -4,13 +4,13 @@ export * from './Avatar'; export * from './Badge'; export * from './Bookmarks'; export * from './Button'; +export * from './Byline'; export * from './ContextMenu'; export * from './Dialog'; export * from './Dropdown'; export * from './Footer'; export * from './GlobalMenu'; export * from './Header'; -export * from './History'; export * from './Icon'; export * from './Layout'; export * from './LayoutAction'; @@ -20,6 +20,8 @@ export * from './Meta'; export * from './RootProvider'; export * from './Searchbar'; export * from './Snackbar'; +export * from './Skeleton'; +export * from './Timeline'; export * from './Toolbar'; export * from './Page'; export * from './Transmission'; diff --git a/lib/css/theme-article.css b/lib/css/theme-article.css index c2e6d375..9da33b3c 100644 --- a/lib/css/theme-article.css +++ b/lib/css/theme-article.css @@ -7,8 +7,8 @@ --theme-border-default: var(--neutral-border-default); --theme-border-strong: var(--neutral-border-strong); --theme-border-subtle: var(--neutral-border-subtle); - --theme-surface-active: var(--neutral-surface-active); - --theme-surface-default: var(--neutral-surface-default); + --theme-surface-active: var(--company-surface-active); + --theme-surface-default: var(--company-surface-default); --theme-surface-hover: var(--neutral-surface-hover); --theme-text-default: var(--neutral-text-default); --theme-text-subtle: var(--neutral-text-subtle); diff --git a/lib/examples/avatar/brreg-logo.png b/lib/examples/avatar/brreg-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9b89e95084218070105bf5bb5d7cc6e51c5978be GIT binary patch literal 5342 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 literal 0 HcmV?d00001 diff --git a/lib/examples/avatar/brreg.ts b/lib/examples/avatar/brreg.ts new file mode 100644 index 00000000..1913a5d6 --- /dev/null +++ b/lib/examples/avatar/brreg.ts @@ -0,0 +1,8 @@ +import type { AvatarProps } from '../../components'; +import logo from './brreg-logo.png'; + +export const brreg: AvatarProps = { + type: 'company', + name: 'Brønnøysundregistrene', + imageUrl: logo, +}; diff --git a/lib/examples/avatar/index.ts b/lib/examples/avatar/index.ts new file mode 100644 index 00000000..be85aeb2 --- /dev/null +++ b/lib/examples/avatar/index.ts @@ -0,0 +1,5 @@ +export * from './oslo'; +export * from './brreg'; +export * from './ssb'; +export * from './skatt'; +export * from './nav'; diff --git a/lib/examples/avatar/nav-logo.png b/lib/examples/avatar/nav-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..57cc8bef05867edcbb487e7f19be224073372de7 GIT binary patch literal 2567 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 z⪻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 DYUgy6 literal 0 HcmV?d00001 diff --git a/lib/examples/avatar/oslo.ts b/lib/examples/avatar/oslo.ts new file mode 100644 index 00000000..96e1bad8 --- /dev/null +++ b/lib/examples/avatar/oslo.ts @@ -0,0 +1,8 @@ +import type { AvatarProps } from '../../components'; +import logo from './oslo-logo.png'; + +export const oslo: AvatarProps = { + type: 'company', + name: 'Oslo kommune', + imageUrl: logo, +}; diff --git a/lib/examples/avatar/skatt-logo.png b/lib/examples/avatar/skatt-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7e419cdb730a3215bc0f932de6d4d3ccc4600d17 GIT binary patch literal 2088 zcmb7_dpy&98^?bR6=7{mBxaG#lRJ}pM06XkNp8!b71@MXSQ4Qj=iN>@73xM&VGi+V zPVqR*7$fJL(wakaY(->vg?8e_Y?|dtKN2p1rM=+(DIt0078Y zpT}MldH0_tB`&)Ceths3Iq87&&Orbmqwv$jfX8{t0C3>FHP-x6Xx<9f*BA@Lw1dbwB?1T@11HlwqlrzeYyqKTyEJ4oT< zjmYwfnKJ|j*S+S#!r7L{ov7_u8#0;yq~YdeErg|I_v#k)z$Kh@^*$*8_b4ZLp_f_4 z&dJXYGEzlky`a6x2F%PB7>+20aW$?a+c6BW) z5ru#LxhD(Y(0kGnh1$I&L-jKe@7x|q`CQK#Sp17B4w~On?uIYS#UwCyDZ*F@+7;G( zZR%MJrT`Zz`C!=RU4>(ohjhoUnpH4-`*?@U*mP@oI{U`urA7V8kQ@ndfOrwk9x2Vl zKON|e3ZpmCXzL$`lbf2FLZ;7#+ZK@-!TkF6D#CR+X69yj5;PoX*8eFEEQK_((amre zc6R1ive_FO8%wX=_dSc8o|>8(<(in9-mJdT)xDCHl{JdT>t_45&pA6gYnD)16Wijv zwd>u&JEpRS$iuM@6d{Kd)v{`L8c)we*o5;eoSd?UeS#ZZ#t0rH5{*`egF{au0f0uM z!Hn0=k;xpp1_7L%X{k+J!L&8pnw5zoKAU#5zw%CWDg~70DPN1QcOkL~$;mUGMy=}u zkqr4Vd4-v9!I14ze`hDw%F4>mZ{_J(W~R==>G&sfDUMX!wj<91lAD+L*v32|fV8vF^$%kL$}lC=gbx~z$M=~N0yV-WYhD+Mrbjx{LVl1O1$DhwgDO%MFavt71UjX5(oq+9i5bv>`?z7?rneV=7ubj_SyUS zRStL+S$5Y}**iOHK{IrMv9zs8;{if*sVhDDYw_83`j!L}2G~0}g)9xK5rVaoRT{X5 zVEt};$5{bXs0~^rZImzjAwl%P%+S4fc$#>NGSbM>lI>NStE-k=xa{dkXHWv9McsZF zHas>4?SE4;${!gS`QsGf+asfP9_9$i+>#Y zEzZTY?a(Vsj3}-9rFKJu0}cgZ;y`DgVyWFT=|KI3`|a)R%Xw2`cIj{T$At?)c^7Wq zj+}|84IIZF1t(2GHz|=FA3tiJY`AkKpHOM|;RNwl@O{+l-of0W=AErr*DwQ=sm2=i zjzOBInWclo?yhJ~B*6&^H0+Nq|0tVy_}>kQqSsV=K3Y%Tg<5iM*3ZvF5ivkQVh`){ z%*#>>a8XgwT}Bj%)ERx(d@kS5km$9jn-D|0R-=F{e*wm}ectO%81S;OvGFeJjMLCZ z`KxbWf!8O-O<09LT9!X*dz2#XCWebl%#}fdpkk3wa{iyAD^1G{rL_qJ=m1LeDu=?@3kr&5#ddKHrJ%S{yPcAF;&^n&9~uZ6u~uSDW8*H~
    #Ko2JS?Lm%IB1`qGf#$9Api>*CKFCse+$zP{?>KB~V}LHB>d z4_<%CRzLdESv1zm%gg;kLz|$Ux~DZGl$zw7Ub&8YV*|wUboGhP^e4CyK{N<*#Yi=M zZ!b1FV%>pEcE;6m5wH8G}_S6(Ae16%uK!IHH*dS zPu+aO@u+rXMlo6oc)6)KL5jLvC&#op8Tz1y6+|(ccoXouXz70U>zHbuvn>sxP$*GR z(<>Cz7OR%96+KUBURqpq(VbXduN%Ly!sj;z^96|@b?d2?eaMy$w=y?F?~nUVOg3OR zRi`LB>G>$ZWhX~9=5xmCLbkB=_S`u;e?cX&A@y7l+oPIL=~c^d*OLW-zOR3GZGIcM zz2>cQVXmOVs-`9=Gc!tlwF}OTO=8Enz_PoSWa2C!*2!AeYF6crdd|%*1jg$hGcW!f zcL`B8AIL7baNA+{lsq{n2`Uq(0doTyO+oYelke{UEa`N!Q!`ADEg91FH1O)zXWIqh v5Ie&E1Hb=JlY;m+EdNE#Wt^m>y4<=MKHP9zuVt)Ugnq!<(iZ#D!kzk0)voZo literal 0 HcmV?d00001 diff --git a/lib/examples/avatar/skatt.ts b/lib/examples/avatar/skatt.ts new file mode 100644 index 00000000..853f3a1a --- /dev/null +++ b/lib/examples/avatar/skatt.ts @@ -0,0 +1,8 @@ +import type { AvatarProps } from '../../components'; +import logo from './skatt-logo.png'; + +export const skatt: AvatarProps = { + type: 'company', + name: 'Skatteetaten', + imageUrl: logo, +}; diff --git a/lib/examples/avatar/ssb-logo.png b/lib/examples/avatar/ssb-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..621320cc85a4ad8fb3dfed7676747e23974e01f5 GIT binary patch literal 6622 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 +

    + Du mottar nabovarselet fordi Borhaven Arkitekter AS har planer om å bygge eller gjøre endringer i nærheten av + følgende eiendom: +

    +

    + Eugenies gate 13B, gårdsnr. 217, bruksnr. 501, seksjonsnr. 0, festenr. 0. +

    + + ), + attachments: { + title: '7 vedlegg', + items: [ + { + href: '#', + label: 'Nabovarsel.pdf', + }, + { + href: '#', + label: 'A10-01 Situasjonsplan.pdf', + }, + { + href: '#', + label: 'A40-01 Fasade Nord Ny.pdf', + }, + { + href: '#', + label: 'A40-01 Fasade Øst Ny.pdf', + }, + { + href: '#', + label: 'A40-01 Fasade Vest Ny.pdf', + }, + { + href: '#', + label: 'A40-01 Fasade Sør Ny.pdf', + }, + { + href: '#', + label: 'A30-01 Snitt A Ny.pdf', + }, + { + href: '#', + label: 'A30-03 Snitt B Ny.pdf', + }, + { + href: '#', + label: 'Redegjørelse Wilhelms gt 10.pdf', + }, + ], + }, + actions: [ + { + id: '1', + priority: 'secondary', + label: 'Gi tilbakemelding', + }, + ], + additionalInfo: { + title: 'Mer informasjon', + children: ( +

    + Hvis du mener at byggeplanene påvirker deg negativt, må du sende inn merknader innen 14 dager. Har du ingen + merknader trenger du ikke å gjør enoe som helst. Mer om nabovarsel. +

    + ), + }, + contactInfo: { + title: 'Ta kontakt', + children:

    Spørsmål om byggeplanene kan rettes til ansvarlig arkitekt Borhaven Arkitekter på tlf. 905 05 345.

    , + }, +}; diff --git a/lib/examples/dialog/index.ts b/lib/examples/dialog/index.ts new file mode 100644 index 00000000..ea30e7bb --- /dev/null +++ b/lib/examples/dialog/index.ts @@ -0,0 +1,18 @@ +export * from './dialogContextMenu'; +export * from './dialogHistoryItems'; +export * from './dialogListItems'; + +export * from './transmissionList'; + +export * from './simpleLetterDialog'; +export * from './extendedLetterDialog'; +export * from './metadataDialog'; + +export * from './reportingDialog'; +export * from './reportingDraftDialog'; +export * from './reportingInProgressDialog'; +export * from './reportingCompletedDialog'; + +export * from './transmissionsDialog'; +export * from './transmissionsInProgressDialog'; +export * from './transmissionsCompletedDialog'; diff --git a/lib/examples/dialog/metadataDialog.tsx b/lib/examples/dialog/metadataDialog.tsx new file mode 100644 index 00000000..449a5b10 --- /dev/null +++ b/lib/examples/dialog/metadataDialog.tsx @@ -0,0 +1,91 @@ +import type { DialogProps } from '../../components'; +import { nav as sender } from '../avatar/'; + +export const metadataDialog: DialogProps = { + id: 'metadata', + sender, + recipient: { name: 'Bergen bar' }, + updatedAt: '2024-12-01 09:30', + updatedAtLabel: '1. desember 2024 kl 09.30', + title: 'Sykmelding Sander Svendsen', + summary: 'Sander Svendsen er sykmeldt i 4 dager fra 2. juli.', + body: ( + <> +
    Sykmeldingen gjelder
    +

    2.–5. desember 2024.

    +
    Nærmeste leder
    +

    + Ikke oppgitt. +

    +
    Ansvarlig lege
    +

    Mark Medisin + 47 23369090

    + + ), + actions: [ + { + id: '1', + priority: 'primary', + label: 'Oppgi nærmeste leder', + }, + ], + history: { + updatedAtLabel: 'Sander Svendsens sykehistorikk', + summary: '73 dager sykmeldt i år', + expandLabel: 'Vis historikk', + collapseLabel: 'Skjul historikk', + items: [ + { + createdAt: '', + createdAtLabel: '1. januar 2024', + summary: '14 dager sykmeldt fra 12. januar–26. januar.', + }, + { + createdAt: '', + createdAtLabel: '4. februar 2024', + summary: '7 dagers sykmeldt fra 6. februar–12. februar.', + }, + { + createdAt: '', + createdAtLabel: '15. april 2024', + summary: '45 dagers sykmeldt fra 15. april–30. mai 2024.', + }, + { + createdBy: { + type: 'company', + name: 'Bergen bar', + }, + createdAt: '', + createdAtLabel: '1. mai 2024', + summary: 'Inntektsmelding ble sendt', + }, + { + createdAt: '', + createdAtLabel: '4. november 2024', + summary: '7 dagers sykmeldt fra 4. november–11. november.', + }, + { + createdAt: '', + createdAtLabel: '4. november 2024', + summary: '7 dagers sykmeldt fra 4. november–11. november.', + }, + ], + }, + additionalInfo: { + title: 'Mer informasjon', + children: ( +

    + Virksomheten får melding når det skjer noe nytt i et sykesykmeldt. Hvilke meldinger man får, avhenger av rollen + man har. Slik går du som arbeidsgiver går frem for å håndtere sykepenger. +

    + ), + }, + contactInfo: { + title: 'Ta kontakt', + children: ( +

    + Du kan kontakte oss på telefon 800 80 000 eller på skatteetaten.no/kontakt. Ditt referansenummer er SK985-09. + Hvis du ringer fra utlandet er telefonnummeret +47 22 07 70 00 +

    + ), + }, +}; diff --git a/lib/examples/dialog/reportingCompletedDialog.tsx b/lib/examples/dialog/reportingCompletedDialog.tsx new file mode 100644 index 00000000..0e2339ed --- /dev/null +++ b/lib/examples/dialog/reportingCompletedDialog.tsx @@ -0,0 +1,32 @@ +import type { DialogProps } from '../../components'; +import { reportingHistoryItems } from './reportingHistoryItems'; +import { reportingInProgressDialog } from './reportingInProgressDialog'; + +const latestHistoryItem = reportingHistoryItems[reportingHistoryItems?.length - 1]; + +export const reportingCompletedDialog: DialogProps = { + ...reportingInProgressDialog, + status: { + value: 'completed', + label: 'Avsluttet', + }, + updatedAtLabel: '27. november 2024 kl 10.30', + summary: 'Bedriftsdata er godkjent.', + body: undefined, + attachments: { + title: '1 vedlegg', + items: [ + { + href: '#', + label: 'Godkjent bedriftsdata.pdf', + }, + ], + }, + history: { + updatedAtLabel: '4 dager siden', + summary: latestHistoryItem?.summary, + expandLabel: 'Vis historikk', + collapseLabel: 'Skjul historikk', + items: reportingHistoryItems, + }, +}; diff --git a/lib/examples/dialog/reportingDialog.tsx b/lib/examples/dialog/reportingDialog.tsx new file mode 100644 index 00000000..59a41fa9 --- /dev/null +++ b/lib/examples/dialog/reportingDialog.tsx @@ -0,0 +1,45 @@ +import type { DialogProps } from '../../components'; +import { ssb } from '../avatar/'; + +export const reportingDialog: DialogProps = { + id: 'reporting', + status: { + value: 'requires-attention', + label: 'Krever handling', + }, + sender: ssb, + dueAt: '2024-10-31', + dueAtLabel: 'Frist: 31. oktober 2024', + title: 'Rapportering av bedriftsdata', + summary: 'Du må levere bedriftsdata innen 31. oktober.', + attachments: { + title: '1 vedlegg', + items: [ + { + href: '#', + label: 'Vedtak om rapportering av bedriftsdata.pdf', + }, + ], + }, + actions: [ + { + id: '1', + priority: 'primary', + label: 'Rapporter bedriftsdata', + }, + ], + additionalInfo: { + title: 'Mer informasjon', + children: ( +

    + Din bedrift er en av 8.000 virksomheter som har opplysningsplikt i 2024. Statistikken er viktig for samfunnet og + det er ikke valgfritt å delta. Hvis dere ikke sender opplysningene innen fristen, vil foretaket kunne få + tvangsmulkt. Les mer på SSB.no +

    + ), + }, + contactInfo: { + title: 'Ta kontakt', + children:

    Little itpsum.

    , + }, +}; diff --git a/lib/examples/dialog/reportingDraftDialog.tsx b/lib/examples/dialog/reportingDraftDialog.tsx new file mode 100644 index 00000000..7e690d16 --- /dev/null +++ b/lib/examples/dialog/reportingDraftDialog.tsx @@ -0,0 +1,40 @@ +import type { DialogProps } from '../../components'; +import { reportingDialog } from './reportingDialog'; + +export const reportingDraftDialog: DialogProps = { + ...reportingDialog, + status: { + value: 'draft', + label: 'Utkast', + }, + timeline: { + title: '1 utkast', + items: [ + { + updatedAt: '2024-11-27 10:24', + updatedAtLabel: '27. november 2024 kl 10.24', + summary: 'Utkast opprettet', + items: [ + { + type: { value: 'draft', label: 'Utkast' }, + sender: { + type: 'person', + name: 'Ola Nordmann', + }, + title: 'Bedriftsdata', + summary: 'Bedriftsdata er levert.', + attachments: { + title: '1 vedlegg', + items: [ + { + label: 'Bedriftsdata.pdf', + href: '', + }, + ], + }, + }, + ], + }, + ], + }, +}; diff --git a/lib/examples/dialog/reportingHistoryItems.tsx b/lib/examples/dialog/reportingHistoryItems.tsx new file mode 100644 index 00000000..ac720e70 --- /dev/null +++ b/lib/examples/dialog/reportingHistoryItems.tsx @@ -0,0 +1,54 @@ +import type { DialogHistoryItemProps } from '../../components'; +import { ssb as sender } from '../avatar/'; + +export const reportingHistoryItems: DialogHistoryItemProps[] = [ + { + createdBy: sender, + createdAt: '', + createdAtLabel: '24. november 2024 kl 15.30', + summary: 'Du må levere bedriftsdata innen 1. januar.', + attachments: { + title: '1 vedlegg', + items: [ + { + label: 'Vedtak om innlevering av bedriftsdata.pdf', + href: '', + }, + ], + }, + }, + { + createdAt: '', + createdAtLabel: '27. november 2024 kl 10.24', + summary: 'Bedriftsdata ble levert.', + transmissions: { + title: '1 forsendelse', + items: [ + { + createdAtLabel: '27. november 2024 kl 10.24', + sender: { + type: 'person', + name: 'Ola Nordmann', + }, + title: 'Bedriftsdata', + summary: 'Bedriftsdata er levert.', + attachments: { + title: '1 vedlegg', + items: [ + { + label: 'Bedriftsdata.pdf', + href: '', + }, + ], + }, + }, + ], + }, + }, + { + createdBy: sender, + createdAt: '', + createdAtLabel: '29. november 2024 kl 10.24', + summary: 'Saken er sendt til manuell behandling.', + }, +]; diff --git a/lib/examples/dialog/reportingInProgressDialog.tsx b/lib/examples/dialog/reportingInProgressDialog.tsx new file mode 100644 index 00000000..33e81959 --- /dev/null +++ b/lib/examples/dialog/reportingInProgressDialog.tsx @@ -0,0 +1,43 @@ +import type { DialogProps } from '../../components'; +import { reportingDialog } from './reportingDialog'; +import { reportingHistoryItems } from './reportingHistoryItems'; + +const historyItems = reportingHistoryItems.slice(0, 2); +const latestHistoryItem = historyItems[historyItems.length - 1]; + +export const reportingInProgressDialog: DialogProps = { + ...reportingDialog, + status: { + value: 'in-progress', + label: 'Under arbeid', + }, + dueAt: undefined, + dueAtLabel: undefined, + updatedAtLabel: '27. november 2024 kl 10.30', + + summary: 'Saken er sendt til manuell behandling. Forventet behandlingstid: 2 uker.', + body: ( + <> +

    Hva skjer nå?

    +

    Saken din har fått saksbehandler og blir behandlet manuelt.

    +
      +
    • + Din saksbehandler: Siri Saksbehander +
    • +
    • + Ditt saksnummer: XRT0987 +
    • +
    +

    Oppgi saksnummer ved kontakt.

    + + ), + actions: undefined, + attachments: undefined, + history: { + updatedAtLabel: '2 dager siden', + summary: latestHistoryItem?.summary, + expandLabel: 'Vis historikk', + collapseLabel: 'Skjul historikk', + items: historyItems, + }, +}; diff --git a/lib/examples/dialog/simpleLetterDialog.tsx b/lib/examples/dialog/simpleLetterDialog.tsx new file mode 100644 index 00000000..52072dec --- /dev/null +++ b/lib/examples/dialog/simpleLetterDialog.tsx @@ -0,0 +1,43 @@ +import type { DialogProps } from '../../components'; +import { skatt } from '../avatar/'; + +export const simpleLetterDialog: DialogProps = { + id: 'aksjeoppgave', + sender: skatt, + updatedAt: '2024-03-01 09:30', + updatedAtLabel: '1. mars 2024 kl 09.30', + title: 'Aksjeoppgaven 2023', + summary: 'Aksjeoppgaven for 2023 er klar.', + attachments: { + title: '2 vedlegg', + items: [ + { + href: '#', + label: 'RF1088F Forenklet aksjeoppgave.pdf', + }, + { + href: '#', + label: 'RF1088D Detaljert aksjeoppgave.pdf', + }, + ], + }, + additionalInfo: { + title: 'Mer informasjon', + children: ( +

    + Alle aksjonærer mottar aksjeoppgaven fra Skatteetaten. Den gir en oversikt over dine aksjer i norske + aksjeselskap. Aksjeoppgaven inneholder også utenlandske selskap registrert på Oslo Børs og egenkapitalbevis i + norske sparebanker. +

    + ), + }, + contactInfo: { + title: 'Ta kontakt', + children: ( +

    + Du kan kontakte oss på telefon 800 80 000 eller på skatteetaten.no/kontakt. Ditt referansenummer er SK985-09. + Hvis du ringer fra utlandet er telefonnummeret +47 22 07 70 00 +

    + ), + }, +}; diff --git a/lib/examples/dialog/transmissionList.ts b/lib/examples/dialog/transmissionList.ts new file mode 100644 index 00000000..8e2847b6 --- /dev/null +++ b/lib/examples/dialog/transmissionList.ts @@ -0,0 +1,97 @@ +import type { TransmissionItemProps } from '../../components'; +import { skatt } from '../avatar'; + +export const transmissionList: TransmissionItemProps[] = [ + { + type: { + value: 'submission', + label: 'Sendt', + }, + sender: { + name: 'Per Olav Olsen', + }, + title: 'Tredjepartsopplysninger ble levert', + createdAt: '2024-01-05 07:30', + createdAtLabel: '5. januar 2024 kl 07.30', + summary: + 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', + }, + { + type: { + value: 'acceptance', + label: 'Godkjent', + }, + createdAt: '2024-01-05 09:10', + createdAtLabel: '5. januar 2024 kl 09.10', + sender: skatt, + title: 'Leveransen er godkjent, men inneholder feil', + summary: + 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', + attachments: { + title: '2 vedlegg', + items: [ + { + label: 'Dokument 1.pdf', + href: '', + }, + { + label: 'Dokument 2.pdf', + href: '', + }, + ], + }, + }, + { + type: { + value: 'submission', + label: 'Sendt', + }, + sender: { + name: 'Siren Søftebø', + }, + title: 'Tredjepartsopplysninger ble levert', + createdAt: '2024-01-14 13:25', + createdAtLabel: '15. januar 2024 kl 13.25', + summary: + 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', + }, + { + type: { + value: 'rejection', + label: 'Avvist', + }, + createdAt: '2024-01-15 14:45', + createdAtLabel: '15. januar 2024 kl 14.45', + sender: skatt, + title: 'Leveransen er avvist', + summary: + 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', + attachments: { + title: '2 vedlegg', + items: [ + { + label: 'Dokument 1.pdf', + href: '', + }, + { + label: 'Dokument 2.pdf', + href: '', + }, + ], + }, + }, + { + type: { + value: 'correction', + label: 'Rettelse', + }, + sender: { + name: 'Siren Søftebø', + }, + title: 'Tredjepartsopplysninger ble levert', + createdAt: '2024-01-14 13:25', + createdAtLabel: '15. januar 2024 kl 13.25', + summary: + 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', + }, +]; diff --git a/lib/examples/dialog/transmissionsCompletedDialog.tsx b/lib/examples/dialog/transmissionsCompletedDialog.tsx new file mode 100644 index 00000000..dfb970a3 --- /dev/null +++ b/lib/examples/dialog/transmissionsCompletedDialog.tsx @@ -0,0 +1,42 @@ +import type { DialogProps } from '../../components'; +import { skatt } from '../avatar/'; + +import { transmissionsHistoryItems } from './transmissionsHistoryItems'; + +const historyItems = transmissionsHistoryItems; +const latestHistoryItem = historyItems[historyItems?.length - 1]; + +export const transmissionsCompletedDialog: DialogProps = { + id: 'transmissions', + status: { + value: 'completed', + label: 'Avsluttet', + }, + updatedAt: '2024-02-15 09:00', + updatedAtLabel: '15. februar 2024 kl 09.00', + sender: skatt, + title: 'Tredjepartsopplysninger for boligselskap', + summary: 'Skjemaet er lukket for rapportering og korreksjoner.', + body:

    Opplysningene du har rapportert blir forhåndsutfylt i skattemeldingen til sameierne.

    , + attachments: { + title: '2 vedlegg', + items: [ + { label: 'Rapporterte opplysninger.pdf', href: '#' }, + { label: 'Tilbakemeldinger fra Skatteetaten.pdf', href: '#' }, + ], + }, + history: { + updatedAtLabel: '14 dager siden', + summary: latestHistoryItem.summary, + items: historyItems, + }, + additionalInfo: { + title: 'Mer informasjon', + children: ( +

    + Sameier med 9 eller flere boligseksjoner skal levere opplysninger om sameiers andel av felles inntekter, + utgifter, formue og gjeld. Mer informasjon. +

    + ), + }, +}; diff --git a/lib/examples/dialog/transmissionsDialog.tsx b/lib/examples/dialog/transmissionsDialog.tsx new file mode 100644 index 00000000..aff8cf41 --- /dev/null +++ b/lib/examples/dialog/transmissionsDialog.tsx @@ -0,0 +1,31 @@ +import type { DialogProps } from '../../components'; +import { skatt } from '../avatar/'; + +import { transmissionsTimeline } from './transmissionsTimeline'; + +export const transmissionsDialog: DialogProps = { + id: 'transmissions', + updatedAt: '2024-02-02 09:00', + updatedAtLabel: '2. januar 2024 kl 09.00', + sender: skatt, + title: 'Tredjepartsopplysninger for boligselskap', + summary: + 'Her finner du alle innsendinger og tilbakemeldinger for tredjepartsopplysninger for boligselskap 2023. Frist for å levere er 20. januar 2024.', + actions: [ + { + id: '1', + priority: 'secondary', + label: 'Lever tredjepartsopplysninger', + }, + ], + timeline: transmissionsTimeline, + additionalInfo: { + title: 'Mer informasjon', + children: ( +

    + Sameier med 9 eller flere boligseksjoner skal levere opplysninger om sameiers andel av felles inntekter, + utgifter, formue og gjeld. Mer informasjon. +

    + ), + }, +}; diff --git a/lib/examples/dialog/transmissionsHistoryItems.ts b/lib/examples/dialog/transmissionsHistoryItems.ts new file mode 100644 index 00000000..49080f73 --- /dev/null +++ b/lib/examples/dialog/transmissionsHistoryItems.ts @@ -0,0 +1,202 @@ +import type { DialogHistoryItemProps } from '../../components'; +import { skatt } from '../avatar'; + +export const transmissionsHistoryItems: DialogHistoryItemProps[] = [ + { + createdBy: skatt, + createdAt: '2023-10-15 08:00', + createdAtLabel: '15. oktober 2023 kl 08.00', + summary: 'Du må levere tredjepartsopplysninger for boligselskap.', + attachments: { + items: [ + { + href: '#', + label: 'Rapportering av tredjepartsopplysninger for boligselskap.pdf', + }, + ], + }, + }, + { + createdBy: skatt, + createdAt: '2024-01-02 08:00', + createdAtLabel: '2. januar 2024 kl 08.00', + summary: 'Du kan nå levere tredjepartsopplysninger.', + }, + { + createdAt: '2024-01-05 09:10', + createdAtLabel: '5. januar 2024 kl 09.10', + summary: 'Leveransen er godkjent, men inneholder feil', + transmissions: { + title: '2 forsendelser', + items: [ + { + type: { + value: 'submission', + label: 'Sendt', + }, + sender: { + name: 'Per Olav Olsen', + }, + title: 'Tredjepartsopplysninger ble levert', + createdAt: '2024-01-05 07:30', + createdAtLabel: '5. januar 2024 kl 07.30', + summary: + 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', + }, + { + type: { + value: 'acceptance', + label: 'Godkjent', + }, + createdAt: '2024-01-05 09:10', + createdAtLabel: '5. januar 2024 kl 09.10', + sender: skatt, + title: 'Leveransen er godkjent, men inneholder feil', + summary: + 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', + attachments: { + title: '2 vedlegg', + items: [ + { + label: 'Dokument 1.pdf', + href: '', + }, + { + label: 'Dokument 2.pdf', + href: '', + }, + ], + }, + }, + ], + }, + }, + { + createdAt: '2024-01-09 12:22', + createdAtLabel: '9. januar 2024 kl 12.22', + summary: 'Leveransen er godkjent', + transmissions: { + title: '2 forsendelser', + items: [ + { + type: { + value: 'submission', + label: 'Sendt', + }, + sender: { + name: 'Kari Susanne Pettersen', + }, + title: 'Tredjepartsopplysninger ble levert', + createdAt: '2024-01-09 10:45', + createdAtLabel: '9. januar 2024 kl 10.45', + summary: + 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', + }, + { + type: { + value: 'acceptance', + label: 'Godkjent', + }, + createdAt: '2024-01-09 12:22', + createdAtLabel: '9. januar 2024 kl 12.22', + sender: skatt, + title: 'Leveransen er godkjent', + summary: + 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', + attachments: { + title: '2 vedlegg', + items: [ + { + label: 'Dokument 1.pdf', + href: '', + }, + { + label: 'Dokument 2.pdf', + href: '', + }, + ], + }, + }, + ], + }, + }, + { + createdAt: '2024-01-15 14:45', + createdAtLabel: '15. januar 2024 kl 14.45', + summary: 'Leveransen er avvist', + transmissions: { + title: '2 forsendelser', + items: [ + { + type: { + value: 'submission', + label: 'Sendt', + }, + sender: { + name: 'Siren Søftebø', + }, + title: 'Tredjepartsopplysninger ble levert', + createdAt: '2024-01-14 13:25', + createdAtLabel: '15. januar 2024 kl 13.25', + summary: + 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', + }, + { + type: { + value: 'rejection', + label: 'Avvist', + }, + createdAt: '2024-01-15 14:45', + createdAtLabel: '15. januar 2024 kl 14.45', + sender: skatt, + title: 'Leveransen er avvist', + summary: + 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', + attachments: { + title: '2 vedlegg', + items: [ + { + label: 'Dokument 1.pdf', + href: '', + }, + { + label: 'Dokument 2.pdf', + href: '', + }, + ], + }, + }, + ], + }, + }, + { + createdBy: skatt, + createdAt: '2024-01-31 08:00', + createdAtLabel: '31. januar 2024 kl 08.00', + summary: 'Skjemaet er lukket for ordinær rapportering. Du kan gjøre korreksjoner tom. 15. februar.', + }, + { + createdAt: '2024-01-21 13:45', + createdAtLabel: '21. januar 2024 kl 13.45', + summary: 'Tredjepartsopplysninger ble levert', + transmissions: { + title: '1 forsendelse', + items: [ + { + type: { + value: 'correction', + label: 'Rettelse', + }, + sender: { + name: 'Siren Søftebø', + }, + title: 'Tredjepartsopplysninger ble levert', + createdAt: '2024-01-14 13:25', + createdAtLabel: '15. januar 2024 kl 13.25', + summary: + 'Skatteetaten har godkjent leveransen, men det er feil i oppgaver du må se nærmere på. Se tilbakemelding of feilliste under.', + }, + ], + }, + }, +]; diff --git a/lib/examples/dialog/transmissionsInProgressDialog.tsx b/lib/examples/dialog/transmissionsInProgressDialog.tsx new file mode 100644 index 00000000..73909e32 --- /dev/null +++ b/lib/examples/dialog/transmissionsInProgressDialog.tsx @@ -0,0 +1,45 @@ +import type { DialogProps } from '../../components'; +import { skatt } from '../avatar/'; + +import { transmissionsHistoryItems } from './transmissionsHistoryItems'; +import { transmissionsTimeline } from './transmissionsTimeline'; + +const historyItems = transmissionsHistoryItems?.filter( + (item) => item.createdAt && new Date(item.createdAt) < new Date('2024-02-02'), +); +const latestHistoryItem = historyItems[historyItems?.length - 1]; + +export const transmissionsInProgressDialog: DialogProps = { + id: 'transmissions', + status: { + value: 'in-progress', + label: 'Under arbeid', + }, + updatedAt: '2024-02-02 09:00', + updatedAtLabel: '2. januar 2024 kl 09.00', + sender: skatt, + title: 'Tredjepartsopplysninger for boligselskap', + summary: 'Skjemaet er lukket for ordinær rapportering. Du kan gjøre korreksjoner tom. 15. februar.', + actions: [ + { + id: '1', + priority: 'secondary', + label: 'Lever korreksjoner', + }, + ], + history: { + updatedAtLabel: '3 dager siden', + summary: latestHistoryItem.summary, + items: historyItems, + }, + timeline: transmissionsTimeline, + additionalInfo: { + title: 'Mer informasjon', + children: ( +

    + Sameier med 9 eller flere boligseksjoner skal levere opplysninger om sameiers andel av felles inntekter, + utgifter, formue og gjeld. Mer informasjon. +

    + ), + }, +}; diff --git a/lib/examples/dialog/transmissionsTimeline.ts b/lib/examples/dialog/transmissionsTimeline.ts new file mode 100644 index 00000000..80710a84 --- /dev/null +++ b/lib/examples/dialog/transmissionsTimeline.ts @@ -0,0 +1,24 @@ +import type { DialogTimelineProps } from '../../components'; +import { transmissionsHistoryItems } from './transmissionsHistoryItems'; + +const items = transmissionsHistoryItems + .filter((item) => item.transmissions) + .map((item) => { + const items = item.transmissions?.items || []; + const latestItem = items[items.length - 1]; + return { + ...item, + summary: latestItem?.title, + updatedAt: item?.createdAt, + updatedAtLabel: item?.createdAtLabel, + items: item?.transmissions?.items, + }; + }); + +export const transmissionsTimeline: DialogTimelineProps = { + title: items.length + ' forsendelser', + items: items + .slice() + .reverse() + .map(({ createdAt, ...rest }) => rest) as DialogTimelineProps['items'], +}; diff --git a/lib/examples/index.ts b/lib/examples/index.ts index 9449d55c..98990716 100644 --- a/lib/examples/index.ts +++ b/lib/examples/index.ts @@ -8,3 +8,5 @@ export * from './footer'; export * from './useInboxSearch'; export * from './useAccountMenu'; + +export * from './dialog/'; diff --git a/lib/stories/Inbox/BookmarksPage.tsx b/lib/stories/Inbox/BookmarksPage.tsx index 10e2403a..d8bdc3b7 100644 --- a/lib/stories/Inbox/BookmarksPage.tsx +++ b/lib/stories/Inbox/BookmarksPage.tsx @@ -6,7 +6,7 @@ import { ListItem, MetaItem, PageBase, - SectionBase, + Section, SectionFooter, SectionHeader, Typography, @@ -64,7 +64,7 @@ export function BookmarksPage() { return ( - +
    {title} @@ -72,7 +72,7 @@ export function BookmarksPage() { Sist oppdatert: 10 minutter siden. - +
    ); } diff --git a/lib/stories/Inbox/ProfilePage.tsx b/lib/stories/Inbox/ProfilePage.tsx index f1443615..ff60a27b 100644 --- a/lib/stories/Inbox/ProfilePage.tsx +++ b/lib/stories/Inbox/ProfilePage.tsx @@ -7,7 +7,7 @@ import { MetaItem, PageBase, PageHeader, - SectionBase, + Section, SectionFooter, SectionHeader, Typography, diff --git a/lib/stories/Inbox/SettingsPage.tsx b/lib/stories/Inbox/SettingsPage.tsx index ea3f4611..596a2dc1 100644 --- a/lib/stories/Inbox/SettingsPage.tsx +++ b/lib/stories/Inbox/SettingsPage.tsx @@ -5,7 +5,7 @@ import { ListItem, MetaItem, PageBase, - SectionBase, + Section, SectionFooter, SectionHeader, Typography, diff --git a/package.json b/package.json index 965aeec8..cd56fb29 100644 --- a/package.json +++ b/package.json @@ -3,16 +3,10 @@ "version": "0.9.1", "main": "dist/index.js", "types": "dist/index.d.ts", - "files": [ - "dist", - "!dist/stories", - "!dist/examples" - ], + "files": ["dist", "!dist/stories", "!dist/examples"], "type": "module", "description": "Reusable react components", - "sideEffects": [ - "*.css" - ], + "sideEffects": ["*.css"], "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "storybook": "storybook dev -p 6006", diff --git a/tsconfig.json b/tsconfig.json index d9b28ff5..86486594 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,6 +18,6 @@ "allowSyntheticDefaultImports": true, "types": ["./typings.d.ts", "vite/client"] }, - "include": ["./lib/**/*.ts", "./lib/hooks/*.tsx", "./**/*.d.ts"], + "include": ["./lib/**/*.ts", "./lib/hooks/*.tsx", "./**/*.d.ts", "lib/examples/dialog/sykmeldingDialog.tsz"], "exclude": ["./lib/stories/**/*", "./lib/components/Icon/__AkselIcon.tsx"] }