Skip to content

Commit a74236a

Browse files
committed
feat(ui-heading,shared-types): add new aiHeading prop and design. Also add h6 level to heading
INSTUI-4616
1 parent 94ed2c3 commit a74236a

File tree

9 files changed

+143
-39
lines changed

9 files changed

+143
-39
lines changed

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/shared-types/src/ComponentThemeVariables.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,9 @@ export type HeadingTheme = Typography & {
662662
h5FontSize: Typography['fontSizeSmall']
663663
h5FontWeight: Typography['fontWeightNormal']
664664
h5FontFamily: Typography['fontFamily']
665+
h6FontSize: Typography['fontSizeXSmall']
666+
h6FontWeight: Typography['fontWeightNormal']
667+
h6FontFamily: Typography['fontFamily']
665668
primaryInverseColor: string
666669
primaryColor: string
667670
secondaryColor: string

packages/ui-heading/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"@instructure/shared-types": "10.21.0",
3030
"@instructure/ui-prop-types": "10.21.0",
3131
"@instructure/ui-react-utils": "10.21.0",
32+
"@instructure/ui-icons": "10.21.0",
3233
"@instructure/ui-testable": "10.21.0",
3334
"@instructure/ui-view": "10.21.0",
3435
"prop-types": "^15.8.1"

packages/ui-heading/src/Heading/README.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,19 @@ type: example
3434
</div>
3535
```
3636

37+
### AI Heading
38+
39+
Pre-configured and with unique styles, the `ai-headings` are used for standardized, ai-related components.
40+
3741
```js
3842
---
3943
type: example
4044
---
41-
<Heading>Default Heading</Heading>
45+
<div style={{display: 'flex', flexDirection: 'column', gap: '24px'}}>
46+
<Heading aiVariant="stacked">Nutrition Facts</Heading>
47+
<Heading aiVariant="horizontal">Nutrition Facts</Heading>
48+
<Heading aiVariant="iconOnly">Nutrition Facts</Heading>
49+
</div>
4250
```
4351

4452
### Heading level
@@ -70,20 +78,19 @@ type: example
7078
<Heading>I inherit my color via the CSS cascade (default)</Heading>
7179
<Heading color="primary">I am primary color</Heading>
7280
<Heading color="secondary">I am secondary color</Heading>
73-
<Heading color="ai">I am AI color</Heading>
7481
</div>
7582
```
7683

7784
### Icons
7885

79-
With the `renderIcon` prop, an icon can be rendered before the text. Only current use-case is for the `ai heading`
86+
With the `renderIcon` prop, an icon can be rendered before the text.
8087

8188
```js
8289
---
8390
type: example
8491
---
8592
<div>
86-
<Heading color="ai" renderIcon={<IconAiColoredSolid/>}>I am AI color with icon</Heading>
93+
<Heading renderIcon={<IconAdminSolid/>}>I am heading with icon</Heading>
8794
</div>
8895
```
8996

packages/ui-heading/src/Heading/index.tsx

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
callRenderProp
3232
} from '@instructure/ui-react-utils'
3333
import { testable } from '@instructure/ui-testable'
34+
import { IconAiColoredSolid } from '@instructure/ui-icons'
3435

3536
import { withStyle } from '@instructure/emotion'
3637

@@ -107,18 +108,58 @@ class Heading extends Component<HeadingProps> {
107108
}
108109

109110
renderContent() {
110-
const { children, renderIcon } = this.props
111+
const { children, renderIcon, aiVariant } = this.props
111112

112-
if (renderIcon) {
113+
if (renderIcon && !aiVariant) {
113114
return (
114-
<>
115+
<span css={[this.props.styles?.withIcon]} aria-hidden="true">
115116
{callRenderProp(renderIcon)}&nbsp;{children}
116-
</>
117+
</span>
118+
)
119+
}
120+
if (aiVariant === 'stacked') {
121+
return (
122+
<span css={[this.props.styles?.withIcon]} aria-hidden="true">
123+
<span css={this.props.styles?.igniteAIStacked}>
124+
<IconAiColoredSolid />
125+
<span css={this.props.styles?.igniteAI}>IgniteAI</span>
126+
</span>
127+
{children}
128+
</span>
129+
)
130+
}
131+
if (aiVariant === 'horizontal') {
132+
return (
133+
<span css={this.props.styles?.withIcon} aria-hidden="true">
134+
<IconAiColoredSolid />
135+
<span css={this.props.styles?.igniteAI}>IgniteAI</span>
136+
{children}
137+
</span>
138+
)
139+
}
140+
if (aiVariant === 'iconOnly') {
141+
return (
142+
<span css={this.props.styles?.withIcon} aria-hidden="true">
143+
<IconAiColoredSolid />
144+
&nbsp;{children}
145+
</span>
117146
)
118147
}
119148
return children
120149
}
121150

151+
//overriding default screen reader functionality is needed to read spans in h tags correctly
152+
getAriaLabel() {
153+
const { aiVariant, children, renderIcon } = this.props
154+
if (aiVariant === 'stacked' || aiVariant === 'horizontal') {
155+
return `IgniteAI, ${children}`
156+
}
157+
if (aiVariant === 'iconOnly' || renderIcon) {
158+
return `${children}`
159+
}
160+
return undefined
161+
}
162+
122163
render() {
123164
const {
124165
border,
@@ -155,6 +196,7 @@ class Heading extends Component<HeadingProps> {
155196
as={ElementType}
156197
elementRef={this.handleRef}
157198
margin={margin}
199+
aria-label={this.getAriaLabel()}
158200
>
159201
{this.renderContent()}
160202
</View>

packages/ui-heading/src/Heading/props.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ import type {
4242
type HeadingLevel<U extends keyof JSX.IntrinsicElements> = U
4343

4444
type HeadingOwnProps = {
45+
/**
46+
* transforms heading into an ai variant
47+
*/
48+
aiVariant?: 'stacked' | 'horizontal' | 'iconOnly'
4549
/**
4650
* The text content of the Heading
4751
*/
@@ -51,7 +55,7 @@ type HeadingOwnProps = {
5155
*/
5256
border?: 'none' | 'top' | 'bottom'
5357
/**
54-
* The font color to render
58+
* The font color to render, NOTE: `ai` color is deprecated. Use the `aiVariant` prop instead
5559
*/
5660
color?:
5761
| 'primary'
@@ -63,7 +67,7 @@ type HeadingOwnProps = {
6367
/**
6468
* The *visual* appearance of the Heading: h1 is largest; h5 is smallest.
6569
*/
66-
level?: HeadingLevel<'h1' | 'h2' | 'h3' | 'h4' | 'h5'> | 'reset'
70+
level?: HeadingLevel<'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'> | 'reset'
6771
/**
6872
* Choose the element Heading should render as. Will default to the `level` prop
6973
* if not specified.
@@ -107,9 +111,12 @@ type HeadingProps = HeadingOwnProps &
107111
WithStyleProps<HeadingTheme, HeadingStyle> &
108112
OtherHTMLAttributes<HeadingOwnProps>
109113

110-
type HeadingStyle = ComponentStyle<'heading'>
114+
type HeadingStyle = ComponentStyle<
115+
'heading' | 'igniteAI' | 'igniteAIStacked' | 'withIcon'
116+
>
111117

112118
const propTypes: PropValidators<PropKeys> = {
119+
aiVariant: PropTypes.oneOf(['stacked', 'horizontal', 'iconOnly']),
113120
border: PropTypes.oneOf(['none', 'top', 'bottom']),
114121
children: childrenOrValue,
115122
color: PropTypes.oneOf([
@@ -140,6 +147,7 @@ const propTypes: PropValidators<PropKeys> = {
140147
}
141148

142149
const allowedProps: AllowedPropKeys = [
150+
'aiVariant',
143151
'border',
144152
'children',
145153
'color',

packages/ui-heading/src/Heading/styles.ts

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const generateStyle = (
3939
componentTheme: HeadingTheme,
4040
props: HeadingProps
4141
): HeadingStyle => {
42-
const { level, color, border, variant, renderIcon } = props
42+
const { level, color, border, variant, aiVariant } = props
4343

4444
const variants: Record<NonNullable<HeadingProps['variant']>, object> = {
4545
titlePageDesktop: {
@@ -130,6 +130,11 @@ const generateStyle = (
130130
fontSize: componentTheme.h5FontSize,
131131
fontWeight: componentTheme.h5FontWeight
132132
},
133+
h6: {
134+
fontFamily: componentTheme.h6FontFamily,
135+
fontSize: componentTheme.h6FontSize,
136+
fontWeight: componentTheme.h6FontWeight
137+
},
133138
reset: {
134139
margin: 0,
135140
fontSize: 'inherit',
@@ -188,13 +193,6 @@ const generateStyle = (
188193
label: 'heading',
189194
lineHeight: componentTheme.lineHeight,
190195
margin: 0,
191-
//need this for icons to render them vertically centered
192-
...(renderIcon
193-
? {
194-
display: 'flex',
195-
alignItems: 'center'
196-
}
197-
: {}),
198196
// NOTE: the input styles exist to accommodate the InPlaceEdit component
199197
// NOTE: needs separate groups for `:is()` and `:-webkit-any()` because of css selector group validation (see https://www.w3.org/TR/selectors-3/#grouping)
200198
'&:is(input)[type]': inputStyles,
@@ -203,6 +201,33 @@ const generateStyle = (
203201
...(variant ? variants[variant] : levelStyles[level!]),
204202
...colorStyles[color!],
205203
...borderStyles[border!]
204+
},
205+
igniteAI: {
206+
label: 'heading__ignite-ai',
207+
background: `
208+
linear-gradient(to bottom, ${componentTheme.aiTextTopGradientColor} 0%, ${componentTheme.aiTextBottomGradientColor} 100%) text`,
209+
border: 'solid transparent',
210+
WebkitTextFillColor: 'transparent',
211+
paddingRight: '.25rem'
212+
},
213+
igniteAIStacked: {
214+
label: 'heading__ignite-ai-stacked',
215+
fontSize: '1rem',
216+
lineHeight: '1.25rem',
217+
display: 'flex',
218+
alignItems: 'center'
219+
},
220+
withIcon: {
221+
label: 'heading__with-icon',
222+
display: 'flex',
223+
alignItems: 'center',
224+
...(aiVariant === 'stacked'
225+
? {
226+
display: 'flex',
227+
flexDirection: 'column',
228+
alignItems: 'flex-start'
229+
}
230+
: {})
206231
}
207232
}
208233
}

packages/ui-heading/src/Heading/theme.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,6 @@ const generateComponentTheme = (theme: Theme): HeadingTheme => {
3636
const themeSpecificStyle: ThemeSpecificStyle<HeadingTheme> = {
3737
canvas: {
3838
primaryColor: theme['ic-brand-font-color-dark']
39-
},
40-
instructure: {
41-
h1FontFamily: typography?.fontFamilyHeading,
42-
h2FontFamily: typography?.fontFamilyHeading,
43-
h3FontWeight: typography?.fontWeightBold,
44-
h3FontSize: '2.125rem',
45-
h4FontWeight: typography?.fontWeightBold,
46-
h4FontSize: typography?.fontSizeLarge,
47-
h5FontWeight: typography?.fontWeightBold,
48-
h5FontSize: typography?.fontSizeMedium
4939
}
5040
}
5141

@@ -74,6 +64,10 @@ const generateComponentTheme = (theme: Theme): HeadingTheme => {
7464
h5FontWeight: typography?.fontWeightNormal,
7565
h5FontFamily: typography?.fontFamily,
7666

67+
h6FontSize: typography?.fontSizeXSmall,
68+
h6FontWeight: typography?.fontWeightNormal,
69+
h6FontFamily: typography?.fontFamily,
70+
7771
primaryInverseColor: colors?.contrasts?.white1010,
7872
primaryColor: colors?.contrasts?.grey125125,
7973

packages/ui-heading/tsconfig.build.json

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,38 @@
77
},
88
"include": ["src"],
99
"references": [
10-
{ "path": "../console/tsconfig.build.json" },
11-
{ "path": "../emotion/tsconfig.build.json" },
12-
{ "path": "../shared-types/tsconfig.build.json" },
13-
{ "path": "../ui-axe-check/tsconfig.build.json" },
14-
{ "path": "../ui-prop-types/tsconfig.build.json" },
15-
{ "path": "../ui-react-utils/tsconfig.build.json" },
16-
{ "path": "../ui-testable/tsconfig.build.json" },
17-
{ "path": "../ui-view/tsconfig.build.json" },
18-
{ "path": "../ui-babel-preset/tsconfig.build.json" },
19-
{ "path": "../ui-themes/tsconfig.build.json" }
10+
{
11+
"path": "../console/tsconfig.build.json"
12+
},
13+
{
14+
"path": "../emotion/tsconfig.build.json"
15+
},
16+
{
17+
"path": "../shared-types/tsconfig.build.json"
18+
},
19+
{
20+
"path": "../ui-axe-check/tsconfig.build.json"
21+
},
22+
{
23+
"path": "../ui-prop-types/tsconfig.build.json"
24+
},
25+
{
26+
"path": "../ui-react-utils/tsconfig.build.json"
27+
},
28+
{
29+
"path": "../ui-testable/tsconfig.build.json"
30+
},
31+
{
32+
"path": "../ui-icons/tsconfig.build.json"
33+
},
34+
{
35+
"path": "../ui-view/tsconfig.build.json"
36+
},
37+
{
38+
"path": "../ui-babel-preset/tsconfig.build.json"
39+
},
40+
{
41+
"path": "../ui-themes/tsconfig.build.json"
42+
}
2043
]
2144
}

0 commit comments

Comments
 (0)