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

feat(typography): add Paragraph component #724

Merged
merged 5 commits into from
Apr 21, 2020
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
16 changes: 8 additions & 8 deletions packages/typography/.size-snapshot.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
{
"dist/index.cjs.js": {
"bundled": 16687,
"minified": 12165,
"gzipped": 2674
"bundled": 18050,
"minified": 13198,
"gzipped": 2807
},
"dist/index.esm.js": {
"bundled": 15576,
"minified": 11125,
"gzipped": 2545,
"bundled": 16866,
"minified": 12087,
"gzipped": 2671,
"treeshaked": {
"rollup": {
"code": 8012,
"code": 8714,
"import_statements": 273
},
"webpack": {
"code": 9782
"code": 10538
}
}
}
Expand Down
93 changes: 93 additions & 0 deletions packages/typography/examples/paragraph.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
Paragraphs may be sized as `small`, `medium` (the default), or `large`.
Sizing only controls spacing between sibling paragraphs, but the intention is
that the paragraph will contain typography which is sized to match.

```jsx
const { Well } = require('@zendeskgarden/react-notifications/src');
const { Toggle, Field, Input, Label, Range } = require('@zendeskgarden/react-forms/src');
const {
Dropdown,
Select,
Field: SelectField,
Label: SelectLabel,
Menu,
Item: MenuItem
} = require('@zendeskgarden/react-dropdowns/src');

initialState = {
count: 2,
size: Paragraph.defaultProps.size
};

const Typography = ({ size, children, ...props }) => {
switch (size) {
case 'small':
return <SM {...props}>{children}</SM>;
case 'medium':
return <MD {...props}>{children}</MD>;
case 'large':
return <LG {...props}>{children}</LG>;
}
};

<Grid>
<Row>
<Col>
<Well isRecessed style={{ width: 300 }}>
<Dropdown selectedItem={state.size} onSelect={size => setState({ size })}>
<SelectField>
<SelectLabel>Size</SelectLabel>
<Select isCompact>{state.size}</Select>
</SelectField>
<Menu isCompact>
<MenuItem value="small">small</MenuItem>
<MenuItem value="medium">medium (default)</MenuItem>
<MenuItem value="large">large</MenuItem>
</Menu>
</Dropdown>
<Field className="u-mt-xs">
<Label>Count</Label>
<Range
max={3}
min={1}
value={state.count}
onChange={event => setState({ count: event.target.value })}
/>
</Field>
</Well>
</Col>
<Col>
<Paragraph size={state.size}>
<Typography size={state.size} as="span">
Veggies es bonus vobis, proinde vos postulo essum magis kohlrabi welsh onion daikon
amaranth tatsoi tomatillo melon <Code size={state.size}>azuki</Code> bean garlic. Parsley
shallot courgette tatsoi pea sprouts fava bean collard greens{' '}
<Code size={state.size}>dandelion</Code> okra wakame tomato. Dandelion cucumber earthnut
pea peanut soko zucchini.
</Typography>
</Paragraph>
{state.count >= 2 && (
<Paragraph>
<Typography size={state.size} as="span">
Soko radicchio bunya nuts gram dulse silver beet parsnip napa cabbage lotus root sea
lettuce <Code size={state.size}>brussels</Code> sprout cabbage. Catsear cauliflower
garbanzo yarrow salsify chicory garlic bell <Code size={state.size}>pepper</Code> napa
cabbage lettuce tomato kale arugula melon sierra leone bologi rutabaga tigernut.
</Typography>
</Paragraph>
)}
{state.count == 3 && (
<Paragraph>
<Typography size={state.size} as="span">
Water spinach arugula pea tatsoi aubergine spring onion bush tomato kale radicchio
turnip chicory salsify pea sprouts <Code size={state.size}>fava</Code> bean. Dandelion
zucchini burdock yarrow chickpea dandelion sorrel courgette turnip greens{' '}
<Code size={state.size}>tigernut</Code> soybean radish artichoke wattle seed endive
groundnut broccoli arugula.
</Typography>
</Paragraph>
)}
</Col>
</Row>
</Grid>;
```
53 changes: 53 additions & 0 deletions packages/typography/src/elements/Paragraph.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* Copyright Zendesk, Inc.
*
* Use of this source code is governed under the Apache License, Version 2.0
* found at http://www.apache.org/licenses/LICENSE-2.0.
*/

import React from 'react';
import { render, renderRtl } from 'garden-test-utils';
import { DEFAULT_THEME } from '@zendeskgarden/react-theming';
import Paragraph from './Paragraph';
import { StyledParagraph } from '../styled';

describe('Paragraph', () => {
it('applies correct styling with RTL locale', () => {
const { container } = renderRtl(<Paragraph />);

expect(container.firstChild).toHaveStyleRule('direction', 'rtl');
});

it('passes ref to underlying DOM element', () => {
const ref = React.createRef<HTMLParagraphElement>();
const { container } = render(<Paragraph ref={ref} />);

expect(container.firstChild).toBe(ref.current);
});

describe('size', () => {
it('renders small styling if provided', () => {
const { container } = render(<Paragraph size="small" />);

expect(container.firstChild).toHaveStyleRule('margin-top', DEFAULT_THEME.lineHeights.sm, {
modifier: ` + ${StyledParagraph}`
});
});

it('renders medium styling if provided', () => {
const { container } = render(<Paragraph size="medium" />);

expect(container.firstChild).toHaveStyleRule('margin-top', DEFAULT_THEME.lineHeights.md, {
modifier: ` + ${StyledParagraph}`
});
});

it('renders large styling if provided', () => {
const { container } = render(<Paragraph size="large" />);

expect(container.firstChild).toHaveStyleRule('margin-top', DEFAULT_THEME.lineHeights.lg, {
modifier: ` + ${StyledParagraph}`
});
});
});
});
46 changes: 46 additions & 0 deletions packages/typography/src/elements/Paragraph.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Copyright Zendesk, Inc.
*
* Use of this source code is governed under the Apache License, Version 2.0
* found at http://www.apache.org/licenses/LICENSE-2.0.
*/

import React, { HTMLAttributes } from 'react';
import PropTypes from 'prop-types';
import { StyledParagraph } from '../styled';

export interface IParagraphProps extends HTMLAttributes<HTMLParagraphElement> {
size?: 'small' | 'medium' | 'large';
}

/**
* Accepts all `<p>` attributes and events
*/
const Paragraph: React.FunctionComponent<
IParagraphProps & React.RefAttributes<HTMLParagraphElement>
> = React.forwardRef<HTMLParagraphElement, IParagraphProps>(({ size, ...other }, ref) => {
let _size: 'sm' | 'md' | 'lg';

if (size === 'small') {
_size = 'sm';
} else if (size === 'medium') {
_size = 'md';
} else {
_size = 'lg';
}

return <StyledParagraph ref={ref} size={_size} {...other} />;
});

Paragraph.displayName = 'Paragraph';

Paragraph.propTypes = {
size: PropTypes.oneOf(['small', 'medium', 'large'])
};

Paragraph.defaultProps = {
size: 'medium'
};

/** @component */
export default Paragraph;
2 changes: 1 addition & 1 deletion packages/typography/src/elements/lists/OrderedList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const OrderedList = React.forwardRef<HTMLOListElement, IOrderedListProps>(
({ size, type, ...other }, ref) => {
return (
<OrderedListContext.Provider value={{ size: size! }}>
<StyledOrderedList ref={ref} listType={type!} {...other} />
<StyledOrderedList ref={ref} listType={type} {...other} />
</OrderedListContext.Provider>
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/typography/src/elements/lists/UnorderedList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ interface IUnorderedListProps extends HTMLAttributes<HTMLUListElement> {
const UnorderedList = React.forwardRef<HTMLUListElement, IUnorderedListProps>(
({ size, type, ...other }, ref) => (
<UnorderedListContext.Provider value={{ size: size! }}>
<StyledUnorderedList ref={ref} listType={type!} {...other} />
<StyledUnorderedList ref={ref} listType={type} {...other} />
</UnorderedListContext.Provider>
)
);
Expand Down
1 change: 1 addition & 0 deletions packages/typography/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ export { default as XXL } from './elements/XXL';
export { default as XXXL } from './elements/XXXL';
export { default as Code } from './elements/Code';
export { default as Ellipsis } from './elements/Ellipsis';
export { default as Paragraph } from './elements/Paragraph';
export { default as OrderedList } from './elements/lists/OrderedList';
export { default as UnorderedList } from './elements/lists/UnorderedList';
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('StyledCode', () => {
it('renders the expected element', () => {
const { container } = render(<StyledCode />);

expect(container.firstChild.nodeName).toBe('CODE');
expect(container.firstChild!.nodeName).toBe('CODE');
});

it('renders default styling', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('StyledOrderedList', () => {
it('renders the expected element', () => {
const { container } = render(<StyledOrderedList />);

expect(container.firstChild.nodeName).toBe('OL');
expect(container.firstChild!.nodeName).toBe('OL');
});

it('renders expected RTL direction', () => {
Expand Down Expand Up @@ -65,7 +65,7 @@ describe('StyledUnorderedList', () => {
it('renders the expected element', () => {
const { container } = render(<StyledUnorderedList />);

expect(container.firstChild.nodeName).toBe('UL');
expect(container.firstChild!.nodeName).toBe('UL');
});

it('renders expected RTL direction', () => {
Expand All @@ -76,19 +76,19 @@ describe('StyledUnorderedList', () => {

describe('type', () => {
it('renders a circle list style', () => {
const { container } = render(<StyledOrderedList listType="circle" />);
const { container } = render(<StyledUnorderedList listType="circle" />);

expect(container.firstChild).toHaveStyleRule('list-style-type', 'circle');
});

it('renders a disc list style', () => {
const { container } = render(<StyledOrderedList listType="disc" />);
const { container } = render(<StyledUnorderedList listType="disc" />);

expect(container.firstChild).toHaveStyleRule('list-style-type', 'disc');
});

it('renders a square list style', () => {
const { container } = render(<StyledOrderedList listType="square" />);
const { container } = render(<StyledUnorderedList listType="square" />);

expect(container.firstChild).toHaveStyleRule('list-style-type', 'square');
});
Expand Down
6 changes: 3 additions & 3 deletions packages/typography/src/styled/StyledList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import styled, { css, DefaultTheme, ThemeProps } from 'styled-components';
import { DEFAULT_THEME, isRtl, retrieveComponentStyles } from '@zendeskgarden/react-theming';

const listStyles = (props: { listType: string } & ThemeProps<DefaultTheme>) => {
const listStyles = (props: { listType?: string } & ThemeProps<DefaultTheme>) => {
const rtl = isRtl(props);

return css`
Expand All @@ -25,7 +25,7 @@ const listStyles = (props: { listType: string } & ThemeProps<DefaultTheme>) => {
const ORDERED_ID = 'typography.ordered_list';

interface IStyledListProps {
listType:
listType?:
| 'decimal'
| 'decimal-leading-zero'
| 'lower-alpha'
Expand All @@ -49,7 +49,7 @@ StyledOrderedList.defaultProps = {
const UNORDERED_ID = 'typography.unordered_list';

interface IStyledUnorderedListProps {
listType: 'circle' | 'disc' | 'square';
listType?: 'circle' | 'disc' | 'square';
}

export const StyledUnorderedList = styled.ul.attrs({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('StyledListItem', () => {
it('renders the expected element', () => {
const { container } = render(<StyledListItem />);

expect(container.firstChild.nodeName).toBe('LI');
expect(container.firstChild!.nodeName).toBe('LI');
});

describe('StyledListItemContent', () => {
Expand Down
51 changes: 51 additions & 0 deletions packages/typography/src/styled/StyledParagraph.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* Copyright Zendesk, Inc.
*
* Use of this source code is governed under the Apache License, Version 2.0
* found at http://www.apache.org/licenses/LICENSE-2.0.
*/

import React from 'react';
import { render, renderRtl } from 'garden-test-utils';
import { DEFAULT_THEME } from '@zendeskgarden/react-theming';
import { StyledParagraph } from './StyledParagraph';

describe('StyledParagraph', () => {
it('renders the expected element', () => {
const { container } = render(<StyledParagraph />);

expect(container.firstChild!.nodeName).toBe('P');
});

it('renders expected RTL direction', () => {
const { container } = renderRtl(<StyledParagraph />);

expect(container.firstChild).toHaveStyleRule('direction', 'rtl');
});

describe('size', () => {
it('renders small size', () => {
const { container } = render(<StyledParagraph size="sm" />);

expect(container.firstChild).toHaveStyleRule('margin-top', DEFAULT_THEME.lineHeights.sm, {
modifier: ` + ${StyledParagraph}`
});
});

it('renders medium size', () => {
const { container } = render(<StyledParagraph size="md" />);

expect(container.firstChild).toHaveStyleRule('margin-top', DEFAULT_THEME.lineHeights.md, {
modifier: ` + ${StyledParagraph}`
});
});

it('renders large size', () => {
const { container } = render(<StyledParagraph size="lg" />);

expect(container.firstChild).toHaveStyleRule('margin-top', DEFAULT_THEME.lineHeights.lg, {
modifier: ` + ${StyledParagraph}`
});
});
});
});
Loading