diff --git a/packages/react-component-library/src/components/Button/Button.stories.tsx b/packages/react-component-library/src/components/Button/Button.stories.tsx
index bb356ec3f1..1d45af16f0 100644
--- a/packages/react-component-library/src/components/Button/Button.stories.tsx
+++ b/packages/react-component-library/src/components/Button/Button.stories.tsx
@@ -1,9 +1,14 @@
import React from 'react'
-import { StoryFn, Meta } from '@storybook/react'
+import styled from 'styled-components'
+
+import { Meta, StoryFn } from '@storybook/react'
import { IconBrightnessLow } from '@royalnavy/icon-library'
-import { Button } from './index'
-import { BUTTON_VARIANT, BUTTON_ICON_POSITION } from './constants'
+import { spacing } from '@royalnavy/design-tokens'
+
+import { Button, ButtonProps } from './index'
+import { BUTTON_ICON_POSITION, BUTTON_VARIANT } from './constants'
+import { SectionDivider } from '../SectionDivider'
import { COMPONENT_SIZE } from '../Forms'
export default {
@@ -24,157 +29,121 @@ Default.args = {
children: 'Default',
}
-export const Primary = Template.bind({})
-Primary.args = {
- variant: BUTTON_VARIANT.PRIMARY,
- children: 'Primary',
-}
-
-export const PrimaryDisabled = Template.bind({})
-PrimaryDisabled.storyName = 'Primary, disabled'
-PrimaryDisabled.args = {
- variant: BUTTON_VARIANT.PRIMARY,
- isDisabled: true,
- children: 'Primary, disabled',
-}
-
-export const PrimaryLoading = Template.bind({})
-PrimaryLoading.storyName = 'Primary, loading'
-PrimaryLoading.args = {
- variant: BUTTON_VARIANT.PRIMARY,
- isLoading: true,
- children: 'Primary, loading',
-}
-
-export const PrimaryLeftIcon = Template.bind({})
-PrimaryLeftIcon.storyName = 'Primary, with left icon'
-PrimaryLeftIcon.args = {
- children: 'Primary',
- icon: ,
- iconPosition: BUTTON_ICON_POSITION.LEFT,
-}
-
-export const PrimaryRightIcon = Template.bind({})
-PrimaryRightIcon.storyName = 'Primary, with right icon'
-PrimaryRightIcon.args = {
- children: 'Primary',
- icon: ,
- iconPosition: BUTTON_ICON_POSITION.RIGHT,
-}
-
-export const IconNoText = Template.bind({})
-IconNoText.storyName = 'Icon, no text'
-IconNoText.args = {
- children: undefined,
- icon: ,
- title: 'Reduce brightness',
-}
-
-export const Secondary = Template.bind({})
-Secondary.args = {
- variant: BUTTON_VARIANT.SECONDARY,
- children: 'Secondary',
-}
-
-export const SecondaryLeftIcon = Template.bind({})
-SecondaryLeftIcon.storyName = 'Secondary, with left icon'
-SecondaryLeftIcon.args = {
- variant: BUTTON_VARIANT.SECONDARY,
- children: 'Secondary',
- icon: ,
- iconPosition: BUTTON_ICON_POSITION.LEFT,
-}
-
-export const SecondaryDisabled = Template.bind({})
-SecondaryDisabled.storyName = 'Secondary, disabled'
-SecondaryDisabled.args = {
- variant: BUTTON_VARIANT.SECONDARY,
- isDisabled: true,
- children: 'Secondary, disabled',
-}
-
-export const SecondaryLoading = Template.bind({})
-SecondaryLoading.storyName = 'Secondary, loading'
-SecondaryLoading.args = {
- variant: BUTTON_VARIANT.SECONDARY,
- isLoading: true,
- children: 'Secondary, loading',
-}
-
-export const Tertiary = Template.bind({})
-Tertiary.args = {
- variant: BUTTON_VARIANT.TERTIARY,
- children: 'Tertiary',
-}
-
-export const TertiaryLeftIcon = Template.bind({})
-TertiaryLeftIcon.storyName = 'Tertiary, with left icon'
-TertiaryLeftIcon.args = {
- variant: BUTTON_VARIANT.TERTIARY,
- children: 'Tertiary',
- icon: ,
- iconPosition: BUTTON_ICON_POSITION.LEFT,
-}
-
-export const TertiaryDisabled = Template.bind({})
-TertiaryDisabled.storyName = 'Tertiary, disabled'
-TertiaryDisabled.args = {
- variant: BUTTON_VARIANT.TERTIARY,
- isDisabled: true,
- children: 'Tertiary, disabled',
-}
-
-export const TertiaryLoading = Template.bind({})
-TertiaryLoading.storyName = 'Tertiary, loading'
-TertiaryLoading.args = {
- variant: BUTTON_VARIANT.TERTIARY,
- isLoading: true,
- children: 'Tertiary, loading',
-}
-
-export const Danger = Template.bind({})
-Danger.args = {
- variant: BUTTON_VARIANT.DANGER,
- children: 'Danger',
-}
-
-export const DangerDisabled = Template.bind({})
-DangerDisabled.storyName = 'Danger, disabled'
-DangerDisabled.args = {
- variant: BUTTON_VARIANT.DANGER,
- isDisabled: true,
- children: 'Danger, disabled',
-}
-
-export const DangerLoading = Template.bind({})
-DangerLoading.storyName = 'Danger, loading'
-DangerLoading.args = {
- variant: BUTTON_VARIANT.DANGER,
- isLoading: true,
- children: 'Danger, loading',
-}
-
-export const Small = Template.bind({})
-Small.args = {
- variant: BUTTON_VARIANT.PRIMARY,
- size: COMPONENT_SIZE.SMALL,
- children: 'Small',
+const StyledButtonStrip = styled.div`
+ max-width: 500px;
+ display: flex;
+ justify-content: start;
+ gap: ${spacing('2')};
+ padding: ${spacing('4')} 0;
+`
+
+type ButtonStripArgs = ButtonProps & {
+ title?: string
+ hideText?: boolean
+}
+
+const ButtonStrip = (args: ButtonStripArgs) => {
+ const localArgs = { ...args }
+ const shouldHideButtonText = !!args.hideText
+ delete localArgs.variant
+ delete localArgs.isDisabled
+ const disabledStates = [false, true]
+
+ return (
+ <>
+
+ {disabledStates.map((state) => (
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+ >
+ )
+}
+
+export const RegularButtons: StoryFn = (args) => {
+ const iconLeftArgs = {
+ ...args,
+ icon: ,
+ iconPosition: BUTTON_ICON_POSITION.LEFT,
+ }
+ const iconRightArgs = {
+ ...iconLeftArgs,
+ iconPosition: BUTTON_ICON_POSITION.RIGHT,
+ }
+ const loadingArgs = {
+ ...args,
+ isLoading: true,
+ }
+
+ const iconOnlyArgs = {
+ ...iconLeftArgs,
+ showText: false,
+ }
+
+ return (
+ <>
+ All variants of {args.size} buttons
+
+
+
+
+
+ >
+ )
+}
+
+const paletteArgTypes = {
+ isDisabled: { table: { disable: true } },
+ isLoading: {
+ control: 'boolean',
+ },
+ size: { table: { disable: true } },
+ icon: { table: { disable: true } },
+ variant: { table: { disable: true } },
+ iconPosition: { table: { disable: true } },
+ type: { table: { disable: true } },
}
-export const SmallLoading = Template.bind({})
-SmallLoading.storyName = 'Small, loading'
-SmallLoading.args = {
- variant: BUTTON_VARIANT.PRIMARY,
- size: COMPONENT_SIZE.SMALL,
- children: 'Small, loading',
- isLoading: true,
+RegularButtons.argTypes = paletteArgTypes
+RegularButtons.args = {
+ size: COMPONENT_SIZE.FORMS,
}
-export const SmallIconNoText = Template.bind({})
-SmallIconNoText.storyName = 'Small, with icon, no text '
-SmallIconNoText.args = {
- variant: BUTTON_VARIANT.PRIMARY,
+export const SmallButtons = RegularButtons.bind({})
+SmallButtons.argTypes = paletteArgTypes
+SmallButtons.args = {
size: COMPONENT_SIZE.SMALL,
- icon: ,
- title: 'Reduce brightness',
}
diff --git a/packages/react-component-library/src/components/Button/Button.tsx b/packages/react-component-library/src/components/Button/Button.tsx
index a469b41fd2..73a833f1d5 100644
--- a/packages/react-component-library/src/components/Button/Button.tsx
+++ b/packages/react-component-library/src/components/Button/Button.tsx
@@ -3,11 +3,13 @@ import React from 'react'
import { BUTTON_ICON_POSITION, BUTTON_VARIANT } from './constants'
import { ComponentWithClass } from '../../common/ComponentWithClass'
-import { StyledButton } from './partials/StyledButton'
-import { StyledIconWrapper } from './partials/StyledIconWrapper'
-import { StyledText } from './partials/StyledText'
-import { StyledIconLoaderWrapper } from './partials/StyledIconLoader'
-import { ComponentSizeType, COMPONENT_SIZE } from '../Forms'
+import {
+ StyledButton,
+ StyledIconLoaderWrapper,
+ StyledIconWrapper,
+ StyledText,
+} from './partials'
+import { COMPONENT_SIZE, ComponentSizeType } from '../Forms'
import { ValueOf } from '../../helpers'
export type ButtonVariantType = ValueOf
diff --git a/packages/react-component-library/src/components/Button/LoadingButtons.tsx b/packages/react-component-library/src/components/Button/LoadingButtons.tsx
deleted file mode 100644
index 0ffeecfaee..0000000000
--- a/packages/react-component-library/src/components/Button/LoadingButtons.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import React, { useEffect, useState } from 'react'
-
-import { Button } from './Button'
-import { BUTTON_VARIANT } from './constants'
-import { COMPONENT_SIZE, ComponentSizeType } from '../Forms'
-
-const allVariants = [
- BUTTON_VARIANT.PRIMARY,
- BUTTON_VARIANT.SECONDARY,
- BUTTON_VARIANT.TERTIARY,
- BUTTON_VARIANT.DANGER,
-]
-
-export const LoadingButtons = ({
- size = COMPONENT_SIZE.FORMS,
-}: {
- size: ComponentSizeType
-}) => {
- const [isLoading, setIsLoading] = useState(allVariants)
-
- useEffect(() => {
- const handleInterval = () => {
- if (!isLoading.length) {
- setIsLoading(allVariants)
- return
- }
-
- setIsLoading((current) => {
- return current.slice(1)
- })
- }
-
- const interval = window.setInterval(handleInterval, 1000)
-
- return () => window.clearInterval(interval)
- }, [isLoading])
-
- return (
- <>
-
-
-
-
-
-
-
- >
- )
-}
diff --git a/packages/react-component-library/src/components/Button/Variants.mdx b/packages/react-component-library/src/components/Button/Variants.mdx
deleted file mode 100644
index fc63cac219..0000000000
--- a/packages/react-component-library/src/components/Button/Variants.mdx
+++ /dev/null
@@ -1,122 +0,0 @@
-import { Meta } from '@storybook/blocks'
-import { IconSettings, } from '@royalnavy/icon-library'
-
-import { COMPONENT_SIZE } from '../Forms'
-import { Button, BUTTON_ICON_POSITION, BUTTON_VARIANT } from '.'
-import { LoadingButtons } from './LoadingButtons'
-
-
-
-# Button Components
-
-> Use standard size buttons by default
-
-### Defaults
-
-
-
-
-
----
-
-
-
-
-
-
-### With icons left
-}>Primary
-} variant={BUTTON_VARIANT.SECONDARY} icon={}>Secondary
-} variant={BUTTON_VARIANT.TERTIARY}>Tertiary
-} variant={BUTTON_VARIANT.DANGER}>Danger
-
----
-}>Primary
-} variant={BUTTON_VARIANT.SECONDARY} icon={}>Secondary
-} variant={BUTTON_VARIANT.TERTIARY}>Tertiary
-} variant={BUTTON_VARIANT.DANGER}>Danger
-
-### With icons right
-}>Primary
-} variant={BUTTON_VARIANT.SECONDARY} icon={}>Secondary
-} variant={BUTTON_VARIANT.TERTIARY}>Tertiary
-} variant={BUTTON_VARIANT.DANGER}>Danger
-
----
-}>Primary
-} variant={BUTTON_VARIANT.SECONDARY} icon={}>Secondary
-} variant={BUTTON_VARIANT.TERTIARY}>Tertiary
-} variant={BUTTON_VARIANT.DANGER}>Danger
-
-### Icons only
-} />
-} variant={BUTTON_VARIANT.SECONDARY} icon={} />
-} variant={BUTTON_VARIANT.TERTIARY} />
-} variant={BUTTON_VARIANT.DANGER} />
-
----
-} />
-} variant={BUTTON_VARIANT.SECONDARY} icon={} />
-} variant={BUTTON_VARIANT.TERTIARY} />
-} variant={BUTTON_VARIANT.DANGER} />
-
-### Loading
-
-
----
-
-## Small
-> Smaller sized buttons should be used sparingly
-
-
-### Defaults
-
-
-
-
-
----
-
-
-
-
-
-
-### With icons left
-}>Primary
-} variant={BUTTON_VARIANT.SECONDARY} icon={}>Secondary
-} variant={BUTTON_VARIANT.TERTIARY}>Tertiary
-} variant={BUTTON_VARIANT.DANGER}>Danger
-
----
-}>Primary
-} variant={BUTTON_VARIANT.SECONDARY} icon={}>Secondary
-} variant={BUTTON_VARIANT.TERTIARY}>Tertiary
-} variant={BUTTON_VARIANT.DANGER}>Danger
-
-### With icons right
-}>Primary
-} variant={BUTTON_VARIANT.SECONDARY} icon={}>Secondary
-} variant={BUTTON_VARIANT.TERTIARY}>Tertiary
-} variant={BUTTON_VARIANT.DANGER}>Danger
-
----
-}>Primary
-} variant={BUTTON_VARIANT.SECONDARY} icon={}>Secondary
-} variant={BUTTON_VARIANT.TERTIARY}>Tertiary
-} variant={BUTTON_VARIANT.DANGER}>Danger
-
-### Icons only
-} />
-} variant={BUTTON_VARIANT.SECONDARY} icon={} />
-} variant={BUTTON_VARIANT.TERTIARY} />
-} variant={BUTTON_VARIANT.DANGER} />
-
----
-} />
-} variant={BUTTON_VARIANT.SECONDARY} icon={} />
-} variant={BUTTON_VARIANT.TERTIARY} />
-} variant={BUTTON_VARIANT.DANGER} />
-
-### Loading
-
diff --git a/packages/react-component-library/src/components/Button/index.ts b/packages/react-component-library/src/components/Button/index.ts
index 5935cac581..889351029d 100644
--- a/packages/react-component-library/src/components/Button/index.ts
+++ b/packages/react-component-library/src/components/Button/index.ts
@@ -1,2 +1,4 @@
export * from './Button'
export * from './constants'
+
+export { getButtonStyles } from './partials/StyledButton'
diff --git a/packages/react-component-library/src/components/Button/partials/StyledButton.tsx b/packages/react-component-library/src/components/Button/partials/StyledButton.tsx
index 6f785ae9fd..af1c54c8ff 100644
--- a/packages/react-component-library/src/components/Button/partials/StyledButton.tsx
+++ b/packages/react-component-library/src/components/Button/partials/StyledButton.tsx
@@ -8,27 +8,29 @@ import { ComponentSizeType, COMPONENT_SIZE } from '../../Forms'
const DROP_SHADOW = `0 2px 6px ${rgba(0, 0, 0, 0.3)}`
const TRANSPARENT_SHADOW = shadow('0')
-const DEFAULT_HOVER_BORDER_SHADOW = `0 0 0 3px ${color('action', '100')}`
-const DANGER_HOVER_BORDER_SHADOW = `0 0 0 3px ${color('danger', '100')}`
+const DEFAULT_HOVER_BORDER_SHADOW = `0 0 0 2px ${color('action', '900')}`
+const DANGER_HOVER_BORDER_SHADOW = `0 0 0 2px ${color('danger', '900')}`
const COLOR_MAP = {
[BUTTON_VARIANT.PRIMARY]: {
color: color('neutral', 'white'),
backgroundColor: color('action', '600'),
- borderColor: color('action', '800'),
- borderWidth: '2px',
- hoverBackgroundColor: color('action', '800'),
+ borderColor: color('action', '600'),
+ borderWidth: 0,
+ hoverBackgroundColor: color('action', '700'),
hoverBoxShadow: DEFAULT_HOVER_BORDER_SHADOW,
activeBackgroundColor: color('action', '900'),
+ focusBorderColor: color('action', '800'),
},
[BUTTON_VARIANT.SECONDARY]: {
color: color('action', '900'),
backgroundColor: color('action', '100'),
borderColor: color('action', '600'),
- borderWidth: '2px',
+ borderWidth: '1px',
hoverBackgroundColor: color('action', '200'),
hoverBoxShadow: DEFAULT_HOVER_BORDER_SHADOW,
activeBackgroundColor: color('action', '300'),
+ focusBorderColor: color('action', '300'),
},
[BUTTON_VARIANT.TERTIARY]: {
color: color('action', '600'),
@@ -38,15 +40,17 @@ const COLOR_MAP = {
hoverBackgroundColor: color('neutral', '000'),
hoverBoxShadow: DEFAULT_HOVER_BORDER_SHADOW,
activeBackgroundColor: color('neutral', '100'),
+ focusBorderColor: color('action', '800'),
},
[BUTTON_VARIANT.DANGER]: {
color: color('neutral', 'white'),
backgroundColor: color('danger', '700'),
borderColor: color('danger', '900'),
- borderWidth: '2px',
+ borderWidth: 0,
hoverBackgroundColor: color('danger', '800'),
hoverBoxShadow: DANGER_HOVER_BORDER_SHADOW,
activeBackgroundColor: color('danger', '900'),
+ focusBorderColor: color('action', '800'),
},
}
@@ -54,12 +58,12 @@ const SIZE_MAP = {
[COMPONENT_SIZE.FORMS]: {
height: '46px',
fontSize: fontSize('m'),
- borderRadius: '15px',
+ borderRadius: '8px',
},
[COMPONENT_SIZE.SMALL]: {
height: '33px',
fontSize: fontSize('base'),
- borderRadius: '10px',
+ borderRadius: '8px',
},
}
@@ -83,9 +87,8 @@ export function getButtonStyles({
align-items: center;
justify-content: center;
border-radius: ${SIZE_MAP[$size].borderRadius};
- box-shadow: ${TRANSPARENT_SHADOW}, ${DROP_SHADOW};
outline: 0;
- padding: 0 ${spacing('6')};
+ padding: 0 ${spacing('7')};
font-size: ${SIZE_MAP[$size].fontSize};
font-weight: 400;
text-decoration: none;
@@ -108,6 +111,11 @@ export function getButtonStyles({
border: ${COLOR_MAP[$variant].borderWidth} solid
${COLOR_MAP[$variant].borderColor};
+ &:focus {
+ border: ${COLOR_MAP[$variant].borderWidth} solid
+ ${COLOR_MAP[$variant].focusBorderColor};
+ }
+
&:focus,
&:hover {
background-color: ${COLOR_MAP[$variant].hoverBackgroundColor};
@@ -116,7 +124,6 @@ export function getButtonStyles({
&:active {
background-color: ${COLOR_MAP[$variant].activeBackgroundColor};
- box-shadow: ${TRANSPARENT_SHADOW}, ${TRANSPARENT_SHADOW};
}
`}
diff --git a/packages/react-component-library/src/components/Button/partials/index.ts b/packages/react-component-library/src/components/Button/partials/index.ts
new file mode 100644
index 0000000000..a2fd372edf
--- /dev/null
+++ b/packages/react-component-library/src/components/Button/partials/index.ts
@@ -0,0 +1,4 @@
+export { StyledButton } from './StyledButton'
+export { StyledIconLoaderWrapper } from './StyledIconLoader'
+export { StyledIconWrapper } from './StyledIconWrapper'
+export { StyledText } from './StyledText'
diff --git a/packages/react-component-library/src/components/DatePicker/partials/StyledDayPicker.tsx b/packages/react-component-library/src/components/DatePicker/partials/StyledDayPicker.tsx
index f2a69a3ffe..00821747c9 100644
--- a/packages/react-component-library/src/components/DatePicker/partials/StyledDayPicker.tsx
+++ b/packages/react-component-library/src/components/DatePicker/partials/StyledDayPicker.tsx
@@ -2,9 +2,8 @@ import DayPicker from 'react-day-picker'
import { color, fontSize, spacing } from '@royalnavy/design-tokens'
import styled, { css } from 'styled-components'
-import { BUTTON_VARIANT } from '../../Button'
+import { BUTTON_VARIANT, getButtonStyles } from '../../Button'
import { COMPONENT_SIZE } from '../../Forms'
-import { getButtonStyles } from '../../Button/partials/StyledButton'
import { isIE11 } from '../../../helpers'
interface StyledDayPickerProps {
diff --git a/sonar-project.properties b/sonar-project.properties
index 28b1ec9655..3a23be349b 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -8,7 +8,7 @@ sonar.projectName=Design System
# Path to sources
sonar.sources=packages/react-component-library/src
sonar.exclusions=**/*.test.ts,**/*.test.tsx*,**/*.stories.tsx*
-sonar.coverage.exclusions=**/*.test.ts,**/*.test.tsx*,**/*.stories.tsx*,packages/react-component-library/src/forms/**/*,packages/react-component-library/src/intro/**/*,packages/react-component-library/src/tokens/**/*,packages/react-component-library/src/components/Button/LoadingButtons.tsx
+sonar.coverage.exclusions=**/*.test.ts,**/*.test.tsx*,**/*.stories.tsx*,packages/react-component-library/src/forms/**/*,packages/react-component-library/src/intro/**/*,packages/react-component-library/src/tokens/**/*
# Path to tests
sonar.javascript.lcov.reportPaths=packages/react-component-library/coverage/lcov.info