Skip to content

Commit a31cd49

Browse files
committed
refactor(ui,ui-form-field,shared-types): add back FormFieldLabel, mark it as deprecated
Some of our users are still using it
1 parent abad1cc commit a31cd49

File tree

8 files changed

+381
-0
lines changed

8 files changed

+381
-0
lines changed

packages/shared-types/src/ComponentThemeVariables.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,14 @@ export type FormFieldLayoutTheme = {
606606
spacing: any // TODO remove any
607607
}
608608

609+
export type FormFieldLabelTheme = {
610+
color: Colors['contrasts']['grey125125']
611+
fontFamily: Typography['fontFamily']
612+
fontWeight: Typography['fontWeightBold']
613+
fontSize: Typography['fontSizeMedium']
614+
lineHeight: Typography['lineHeightFit']
615+
}
616+
609617
export type FormFieldMessageTheme = {
610618
colorHint: Colors['contrasts']['grey125125']
611619
colorError: Colors['contrasts']['red4570']
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2015 - present Instructure, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
import React from 'react'
26+
import { render } from '@testing-library/react'
27+
import { vi } from 'vitest'
28+
import { runAxeCheck } from '@instructure/ui-axe-check'
29+
import '@testing-library/jest-dom'
30+
31+
import { FormFieldLabel } from '../index'
32+
33+
describe('<FormFieldLabel />', () => {
34+
let consoleWarningMock: ReturnType<typeof vi.spyOn>
35+
let consoleErrorMock: ReturnType<typeof vi.spyOn>
36+
37+
beforeEach(() => {
38+
// Mocking console to prevent test output pollution and expect for messages
39+
consoleWarningMock = vi
40+
.spyOn(console, 'warn')
41+
.mockImplementation(() => {}) as any
42+
consoleErrorMock = vi
43+
.spyOn(console, 'error')
44+
.mockImplementation(() => {}) as any
45+
})
46+
47+
afterEach(() => {
48+
consoleWarningMock.mockRestore()
49+
consoleErrorMock.mockRestore()
50+
})
51+
52+
it('should render', () => {
53+
const { container } = render(<FormFieldLabel>Foo</FormFieldLabel>)
54+
55+
const formFieldLabel = container.querySelector(
56+
"span[class$='-formFieldLabel']"
57+
)
58+
59+
expect(formFieldLabel).toBeInTheDocument()
60+
expect(formFieldLabel).toHaveTextContent('Foo')
61+
})
62+
63+
it('should render as specified via the `as` prop', () => {
64+
const { container } = render(<FormFieldLabel as="li">Foo</FormFieldLabel>)
65+
66+
const formFieldLabel = container.querySelector('li')
67+
68+
expect(formFieldLabel).toBeInTheDocument()
69+
expect(formFieldLabel).toHaveTextContent('Foo')
70+
})
71+
72+
it('should meet a11y standards', async () => {
73+
const { container } = render(<FormFieldLabel>Foo</FormFieldLabel>)
74+
75+
const axeCheck = await runAxeCheck(container)
76+
77+
expect(axeCheck).toBe(true)
78+
})
79+
})
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2015 - present Instructure, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
/** @jsx jsx */
26+
import { Component } from 'react'
27+
28+
import {
29+
omitProps,
30+
getElementType,
31+
deprecated
32+
} from '@instructure/ui-react-utils'
33+
import { withStyle, jsx } from '@instructure/emotion'
34+
35+
import generateStyle from './styles'
36+
import generateComponentTheme from './theme'
37+
38+
import { propTypes, allowedProps } from './props'
39+
import type { FormFieldLabelProps } from './props'
40+
41+
/**
42+
---
43+
parent: FormField
44+
---
45+
46+
This is a helper component that is used by most of the custom form
47+
components. In most cases it shouldn't be used directly.
48+
49+
```js
50+
---
51+
type: example
52+
---
53+
<FormFieldLabel>Hello</FormFieldLabel>
54+
```
55+
56+
@deprecated since version 10. This is an internal component that will be
57+
removed in the future
58+
**/
59+
@withStyle(generateStyle, generateComponentTheme)
60+
@deprecated('10', null, 'This component will be removed in a future version')
61+
class FormFieldLabel extends Component<FormFieldLabelProps> {
62+
static readonly componentId = 'FormFieldLabel'
63+
64+
static propTypes = propTypes
65+
static allowedProps = allowedProps
66+
static defaultProps = {
67+
as: 'span'
68+
} as const
69+
70+
ref: Element | null = null
71+
72+
handleRef = (el: Element | null) => {
73+
this.ref = el
74+
}
75+
76+
componentDidMount() {
77+
this.props.makeStyles?.()
78+
}
79+
80+
componentDidUpdate() {
81+
this.props.makeStyles?.()
82+
}
83+
84+
render() {
85+
const ElementType = getElementType(FormFieldLabel, this.props)
86+
87+
const { styles, children } = this.props
88+
89+
return (
90+
<ElementType
91+
{...omitProps(this.props, FormFieldLabel.allowedProps)}
92+
css={styles?.formFieldLabel}
93+
ref={this.handleRef}
94+
>
95+
{children}
96+
</ElementType>
97+
)
98+
}
99+
}
100+
101+
export default FormFieldLabel
102+
export { FormFieldLabel }
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2015 - present Instructure, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
import PropTypes from 'prop-types'
26+
27+
import type {
28+
AsElementType,
29+
PropValidators,
30+
FormFieldLabelTheme,
31+
OtherHTMLAttributes
32+
} from '@instructure/shared-types'
33+
import type { WithStyleProps, ComponentStyle } from '@instructure/emotion'
34+
35+
type FormFieldLabelOwnProps = {
36+
children: React.ReactNode
37+
as?: AsElementType
38+
}
39+
40+
type PropKeys = keyof FormFieldLabelOwnProps
41+
42+
type AllowedPropKeys = Readonly<Array<PropKeys>>
43+
44+
type FormFieldLabelProps = FormFieldLabelOwnProps &
45+
WithStyleProps<FormFieldLabelTheme, FormFieldLabelStyle> &
46+
OtherHTMLAttributes<FormFieldLabelOwnProps>
47+
48+
type FormFieldLabelStyle = ComponentStyle<'formFieldLabel'>
49+
50+
const propTypes: PropValidators<PropKeys> = {
51+
children: PropTypes.node.isRequired,
52+
as: PropTypes.elementType
53+
}
54+
55+
const allowedProps: AllowedPropKeys = ['as', 'children']
56+
57+
export type { FormFieldLabelProps, FormFieldLabelStyle }
58+
export { propTypes, allowedProps }
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2015 - present Instructure, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
import { hasVisibleChildren } from '@instructure/ui-a11y-utils'
26+
27+
import type { FormFieldLabelTheme } from '@instructure/shared-types'
28+
import type { FormFieldLabelProps, FormFieldLabelStyle } from './props'
29+
30+
/**
31+
* ---
32+
* private: true
33+
* ---
34+
* Generates the style object from the theme and provided additional information
35+
* @param {Object} componentTheme The theme variable object.
36+
* @param {Object} props the props of the component, the style is applied to
37+
* @param {Object} state the state of the component, the style is applied to
38+
* @return {Object} The final style object, which will be used in the component
39+
*/
40+
const generateStyle = (
41+
componentTheme: FormFieldLabelTheme,
42+
props: FormFieldLabelProps
43+
): FormFieldLabelStyle => {
44+
const { children } = props
45+
46+
const hasContent = hasVisibleChildren(children)
47+
48+
const labelStyles = {
49+
all: 'initial',
50+
display: 'block',
51+
...(hasContent && {
52+
color: componentTheme.color,
53+
fontFamily: componentTheme.fontFamily,
54+
fontWeight: componentTheme.fontWeight,
55+
fontSize: componentTheme.fontSize,
56+
lineHeight: componentTheme.lineHeight,
57+
margin: 0,
58+
textAlign: 'inherit'
59+
})
60+
}
61+
62+
return {
63+
formFieldLabel: {
64+
label: 'formFieldLabel',
65+
...labelStyles,
66+
67+
// NOTE: needs separate groups for `:is()` and `:-webkit-any()` because of css selector group validation (see https://www.w3.org/TR/selectors-3/#grouping)
68+
'&:is(label)': labelStyles,
69+
'&:-webkit-any(label)': labelStyles
70+
}
71+
}
72+
}
73+
74+
export default generateStyle
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2015 - present Instructure, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
import type { Theme, ThemeSpecificStyle } from '@instructure/ui-themes'
26+
import { FormFieldLabelTheme } from '@instructure/shared-types'
27+
28+
/**
29+
* Generates the theme object for the component from the theme and provided additional information
30+
* @param {Object} theme The actual theme object.
31+
* @return {Object} The final theme object with the overrides and component variables
32+
*/
33+
const generateComponentTheme = (theme: Theme): FormFieldLabelTheme => {
34+
const { colors, typography, key: themeName } = theme
35+
36+
const themeSpecificStyle: ThemeSpecificStyle<FormFieldLabelTheme> = {
37+
canvas: {
38+
color: theme['ic-brand-font-color-dark']
39+
}
40+
}
41+
42+
const componentVariables: FormFieldLabelTheme = {
43+
color: colors?.contrasts?.grey125125,
44+
fontFamily: typography?.fontFamily,
45+
fontWeight: typography?.fontWeightBold,
46+
fontSize: typography?.fontSizeMedium,
47+
lineHeight: typography?.lineHeightFit
48+
}
49+
50+
return {
51+
...componentVariables,
52+
...themeSpecificStyle[themeName]
53+
}
54+
}
55+
56+
export default generateComponentTheme

0 commit comments

Comments
 (0)