diff --git a/.changeset/slimy-bikes-wash.md b/.changeset/slimy-bikes-wash.md new file mode 100644 index 0000000000..94d88263bc --- /dev/null +++ b/.changeset/slimy-bikes-wash.md @@ -0,0 +1,5 @@ +--- +"@marigold/system": patch +--- + +create Element component + normalize file diff --git a/packages/system/src/Element.test.tsx b/packages/system/src/Element.test.tsx new file mode 100644 index 0000000000..618e7a668c --- /dev/null +++ b/packages/system/src/Element.test.tsx @@ -0,0 +1,203 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { useStyles } from './useStyles'; +import { ThemeProvider } from './useTheme'; +import { Element } from './Element'; + +const theme = { + text: { + body: { + fontSize: 1, + color: 'black', + marginTop: '2px', + }, + heading: { + fontSize: 3, + color: 'primary', + }, + padding: { + paddingTop: '2px', + }, + }, +}; + +test('renders a
by default', () => { + render(Text); + const testelem = screen.getByText('Text'); + + expect(testelem instanceof HTMLDivElement).toBeTruthy(); +}); + +test('supports as prop', () => { + render(Text); + const testelem = screen.getByText('Text'); + + expect(testelem instanceof HTMLParagraphElement).toBeTruthy(); +}); + +test('supports HTML className attribute', () => { + render(Text); + const element = screen.getByText('Text'); + + expect(element.getAttribute('class')).toMatch('my-custom-class'); +}); + +test('passes down HTML attributes', () => { + render( + + Text + + ); + const element = screen.getByText('Text'); + + expect(element.getAttribute('id')).toEqual('element-id'); + expect(element.getAttribute('disabled')).toMatch(''); + expect(element.getAttribute('class')).toMatch('my-custom-class'); +}); + +test('forwards ref', () => { + const ref = React.createRef(); + render( + + button + + ); + + expect(ref.current instanceof HTMLButtonElement).toBeTruthy(); +}); + +test('base styles first', () => { + const { getByText } = render(Text); + const testelem = getByText('Text'); + const style = getComputedStyle(testelem); + + expect(style.marginTop).toEqual('0px'); // 0px come from base +}); + +test('variant styles second', () => { + const TestComponent: React.FC<{ variant?: 'body' }> = ({ + variant = 'body', + children, + ...props + }) => { + return ( + + {children} + + ); + }; + + const { getByText } = render( + + Text + + ); + const testelem = getByText('Text'); + const style = getComputedStyle(testelem); + + expect(style.marginTop).not.toEqual('0px'); // 0px come from base + expect(style.marginBottom).toEqual('0px'); // 0px still come from base + expect(style.marginTop).toEqual('2px'); // 2px come from variant +}); + +test('array of variant styles', () => { + const TestComponent: React.FC<{ variant?: 'body' }> = ({ + variant = 'body', + children, + ...props + }) => { + return ( + + {children} + + ); + }; + + const { getByText } = render( + + Text + + ); + const testelem = getByText('Text'); + const style = getComputedStyle(testelem); + + expect(style.marginTop).not.toEqual('0px'); // 0px come from base + expect(style.marginBottom).toEqual('0px'); // 0px still come from base + expect(style.marginTop).toEqual('2px'); // 2px marginTop come from variant + expect(style.paddingTop).toEqual('2px'); // 2px paddingTop come from variant +}); + +test('custom styles with css prop third', () => { + const TestComponent: React.FC<{ variant?: 'body' }> = ({ + variant = 'body', + children, + ...props + }) => { + return ( + + {children} + + ); + }; + + const { getByText } = render( + + Text + + ); + const testelem = getByText('Text'); + const style = getComputedStyle(testelem); + + expect(style.marginTop).not.toEqual('0px'); // do not apply 0px from base + expect(style.marginTop).not.toEqual('2px'); // do not apply 2px from variant + expect(style.marginTop).toEqual('4px'); // apply 4px from custom styles +}); + +test("don't apply the same reset multiple times", () => { + const Button = ({ className }: { className?: string }) => { + const classNames = useStyles({ element: 'button', className }); + return ( + + Click me! + + ); + }; + const Wrapper = () =>