Skip to content
Open
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
15,180 changes: 9,026 additions & 6,154 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/shared-types/src/ComponentThemeVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,7 @@ export type RadioInputTheme = {
toggleSmallFontSize: Typography['fontSizeXSmall']
toggleMediumFontSize: Typography['fontSizeSmall']
toggleLargeFontSize: Typography['fontSizeMedium']
spacing: any // TODO remove any
}

export type RangeInputTheme = {
Expand Down Expand Up @@ -1460,9 +1461,9 @@ export type TextTheme = Typography & {
alertColor: string
warningColor: string
aiColor: string

aiBackgroundColor: string
paragraphMargin: string | 0
spacing: any // TODO remove any
}

export type TextAreaTheme = {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-badge/src/Badge/__tests__/Badge.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ describe('<Badge />', () => {
expect(badge).not.toBeNull()
expect(badgeStyle).not.toBeNull()
expect(badgeStyle).toHaveProperty('bottom')
expect(badgeStyle).toHaveProperty('bottom', 'calc(-5px)')
expect(badgeStyle).toHaveProperty('bottom', 'calc(-1 * 5px)')
expect(badgeStyle).toHaveProperty('inset-inline-start', 'calc(-1 * 5px)')
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,59 @@ describe('<ToggleButton />', () => {
expect(onClick).toHaveBeenCalledTimes(1)
})
})

describe('margin prop', () => {
it('should apply margin with theme tokens', () => {
const { container } = render(
<div>
<ToggleButton
screenReaderLabel="test1"
renderIcon={icon}
renderTooltipContent="tooltip"
status="unpressed"
margin="medium"
/>
<ToggleButton
screenReaderLabel="test2"
renderIcon={icon}
renderTooltipContent="tooltip"
status="unpressed"
margin="large"
/>
<ToggleButton
screenReaderLabel="test3"
renderIcon={icon}
renderTooltipContent="tooltip"
status="unpressed"
margin="space4"
/>
<ToggleButton
screenReaderLabel="test4"
renderIcon={icon}
renderTooltipContent="tooltip"
status="unpressed"
margin="small medium"
/>
</div>
)

const allButtons = container.querySelectorAll('button')

const buttonMedium = allButtons[0] as HTMLElement
const buttonMediumStyle = window.getComputedStyle(buttonMedium)
const buttonLarge = allButtons[1] as HTMLElement
const buttonLargeStyle = window.getComputedStyle(buttonLarge)
const buttonSpace = allButtons[2] as HTMLElement
const buttonSpaceStyle = window.getComputedStyle(buttonSpace)
const buttonMixed = allButtons[3] as HTMLElement
const buttonMixedStyle = window.getComputedStyle(buttonMixed)

// Note: ToggleButton passes margin to IconButton, which uses View component
// View only accepts theme tokens, not custom CSS values
expect(buttonMediumStyle.margin).toBe('1.5rem')
expect(buttonLargeStyle.margin).toBe('2.25rem')
expect(buttonSpaceStyle.margin).toBe('0.25rem')
expect(buttonMixedStyle.margin).toBe('0.75rem 1.5rem')
})
})
})
2 changes: 2 additions & 0 deletions packages/ui-buttons/src/ToggleButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class ToggleButton extends Component<ToggleButtonProps, ToggleButtonState> {
status,
placement,
onClick,
margin,
...props
} = this.props

Expand Down Expand Up @@ -122,6 +123,7 @@ class ToggleButton extends Component<ToggleButtonProps, ToggleButtonState> {
interaction={interaction}
aria-pressed={status === 'pressed'}
data-cid="ToggleButton"
margin={margin}
>
{callRenderProp(renderIcon)}
</IconButton>
Expand Down
7 changes: 7 additions & 0 deletions packages/ui-buttons/src/ToggleButton/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import type {
} from '@instructure/ui-position'
import type { ViewProps } from '@instructure/ui-view'
import { Renderable } from '@instructure/shared-types'
import type { Spacing } from '@instructure/emotion'

type ToggleButtonOwnProps = {
/**
Expand Down Expand Up @@ -110,6 +111,11 @@ type ToggleButtonOwnProps = {
* or a function returning an element.
*/
constrain?: PositionConstraint

/**
* Margin around the component. Accepts a `Spacing` token. See token values and example usage in [this guide](https://instructure.design/#layout-spacing).
*/
margin?: Spacing
}

type PropKeys = keyof ToggleButtonOwnProps
Expand All @@ -129,6 +135,7 @@ const allowedProps: AllowedPropKeys = [
'elementRef',
'interaction',
'isShowingTooltip',
'margin',
'mountNode',
'onClick',
'placement',
Expand Down
29 changes: 29 additions & 0 deletions packages/ui-checkbox/src/Checkbox/__tests__/Checkbox.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,33 @@ describe('<Checkbox />', () => {
expect(axeCheck).toBe(true)
})
})

describe('margin prop', () => {
it('should apply margin with custom CSS value and with tokens', () => {
const { container } = render(
<div>
<Checkbox label="test1" margin="30px" />
<Checkbox label="test2" margin="large" />
<Checkbox label="test3" margin="space4" />
<Checkbox label="test4" margin="small 20px" />
</div>
)

const allCheckboxes = container.querySelectorAll('[data-cid="Checkbox"]')

const checkboxCustom = allCheckboxes[0] as HTMLElement
const checkboxCustomStyle = window.getComputedStyle(checkboxCustom)
const checkboxLarge = allCheckboxes[1] as HTMLElement
const checkboxLargeStyle = window.getComputedStyle(checkboxLarge)
const checkboxSpace = allCheckboxes[2] as HTMLElement
const checkboxSpaceStyle = window.getComputedStyle(checkboxSpace)
const checkboxMixed = allCheckboxes[3] as HTMLElement
const checkboxMixedStyle = window.getComputedStyle(checkboxMixed)

expect(checkboxCustomStyle.margin).toBe('30px')
expect(checkboxLargeStyle.margin).toBe('2.25rem')
expect(checkboxSpaceStyle.margin).toBe('0.25rem')
expect(checkboxMixedStyle.margin).toBe('0.75rem 20px')
})
})
})
11 changes: 10 additions & 1 deletion packages/ui-checkbox/src/Checkbox/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ import type {
OtherHTMLAttributes,
ToggleFacadeTheme
} from '@instructure/shared-types'
import type { WithStyleProps, ComponentStyle } from '@instructure/emotion'
import type {
WithStyleProps,
ComponentStyle,
Spacing
} from '@instructure/emotion'
import type { WithDeterministicIdProps } from '@instructure/ui-react-utils'

type CheckboxOwnProps = {
Expand Down Expand Up @@ -74,6 +78,10 @@ type CheckboxOwnProps = {
inline?: boolean
labelPlacement?: 'top' | 'start' | 'end'
isRequired?: boolean
/**
* Margin around the component. Accepts a `Spacing` token. See token values and example usage in [this guide](https://instructure.design/#layout-spacing).
*/
margin?: Spacing
/**
* A function that provides a reference to the actual underlying input element
*/
Expand Down Expand Up @@ -119,6 +127,7 @@ const allowedProps: AllowedPropKeys = [
'inline',
'labelPlacement',
'isRequired',
'margin',
'inputRef'
]

Expand Down
15 changes: 13 additions & 2 deletions packages/ui-checkbox/src/Checkbox/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import type { CheckboxProps, CheckboxStyle } from './props'
import type { ComponentTheme } from '@instructure/shared-types'
import { mapSpacingToShorthand } from '@instructure/emotion'

/**
* ---
Expand All @@ -39,7 +40,16 @@ const generateStyle = (
componentTheme: ComponentTheme,
props: CheckboxProps
): CheckboxStyle => {
const { inline, disabled } = props
const { inline, disabled, margin } = props

// Calculate margin and support both theme token values like "space4" and custom values like "10px"
const cssMargin = margin
? mapSpacingToShorthand(
margin,
(componentTheme as ComponentTheme & { spacing: Record<string, string> })
.spacing
)
: undefined

return {
requiredInvalid: {
Expand All @@ -49,12 +59,13 @@ const generateStyle = (
paddingLeft: componentTheme.checkErrorInsetWidth
},
indentedToggleError: {
paddingLeft: componentTheme.toggleErrorInsetWidth,
paddingLeft: componentTheme.toggleErrorInsetWidth
},
checkbox: {
label: 'checkbox',
position: 'relative',
width: '100%',
...(margin && { margin: cssMargin }),
...(disabled && {
cursor: 'not-allowed',
pointerEvents: 'none',
Expand Down
1 change: 1 addition & 0 deletions packages/ui-checkbox/src/Checkbox/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const generateComponentTheme = (theme: Theme): any => {
requiredInvalidColor: colors?.contrasts?.red5782,
toggleErrorInsetWidth: `calc(${forms?.inputHeightSmall}*1.5 + ${spacing?.small})`,
checkErrorInsetWidth: `calc(1.25em + ${spacing?.xSmall})`,
spacing: spacing
}

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,4 +233,49 @@ describe('<CheckboxGroup />', () => {
expect(group).not.toHaveAttribute('aria-invalid')
})
})

describe('margin prop', () => {
it('should apply margin with custom CSS value and with tokens', () => {
const { container } = render(
<div>
<CheckboxGroup name="group1" description="Group 1" margin="30px">
<Checkbox label="Option 1" value="1" />
<Checkbox label="Option 2" value="2" />
</CheckboxGroup>
<CheckboxGroup name="group2" description="Group 2" margin="large">
<Checkbox label="Option 1" value="1" />
<Checkbox label="Option 2" value="2" />
</CheckboxGroup>
<CheckboxGroup name="group3" description="Group 3" margin="small">
<Checkbox label="Option 1" value="1" />
<Checkbox label="Option 2" value="2" />
</CheckboxGroup>
<CheckboxGroup
name="group4"
description="Group 4"
margin="small 20px"
>
<Checkbox label="Option 1" value="1" />
<Checkbox label="Option 2" value="2" />
</CheckboxGroup>
</div>
)

const allFieldsets = container.querySelectorAll('fieldset')

const fieldsetCustom = allFieldsets[0] as HTMLElement
const fieldsetCustomStyle = window.getComputedStyle(fieldsetCustom)
const fieldsetLarge = allFieldsets[1] as HTMLElement
const fieldsetLargeStyle = window.getComputedStyle(fieldsetLarge)
const fieldsetSmall = allFieldsets[2] as HTMLElement
const fieldsetSmallStyle = window.getComputedStyle(fieldsetSmall)
const fieldsetMixed = allFieldsets[3] as HTMLElement
const fieldsetMixedStyle = window.getComputedStyle(fieldsetMixed)

expect(fieldsetCustomStyle.margin).toBe('30px')
expect(fieldsetLargeStyle.margin).toBe('2.25rem')
expect(fieldsetSmallStyle.margin).toBe('0.75rem')
expect(fieldsetMixedStyle.margin).toBe('0.75rem 20px')
})
})
})
8 changes: 7 additions & 1 deletion packages/ui-checkbox/src/CheckboxGroup/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { type InputHTMLAttributes } from 'react'
import type { FormMessage } from '@instructure/ui-form-field'
import type { OtherHTMLAttributes } from '@instructure/shared-types'
import type { WithDeterministicIdProps } from '@instructure/ui-react-utils'
import type { Spacing } from '@instructure/emotion'

import { Checkbox } from '../Checkbox'
import type { CheckboxProps } from '../Checkbox/props'
Expand All @@ -44,6 +45,10 @@ type CheckboxGroupOwnProps = {
messages?: FormMessage[]
size?: 'small' | 'medium' | 'large'
layout?: 'stacked' | 'columns' | 'inline'
/**
* Margin around the component. Accepts a `Spacing` token. See token values and example usage in [this guide](https://instructure.design/#layout-spacing).
*/
margin?: Spacing
}

type PropKeys = keyof CheckboxGroupOwnProps
Expand All @@ -67,7 +72,8 @@ const allowedProps: AllowedPropKeys = [
'messages',
'children',
'size',
'layout'
'layout',
'margin'
]

type CheckboxGroupState = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import '@testing-library/jest-dom'

import { FileDrop } from '../index'
import { FileDropProps } from '../props'
import { act } from 'react'
import { act } from '@testing-library/react'

describe('<FileDrop/>', () => {
it('should focus the input when focus is called', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,41 @@ describe('<FormFieldGroup />', () => {

expect(axeCheck).toBe(true)
})

describe('margin prop', () => {
it('should apply margin with custom CSS value and with tokens', () => {
const { container } = render(
<div>
<FormFieldGroup description="Group 1" margin="30px">
<input />
</FormFieldGroup>
<FormFieldGroup description="Group 2" margin="large">
<input />
</FormFieldGroup>
<FormFieldGroup description="Group 3" margin="space4">
<input />
</FormFieldGroup>
<FormFieldGroup description="Group 4" margin="small 20px">
<input />
</FormFieldGroup>
</div>
)

const allFieldsets = container.querySelectorAll('fieldset')

const fieldsetCustom = allFieldsets[0] as HTMLElement
const fieldsetCustomStyle = window.getComputedStyle(fieldsetCustom)
const fieldsetLarge = allFieldsets[1] as HTMLElement
const fieldsetLargeStyle = window.getComputedStyle(fieldsetLarge)
const fieldsetSpace = allFieldsets[2] as HTMLElement
const fieldsetSpaceStyle = window.getComputedStyle(fieldsetSpace)
const fieldsetMixed = allFieldsets[3] as HTMLElement
const fieldsetMixedStyle = window.getComputedStyle(fieldsetMixed)

expect(fieldsetCustomStyle.margin).toBe('30px')
expect(fieldsetLargeStyle.margin).toBe('2.25rem')
expect(fieldsetSpaceStyle.margin).toBe('0.25rem')
expect(fieldsetMixedStyle.margin).toBe('0.75rem 20px')
})
})
})
Loading
Loading