generated from nl-design-system/example
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: create FormLabel react component package
- Loading branch information
1 parent
af681a3
commit dda41cb
Showing
13 changed files
with
505 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@utrecht/form-label-react": major | ||
--- | ||
|
||
Create FormLabel react component package |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"env": { | ||
"jest/globals": true | ||
}, | ||
"rules": { | ||
"react/react-in-jsx-scope": "off" | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
packages/components-react/form-label-react/babel.config.cjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
module.exports = { | ||
presets: [ | ||
'@babel/preset-env', | ||
[ | ||
'@babel/preset-react', | ||
{ | ||
runtime: 'automatic', | ||
}, | ||
], | ||
'@babel/preset-typescript', | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export default { | ||
moduleDirectories: ['node_modules', '<rootDir>/'], | ||
testEnvironment: 'jest-environment-jsdom', | ||
testPathIgnorePatterns: ['/dist/'], | ||
moduleNameMapper: { | ||
'^@utrecht/(.*)$': '<rootDir>/../$1/src/', | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
{ | ||
"name": "@utrecht/form-label-react", | ||
"version": "0.0.0", | ||
"author": "Community for NL Design System", | ||
"description": "Form Label component for the Municipality of Utrecht based on the NL Design System architecture", | ||
"license": "EUPL-1.2", | ||
"main": "./dist/index.cjs.js", | ||
"module": "./dist/index.esm.js", | ||
"types": "./dist/index.d.ts", | ||
"files": [ | ||
"dist/", | ||
"src/" | ||
], | ||
"sideEffects": false, | ||
"scripts": { | ||
"clean": "rimraf dist *.tsbuildinfo .rollup.cache coverage", | ||
"build": "rollup --config ./rollup.config.mjs", | ||
"test": "mkdir -p pages && jest --coverage --verbose", | ||
"typecheck": "tsc --noEmit" | ||
}, | ||
"devDependencies": { | ||
"@babel/plugin-transform-runtime": "7.24.7", | ||
"@babel/preset-env": "7.24.7", | ||
"@babel/preset-react": "7.24.7", | ||
"@babel/preset-typescript": "7.24.7", | ||
"@rollup/plugin-babel": "6.0.4", | ||
"@rollup/plugin-commonjs": "26.0.1", | ||
"@rollup/plugin-json": "6.1.0", | ||
"@rollup/plugin-node-resolve": "15.2.3", | ||
"@rollup/plugin-typescript": "12.1.0", | ||
"@testing-library/dom": "8.20.1", | ||
"@testing-library/jest-dom": "6.5.0", | ||
"@testing-library/react": "16.0.1", | ||
"@testing-library/user-event": "14.5.1", | ||
"@types/jest": "29.5.13", | ||
"@types/react": "18.3.3", | ||
"@types/testing-library__jest-dom": "5.14.9", | ||
"@utrecht/form-label-css": "workspace:*", | ||
"jest": "29.7.0", | ||
"jest-environment-jsdom": "29.7.0", | ||
"react": "18.3.1", | ||
"rollup": "4.23.0", | ||
"rollup-plugin-filesize": "10.0.0", | ||
"rollup-plugin-node-externals": "7.1.2", | ||
"rollup-plugin-peer-deps-external": "2.2.4", | ||
"rollup-plugin-postcss": "4.0.2", | ||
"typescript": "5.6.2" | ||
}, | ||
"keywords": [ | ||
"nl-design-system" | ||
], | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"repository": { | ||
"type": "git+ssh", | ||
"url": "git@github.com:nl-design-system/utrecht.git", | ||
"directory": "packages/components-react/form-label-react" | ||
}, | ||
"peerDependencies": { | ||
"@babel/runtime": "*", | ||
"react": "18", | ||
"react-dom": "18" | ||
}, | ||
"dependencies": { | ||
"clsx": "2.1.1" | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
packages/components-react/form-label-react/rollup.config.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import babel from '@rollup/plugin-babel'; | ||
import commonjs from '@rollup/plugin-commonjs'; | ||
import json from '@rollup/plugin-json'; | ||
import resolve from '@rollup/plugin-node-resolve'; | ||
import typescript from '@rollup/plugin-typescript'; | ||
import { readFileSync } from 'fs'; | ||
import filesize from 'rollup-plugin-filesize'; | ||
import nodeExternal from 'rollup-plugin-node-externals'; | ||
import peerDepsExternal from 'rollup-plugin-peer-deps-external'; | ||
import postcss from 'rollup-plugin-postcss'; | ||
|
||
const packagePath = new URL('./package.json', import.meta.url).pathname; | ||
const packageJson = JSON.parse(readFileSync(packagePath, 'utf8')); | ||
|
||
/** | ||
* @type {import('rollup').RollupOptions} | ||
*/ | ||
export default [ | ||
{ | ||
input: './src/index.tsx', | ||
output: [ | ||
{ | ||
file: packageJson.main, | ||
format: 'cjs', | ||
sourcemap: true, | ||
}, | ||
{ | ||
file: packageJson.module, | ||
format: 'es', | ||
sourcemap: true, | ||
}, | ||
], | ||
plugins: [ | ||
peerDepsExternal(), | ||
commonjs(), | ||
nodeExternal(), | ||
resolve({ browser: true }), | ||
json(), | ||
typescript({ tsconfig: './tsconfig.build.json' }), | ||
babel({ | ||
presets: ['@babel/preset-react'], | ||
babelHelpers: 'runtime', | ||
exclude: ['node_modules/**', 'dist/**'], | ||
extensions: ['.ts', '.tsx'], | ||
inputSourceMap: true, | ||
plugins: ['@babel/plugin-transform-runtime'], | ||
}), | ||
filesize(), | ||
], | ||
}, | ||
{ | ||
input: './src/css.tsx', | ||
output: [ | ||
{ | ||
file: './dist/css.js', | ||
format: 'cjs', | ||
sourcemap: true, | ||
}, | ||
{ | ||
file: './dist/css.mjs', | ||
format: 'es', | ||
sourcemap: true, | ||
}, | ||
], | ||
plugins: [ | ||
peerDepsExternal(), | ||
commonjs(), | ||
nodeExternal(), | ||
resolve({ browser: true }), | ||
json(), | ||
postcss({ | ||
extensions: ['.css', '.scss'], | ||
minimize: true, | ||
}), | ||
typescript({ tsconfig: './tsconfig.build.json' }), | ||
babel({ | ||
presets: ['@babel/preset-react'], | ||
babelHelpers: 'runtime', | ||
exclude: ['node_modules/**', 'dist/**'], | ||
extensions: ['.ts', '.tsx'], | ||
inputSourceMap: true, | ||
plugins: ['@babel/plugin-transform-runtime'], | ||
}), | ||
filesize(), | ||
], | ||
}, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/** | ||
* @license EUPL-1.2 | ||
* Copyright (c) 2020-2025 Frameless B.V. | ||
* Copyright (c) 2021-2025 Gemeente Utrecht | ||
*/ | ||
|
||
import '@utrecht/form-label-css/src/index.scss'; | ||
|
||
export * from './index'; |
147 changes: 147 additions & 0 deletions
147
packages/components-react/form-label-react/src/index.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import { render, screen } from '@testing-library/react'; | ||
import { createRef } from 'react'; | ||
import { FormLabel } from './index'; | ||
import '@testing-library/jest-dom'; | ||
|
||
describe('Form label', () => { | ||
it('renders an HTML label element', () => { | ||
const { container } = render(<FormLabel htmlFor="form-control" />); | ||
|
||
const label = container.querySelector('label:only-child'); | ||
|
||
expect(label).toBeInTheDocument(); | ||
expect(label).toBeVisible(); | ||
}); | ||
|
||
it('renders an HTML label element with for attribute', () => { | ||
const { container } = render(<FormLabel htmlFor="form-control" />); | ||
|
||
const label = container.querySelector('label[for="form-control"]:only-child'); | ||
|
||
expect(label).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders a design system BEM class name', () => { | ||
const { container } = render(<FormLabel htmlFor="form-control" />); | ||
|
||
const label = container.querySelector(':only-child'); | ||
|
||
expect(label).toHaveClass('utrecht-form-label'); | ||
}); | ||
|
||
describe('variant for radio button in radio group', () => { | ||
it('renders a design system BEM class name', () => { | ||
const { container } = render(<FormLabel htmlFor="form-control" type="radio" />); | ||
|
||
const label = container.querySelector(':only-child'); | ||
|
||
expect(label).toHaveClass('utrecht-form-label--radio'); | ||
}); | ||
}); | ||
|
||
describe('variant for checkbox in checkbox group', () => { | ||
it('renders a design system BEM class name', () => { | ||
const { container } = render(<FormLabel htmlFor="form-control" type="checkbox" />); | ||
|
||
const label = container.querySelector(':only-child'); | ||
|
||
expect(label).toHaveClass('utrecht-form-label--checkbox'); | ||
}); | ||
}); | ||
|
||
describe('variant for a disabled form control', () => { | ||
it('renders a design system BEM class name', () => { | ||
const { container } = render(<FormLabel disabled htmlFor="form-control" />); | ||
|
||
const label = container.querySelector(':only-child'); | ||
|
||
expect(label).toHaveClass('utrecht-form-label--disabled'); | ||
}); | ||
}); | ||
|
||
describe('variant for a selected checkbox or radio button', () => { | ||
it('renders a design system BEM class name', () => { | ||
const { container } = render(<FormLabel checked htmlFor="form-control" />); | ||
|
||
const label = container.querySelector(':only-child'); | ||
|
||
expect(label).toHaveClass('utrecht-form-label--checked'); | ||
}); | ||
}); | ||
|
||
// Skipped because in js-dom the element unexpectedly does not have an associated `display` style | ||
it.skip('displays as CSS inline element', () => { | ||
const { container } = render(<FormLabel htmlFor="form-control" />); | ||
|
||
const label = container.querySelector(':only-child'); | ||
|
||
expect(label).toBeVisible(); | ||
expect(label).toHaveStyle({ display: 'inline' }); | ||
}); | ||
|
||
it('renders rich text content', () => { | ||
const { container } = render( | ||
<FormLabel htmlFor="form-control"> | ||
<strong>Current</strong> password | ||
</FormLabel>, | ||
); | ||
|
||
const label = container.querySelector(':only-child'); | ||
|
||
const richText = label?.querySelector('strong'); | ||
|
||
expect(richText).toBeInTheDocument(); | ||
}); | ||
|
||
it('can be associated with an HTML form input', () => { | ||
render( | ||
<> | ||
<FormLabel htmlFor="email">Email</FormLabel> | ||
<input type="email" id="email" /> | ||
</>, | ||
); | ||
|
||
const textbox = screen.getByRole('textbox', { | ||
name: 'Email', | ||
}); | ||
|
||
expect(textbox).toBeInTheDocument(); | ||
expect(textbox).toBeVisible(); | ||
}); | ||
|
||
it('can be hidden', () => { | ||
const { container } = render(<FormLabel hidden htmlFor="form-control" />); | ||
|
||
const label = container.querySelector(':only-child'); | ||
|
||
expect(label).not.toBeVisible(); | ||
}); | ||
|
||
it('can have a custom class name', () => { | ||
const { container } = render(<FormLabel className="question" htmlFor="form-control" />); | ||
|
||
const label = container.querySelector(':only-child'); | ||
|
||
expect(label).toHaveClass('question'); | ||
}); | ||
|
||
it('can have a additional class name', () => { | ||
const { container } = render(<FormLabel className="large" htmlFor="form-control" />); | ||
|
||
const label = container.querySelector(':only-child'); | ||
|
||
expect(label).toHaveClass('large'); | ||
|
||
expect(label).toHaveClass('utrecht-form-label'); | ||
}); | ||
|
||
it('supports ForwardRef in React', () => { | ||
const ref = createRef<HTMLLabelElement>(); | ||
|
||
const { container } = render(<FormLabel htmlFor="form-control" ref={ref} />); | ||
|
||
const div = container.querySelector(':only-child'); | ||
|
||
expect(ref.current).toBe(div); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/** | ||
* @license EUPL-1.2 | ||
* Copyright (c) 2020-2025 Frameless B.V. | ||
* Copyright (c) 2021-2025 Gemeente Utrecht | ||
*/ | ||
|
||
import clsx from 'clsx'; | ||
import { ForwardedRef, forwardRef, LabelHTMLAttributes, PropsWithChildren } from 'react'; | ||
|
||
export interface FormLabelProps extends LabelHTMLAttributes<HTMLLabelElement> { | ||
type?: 'checkbox' | 'radio'; | ||
disabled?: boolean; | ||
checked?: boolean; | ||
} | ||
|
||
export const FormLabel = forwardRef( | ||
( | ||
{ children, className, type, disabled, checked, ...restProps }: PropsWithChildren<FormLabelProps>, | ||
ref: ForwardedRef<HTMLLabelElement>, | ||
) => ( | ||
<label | ||
{...restProps} | ||
ref={ref} | ||
className={clsx( | ||
'utrecht-form-label', | ||
type && `utrecht-form-label--${type}`, | ||
disabled && 'utrecht-form-label--disabled', | ||
checked && 'utrecht-form-label--checked', | ||
className, | ||
)} | ||
> | ||
{children} | ||
</label> | ||
), | ||
); | ||
|
||
FormLabel.displayName = 'FormLabel'; |
6 changes: 6 additions & 0 deletions
6
packages/components-react/form-label-react/tsconfig.build.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"extends": "./tsconfig.json", | ||
"compilerOptions": { | ||
"composite": true | ||
} | ||
} |
Oops, something went wrong.