diff --git a/libraries/core-react/jest.config.js b/libraries/core-react/jest.config.js
index 7ade5bdf27..4075a7ffa4 100644
--- a/libraries/core-react/jest.config.js
+++ b/libraries/core-react/jest.config.js
@@ -2,7 +2,7 @@ module.exports = {
verbose: true,
setupFilesAfterEnv: ['./rtl.setup.ts'],
transform: {
- '.js': 'babel-jest',
+ '.(js)': 'babel-jest',
'.(ts|tsx)': 'ts-jest',
},
testRegex: '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$',
diff --git a/libraries/core-react/src/Button/Button.jsx b/libraries/core-react/src/Button/Button.jsx
deleted file mode 100644
index 7b84577a7b..0000000000
--- a/libraries/core-react/src/Button/Button.jsx
+++ /dev/null
@@ -1,193 +0,0 @@
-// @ts-nocheck
-import React, { forwardRef } from 'react'
-import PropTypes from 'prop-types'
-import styled, { css } from 'styled-components'
-import { Icon } from '..'
-import { button } from './Button.tokens'
-import { typographyTemplate } from '../_common/templates'
-
-const { colors } = button
-
-// display:grid; does not work on Webkit browser engine, so we have to wrap content in element where css-grid works
-const ButtonInner = styled.span`
- display: grid;
- grid-gap: 8px;
- grid-auto-flow: column;
- align-items: center;
- height: 100%;
-`
-
-const Base = ({ base, baseDisabled: disabled }) => {
- const { border, spacing, typography, focus, hover } = base
-
- return css`
- background: ${base.background};
- height: ${base.height};
- width: ${base.width};
- color: ${base.color};
- fill: ${base.color};
- svg {
- justify-self: center;
- height: ${button.icon_size.height};
- width: ${button.icon_size.width};
- }
-
- border-radius: ${border.radius};
- border-color: ${border.color};
- border-width: ${border.width};
- border-style: solid;
-
- ${spacing &&
- css`
- padding-left: ${spacing.left};
- padding-right: ${spacing.right};
- `}
-
- ${typographyTemplate(typography)}
- &::after {
- position: absolute;
- top: -${base.clickboundOffset};
- left: 0;
- width: 100%;
- height: ${base.clickbound};
- content: '';
- }
-
- &:hover {
- background: ${hover.background};
- ${hover.radius &&
- css`
- border-radius: ${hover.radius};
- `}
- }
-
- &:focus {
- outline: none;
- }
-
- &[data-focus-visible-added]:focus {
- outline: ${focus.width} ${focus.type} ${focus.color};
- outline-offset: 2px;
- }
- /* Get rid of ff focus border for buttons */
- &::-moz-focus-inner {
- border: 0;
- }
-
- &:disabled {
- cursor: not-allowed;
- background: ${disabled.background};
- color: ${disabled.color};
- fill: ${disabled.color};
- border-color: ${disabled.border.color};
-
- &:hover {
- background: ${disabled.background};
- }
- }
- `
-}
-
-const ButtonBase = styled.button`
- margin: 0;
- padding: 0;
- ${Base}
- text-decoration: none;
- position: relative;
- cursor: pointer;
- display: inline-block;
-
- &::before {
- position: absolute;
- top: 0;
- left: 0;
- width: auto;
- min-height: auto;
- content: '';
- }
-`
-
-export const Button = forwardRef(function Button(
- { variant, children, disabled, className, color, tabIndex, href, ...other },
- ref,
-) {
- const colorBase = colors[color] || {}
- const base = colorBase[variant] || {}
- const baseDisabled = colors.disabled[variant] || {}
-
- const as = href ? 'a' : other.as ? other.as : 'button'
-
- const baseProps = {
- ...other,
- ref,
- as,
- href,
- }
-
- return (
-
- {children}
-
- )
-})
-
-Button.propTypes = {
- /** @ignore */
- children: ({ children }) => {
- let error
-
- const iconChildIsMissingTitle = React.Children.toArray(children)
- .map(
- ({ type, props: childProps }) =>
- (type || { displayName: '' }).displayName === Icon.displayName &&
- !childProps.title,
- )
- .includes(true)
-
- if (iconChildIsMissingTitle) {
- error = new Error(
- `When using an Icon in the Button, the property "title" is mandatory on Icon to meet accessibility requirements`,
- )
- }
- return error
- },
- /** Specifies color */
- color: PropTypes.oneOf(['primary', 'secondary', 'danger']),
- /** Specifies which variant to use */
- variant: PropTypes.oneOf(['contained', 'outlined', 'ghost', 'ghost_icon']),
- /**
- * If `true`, the button will be disabled.
- */
- disabled: PropTypes.bool,
- /**
- * URL link destination
- * If defined, an 'a' element is used as root instead of 'button'
- */
- href: PropTypes.string,
- /* User to control tabindex, default tabindex needed for button as span */
- tabIndex: PropTypes.number,
- /**
- * @ignore
- */
- className: PropTypes.string,
-}
-
-Button.defaultProps = {
- variant: 'contained',
- color: 'primary',
- disabled: false,
- className: '',
- children: null,
- href: undefined,
- tabIndex: 0,
-}
-
-Button.displayName = 'eds-button'
diff --git a/libraries/core-react/src/Button/Button.test.jsx b/libraries/core-react/src/Button/Button.test.tsx
similarity index 97%
rename from libraries/core-react/src/Button/Button.test.jsx
rename to libraries/core-react/src/Button/Button.test.tsx
index a83f77ebe8..4d28e56406 100644
--- a/libraries/core-react/src/Button/Button.test.jsx
+++ b/libraries/core-react/src/Button/Button.test.tsx
@@ -5,7 +5,8 @@ import '@testing-library/jest-dom'
import 'jest-styled-components'
import styled from 'styled-components'
import { save } from '@equinor/eds-icons'
-import { Button, Icon } from '..'
+import { Button } from './Button'
+import { Icon } from '../Icon'
Icon.add({ save })
diff --git a/libraries/core-react/src/Button/Button.tokens.js b/libraries/core-react/src/Button/Button.tokens.ts
similarity index 55%
rename from libraries/core-react/src/Button/Button.tokens.js
rename to libraries/core-react/src/Button/Button.tokens.ts
index 53fb65b5f8..f82cc6a2ed 100644
--- a/libraries/core-react/src/Button/Button.tokens.js
+++ b/libraries/core-react/src/Button/Button.tokens.ts
@@ -1,8 +1,14 @@
-// @ts-nocheck
import primary from '@equinor/eds-tokens/components/button/buttons-primary.json'
import secondary from '@equinor/eds-tokens/components/button/buttons-secondary.json'
import danger from '@equinor/eds-tokens/components/button/buttons-danger.json'
import disabled from '@equinor/eds-tokens/components/button/buttons-disabled.json'
+import type {
+ Border,
+ Focus,
+ Hover,
+ Spacing,
+ Typography,
+} from '@equinor/eds-tokens'
const colors = {
primary: {
@@ -35,7 +41,41 @@ const colors = {
},
}
-export const button = {
+export type Button = {
+ height: string
+ width?: string
+ background: string
+ color: string
+ border: Border
+ typography: Typography
+ spacing?: Partial
+ focus?: Focus
+ hover?: Hover
+ // TODO Remove these once figma-broker is updated with proper types
+ pressedColor?: string
+ clickboundOffset?: number | string
+ clickbound?: string
+}
+
+type Buttons = {
+ [P in keyof typeof colors]: {
+ [P2 in keyof typeof colors[P]]: Button
+ }
+}
+
+export type ButtonGroups =
+ | Buttons['primary']
+ | Buttons['secondary']
+ | Buttons['danger']
+ | Buttons['disabled']
+
+export const button: {
+ colors: Buttons
+ icon_size: {
+ width: string
+ height: string
+ }
+} = {
colors,
icon_size: {
width: '24px',
diff --git a/libraries/core-react/src/Button/Button.tsx b/libraries/core-react/src/Button/Button.tsx
new file mode 100644
index 0000000000..136e9a1d5b
--- /dev/null
+++ b/libraries/core-react/src/Button/Button.tsx
@@ -0,0 +1,168 @@
+import React, { forwardRef, ElementType } from 'react'
+import styled, { css } from 'styled-components'
+import { button, Button as ButtonType, ButtonGroups } from './Button.tokens'
+import { typographyTemplate } from '../_common/templates'
+
+const { colors } = button
+
+// display:grid; does not work on Webkit browser engine, so we have to wrap content in element where css-grid works
+const ButtonInner = styled.span`
+ display: grid;
+ grid-gap: 8px;
+ grid-auto-flow: column;
+ align-items: center;
+ height: 100%;
+`
+
+const Base = ({
+ token,
+ disabledToken,
+}: {
+ token: ButtonType
+ disabledToken: ButtonType
+}) => {
+ const { border, spacing, typography, focus, hover } = token
+
+ return css`
+ background: ${token.background};
+ height: ${token.height};
+ width: ${token.width};
+ color: ${token.color};
+ fill: ${token.color};
+ svg {
+ justify-self: center;
+ height: ${button.icon_size.height};
+ width: ${button.icon_size.width};
+ }
+
+ border-radius: ${border.radius};
+ border-color: ${border.color};
+ border-width: ${border.width};
+ border-style: solid;
+
+ ${spacing &&
+ css`
+ padding-left: ${spacing.left};
+ padding-right: ${spacing.right};
+ `}
+
+ ${typographyTemplate(typography)}
+ &::after {
+ position: absolute;
+ top: -${token.clickboundOffset};
+ left: 0;
+ width: 100%;
+ height: ${token.clickbound};
+ content: '';
+ }
+
+ &:hover {
+ background: ${hover.background};
+ ${hover.radius &&
+ css`
+ border-radius: ${hover.radius};
+ `}
+ }
+
+ &:focus {
+ outline: none;
+ }
+
+ &[data-focus-visible-added]:focus {
+ outline: ${focus.width} ${focus.type} ${focus.color};
+ outline-offset: 2px;
+ }
+ /* Get rid of ff focus border for buttons */
+ &::-moz-focus-inner {
+ border: 0;
+ }
+
+ &:disabled {
+ cursor: not-allowed;
+ background: ${disabledToken.background};
+ color: ${disabledToken.color};
+ fill: ${disabledToken.color};
+ border-color: ${disabledToken.border.color};
+
+ &:hover {
+ background: ${disabledToken.background};
+ }
+ }
+ `
+}
+
+const ButtonBase = styled.button`
+ margin: 0;
+ padding: 0;
+ ${Base}
+ text-decoration: none;
+ position: relative;
+ cursor: pointer;
+ display: inline-block;
+
+ &::before {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: auto;
+ min-height: auto;
+ content: '';
+ }
+`
+type Props = {
+ /** Specifies color */
+ color?: 'primary' | 'secondary' | 'danger'
+ /** Specifies which variant to use */
+ variant?: 'contained' | 'outlined' | 'ghost' | 'ghost_icon'
+ /**
+ * URL link destination
+ * If defined, an 'a' element is used as root instead of 'button'
+ */
+ href?: string
+ /** Is disabled */
+ disabled?: boolean
+ /** Change html element */
+ as?: ElementType
+ /** ttype */
+ type?: string
+} & React.HTMLAttributes
+
+export const Button = forwardRef(function Button(
+ {
+ color = 'danger',
+ variant = 'contained',
+ children,
+ disabled,
+ href,
+ ...other
+ },
+ ref,
+) {
+ const colorBase: ButtonGroups | Partial = colors[color] || {}
+ const token = colorBase[variant] || {}
+ const disabledToken = colors.disabled[variant] || {}
+
+ const as: ElementType = href ? 'a' : other.as ? other.as : 'button'
+ const type = href || other.as ? undefined : 'button'
+ const tabIndex = disabled ? -1 : other.tabIndex
+
+ const buttonProps = {
+ ref,
+ as,
+ href,
+ type,
+ token,
+ disabledToken,
+ disabled,
+ tabIndex,
+ ...other,
+ }
+
+ return (
+
+ {children}
+
+ )
+})
+
+Button.displayName = 'EdsButton'
diff --git a/libraries/core-react/src/Button/index.js b/libraries/core-react/src/Button/index.ts
similarity index 69%
rename from libraries/core-react/src/Button/index.js
rename to libraries/core-react/src/Button/index.ts
index 92d23cb3e8..4d0a670f4a 100644
--- a/libraries/core-react/src/Button/index.js
+++ b/libraries/core-react/src/Button/index.ts
@@ -1,2 +1 @@
-// @ts-nocheck
export { Button } from './Button'
diff --git a/libraries/tokens/src/types.ts b/libraries/tokens/src/types.ts
index 6aba877d0b..85ce604ebe 100644
--- a/libraries/tokens/src/types.ts
+++ b/libraries/tokens/src/types.ts
@@ -22,9 +22,10 @@ export type TypographyTokens = {
}
export type Border = {
+ type?: 'outline' | 'border'
radius: string
color?: string
- width?: string
+ width?: string | number
}
export type Spacing = {
@@ -63,3 +64,28 @@ export type Spacings = {
xx_small: string
}
}
+
+export type Focus = {
+ type?: 'dashed' | string
+ color: string
+ width: string
+ gap?: string
+}
+
+export type Hover = {
+ background: string
+ radius?: string
+}
+
+export type Pressed = {
+ color: string
+}
+
+export type Clickbound = {
+ height: string
+ width: string
+ offset: {
+ x: string
+ y: string
+ }
+}