Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Refactor subcomponents #1050

Merged
merged 15 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"react-dom": "18.2.0",
"rollup": "4.9.4",
"rollup-plugin-delete": "2.0.0",
"rollup-plugin-dts": "6.1.0",
"rollup-plugin-filesize": "10.0.0",
"rollup-plugin-node-externals": "6.1.2",
"rollup-plugin-node-polyfills": "0.2.1",
Expand Down
15 changes: 14 additions & 1 deletion packages/react/rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import nodeExternal from 'rollup-plugin-node-externals'
import nodePolyfills from 'rollup-plugin-node-polyfills'
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
import typescript from 'rollup-plugin-typescript2'
import dts from 'rollup-plugin-dts'
import del from 'rollup-plugin-delete'

const packageJson = JSON.parse(readFileSync('./package.json', 'utf8'))

Expand Down Expand Up @@ -46,7 +48,7 @@ export default [
include: /node_modules/,
}),
nodePolyfills(),
typescript({ includeDependencies: false }),
typescript({ includeDependencies: false, useTsconfigDeclarationDir: true }),
babel({
presets: ['@babel/preset-react'],
babelHelpers: 'runtime',
Expand All @@ -58,4 +60,15 @@ export default [
filesize(),
],
},
{
input: './dist/dts/index.d.ts',
output: [{ file: 'dist/index.d.ts', format: 'es' }],
plugins: [
dts(),
del({
targets: 'dist/dts',
hook: 'buildEnd',
}),
],
},
]
19 changes: 19 additions & 0 deletions packages/react/src/Breadcrumb/Breadcrumb.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ import { Breadcrumb } from './Breadcrumb'
import '@testing-library/jest-dom'

describe('Breadcrumb', () => {
it('renders', () => {
render(<Breadcrumb />)
const component = screen.getByRole('navigation')
expect(component).toBeInTheDocument()
expect(component).toBeVisible()
})

it('renders a design system BEM class name', () => {
render(<Breadcrumb />)
const component = screen.getByRole('navigation')
expect(component).toHaveClass('amsterdam-breadcrumb')
})

it('renders an additional class name', () => {
render(<Breadcrumb className="extra" />)
const component = screen.getByRole('navigation')
expect(component).toHaveClass('amsterdam-breadcrumb extra')
})

it('renders Breadcrumb component with children', () => {
const breadcrumbItems = [
{ label: 'Item 1', href: '/item-1' },
Expand Down
30 changes: 8 additions & 22 deletions packages/react/src/Breadcrumb/Breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,26 @@
* Copyright (c) 2023 Gemeente Amsterdam
*/

import { clsx } from 'clsx'
import { forwardRef } from 'react'
import type { ForwardedRef, ForwardRefExoticComponent, HTMLAttributes, PropsWithChildren, RefAttributes } from 'react'
import { BreadcrumbItem } from './BreadcrumbItem'

export type BreadcrumbProps = PropsWithChildren<HTMLAttributes<HTMLElement>>

interface BreadcrumbComponent extends ForwardRefExoticComponent<BreadcrumbProps & RefAttributes<HTMLElement>> {
Item: typeof BreadcrumbItem
}

export const Breadcrumb = forwardRef(({ children, ...restProps }: BreadcrumbProps, ref: ForwardedRef<HTMLElement>) => {
return (
<nav {...restProps} className="amsterdam-breadcrumb" ref={ref}>
export const Breadcrumb = forwardRef(
({ children, className, ...restProps }: BreadcrumbProps, ref: ForwardedRef<HTMLElement>) => (
<nav {...restProps} className={clsx('amsterdam-breadcrumb', className)} ref={ref}>
<ol className="amsterdam-breadcrumb__list">{children}</ol>
</nav>
)
}) as BreadcrumbComponent
),
) as BreadcrumbComponent

Breadcrumb.displayName = 'Breadcrumb'

export interface BreadcrumbItemProps extends PropsWithChildren<HTMLAttributes<HTMLLIElement>> {
href: string
}

const BreadcrumbItem = forwardRef(
({ children, href, ...restProps }: BreadcrumbItemProps, ref: ForwardedRef<HTMLLIElement>) => {
return (
<li {...restProps} className="amsterdam-breadcrumb__item" ref={ref}>
<a className="amsterdam-breadcrumb__link" href={href}>
{children}
</a>
</li>
)
},
)

BreadcrumbItem.displayName = 'BreadcrumbItem'
Breadcrumb.Item = BreadcrumbItem
Breadcrumb.Item.displayName = 'Breadcrumb.Item'
41 changes: 41 additions & 0 deletions packages/react/src/Breadcrumb/BreadcrumbItem.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { render, screen } from '@testing-library/react'
import { createRef } from 'react'
import { BreadcrumbItem } from './BreadcrumbItem'
import '@testing-library/jest-dom'

describe('BreadcrumbItem', () => {
it('renders', () => {
render(<BreadcrumbItem href="/" />)
const component = screen.getByRole('listitem')
expect(component).toBeInTheDocument()
expect(component).toBeVisible()
})

it('renders a design system BEM class name', () => {
render(<BreadcrumbItem href="/" />)
const item = screen.getByRole('listitem')
expect(item).toHaveClass('amsterdam-breadcrumb__item')

const link = screen.getByRole('link')
expect(link).toHaveClass('amsterdam-breadcrumb__link')
})

it('renders an additional class name', () => {
render(<BreadcrumbItem href="/" className="extra" />)
const component = screen.getByRole('listitem')
expect(component).toHaveClass('amsterdam-breadcrumb__item extra')
})

it('renders the href attribute', () => {
render(<BreadcrumbItem href="/" />)
const component = screen.getByRole('link')
expect(component).toHaveAttribute('href', '/')
})

it('supports ForwardRef in React', () => {
const ref = createRef<HTMLLIElement>()
render(<BreadcrumbItem href="/" ref={ref} />)
const component = screen.getByRole('listitem')
expect(ref.current).toBe(component)
})
})
24 changes: 24 additions & 0 deletions packages/react/src/Breadcrumb/BreadcrumbItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @license EUPL-1.2+
* Copyright (c) 2023 Gemeente Amsterdam
*/

import { clsx } from 'clsx'
import { forwardRef } from 'react'
import type { ForwardedRef, HTMLAttributes, PropsWithChildren } from 'react'

export interface BreadcrumbItemProps extends PropsWithChildren<HTMLAttributes<HTMLLIElement>> {
href: string
}

export const BreadcrumbItem = forwardRef(
({ children, className, href, ...restProps }: BreadcrumbItemProps, ref: ForwardedRef<HTMLLIElement>) => (
<li {...restProps} className={clsx('amsterdam-breadcrumb__item', className)} ref={ref}>
<a className="amsterdam-breadcrumb__link" href={href}>
{children}
</a>
</li>
),
)

BreadcrumbItem.displayName = 'BreadcrumbItem'
VincentSmedinga marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 2 additions & 1 deletion packages/react/src/Breadcrumb/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { Breadcrumb } from './Breadcrumb'
export type { BreadcrumbProps, BreadcrumbItemProps } from './Breadcrumb'
export type { BreadcrumbProps } from './Breadcrumb'
export type { BreadcrumbItemProps } from './BreadcrumbItem'
dlnr marked this conversation as resolved.
Show resolved Hide resolved
52 changes: 10 additions & 42 deletions packages/react/src/Card/Card.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,60 +14,28 @@ describe('Card', () => {
})

it('renders a design system BEM class name', () => {
const cardRender = render(<Card />)
const { container: cardHeadingGroupRender } = render(<Card.HeadingGroup tagline="test" />)
const cardLinkRender = render(<Card.Link href="/" />)
render(<Card />)

const card = cardRender.getByRole('article')
const cardHeadingGroup = cardHeadingGroupRender.querySelector(':only-child')
const cardLink = cardLinkRender.getByRole('link')
const component = screen.getByRole('article')

expect(card).toHaveClass('amsterdam-card')
expect(cardHeadingGroup).toHaveClass('amsterdam-card__heading-group')
expect(cardLink).toHaveClass('amsterdam-card__link')
expect(component).toHaveClass('amsterdam-card')
})

it('renders an additional class name', () => {
const cardRender = render(<Card className="extra" />)
const { container: cardHeadingGroupRender } = render(<Card.HeadingGroup tagline="test" className="extra" />)
const cardLinkRender = render(<Card.Link href="/" className="extra" />)
render(<Card className="extra" />)

const card = cardRender.getByRole('article')
const cardHeadingGroup = cardHeadingGroupRender.querySelector(':only-child')
const cardLink = cardLinkRender.getByRole('link')
const component = screen.getByRole('article')

expect(card).toHaveClass('extra')
expect(cardHeadingGroup).toHaveClass('extra')
expect(cardLink).toHaveClass('extra')

expect(card).toHaveClass('amsterdam-card')
expect(cardHeadingGroup).toHaveClass('amsterdam-card__heading-group')
expect(cardLink).toHaveClass('amsterdam-card__link')
})

it('renders a tagline', () => {
render(<Card.HeadingGroup tagline="tagline" />)

const tagline = screen.getByText('tagline')

expect(tagline).toBeInTheDocument()
expect(component).toHaveClass('amsterdam-card extra')
})

it('supports ForwardRef in React', () => {
const cardRef = createRef<HTMLElement>()
const cardHeadingGroupRef = createRef<HTMLElement>()
const cardLinkRef = createRef<HTMLAnchorElement>()
const ref = createRef<HTMLElement>()

const cardRender = render(<Card ref={cardRef} />)
const { container: cardHeadingGroupRender } = render(<Card.HeadingGroup tagline="test" ref={cardHeadingGroupRef} />)
const cardLinkRender = render(<Card.Link href="/" ref={cardLinkRef} />)
render(<Card ref={ref} />)

const card = cardRender.getByRole('article')
const cardHeadingGroup = cardHeadingGroupRender.querySelector(':only-child')
const cardLink = cardLinkRender.getByRole('link')
const component = screen.getByRole('article')

expect(cardRef.current).toBe(card)
expect(cardHeadingGroupRef.current).toBe(cardHeadingGroup)
expect(cardLinkRef.current).toBe(cardLink)
expect(ref.current).toBe(component)
})
})
40 changes: 3 additions & 37 deletions packages/react/src/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,9 @@

import clsx from 'clsx'
import { forwardRef } from 'react'
import type {
AnchorHTMLAttributes,
ForwardedRef,
ForwardRefExoticComponent,
HTMLAttributes,
PropsWithChildren,
RefAttributes,
} from 'react'
import { Paragraph } from '../Paragraph'

export interface CardHeadingProps extends PropsWithChildren<HTMLAttributes<HTMLElement>> {
tagline: string
}

export const CardHeadingGroup = forwardRef(
({ children, className, tagline, ...restProps }: CardHeadingProps, ref: ForwardedRef<HTMLElement>) => (
<hgroup {...restProps} ref={ref} className={clsx('amsterdam-card__heading-group', className)}>
{children}
<Paragraph size="small">{tagline}</Paragraph>
</hgroup>
),
)

CardHeadingGroup.displayName = 'CardHeadingGroup'

export const CardLink = forwardRef(
(
{ children, className, ...otherProps }: PropsWithChildren<AnchorHTMLAttributes<HTMLAnchorElement>>,
ref: ForwardedRef<HTMLAnchorElement>,
) => (
<a {...otherProps} ref={ref} className={clsx('amsterdam-card__link', className)}>
{children}
</a>
),
)

CardLink.displayName = 'CardLink'
import type { ForwardedRef, ForwardRefExoticComponent, HTMLAttributes, PropsWithChildren, RefAttributes } from 'react'
import { CardHeadingGroup } from './CardHeadingGroup'
import { CardLink } from './CardLink'

export interface CardProps extends PropsWithChildren<HTMLAttributes<HTMLElement>> {}

Expand Down
48 changes: 48 additions & 0 deletions packages/react/src/Card/CardHeadingGroup.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { render, screen } from '@testing-library/react'
import { createRef } from 'react'
import { CardHeadingGroup } from './CardHeadingGroup'
import '@testing-library/jest-dom'

describe('CardHeadingGroup', () => {
it('renders', () => {
const { container } = render(<CardHeadingGroup tagline="test" />)

const component = container.querySelector(':only-child')
VincentSmedinga marked this conversation as resolved.
Show resolved Hide resolved

expect(component).toBeInTheDocument()
expect(component).toBeVisible()
})

it('renders a design system BEM class name', () => {
const { container } = render(<CardHeadingGroup tagline="test" />)

const component = container.querySelector(':only-child')

expect(component).toHaveClass('amsterdam-card__heading-group')
})

it('renders an additional class name', () => {
const { container } = render(<CardHeadingGroup tagline="test" className="extra" />)

const component = container.querySelector(':only-child')

expect(component).toHaveClass('amsterdam-card__heading-group extra')
})

it('renders a tagline', () => {
render(<CardHeadingGroup tagline="tagline" />)

const tagline = screen.getByText('tagline')

expect(tagline).toBeInTheDocument()
})

it('supports ForwardRef in React', () => {
const ref = createRef<HTMLElement>()
const { container } = render(<CardHeadingGroup tagline="test" ref={ref} />)

const component = container.querySelector(':only-child')

expect(ref.current).toBe(component)
})
})
24 changes: 24 additions & 0 deletions packages/react/src/Card/CardHeadingGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @license EUPL-1.2+
* Copyright (c) 2023 Gemeente Amsterdam
*/

import clsx from 'clsx'
import { forwardRef } from 'react'
import type { ForwardedRef, HTMLAttributes, PropsWithChildren } from 'react'
import { Paragraph } from '../Paragraph'

export interface CardHeadingGroupProps extends PropsWithChildren<HTMLAttributes<HTMLElement>> {
tagline: string
}

export const CardHeadingGroup = forwardRef(
({ children, className, tagline, ...restProps }: CardHeadingGroupProps, ref: ForwardedRef<HTMLElement>) => (
<hgroup {...restProps} ref={ref} className={clsx('amsterdam-card__heading-group', className)}>
{children}
<Paragraph size="small">{tagline}</Paragraph>
</hgroup>
),
)

CardHeadingGroup.displayName = 'CardHeadingGroup'
Loading