Skip to content

Commit

Permalink
Merge branch 'main' into adnasa-calendar-utils-typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
kodiakhq[bot] authored Apr 22, 2021
2 parents 2a44713 + bf77496 commit 2176f7a
Show file tree
Hide file tree
Showing 60 changed files with 1,113 additions and 704 deletions.
10 changes: 10 additions & 0 deletions .changeset/five-impalas-impress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@commercetools-uikit/accessible-button': patch
'@commercetools-uikit/flat-button': patch
'@commercetools-uikit/icon-button': patch
'@commercetools-uikit/primary-button': patch
'@commercetools-uikit/secondary-button': patch
'@commercetools-uikit/secondary-icon-button': patch
---

Migrate to `TypeScript` and migrate docs to README generator.
5 changes: 5 additions & 0 deletions .changeset/nasty-hats-fold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@commercetools-uikit/field-errors': patch
---

Migrate `<FieldErrors />` to TypeScript
5 changes: 5 additions & 0 deletions .changeset/sour-pillows-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@commercetools-uikit/accessible-button': patch
---

Update `buttonAttributes` to support `unknown` type.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"@changesets/changelog-github": "0.3.0",
"@changesets/cli": "2.14.1",
"@commercetools-frontend/babel-preset-mc-app": "18.5.6",
"@commercetools-frontend/eslint-config-mc-app": "18.5.4",
"@commercetools-frontend/eslint-config-mc-app": "19.0.1",
"@commercetools/github-labels": "1.1.0",
"@commitlint/cli": "12.0.1",
"@commitlint/config-conventional": "12.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ type TAccessibleButtonProps = {
/**
* Any HTML attributes to be forwarded to the HTML element.
*/
buttonAttributes?: Record<string, string>;
buttonAttributes?: Record<string, unknown>;
};

const defaultProps: Pick<
Expand Down
80 changes: 57 additions & 23 deletions packages/components/buttons/flat-button/README.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,78 @@
# Buttons: Flat Button
<!-- THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -->
<!-- This file is created by the `yarn generate-readme` script. -->

# FlatButton

## Description

Flat buttons are minimal and a flat variation of primary and secondary buttons.

## Installation

```
yarn add @commercetools-uikit/flat-button
```

```
npm --save install @commercetools-uikit/flat-button
```

Additionally install the peer dependencies (if not present)

```
yarn add react
```

```
npm --save install react
```

## Usage

```js
```jsx
import React from 'react';
import FlatButton from '@commercetools-uikit/flat-button';
import { InformationIcon } from '@commercetools-uikit/icons';

<FlatButton
tone="primary"
icon={<InformationIcon />}
label="A label text"
onClick={() => alert('Button clicked')}
isDisabled={false}
/>;
```
const Example = () => (
<FlatButton
tone="primary"
icon={<InformationIcon />}
label="A label text"
onClick={() => alert('Button clicked')}
isDisabled={false}
/>
);

iconClass label url onClick
export default Example;
```

## Properties

| Props | Type | Required | Values | Default | Description |
| -------------- | --------------------- | :------: | --------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `tone` | `oneOf` | - | `primary`, `secondary`, `iverted` | `primary` | - |
| `type` | `string` | - | `submit`, `reset`, `button` | `button` | Used as the HTML `type` attribute. |
| `label` | `string` || - | - | Should describe what the button is for |
| `onClick` | `func` || - | - | What the button will trigger when clicked |
| `icon` | `element` | - | - | - | The icon of the button |
| `iconPosition` | `oneOf` | - | `left`, `right` | `left` | The position of the icon |
| `isDisabled` | `boolean` | - | - | - | Tells when the button should present a disabled state |
| `as` | `string` or `element` | - | - | - | You may pass in a string like "a" to have the button render as an anchor tag instead. Or you could pass in a React Component, like a `Link`. |
| Props | Type | Required | Default | Description |
| -------------- | ----------------------------------------------------------------------- | :------: | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `as` | `union`<br/>Possible values:<br/>`string , ElementType` | | | You may pass in a string like "a" to have the button render as an anchor tag instead.&#xA;<br/>&#xA;Or you could pass in a React Component, like a `Link`. |
| `tone` | `union`<br/>Possible values:<br/>`'primary' , 'secondary' , 'inverted'` | | `'primary'` | Indicates the color scheme of button |
| `type` | `union`<br/>Possible values:<br/>`'submit' , 'reset' , 'button'` | | `'button'` | Used as the HTML `type` attribute. |
| `label` | `string` || | Should describe what the button is for |
| `onClick` | `Function`<br/>[See signature.](#signature-onClick) | | | Handler when the button is clicked&#xA;<br />&#xA;Signature: (event: MouseEvent\<HTMLButtonElement) => void |
| `icon` | `ReactReactElement` | | | The icon of the button |
| `iconPosition` | `union`<br/>Possible values:<br/>`'left' , 'right'` | | `'left'` | The position of the icon |
| `isDisabled` | `boolean` | | `false` | Determines if the button is disabled.&#xA;<br />&#xA;Note that this influences the `tone` and `onClick` will not be triggered in this state. |

## Signatures

The component further forwards all valid HTML attributes to the underlying `button` component.
### Signature `onClick`

```ts
(
event: MouseEvent<HTMLButtonElement> | KeyboardEvent<HTMLButtonElement>
) => void
```

## Where to use

Main Functions and use cases are:

- Secondary or primary action _example: clear filters_

- Expand/Collapse list of fields _example: product attributes_
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Where to use

Main Functions and use cases are:

- Secondary or primary action _example: clear filters_
- Expand/Collapse list of fields _example: product attributes_
15 changes: 15 additions & 0 deletions packages/components/buttons/flat-button/docs/usage-example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import FlatButton from '@commercetools-uikit/flat-button';
import { InformationIcon } from '@commercetools-uikit/icons';

const Example = () => (
<FlatButton
tone="primary"
icon={<InformationIcon />}
label="A label text"
onClick={() => alert('Button clicked')}
isDisabled={false}
/>
);

export default Example;
3 changes: 1 addition & 2 deletions packages/components/buttons/flat-button/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
"@emotion/styled": "^11.0.0",
"common-tags": "1.8.0",
"lodash": "4.17.20",
"prop-types": "15.7.2",
"react-required-if": "1.0.3"
"prop-types": "15.7.2"
},
"devDependencies": {
"react": "17.0.1"
Expand Down
30 changes: 30 additions & 0 deletions packages/components/buttons/flat-button/src/flat-button.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { TFlatButtonProps, TExtendedTheme } from './flat-button';

export const getButtonIconColor = (
props: Pick<TFlatButtonProps, 'isDisabled' | 'tone'>
) => {
if (props.isDisabled) return 'neutral60';
else if (props.tone === 'primary') return 'primary';
else if (props.tone === 'secondary') return 'solid';
else if (props.tone === 'inverted') return 'surface';
return 'solid';
};

export const getTextColor = (
tone: TFlatButtonProps['tone'],
isHover: boolean = false,
overwrittenVars: TExtendedTheme
): string => {
switch (tone) {
case 'primary':
return isHover
? overwrittenVars.colorPrimary25
: overwrittenVars.colorPrimary;
case 'secondary':
return overwrittenVars.colorSolid;
case 'inverted':
return overwrittenVars.fontColorForTextWhenInverted;
default:
return 'inherit';
}
};
Original file line number Diff line number Diff line change
@@ -1,29 +1,80 @@
import React from 'react';
import PropTypes from 'prop-types';
import type { Theme } from '@emotion/react';
import React, { ElementType, MouseEvent, KeyboardEvent } from 'react';
import { css, useTheme } from '@emotion/react';
import omit from 'lodash/omit';
import requiredIf from 'react-required-if';
import { customProperties as vars } from '@commercetools-uikit/design-system';
import { filterInvalidAttributes } from '@commercetools-uikit/utils';
import Text from '@commercetools-uikit/text';
import AccessibleButton from '@commercetools-uikit/accessible-button';
import { getTextColor, getButtonIconColor } from './flat-button.styles';

const propsToOmit = ['type'];

const ButtonIcon = (props) => {
if (!props.icon) return null;
export type TExtendedTheme = Theme & {
[key: string]: string;
};
export type TFlatButtonProps = {
/**
* You may pass in a string like "a" to have the button render as an anchor tag instead.
* <br/>
* Or you could pass in a React Component, like a `Link`.
*/
as?: string | ElementType;
/**
* Indicates the color scheme of button
*/
tone?: 'primary' | 'secondary' | 'inverted';
/**
* Used as the HTML `type` attribute.
*/
type?: 'submit' | 'reset' | 'button';
/**
* Should describe what the button is for
*/
label: string;
/**
* Handler when the button is clicked
* <br />
* Signature: (event: MouseEvent<HTMLButtonElement) => void
*/
onClick?: (
event: MouseEvent<HTMLButtonElement> | KeyboardEvent<HTMLButtonElement>
) => void;
/**
* The icon of the button
*/
icon?: React.ReactElement;
/**
* The position of the icon
*/
iconPosition?: 'left' | 'right';
/**
* Determines if the button is disabled.
* <br />
* Note that this influences the `tone` and `onClick` will not be triggered in this state.
*/
isDisabled?: boolean;
};

let iconColor = 'solid';
if (props.isDisabled) iconColor = 'neutral60';
else if (props.tone === 'primary') iconColor = 'primary';
else if (props.tone === 'secondary') iconColor = 'solid';
else if (props.tone === 'inverted') iconColor = 'surface';
const defaultProps: Pick<
TFlatButtonProps,
'tone' | 'isDisabled' | 'type' | 'iconPosition'
> = {
tone: 'primary',
type: 'button',
iconPosition: 'left',
isDisabled: false,
};

const ButtonIcon = (
props: Pick<TFlatButtonProps, 'as' | 'isDisabled' | 'tone' | 'icon'>
) => {
if (!props.icon) return null;
const iconColor = getButtonIconColor(props);
const Icon = React.cloneElement(props.icon, {
size: 'medium',
color: iconColor,
});

if (props.as && props.as !== 'button') {
return (
<span
Expand All @@ -38,40 +89,22 @@ const ButtonIcon = (props) => {
return Icon;
};
ButtonIcon.displayName = 'ButtonIcon';
ButtonIcon.propTypes = {
icon: PropTypes.element,
tone: PropTypes.oneOf(['primary', 'secondary', 'inverted']),
isDisabled: PropTypes.bool,
};

const getTextColor = (tone, isHover = false, overwrittenVars) => {
switch (tone) {
case 'primary':
return isHover
? overwrittenVars.colorPrimary25
: overwrittenVars.colorPrimary;
case 'secondary':
return overwrittenVars.colorSolid;
case 'inverted':
return overwrittenVars.fontColorForTextWhenInverted;
default:
return 'inherit';
}
};

export const FlatButton = (props) => {
const FlatButton = (props: TFlatButtonProps) => {
const dataProps = {
'data-track-component': 'FlatButton',
...filterInvalidAttributes(omit(props, propsToOmit)),
// if there is a divergence between `isDisabled` and `disabled`,
// we fall back to `isDisabled`
disabled: props.isDisabled,
};

const theme = useTheme();
const overwrittenVars = {
const overwrittenVars: TExtendedTheme = {
...vars,
...theme,
};

return (
<AccessibleButton
as={props.as}
Expand Down Expand Up @@ -129,21 +162,6 @@ export const FlatButton = (props) => {
};

FlatButton.displayName = 'FlatButton';
FlatButton.propTypes = {
as: PropTypes.oneOfType([PropTypes.string, PropTypes.elementType]),
tone: PropTypes.oneOf(['primary', 'secondary', 'inverted']),
type: PropTypes.oneOf(['submit', 'reset', 'button']),
label: PropTypes.string.isRequired,
onClick: requiredIf(PropTypes.func, (props) => !props.as),
icon: PropTypes.element,
iconPosition: PropTypes.oneOf(['left', 'right']),
isDisabled: PropTypes.bool,
};
FlatButton.defaultProps = {
tone: 'primary',
type: 'button',
iconPosition: 'left',
isDisabled: false,
};
FlatButton.defaultProps = defaultProps;

export default FlatButton;
Loading

0 comments on commit 2176f7a

Please sign in to comment.