Skip to content

Commit

Permalink
feat(core-text-button): create TextButton component per DJR-3057
Browse files Browse the repository at this point in the history
  • Loading branch information
meeschka authored and jraff committed Dec 8, 2020
1 parent 985c6ee commit d1dfaee
Show file tree
Hide file tree
Showing 10 changed files with 288 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/TextButton/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# TDS Core: TextButton

Text Buttons are buttons that visually look like links but react to a user's action. They are only available in the common variant.
52 changes: 52 additions & 0 deletions packages/TextButton/TextButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { componentWithName, or } from '@tds/util-prop-types'
import { colorGreyRaven, colorWhite, colorGreyGainsboro, colorGreyShark } from '@tds/core-colours'
import { medium } from '@tds/shared-typography'
import { safeRest } from '@tds/util-helpers'

const baseButton = {
boxSizing: 'border-box',
padding: '0.25rem 0rem',
cursor: 'pointer',
background: colorWhite,
transition: 'all 0.2s ease-in-out',
position: 'relative',
borderRadius: '0.1875rem',
color: colorGreyShark,
textDecoration: 'underline',
borderStyle: 'none',
'&:hover': {
textDecoration: 'none',
},
'&:active': {
background: colorGreyGainsboro,
boxShadow: `0 0 0 0.125rem ${colorGreyGainsboro}`,
},
'&:focus': {
outline: 'none !important',
boxShadow: `0 0 0 0.125rem ${colorGreyRaven}`,
},
'@media (prefers-reduced-motion: reduce)': {
transition: 'none !important',
},
}

export const StyledTextButton = styled.button(baseButton, medium)

/**
* @version ./package.json
*/
const TextButton = ({ children, ...rest }) => (
<StyledTextButton {...safeRest(rest)}>{children}</StyledTextButton>
)

TextButton.propTypes = {
/**
* The label. It can include the `A11yContent` component or strings.
*/
children: or([PropTypes.string, componentWithName('A11yContent')]).isRequired,
}

export default TextButton
39 changes: 39 additions & 0 deletions packages/TextButton/TextButton.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
### Minimal usage

Provide a function as the `onClick` prop to perform an action when clicked.

### Usage criteria

- Text Buttons are buttons that visually look like links but react to a user's action.
- They are only available in the common variant.
- Like regular Buttons, text should be kept short and precise (recommended 2-24 characters)
- Make use of the A11yContent core component to provide more written context for assistive technology users for when they navigate a page using only button landmarks
- Make sure the TextButton text describes an action (for example, 'Remove Address')

### Sample Usage

```jsx
<TextButton
onClick={() =>
alert(
'This is where you could launch a modal, make an api call to delete or update something, etc.'
)
}
>
Click this
</TextButton>
```

#### Using A11yContent

Use the `A11yContent` component to create invisible text that is read out loud by screen readers.

```jsx
<TextButton onClick={() =>
alert(
'This is where you could launch a modal, make an api call to delete or update something, etc.'
)>
<A11yContent>testing</A11yContent>
With A11y Content
</TextButton>
```
52 changes: 52 additions & 0 deletions packages/TextButton/__tests__/TextButton.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from 'react'
import { shallow, render } from 'enzyme'
// import 'jest-styled-components'

import A11yContent from '../../A11yContent'

import TextButton from '../TextButton'

describe('TextButton', () => {
const doShallow = (props = {}) => shallow(<TextButton {...props} />)

it('renders', () => {
const textButton = render(<TextButton>This is text</TextButton>)

expect(textButton).toMatchSnapshot()
})

it('displays child text', () => {
const textButton = shallow(<TextButton>This is text</TextButton>)

expect(textButton.text().includes('This is text')).toBe(true)
})

it('should contain A11yContent', () => {
const textButton = shallow(
<TextButton>
Go home
<A11yContent>testing</A11yContent>
</TextButton>
)

expect(textButton).toContainReact(<A11yContent>testing</A11yContent>)
})

it('should do something when clicked', () => {
const mockCallBack = jest.fn()
const button = shallow(<TextButton onClick={mockCallBack}>Text</TextButton>)
button.simulate('click')
expect(mockCallBack.mock.calls.length).toEqual(1)
})

it('does not allow custom CSS', () => {
const textButton = doShallow({
className: 'my-custom-class',
style: { color: 'hotpink' },
children: 'Text',
})

expect(textButton).not.toHaveProp('className', 'my-custom-class')
expect(textButton).not.toHaveProp('style')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`TextButton renders 1`] = `
.c0 {
box-sizing: border-box;
padding: 0.25rem 0rem;
cursor: pointer;
background: #fff;
-webkit-transition: all 0.2s ease-in-out;
transition: all 0.2s ease-in-out;
position: relative;
border-radius: 0.1875rem;
color: #2a2c2e;
-webkit-text-decoration: underline;
text-decoration: underline;
border-style: none;
word-wrap: break-word;
font-size: 1rem;
-webkit-letter-spacing: -0.8px;
-moz-letter-spacing: -0.8px;
-ms-letter-spacing: -0.8px;
letter-spacing: -0.8px;
line-height: 1.5;
}
.c0:hover {
-webkit-text-decoration: none;
text-decoration: none;
}
.c0:active {
background: #d8d8d8;
box-shadow: 0 0 0 0.125rem #d8d8d8;
}
.c0:focus {
outline: none !important;
box-shadow: 0 0 0 0.125rem #71757b;
}
@media (prefers-reduced-motion:reduce) {
.c0 {
-webkit-transition: none !important;
transition: none !important;
}
}
<button
class="c0"
>
This is text
</button>
`;
3 changes: 3 additions & 0 deletions packages/TextButton/index.cjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const TextButton = require('./dist/index.cjs')

module.exports = TextButton
3 changes: 3 additions & 0 deletions packages/TextButton/index.es.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import TextButton from './dist/index.es'

export default TextButton
41 changes: 41 additions & 0 deletions packages/TextButton/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions packages/TextButton/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "@tds/core-text-button",
"version": "1.0.0-0",
"description": "",
"main": "index.cjs.js",
"module": "index.es.js",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/telus/tds-core.git"
},
"publishConfig": {
"access": "public"
},
"author": "TELUS digital",
"engines": {
"node": ">=8"
},
"bugs": {
"url": "https://github.com/telus/tds-core/issues"
},
"homepage": "http://tds.telus.com",
"peerDependencies": {
"react": "^16.8.2",
"react-dom": "^16.8.2",
"styled-components": "^4.1.3 || ^5.1.0"
},
"dependencies": {
"@tds/core-colours": "^2.2.1",
"@tds/shared-typography": "^1.3.5",
"@tds/util-helpers": "^1.1.0",
"@tds/util-prop-types": "^1.4.0",
"prop-types": "^15.5.10"
}
}
7 changes: 7 additions & 0 deletions packages/TextButton/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import configure from '../../config/rollup.config'
import { dependencies } from './package.json'

export default configure({
input: './TextButton.jsx',
dependencies,
})

0 comments on commit d1dfaee

Please sign in to comment.