Skip to content

Commit 47868fc

Browse files
committed
feat(ui-buttons,shared-types): add ai-primary and ai-secondary colors to buttons
INSTUI-4546
1 parent 72af55e commit 47868fc

File tree

8 files changed

+214
-47
lines changed

8 files changed

+214
-47
lines changed

packages/shared-types/src/ComponentThemeVariables.ts

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -174,90 +174,96 @@ export type BaseButtonTheme = {
174174
iconTextGap: Spacing['xSmall']
175175
iconTextGapCondensed: Spacing['xxSmall']
176176

177-
primaryColor: Colors['contrasts']['white1010']
178-
primaryBorderColor: Colors['contrasts']['blue5782']
179-
primaryBackground: Colors['contrasts']['blue4570']
180-
primaryHoverBackground: Colors['contrasts']['blue5782']
181-
primaryActiveBackground: Colors['contrasts']['blue5782']
177+
primaryColor: string
178+
primaryBorderColor: string
179+
primaryBackground: string
180+
primaryHoverBackground: string
181+
primaryActiveBackground: string
182182
primaryActiveBoxShadow: string
183-
primaryGhostColor: Colors['contrasts']['blue4570']
184-
primaryGhostBorderColor: Colors['contrasts']['blue4570']
183+
primaryGhostColor: string
184+
primaryGhostBorderColor: string
185185
primaryGhostBackground: string
186-
primaryGhostHoverBackground: Colors['contrasts']['blue1212']
186+
primaryGhostHoverBackground: string
187187
primaryGhostActiveBackground: string
188188
primaryGhostActiveBoxShadow: string
189189
primaryBoxShadow: string
190190
primaryGhostBoxShadow: string
191191
primaryHoverBoxShadow: string
192192
primaryGhostHoverBoxShadow: string
193193

194-
secondaryColor: Colors['contrasts']['grey125125']
195-
secondaryBorderColor: Colors['contrasts']['grey1424']
196-
secondaryBackground: Colors['contrasts']['grey1111']
197-
secondaryHoverBackground: Colors['contrasts']['grey1214']
198-
secondaryActiveBackground: Colors['contrasts']['grey1214']
194+
secondaryColor: string
195+
secondaryBorderColor: string
196+
secondaryBackground: string
197+
secondaryHoverBackground: string
198+
secondaryActiveBackground: string
199199
secondaryActiveBoxShadow: string
200-
secondaryGhostColor: Colors['contrasts']['grey125125']
201-
secondaryGhostBorderColor: Colors['contrasts']['grey125125']
200+
secondaryGhostColor: string
201+
secondaryGhostBorderColor: string
202202
secondaryGhostBackground: string
203-
secondaryGhostHoverBackground: Colors['contrasts']['grey1111']
203+
secondaryGhostHoverBackground: string
204204
secondaryGhostActiveBackground: string
205205
secondaryGhostActiveBoxShadow: string
206206
secondaryBoxShadow: string
207207
secondaryGhostBoxShadow: string
208208
secondaryHoverBoxShadow: string
209209
secondaryGhostHoverBoxShadow: string
210210

211-
successColor: Colors['contrasts']['white1010']
212-
successBorderColor: Colors['contrasts']['green5782']
213-
successBackground: Colors['contrasts']['green4570']
214-
successHoverBackground: Colors['contrasts']['green5782']
215-
successActiveBackground: Colors['contrasts']['green5782']
211+
successColor: string
212+
successBorderColor: string
213+
successBackground: string
214+
successHoverBackground: string
215+
successActiveBackground: string
216216
successActiveBoxShadow: string
217-
successGhostColor: Colors['contrasts']['green4570']
218-
successGhostBorderColor: Colors['contrasts']['green4570']
217+
successGhostColor: string
218+
successGhostBorderColor: string
219219
successGhostBackground: string
220-
successGhostHoverBackground: Colors['contrasts']['green1212']
220+
successGhostHoverBackground: string
221221
successGhostActiveBackground: string
222222
successGhostActiveBoxShadow: string
223223
successBoxShadow: string
224224
successGhostBoxShadow: string
225225
successHoverBoxShadow: string
226226
successGhostHoverBoxShadow: string
227227

228-
dangerColor: Colors['contrasts']['white1010']
229-
dangerBorderColor: Colors['contrasts']['red5782']
230-
dangerBackground: Colors['contrasts']['red4570']
231-
dangerHoverBackground: Colors['contrasts']['red5782']
232-
dangerActiveBackground: Colors['contrasts']['red5782']
228+
dangerColor: string
229+
dangerBorderColor: string
230+
dangerBackground: string
231+
dangerHoverBackground: string
232+
dangerActiveBackground: string
233233
dangerActiveBoxShadow: string
234-
dangerGhostColor: Colors['contrasts']['red4570']
235-
dangerGhostBorderColor: Colors['contrasts']['red4570']
234+
dangerGhostColor: string
235+
dangerGhostBorderColor: string
236236
dangerGhostBackground: string
237-
dangerGhostHoverBackground: Colors['contrasts']['red1212']
237+
dangerGhostHoverBackground: string
238238
dangerGhostActiveBackground: string
239239
dangerGhostActiveBoxShadow: string
240240
dangerBoxShadow: string
241241
dangerGhostBoxShadow: string
242242
dangerHoverBoxShadow: string
243243
dangerGhostHoverBoxShadow: string
244244

245-
primaryInverseColor: Colors['contrasts']['grey125125']
246-
primaryInverseBorderColor: Colors['contrasts']['grey1214']
247-
primaryInverseBackground: Colors['contrasts']['white1010']
248-
primaryInverseHoverBackground: Colors['contrasts']['grey1111']
249-
primaryInverseActiveBackground: Colors['contrasts']['white1010']
245+
primaryInverseColor: string
246+
primaryInverseBorderColor: string
247+
primaryInverseBackground: string
248+
primaryInverseHoverBackground: string
249+
primaryInverseActiveBackground: string
250250
primaryInverseActiveBoxShadow: string
251-
primaryInverseGhostColor: Colors['contrasts']['white1010']
252-
primaryInverseGhostBorderColor: Colors['contrasts']['white1010']
251+
primaryInverseGhostColor: string
252+
primaryInverseGhostBorderColor: string
253253
primaryInverseGhostBackground: string
254-
primaryInverseGhostHoverBackground: Colors['contrasts']['grey1111']
254+
primaryInverseGhostHoverBackground: string
255255
primaryInverseGhostActiveBackground: string
256256
primaryInverseGhostActiveBoxShadow: string
257257
primaryInverseBoxShadow: string
258258
primaryInverseGhostBoxShadow: string
259259
primaryInverseHoverBoxShadow: string
260260
primaryInverseGhostHoverBoxShadow: string
261+
262+
aiBackgroundTopGradientColor: string
263+
aiBackgroundBottomGradientColor: string
264+
aiBorderTopGradientColor: string
265+
aiBorderBottomGradientColor: string
266+
aiActiveBoxShadow: string
261267
}
262268

263269
export type CloseButtonTheme = {

packages/ui-buttons/src/BaseButton/props.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,14 @@ type BaseButtonOwnProps = {
7676
/**
7777
* Specifies the color for the `Button`.
7878
*/
79-
color?: 'primary' | 'primary-inverse' | 'secondary' | 'success' | 'danger'
79+
color?:
80+
| 'primary'
81+
| 'primary-inverse'
82+
| 'secondary'
83+
| 'success'
84+
| 'danger'
85+
| 'ai-primary'
86+
| 'ai-secondary'
8087

8188
/**
8289
* Override the `Button`'s default focus outline color.
@@ -194,7 +201,9 @@ const propTypes: PropValidators<PropKeys> = {
194201
'primary-inverse',
195202
'secondary',
196203
'success',
197-
'danger'
204+
'danger',
205+
'ai-primary',
206+
'ai-secondary'
198207
]),
199208
focusColor: PropTypes.oneOf(['info', 'inverse']),
200209
display: PropTypes.oneOf(['inline-block', 'block']),

packages/ui-buttons/src/BaseButton/styles.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import type {
2929
BaseButtonStyle
3030
} from './props'
3131

32+
import { darken, lighten } from '@instructure/ui-color-utils'
33+
3234
/**
3335
* ---
3436
* private: true
@@ -131,6 +133,102 @@ const generateStyle = (
131133
}
132134

133135
const colorVariants = {
136+
'ai-primary': {
137+
default: {
138+
color: componentTheme.primaryColor,
139+
background: `
140+
linear-gradient(165deg, ${componentTheme.aiBackgroundTopGradientColor} -20.97%, ${componentTheme.aiBackgroundBottomGradientColor} 141.21%) padding-box,
141+
linear-gradient(125deg, ${componentTheme.aiBorderTopGradientColor} 0%, ${componentTheme.aiBorderBottomGradientColor} 141.21%) border-box`,
142+
border: 'solid transparent',
143+
boxShadow: componentTheme.primaryBoxShadow
144+
},
145+
active: {
146+
background: `
147+
linear-gradient(165deg, ${darken(
148+
componentTheme.aiBackgroundTopGradientColor,
149+
10
150+
)} -20.97%, ${darken(
151+
componentTheme.aiBackgroundBottomGradientColor,
152+
10
153+
)} 141.21%) padding-box,
154+
linear-gradient(125deg, ${darken(
155+
componentTheme.aiBorderTopGradientColor,
156+
10
157+
)} 0%, ${darken(
158+
componentTheme.aiBorderBottomGradientColor,
159+
10
160+
)} 141.21%) border-box`,
161+
border: 'solid transparent',
162+
boxShadow: componentTheme.aiActiveBoxShadow
163+
},
164+
hover: {
165+
background: `
166+
linear-gradient(165deg, ${darken(
167+
componentTheme.aiBackgroundTopGradientColor,
168+
10
169+
)} -20.97%, ${darken(
170+
componentTheme.aiBackgroundBottomGradientColor,
171+
10
172+
)} 141.21%) padding-box,
173+
linear-gradient(125deg, ${darken(
174+
componentTheme.aiBorderTopGradientColor,
175+
10
176+
)} 0%, ${darken(
177+
componentTheme.aiBorderBottomGradientColor,
178+
10
179+
)} 141.21%) border-box`,
180+
border: 'solid transparent',
181+
boxShadow: componentTheme.primaryHoverBoxShadow
182+
}
183+
},
184+
'ai-secondary': {
185+
default: {
186+
background: `
187+
linear-gradient(to bottom, ${componentTheme.aiBorderTopGradientColor} 0%, ${componentTheme.aiBorderBottomGradientColor} 100%) text,
188+
linear-gradient(white) padding-box,
189+
linear-gradient(to bottom, ${componentTheme.aiBorderTopGradientColor} -40%, ${componentTheme.aiBorderBottomGradientColor} 140%) border-box`,
190+
border: 'solid transparent',
191+
boxShadow: componentTheme.primaryBoxShadow,
192+
WebkitTextFillColor: 'transparent'
193+
},
194+
active: {
195+
background: `
196+
linear-gradient(165deg, ${darken(
197+
componentTheme.aiBackgroundTopGradientColor,
198+
10
199+
)} -20.97%, ${darken(
200+
componentTheme.aiBackgroundBottomGradientColor,
201+
10
202+
)} 141.21%) padding-box,
203+
linear-gradient(125deg, ${darken(
204+
componentTheme.aiBorderTopGradientColor,
205+
10
206+
)} 0%, ${darken(
207+
componentTheme.aiBorderBottomGradientColor,
208+
10
209+
)} 141.21%) border-box`,
210+
border: 'solid transparent',
211+
boxShadow: componentTheme.aiActiveBoxShadow
212+
},
213+
hover: {
214+
background: `
215+
linear-gradient(to bottom, ${
216+
componentTheme.aiBorderTopGradientColor
217+
} 0%, ${componentTheme.aiBorderBottomGradientColor} 100%) text,
218+
linear-gradient(165deg, ${lighten(
219+
componentTheme.aiBackgroundTopGradientColor,
220+
70
221+
)} -20.97%, ${lighten(
222+
componentTheme.aiBackgroundBottomGradientColor,
223+
70
224+
)} 141.21%) padding-box,
225+
linear-gradient(to bottom, ${
226+
componentTheme.aiBorderTopGradientColor
227+
} -40%, ${componentTheme.aiBorderBottomGradientColor} 140%) border-box`,
228+
border: 'solid transparent',
229+
boxShadow: componentTheme.primaryHoverBoxShadow
230+
}
231+
},
134232
primary: withBackground
135233
? {
136234
default: {

packages/ui-buttons/src/BaseButton/theme.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,13 @@ const generateComponentTheme = (theme: Theme): BaseButtonTheme => {
196196
primaryInverseBoxShadow: 'none',
197197
primaryInverseGhostBoxShadow: 'none',
198198
primaryInverseHoverBoxShadow: 'none',
199-
primaryInverseGhostHoverBoxShadow: 'none'
199+
primaryInverseGhostHoverBoxShadow: 'none',
200+
201+
aiBackgroundTopGradientColor: colors?.contrasts?.violet4570,
202+
aiBackgroundBottomGradientColor: colors?.contrasts?.sea4570,
203+
aiBorderTopGradientColor: colors?.contrasts?.violet5790,
204+
aiBorderBottomGradientColor: colors?.contrasts?.sea5790,
205+
aiActiveBoxShadow: '0px 0px 5px 0px #013451 inset'
200206
}
201207

202208
return {

packages/ui-buttons/src/Button/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,24 @@ type: example
2525
<Button color="success" margin="small">Success</Button>
2626
<Button color="danger" margin="small">Danger</Button>
2727
<Button color="primary-inverse" margin="small">Primary Inverse</Button>
28+
<Button color="ai-primary" margin="small">AI Primary</Button>
29+
<Button color="ai-secondary" margin="small">AI Secondary</Button>
30+
</View>
31+
```
32+
33+
### AI buttons
34+
35+
There is a specific need for `AI buttons`, which has an icon and gradient colors for `background` and `borders`. Here are the preset examples you can use. (the `IconButton` examples are also included for convenience)
36+
37+
```js
38+
---
39+
type: example
40+
---
41+
<View display="block">
42+
<Button color="ai-primary" renderIcon={IconAiSolid} margin="small">AI Primary</Button>
43+
<Button color="ai-secondary" renderIcon={IconAiColoredSolid} margin="small">AI Secondary</Button>
44+
<IconButton color="ai-primary" screenReaderLabel="AI button" margin="small"><IconAiSolid/></IconButton>
45+
<IconButton color="ai-secondary" screenReaderLabel="AI button" margin="small"><IconAiColoredSolid/></IconButton>
2846
</View>
2947
```
3048

packages/ui-buttons/src/Button/props.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,14 @@ type ButtonOwnProps = {
7070
/**
7171
* Specifies the color for the `Button`.
7272
*/
73-
color?: 'primary' | 'primary-inverse' | 'secondary' | 'success' | 'danger'
73+
color?:
74+
| 'primary'
75+
| 'primary-inverse'
76+
| 'secondary'
77+
| 'success'
78+
| 'danger'
79+
| 'ai-primary'
80+
| 'ai-secondary'
7481

7582
/**
7683
* Override the `Button`'s default focus outline color.
@@ -145,7 +152,9 @@ const propTypes: PropValidators<PropKeys> = {
145152
'primary-inverse',
146153
'secondary',
147154
'success',
148-
'danger'
155+
'danger',
156+
'ai-primary',
157+
'ai-secondary'
149158
]),
150159
focusColor: PropTypes.oneOf(['info', 'inverse']),
151160
display: PropTypes.oneOf(['inline-block', 'block']),

packages/ui-buttons/src/IconButton/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@ type: example
3838
</Tooltip>
3939
```
4040

41+
### AI Icon buttons
42+
43+
```js
44+
---
45+
type: example
46+
---
47+
<View display="block">
48+
<IconButton color="ai-primary" screenReaderLabel="AI button" margin="small"><IconAiSolid/></IconButton>
49+
<IconButton color="ai-secondary" screenReaderLabel="AI button" margin="small"><IconAiColoredSolid/></IconButton>
50+
</View>
51+
```
52+
4153
### Shaping
4254

4355
The `shape` prop specifies if the IconButton will render as a `rectangle` or `circle`.

packages/ui-buttons/src/IconButton/props.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,14 @@ type IconButtonOwnProps = {
8181
/**
8282
* Specifies the color for the `IconButton`.
8383
*/
84-
color?: 'primary' | 'primary-inverse' | 'secondary' | 'success' | 'danger'
84+
color?:
85+
| 'primary'
86+
| 'primary-inverse'
87+
| 'secondary'
88+
| 'success'
89+
| 'danger'
90+
| 'ai-primary'
91+
| 'ai-secondary'
8592

8693
/**
8794
* Override the `Button`'s default focus outline color.
@@ -152,7 +159,9 @@ const propTypes: PropValidators<PropKeys> = {
152159
'primary-inverse',
153160
'secondary',
154161
'success',
155-
'danger'
162+
'danger',
163+
'ai-primary',
164+
'ai-secondary'
156165
]),
157166
focusColor: PropTypes.oneOf(['info', 'inverse']),
158167
shape: PropTypes.oneOf(['rectangle', 'circle']),

0 commit comments

Comments
 (0)