Skip to content

Commit

Permalink
chore: refa <Input> and <Input.Field> components and support icons (#…
Browse files Browse the repository at this point in the history
…2824)

Co-authored-by: Sebastian Sebald <sebastian.sebald@reservix.de>
  • Loading branch information
sarahgm and sebald committed Feb 27, 2023
1 parent de69c7a commit 33329ac
Show file tree
Hide file tree
Showing 18 changed files with 190 additions and 159 deletions.
6 changes: 6 additions & 0 deletions .changeset/healthy-dancers-explode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@marigold/docs": patch
"@marigold/components": minor
---

chore: refa <Input> and <Input.Field> components and support icons
8 changes: 3 additions & 5 deletions docs/src/demos/components/FieldGroup/bookings-form.demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
ThemeProvider,
Stack,
FieldBase,
Input,
Select,
TextArea,
} from '@marigold/components';
Expand All @@ -31,11 +30,10 @@ export const BookingForm = () => (
</Stack>
<Stack space="xsmall">
<TextField label="Straße" />
{/* This shouldn't be used, we need to fix it */}
<FieldBase label="PLZ / Ort">
<Inline space="xsmall">
<Input width="50px" />
<Input />
<TextField arial-label="PLZ" width="50px" />
<TextField arial-label="Ort" width="100px" />
</Inline>
</FieldBase>
<TextField label="Adresszusatz" />
Expand All @@ -54,7 +52,7 @@ export const BookingForm = () => (
{/* This shouldn't be used, we need to fix it */}
<FieldBase label="nach Kundennummern suchen">
<Inline space="xsmall">
<Input type="search" width="150px" />
<TextField arial-label="Search" type="search" width="150px" />
<Button variant="secondary" size="small">
Suchen
</Button>
Expand Down
3 changes: 0 additions & 3 deletions docs/src/demos/components/Input/index.ts

This file was deleted.

8 changes: 0 additions & 8 deletions docs/src/demos/components/Input/input-disabled.demo.tsx

This file was deleted.

18 changes: 0 additions & 18 deletions docs/src/demos/components/Input/input-type.demo.tsx

This file was deleted.

8 changes: 0 additions & 8 deletions docs/src/demos/components/Input/input.demo.tsx

This file was deleted.

4 changes: 3 additions & 1 deletion docs/src/demos/components/Label/label-input.demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Label, Input } from '@marigold/components';
export const LabelInput = () => (
<Label htmlFor="input">
Type in your Firstname
<Input id="input" type="text" placeholder="Firstname" />
<Input>
<Input.Field id="input" type="text" placeholder="Firstname" />
</Input>
</Label>
);
1 change: 0 additions & 1 deletion docs/src/demos/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export * from './Headline';
export * from './Icon';
export * from './Image';
export * from './Inline';
export * from './Input';
export * from './Inset';
export * from './Label';
export * from './Link';
Expand Down
4 changes: 0 additions & 4 deletions docs/src/pages/components/number-field.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ To import the component you just have to use this code below.
import { NumberField } from '@marigold/components';
```

### Appearance

<AppearanceTable component={title} />

### Props

<PropsTable
Expand Down
18 changes: 16 additions & 2 deletions packages/components/src/Input/Input.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React from 'react';
import type { Meta, ComponentStory } from '@storybook/react';
import { Input } from './Input';
import isChromatic from 'chromatic';
import { Delete, Search } from '@marigold/icons';
import { Button } from '../Button';
import { Input } from './Input';

export default {
title: 'Components/Input',
Expand Down Expand Up @@ -43,10 +45,22 @@ export default {
} as Meta;

export const Basic: ComponentStory<typeof Input> = args => (
<Input placeholder="Placeholder..." {...args} />
<Input>
<Input.Field placeholder="Placeholder..." {...args} disabled />
</Input>
);

Basic.parameters = {
chromatic: { viewports: [320, 1200] },
theme: isChromatic() ? 'b2b' : 'stacked',
};

export const WithIcons: ComponentStory<typeof Input> = args => (
<Input>
<Search />
<Input.Field placeholder="Placeholder..." />
<Button size="small" variant="text">
<Delete />
</Button>
</Input>
);
63 changes: 57 additions & 6 deletions packages/components/src/Input/Input.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { render, screen } from '@testing-library/react';
import { ThemeProvider } from '@marigold/system';
import { Input } from './Input';
import { Delete, Search } from '@marigold/icons';

const theme = {
fonts: {
Expand All @@ -25,29 +26,35 @@ const theme = {
test('supports default variant and themeSection', () => {
render(
<ThemeProvider theme={theme}>
<Input title="input" />
<Input data-testid="input">
<Input.Field title="input" />
</Input>
</ThemeProvider>
);
const input = screen.getByTitle('input');
const input = screen.getByTestId('input');

expect(input).toHaveStyle(`font-family: Inter`);
});

test('accepts other variant than default', () => {
render(
<ThemeProvider theme={theme}>
<Input title="input" variant="robo" />
<Input data-testid="input" variant="robo">
<Input.Field title="input" />
</Input>
</ThemeProvider>
);
const input = screen.getByTitle('input');
const input = screen.getByTestId('input');

expect(input).toHaveStyle(`font-family: Roboto`);
});

test('renders correct HTML element', () => {
render(
<ThemeProvider theme={theme}>
<Input title="input" />
<Input data-testid="input">
<Input.Field title="input" />
</Input>
</ThemeProvider>
);
const input = screen.getByTitle('input');
Expand All @@ -58,10 +65,54 @@ test('renders correct HTML element', () => {
test('supports custom prop', () => {
render(
<ThemeProvider theme={theme}>
<Input title="input" placeholder="placeholder" />
<Input data-testid="input">
<Input.Field title="input" placeholder="placeholder" />
</Input>
</ThemeProvider>
);
const input = screen.getByTitle('input');

expect(input).toHaveAttribute('placeholder');
});

test('renders correct HTML Div element', () => {
render(
<ThemeProvider theme={theme}>
<Input data-testid="input">
<Input.Field title="input" />
</Input>
</ThemeProvider>
);
const input = screen.getByTestId('input');

expect(input instanceof HTMLDivElement).toBeTruthy();
});

test('renders space prop', () => {
render(
<ThemeProvider theme={theme}>
<Input data-testid="input" space="4px">
<Input.Field title="input" />
</Input>
</ThemeProvider>
);
const input = screen.getByTestId('input');

expect(input).toHaveStyle('gap: 4px');
});

test('renders icons within', () => {
render(
<ThemeProvider theme={theme}>
<Input data-testid="input">
<Search />
<Input.Field title="input" />
<Delete />
</Input>
</ThemeProvider>
);
const input = screen.getByTestId('input');

// eslint-disable-next-line testing-library/no-node-access
expect(input.children).toBeTruthy();
});
56 changes: 42 additions & 14 deletions packages/components/src/Input/Input.tsx
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,27 +1,55 @@
import React, { forwardRef } from 'react';
import {
Box,
ResponsiveStyleValue,
ThemeExtension,
useComponentStyles,
} from '@marigold/system';
import { HtmlProps } from '@marigold/types';
import { Box, ThemeExtension, useComponentStyles } from '@marigold/system';
import React, { ReactNode } from 'react';
import { InputField } from './InputField';

// Theme Extension
// ---------------
export interface InputThemeExtension extends ThemeExtension<'Input'> {}

// Props
// ---------------
export interface InputOwnProps extends Omit<HtmlProps<'input'>, 'size'> {
size?: string;
export interface InputProps extends Omit<HtmlProps<'div'>, 'size'> {
children: ReactNode;
space?: ResponsiveStyleValue<string>;
variant?: string;
size?: string;
}

export interface InputProps
extends Omit<React.ComponentPropsWithRef<'input'>, 'size'>,
InputOwnProps {}

// Component
// ---------------
export const Input = forwardRef<HTMLInputElement, InputOwnProps>(
({ variant, size, type = 'text', ...props }: InputOwnProps, ref) => {
const styles = useComponentStyles('Input', { variant, size });
return <Box {...props} ref={ref} as="input" type={type} css={styles} />;
}
);
export const Input = ({
space = 'xsmall',
children,
variant,
size,
...props
}: InputProps) => {
const [leading, input, trailing] = React.Children.toArray(children);

const styles = useComponentStyles('Input', { variant, size });

return (
<Box
__baseCSS={{
display: 'flex',
alignItems: 'center',
width: '100%',
gap: space,
}}
css={styles}
{...props}
>
{leading}
{input}
{trailing}
</Box>
);
};

Input.Field = InputField;
27 changes: 27 additions & 0 deletions packages/components/src/Input/InputField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { forwardRef } from 'react';
import { HtmlProps } from '@marigold/types';
import { Box } from '@marigold/system';

// Props
// ---------------
export interface InputFieldOwnProps extends Omit<HtmlProps<'input'>, 'size'> {}

export interface InputFieldProps
extends Omit<React.ComponentPropsWithRef<'input'>, 'size'>,
InputFieldOwnProps {}

// Component
// ---------------
export const InputField = forwardRef<HTMLInputElement, InputFieldOwnProps>(
({ type = 'text', ...props }: InputFieldOwnProps, ref) => {
return (
<Box
__baseCSS={{ border: 0, width: '100%', outline: 'none' }}
{...props}
ref={ref}
as="input"
type={type}
/>
);
}
);
1 change: 1 addition & 0 deletions packages/components/src/Input/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './InputField';
export * from './Input';
31 changes: 4 additions & 27 deletions packages/components/src/NumberField/NumberField.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,10 @@ test('input can be styled via "Input" styles', () => {
</ThemeProvider>
);
const numberField = screen.getByTestId('number-field');
expect(numberField).toHaveStyle(`border-color: ${theme.colors.blue}`);
// eslint-disable-next-line testing-library/no-node-access
expect(numberField.parentElement).toHaveStyle(
`border-color: ${theme.colors.blue}`
);
});

test('group and stepper can styled via "NumberField" styles', () => {
Expand All @@ -152,32 +155,6 @@ test('group and stepper can styled via "NumberField" styles', () => {
expect(steppers[1]).toHaveStyle(`color: ${theme.colors.black}`);
});

test('passes down variant and size', () => {
render(
<ThemeProvider theme={theme}>
<NumberField
data-testid="number-field"
label="Label"
description="Description"
variant="lime"
size="small"
/>
</ThemeProvider>
);

const numberField = screen.getByTestId('number-field');
expect(numberField).toHaveStyle(`color: ${theme.colors.lime}`);
expect(numberField).toHaveStyle(`font-size: ${theme.fontSizes['small-1']}px`);

const label = screen.getByText('Label');
expect(label).toHaveStyle(`color: ${theme.colors.lime}`);
expect(label).toHaveStyle(`font-size: ${theme.fontSizes['small-1']}px`);

const description = screen.getByText('Description');
expect(description).toHaveStyle(`color: ${theme.colors.lime}`);
expect(description).toHaveStyle(`font-size: ${theme.fontSizes['small-1']}px`);
});

test('allows to set width via prop', () => {
render(
<ThemeProvider theme={theme}>
Expand Down
Loading

0 comments on commit 33329ac

Please sign in to comment.