Skip to content

Commit d824af3

Browse files
committed
feat(button): add subtle hue for the ionic theme
1 parent 19c944a commit d824af3

File tree

8 files changed

+194
-107
lines changed

8 files changed

+194
-107
lines changed

core/api.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ ion-button,prop,expand,"block" | "full" | undefined,undefined,false,true
390390
ion-button,prop,fill,"clear" | "default" | "outline" | "solid" | undefined,undefined,false,true
391391
ion-button,prop,form,HTMLFormElement | string | undefined,undefined,false,false
392392
ion-button,prop,href,string | undefined,undefined,false,false
393+
ion-button,prop,hue,"bold" | "subtle" | undefined,'bold',false,false
393394
ion-button,prop,mode,"ios" | "md",undefined,false,false
394395
ion-button,prop,rel,string | undefined,undefined,false,false
395396
ion-button,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false

core/src/components.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,10 @@ export namespace Components {
562562
* Contains a URL or a URL fragment that the hyperlink points to. If this property is set, an anchor tag will be rendered.
563563
*/
564564
"href": string | undefined;
565+
/**
566+
* Set to `"bold"` for a button with vibrant, bold colors or to `"subtle"` for a button with muted, subtle colors.
567+
*/
568+
"hue"?: 'bold' | 'subtle';
565569
/**
566570
* The mode determines the platform behaviors of the component.
567571
*/
@@ -6019,6 +6023,10 @@ declare namespace LocalJSX {
60196023
* Contains a URL or a URL fragment that the hyperlink points to. If this property is set, an anchor tag will be rendered.
60206024
*/
60216025
"href"?: string | undefined;
6026+
/**
6027+
* Set to `"bold"` for a button with vibrant, bold colors or to `"subtle"` for a button with muted, subtle colors.
6028+
*/
6029+
"hue"?: 'bold' | 'subtle';
60226030
/**
60236031
* The mode determines the platform behaviors of the component.
60246032
*/

core/src/components/button/button.ionic.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@
5252
--ripple-color: var(--background-activated);
5353
}
5454

55+
:host(.button-solid.button-subtle) {
56+
--background: #{globals.ion-color(primary, base, $subtle: true)};
57+
--background-activated: #{globals.ion-color(primary, shade, $subtle: true)};
58+
--color: #{globals.ion-color(primary, contrast, $subtle: true)};
59+
}
60+
5561
// Outline Button
5662
// --------------------------------------------------
5763

@@ -81,6 +87,19 @@
8187
// Ripple Effect
8288
// -------------------------------------------------------------------------------
8389

90+
:host(.button-solid.button-subtle.ion-color) .button-native {
91+
background: globals.current-color(base, $subtle: true);
92+
color: globals.current-color(contrast, $subtle: true);
93+
}
94+
95+
:host(.button-solid.button-subtle.ion-color.ion-activated) .button-native::after {
96+
background: globals.current-color(shade, $subtle: true);
97+
}
98+
99+
:host(.button-solid.button-subtle.ion-color.ion-focused) .button-native::after {
100+
background: globals.current-color(tint, $subtle: true);
101+
}
102+
84103
:host(.button-solid.ion-color) ion-ripple-effect {
85104
color: globals.current-color(shade);
86105
}

core/src/components/button/button.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
7575
*/
7676
@Prop({ reflect: true }) expand?: 'full' | 'block';
7777

78+
/**
79+
* Set to `"bold"` for a button with vibrant, bold colors or to `"subtle"` for
80+
* a button with muted, subtle colors.
81+
*/
82+
@Prop() hue?: 'bold' | 'subtle' = 'bold';
83+
7884
/**
7985
* Set to `"clear"` for a transparent button that resembles a flat button, to `"outline"`
8086
* for a transparent button with a border, or to `"solid"` for a button with a filled background.
@@ -349,8 +355,20 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
349355
};
350356

351357
render() {
352-
const { buttonType, type, disabled, rel, target, href, color, expand, hasIconOnly, strong, inheritedAttributes } =
353-
this;
358+
const {
359+
buttonType,
360+
type,
361+
disabled,
362+
rel,
363+
target,
364+
href,
365+
color,
366+
expand,
367+
hue,
368+
hasIconOnly,
369+
strong,
370+
inheritedAttributes,
371+
} = this;
354372

355373
const theme = getIonTheme(this);
356374
const mode = getIonMode(this);
@@ -394,6 +412,7 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
394412
[theme]: true,
395413
[buttonType]: true,
396414
[`${buttonType}-${expand}`]: expand !== undefined,
415+
[`${buttonType}-${hue}`]: hue !== undefined,
397416
[`${buttonType}-${size}`]: size !== undefined,
398417
[`${buttonType}-${shape}`]: true,
399418
[`${buttonType}-${fill}`]: true,

core/src/components/button/test/basic/index.html

Lines changed: 140 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@
1212
<script src="../../../../../scripts/testing/scripts.js"></script>
1313
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
1414
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
15+
16+
<style>
17+
.container {
18+
display: grid;
19+
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
20+
}
21+
22+
ion-button {
23+
margin: 8px 4px;
24+
}
25+
</style>
1526
</head>
1627

1728
<body>
@@ -23,108 +34,136 @@
2334
</ion-header>
2435

2536
<ion-content class="ion-padding ion-text-center" id="content" no-bounce>
26-
<p>
27-
<ion-button id="default">Default</ion-button>
28-
<ion-button class="ion-focused">Default.focused</ion-button>
29-
<ion-button class="ion-activated">Default.activated</ion-button>
30-
</p>
31-
32-
<p>
33-
<ion-button color="primary">Primary</ion-button>
34-
<ion-button class="ion-focused" color="primary">Primary.focused</ion-button>
35-
<ion-button class="ion-activated" color="primary">Primary.activated</ion-button>
36-
</p>
37-
38-
<p>
39-
<ion-button color="secondary">Secondary</ion-button>
40-
<ion-button class="ion-focused" color="secondary">Secondary.focused</ion-button>
41-
<ion-button class="ion-activated" color="secondary">Secondary.activated</ion-button>
42-
</p>
43-
44-
<p>
45-
<ion-button color="tertiary">Tertiary</ion-button>
46-
<ion-button class="ion-focused" color="tertiary">Tertiary.focused</ion-button>
47-
<ion-button class="ion-activated" color="tertiary">Tertiary.activated</ion-button>
48-
</p>
49-
50-
<p>
51-
<ion-button color="success">Success</ion-button>
52-
<ion-button class="ion-focused" color="success">Success.focused</ion-button>
53-
<ion-button class="ion-activated" color="success">Success.activated</ion-button>
54-
</p>
55-
56-
<p>
57-
<ion-button color="warning">Warning</ion-button>
58-
<ion-button class="ion-focused" color="warning">Warning.focused</ion-button>
59-
<ion-button class="ion-activated" color="warning">Warning.activated</ion-button>
60-
</p>
61-
62-
<p>
63-
<ion-button color="danger">Danger</ion-button>
64-
<ion-button class="ion-focused" color="danger">Danger.focused</ion-button>
65-
<ion-button class="ion-activated" color="danger">Danger.activated</ion-button>
66-
</p>
67-
68-
<p>
69-
<ion-button color="light">Light</ion-button>
70-
<ion-button class="ion-focused" color="light">Light.focused</ion-button>
71-
<ion-button class="ion-activated" color="light">Light.activated</ion-button>
72-
</p>
73-
74-
<p>
75-
<ion-button color="medium">Medium</ion-button>
76-
<ion-button class="ion-focused" color="medium">Medium.focused</ion-button>
77-
<ion-button class="ion-activated" color="medium">Medium.activated</ion-button>
78-
</p>
79-
80-
<p>
81-
<ion-button color="dark">Dark</ion-button>
82-
<ion-button class="ion-focused" color="dark">Dark.focused</ion-button>
83-
<ion-button class="ion-activated" color="dark">Dark.activated</ion-button>
84-
</p>
85-
86-
<p>
87-
<ion-button style="--opacity: 0.2">Opacity: 0.2</ion-button>
88-
</p>
89-
90-
<p>
91-
<ion-button expand="block" id="disabledButton" disabled>Button Disabled</ion-button>
92-
<ion-button expand="block" color="secondary" disabled>Secondary Disabled</ion-button>
93-
<ion-button expand="block" color="tertiary" style="--opacity: 1" disabled>Disabled opacity: 1</ion-button>
94-
</p>
95-
96-
<p>
97-
<ion-button expand="block" onclick="toggleDisabled()">Toggle Disabled</ion-button>
98-
</p>
99-
100-
<p>
101-
<ion-button id="dynamicColor1" onclick="changeColor(event)">Change Color</ion-button>
102-
<ion-button id="dynamicColor2" onclick="changeColor(event)" fill="outline">Change Color</ion-button>
103-
</p>
37+
<div class="container">
38+
<div class="item">
39+
<h2>Bold (default) Buttons</h2>
40+
41+
<p>
42+
<ion-button id="default">Default</ion-button>
43+
<ion-button class="ion-focused">Default.focused</ion-button>
44+
<ion-button class="ion-activated">Default.activated</ion-button>
45+
</p>
46+
47+
<p>
48+
<ion-button color="primary">Primary</ion-button>
49+
<ion-button class="ion-focused" color="primary">Primary.focused</ion-button>
50+
<ion-button class="ion-activated" color="primary">Primary.activated</ion-button>
51+
</p>
52+
53+
<p>
54+
<ion-button color="secondary">Secondary</ion-button>
55+
<ion-button class="ion-focused" color="secondary">Secondary.focused</ion-button>
56+
<ion-button class="ion-activated" color="secondary">Secondary.activated</ion-button>
57+
</p>
58+
59+
<p>
60+
<ion-button color="tertiary">Tertiary</ion-button>
61+
<ion-button class="ion-focused" color="tertiary">Tertiary.focused</ion-button>
62+
<ion-button class="ion-activated" color="tertiary">Tertiary.activated</ion-button>
63+
</p>
64+
65+
<p>
66+
<ion-button color="success">Success</ion-button>
67+
<ion-button class="ion-focused" color="success">Success.focused</ion-button>
68+
<ion-button class="ion-activated" color="success">Success.activated</ion-button>
69+
</p>
70+
71+
<p>
72+
<ion-button color="warning">Warning</ion-button>
73+
<ion-button class="ion-focused" color="warning">Warning.focused</ion-button>
74+
<ion-button class="ion-activated" color="warning">Warning.activated</ion-button>
75+
</p>
76+
77+
<p>
78+
<ion-button color="danger">Danger</ion-button>
79+
<ion-button class="ion-focused" color="danger">Danger.focused</ion-button>
80+
<ion-button class="ion-activated" color="danger">Danger.activated</ion-button>
81+
</p>
82+
83+
<p>
84+
<ion-button color="light">Light</ion-button>
85+
<ion-button class="ion-focused" color="light">Light.focused</ion-button>
86+
<ion-button class="ion-activated" color="light">Light.activated</ion-button>
87+
</p>
88+
89+
<p>
90+
<ion-button color="medium">Medium</ion-button>
91+
<ion-button class="ion-focused" color="medium">Medium.focused</ion-button>
92+
<ion-button class="ion-activated" color="medium">Medium.activated</ion-button>
93+
</p>
94+
95+
<p>
96+
<ion-button color="dark">Dark</ion-button>
97+
<ion-button class="ion-focused" color="dark">Dark.focused</ion-button>
98+
<ion-button class="ion-activated" color="dark">Dark.activated</ion-button>
99+
</p>
100+
</div>
101+
102+
<div class="item">
103+
<h2>Subtle Buttons</h2>
104+
105+
<p>
106+
<ion-button hue="subtle" id="default">Default</ion-button>
107+
<ion-button hue="subtle" class="ion-focused">Default.focused</ion-button>
108+
<ion-button hue="subtle" class="ion-activated">Default.activated</ion-button>
109+
</p>
110+
111+
<p>
112+
<ion-button hue="subtle" color="primary">Primary</ion-button>
113+
<ion-button hue="subtle" color="primary" class="ion-focused">Primary.focused</ion-button>
114+
<ion-button hue="subtle" color="primary" class="ion-activated">Primary.activated</ion-button>
115+
</p>
116+
117+
<p>
118+
<ion-button hue="subtle" color="secondary">Secondary</ion-button>
119+
<ion-button hue="subtle" class="ion-focused" color="secondary">Secondary.focused</ion-button>
120+
<ion-button hue="subtle" class="ion-activated" color="secondary">Secondary.activated</ion-button>
121+
</p>
122+
123+
<p>
124+
<ion-button hue="subtle" color="tertiary">Tertiary</ion-button>
125+
<ion-button hue="subtle" class="ion-focused" color="tertiary">Tertiary.focused</ion-button>
126+
<ion-button hue="subtle" class="ion-activated" color="tertiary">Tertiary.activated</ion-button>
127+
</p>
128+
129+
<p>
130+
<ion-button hue="subtle" color="success">Success</ion-button>
131+
<ion-button hue="subtle" color="success" class="ion-focused">Success.focused</ion-button>
132+
<ion-button hue="subtle" color="success" class="ion-activated">Success.activated</ion-button>
133+
</p>
134+
135+
<p>
136+
<ion-button hue="subtle" color="warning">Warning</ion-button>
137+
<ion-button hue="subtle" color="warning" class="ion-focused">Warning.focused</ion-button>
138+
<ion-button hue="subtle" color="warning" class="ion-activated">Warning.activated</ion-button>
139+
</p>
140+
141+
<p>
142+
<ion-button hue="subtle" color="danger">Danger</ion-button>
143+
<ion-button hue="subtle" color="danger" class="ion-focused">Danger.focused</ion-button>
144+
<ion-button hue="subtle" color="danger" class="ion-activated">Danger.activated</ion-button>
145+
</p>
146+
147+
<p>
148+
<ion-button hue="subtle" color="light">Light</ion-button>
149+
<ion-button hue="subtle" color="light" class="ion-focused">Light.focused</ion-button>
150+
<ion-button hue="subtle" color="light" class="ion-activated">Light.activated</ion-button>
151+
</p>
152+
153+
<p>
154+
<ion-button hue="subtle" color="medium">Medium</ion-button>
155+
<ion-button hue="subtle" color="medium" class="ion-focused">Medium.focused</ion-button>
156+
<ion-button hue="subtle" color="medium" class="ion-activated">Medium.activated</ion-button>
157+
</p>
158+
159+
<p>
160+
<ion-button hue="subtle" color="dark">Dark</ion-button>
161+
<ion-button hue="subtle" color="dark" class="ion-focused">Dark.focused</ion-button>
162+
<ion-button hue="subtle" color="dark" class="ion-activated">Dark.activated</ion-button>
163+
</p>
164+
</div>
165+
</div>
104166
</ion-content>
105167
</ion-app>
106-
107-
<script>
108-
testingColors = ['primary', 'secondary', 'danger', 'dark'];
109-
testingColorIndex = {
110-
dynamicColor1: 0,
111-
dynamicColor2: 0,
112-
};
113-
114-
function changeColor(ev) {
115-
el = ev.currentTarget;
116-
117-
testingColorIndex[el.id] =
118-
testingColorIndex[el.id] >= testingColors.length - 1 ? 0 : testingColorIndex[el.id] + 1;
119-
newColor = testingColors[testingColorIndex[el.id]];
120-
121-
el.color = newColor;
122-
}
123-
124-
function toggleDisabled() {
125-
var buttonEl = document.getElementById('disabledButton');
126-
buttonEl.disabled = !buttonEl.disabled;
127-
}
128-
</script>
129168
</body>
130169
</html>

packages/angular/src/directives/proxies.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,14 +345,14 @@ export declare interface IonBreadcrumbs extends Components.IonBreadcrumbs {
345345

346346

347347
@ProxyCmp({
348-
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'theme', 'type']
348+
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'hue', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'theme', 'type']
349349
})
350350
@Component({
351351
selector: 'ion-button',
352352
changeDetection: ChangeDetectionStrategy.OnPush,
353353
template: '<ng-content></ng-content>',
354354
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
355-
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'theme', 'type'],
355+
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'hue', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'theme', 'type'],
356356
})
357357
export class IonButton {
358358
protected el: HTMLIonButtonElement;

packages/angular/standalone/src/directives/proxies.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,14 +440,14 @@ export declare interface IonBreadcrumbs extends Components.IonBreadcrumbs {
440440

441441
@ProxyCmp({
442442
defineCustomElementFn: defineIonButton,
443-
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'theme', 'type']
443+
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'hue', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'theme', 'type']
444444
})
445445
@Component({
446446
selector: 'ion-button',
447447
changeDetection: ChangeDetectionStrategy.OnPush,
448448
template: '<ng-content></ng-content>',
449449
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
450-
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'theme', 'type'],
450+
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'hue', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'theme', 'type'],
451451
standalone: true
452452
})
453453
export class IonButton {

0 commit comments

Comments
 (0)