diff --git a/.github/workflows/lint-pr.yaml b/.github/workflows/lint-pr.yaml index c32415f56ab..4ce813deaef 100644 --- a/.github/workflows/lint-pr.yaml +++ b/.github/workflows/lint-pr.yaml @@ -51,6 +51,7 @@ jobs: resource-adm resource-registry settings + studio-root subform testing text diff --git a/frontend/studio-root/components/ContactSection/ContactSection.module.css b/frontend/studio-root/components/ContactSection/ContactSection.module.css new file mode 100644 index 00000000000..f7e10911a7d --- /dev/null +++ b/frontend/studio-root/components/ContactSection/ContactSection.module.css @@ -0,0 +1,40 @@ +.section { + background-color: var(--colors-grey-100); + border-radius: 4px; + display: flex; + gap: var(--fds-spacing-6); + padding: var(--fds-spacing-8); + max-width: 735px; +} + +.iconContainer { + background-color: var(--primary-color-700); + border-radius: 100%; + color: var(--colors-white); + display: flex; + align-items: center; + justify-content: center; + height: 60px; + width: 60px; + box-sizing: border-box; +} + +.icon { + font-size: var(--fds-sizing-7); +} + +.textContainer { + flex: 1; +} + +@media (min-width: 768px) { + .section { + padding: var(--fds-spacing-12); + } +} + +@media (min-width: 960px) { + .section { + padding-right: var(--fds-spacing-22); + } +} diff --git a/frontend/studio-root/components/ContactSection/ContactSection.test.tsx b/frontend/studio-root/components/ContactSection/ContactSection.test.tsx new file mode 100644 index 00000000000..d317125678b --- /dev/null +++ b/frontend/studio-root/components/ContactSection/ContactSection.test.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { ContactSection, type ContactSectionProps } from './ContactSection'; +import { render, screen } from '@testing-library/react'; +import { SlackIcon } from '@studio/icons'; + +const defaultContactSectionProps: ContactSectionProps = { + title: '', + description: '', + link: { + name: '', + href: '', + }, + Icon: SlackIcon, +}; + +describe('ContactSection', () => { + it('should render with provided props', () => { + const props: ContactSectionProps = { + ...defaultContactSectionProps, + title: 'Get in touch', + description: 'We are helpfull', + Icon: SlackIcon, + link: { + name: 'Get in touch', + href: 'mailto:email@unittest.com', + }, + additionalContent: 'additional content', + }; + renderContactSection(props); + + const icon = screen.getByTitle(props.title); + expect(icon).toBeInTheDocument(); + + const heading = screen.getByRole('heading', { name: props.title, level: 2 }); + expect(heading).toBeInTheDocument(); + + const description = screen.getByText(props.description); + expect(description).toBeInTheDocument(); + + const additionalContent = screen.getByText(props.additionalContent as string); + expect(additionalContent).toBeInTheDocument(); + + const link = screen.getByRole('link', { name: props.link.name }); + expect(link).toBeInTheDocument(); + expect(link).toHaveAttribute('href', props.link.href); + }); +}); + +function renderContactSection(props: ContactSectionProps = defaultContactSectionProps): void { + render(); +} diff --git a/frontend/studio-root/components/ContactSection/ContactSection.tsx b/frontend/studio-root/components/ContactSection/ContactSection.tsx new file mode 100644 index 00000000000..64b1d882402 --- /dev/null +++ b/frontend/studio-root/components/ContactSection/ContactSection.tsx @@ -0,0 +1,38 @@ +import React, { type ComponentType, type ReactElement, type ReactNode } from 'react'; +import { StudioHeading, StudioLink, StudioParagraph } from '@studio/components'; +import { type IconProps } from '@studio/icons'; +import classes from './ContactSection.module.css'; + +export type ContactSectionProps = { + title: string; + description: string; + link: { + name: string; + href: string; + }; + Icon: ComponentType; + additionalContent?: ReactNode; +}; +export const ContactSection = ({ + title, + description, + link, + Icon, + additionalContent, +}: ContactSectionProps): ReactElement => { + return ( +
+
+ +
+
+ + {title} + + {description} + {additionalContent && {additionalContent}} + {link.name} +
+
+ ); +}; diff --git a/frontend/studio-root/components/ContactSection/index.ts b/frontend/studio-root/components/ContactSection/index.ts new file mode 100644 index 00000000000..3c10a9d8ee4 --- /dev/null +++ b/frontend/studio-root/components/ContactSection/index.ts @@ -0,0 +1 @@ +export { ContactSection, type ContactSectionProps } from './ContactSection'; diff --git a/frontend/studio-root/pages/Contact/ContactPage.module.css b/frontend/studio-root/pages/Contact/ContactPage.module.css index 7b5b101c6b6..9bc0ade813f 100644 --- a/frontend/studio-root/pages/Contact/ContactPage.module.css +++ b/frontend/studio-root/pages/Contact/ContactPage.module.css @@ -10,7 +10,6 @@ flex-direction: column; font-family: var(--studio-font-family); position: relative; - margin: var(--fds-spacing-10) auto; max-width: 1230px; } @@ -22,47 +21,8 @@ margin: var(--fds-spacing-12) var(--fds-spacing-8); } -.section { - background-color: var(--colors-grey-100); - border-radius: 4px; - display: flex; - gap: var(--fds-spacing-6); - padding: var(--fds-spacing-8); - max-width: 735px; -} - -.iconContainer { - background-color: var(--primary-color-700); - border-radius: 100%; - color: var(--colors-white); - display: flex; - align-items: center; - justify-content: center; - height: 60px; - width: 60px; - box-sizing: border-box; -} - -.icon { - font-size: 2.3rem; -} - -.textContainer { - flex: 1; -} - @media (min-width: 768px) { .content { margin: var(--fds-spacing-18); } - - .section { - padding: var(--fds-spacing-12); - } -} - -@media (min-width: 960px) { - .section { - padding-right: var(--fds-spacing-22); - } } diff --git a/frontend/studio-root/pages/Contact/ContactPage.tsx b/frontend/studio-root/pages/Contact/ContactPage.tsx index 0196d83a43a..7aa6d6e8f8d 100644 --- a/frontend/studio-root/pages/Contact/ContactPage.tsx +++ b/frontend/studio-root/pages/Contact/ContactPage.tsx @@ -1,16 +1,19 @@ import React from 'react'; import classes from './ContactPage.module.css'; -import { Heading, Link, Paragraph } from '@digdir/designsystemet-react'; import { Trans, useTranslation } from 'react-i18next'; import { EnvelopeClosedIcon, SlackIcon, GitHubIcon } from '@studio/icons'; -import classNames from 'classnames'; import { GetInTouchWith } from 'app-shared/getInTouch'; import { EmailContactProvider, GitHubIssueContactProvider, SlackContactProvider, } from 'app-shared/getInTouch/providers'; -import { StudioPageImageBackgroundContainer } from '@studio/components'; +import { + StudioPageImageBackgroundContainer, + StudioHeading, + StudioParagraph, +} from '@studio/components'; +import { ContactSection, type ContactSectionProps } from '../../components/ContactSection'; export const ContactPage = (): React.ReactElement => { const { t } = useTranslation(); @@ -18,64 +21,57 @@ export const ContactPage = (): React.ReactElement => { const contactBySlack = new GetInTouchWith(new SlackContactProvider()); const contactByGitHubIssue = new GetInTouchWith(new GitHubIssueContactProvider()); + const contactSections: Array = [ + { + title: t('contact.email.heading'), + description: t('contact.email.content'), + link: { + name: t('general.service_desk.email'), + href: contactByEmail.url('serviceDesk'), + }, + Icon: EnvelopeClosedIcon, + }, + { + title: t('contact.slack.heading'), + description: t('contact.slack.content'), + additionalContent: ( + +
    + +
  • + +
+
+ ), + link: { + name: t('contact.slack.link'), + href: contactBySlack.url('product-altinn-studio'), + }, + Icon: SlackIcon, + }, + { + title: t('contact.github_issue.heading'), + description: t('contact.github_issue.content'), + link: { + name: t('contact.github_issue.link_label'), + href: contactByGitHubIssue.url('choose'), + }, + Icon: GitHubIcon, + }, + ]; + return (
- + {t('general.contact')} - +
-
-
- -
-
- - {t('contact.email.heading')} - - {t('contact.email.content')} - - {t('general.service_desk.email')} - -
-
-
-
- -
-
- - {t('contact.slack.heading')} - - {t('contact.slack.content')} - -
    - -
  • - -
-
- - {t('contact.slack.link')} - -
-
-
-
- -
-
- - {t('contact.github_issue.heading')} - - {t('contact.github_issue.content')} - - {t('contact.github_issue.link_label')} - -
-
+ {contactSections.map((contactSection) => ( + + ))}