Skip to content

Commit 32d5e4e

Browse files
committed
feat(toolbar): add titlePlacement property to determine how to align title
1 parent 9b02bfe commit 32d5e4e

6 files changed

Lines changed: 82 additions & 10 deletions

File tree

core/src/components.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4463,6 +4463,10 @@ export namespace Components {
44634463
* The theme determines the visual appearance of the component.
44644464
*/
44654465
"theme"?: "ios" | "md" | "ionic";
4466+
/**
4467+
* Where to place the title relative to the other toolbar content. `"start"`: The title will appear to the left of the toolbar content in LTR and to the right in RTL. `"center"`: The title will appear in the center of the toolbar. `"end"`: The title will appear to the right of the toolbar content in LTR and to the left in RTL.
4468+
*/
4469+
"titlePlacement"?: 'start' | 'center' | 'end';
44664470
}
44674471
}
44684472
export interface IonAccordionGroupCustomEvent<T> extends CustomEvent<T> {
@@ -10590,6 +10594,10 @@ declare namespace LocalJSX {
1059010594
* The theme determines the visual appearance of the component.
1059110595
*/
1059210596
"theme"?: "ios" | "md" | "ionic";
10597+
/**
10598+
* Where to place the title relative to the other toolbar content. `"start"`: The title will appear to the left of the toolbar content in LTR and to the right in RTL. `"center"`: The title will appear in the center of the toolbar. `"end"`: The title will appear to the right of the toolbar content in LTR and to the left in RTL.
10599+
*/
10600+
"titlePlacement"?: 'start' | 'center' | 'end';
1059310601
}
1059410602

1059510603
interface IonAccordionAttributes {
@@ -11382,6 +11390,7 @@ declare namespace LocalJSX {
1138211390
}
1138311391
interface IonToolbarAttributes {
1138411392
"color": Color;
11393+
"titlePlacement": 'start' | 'center' | 'end';
1138511394
}
1138611395

1138711396
interface IntrinsicElements {

core/src/components/toolbar/toolbar.ionic.scss

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,6 @@
5959
@include globals.padding-horizontal(globals.$ion-space-200);
6060
}
6161

62-
:host(.toolbar-title-default) ::slotted(ion-title) {
63-
text-align: center;
64-
}
65-
6662
:host(.toolbar-title-large) ::slotted(ion-title) {
6763
@include globals.padding-horizontal(globals.$ion-space-400);
6864
}
@@ -116,3 +112,18 @@
116112

117113
flex: 0 0 var(--primary-secondary-size, 0);
118114
}
115+
116+
// Toolbar Title Placement
117+
// --------------------------------------------------
118+
119+
:host(.toolbar-title-placement-start) {
120+
text-align: start;
121+
}
122+
123+
:host(.toolbar-title-placement-center) {
124+
text-align: center;
125+
}
126+
127+
:host(.toolbar-title-placement-end) {
128+
text-align: end;
129+
}

core/src/components/toolbar/toolbar.tsx

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ComponentInterface } from '@stencil/core';
2-
import { Component, Element, forceUpdate, h, Host, Listen, Prop } from '@stencil/core';
2+
import { Component, Element, forceUpdate, h, Host, Listen, Prop, Watch } from '@stencil/core';
33
import { createColorClasses, hostContext } from '@utils/theme';
44

55
import { getIonTheme } from '../../global/ionic-global';
@@ -30,6 +30,14 @@ import type { Color, CssClassMap, StyleEventDetail } from '../../interface';
3030
})
3131
export class Toolbar implements ComponentInterface {
3232
private childrenStyles = new Map<string, CssClassMap>();
33+
private readonly slotClasses = [
34+
'has-start-content',
35+
'has-end-content',
36+
'has-primary-content',
37+
'has-secondary-content',
38+
];
39+
private readonly showClasses = ['show-start', 'show-end', 'show-primary', 'show-secondary'];
40+
private readonly slotSizeVars = ['--start-end-size', '--primary-secondary-size'];
3341

3442
@Element() el!: HTMLIonToolbarElement;
3543

@@ -40,6 +48,14 @@ export class Toolbar implements ComponentInterface {
4048
*/
4149
@Prop({ reflect: true }) color?: Color;
4250

51+
/**
52+
* Where to place the title relative to the other toolbar content.
53+
* `"start"`: The title will appear to the left of the toolbar content in LTR and to the right in RTL.
54+
* `"center"`: The title will appear in the center of the toolbar.
55+
* `"end"`: The title will appear to the right of the toolbar content in LTR and to the left in RTL.
56+
*/
57+
@Prop() titlePlacement?: 'start' | 'center' | 'end';
58+
4359
componentWillLoad() {
4460
const buttons = Array.from(this.el.querySelectorAll('ion-buttons'));
4561

@@ -67,6 +83,24 @@ export class Toolbar implements ComponentInterface {
6783
this.updateSlotWidths();
6884
}
6985

86+
@Watch('titlePlacement')
87+
titlePlacementChanged() {
88+
this.updateSlotClasses();
89+
}
90+
91+
/**
92+
* Gets the title placement.
93+
* Returns the title placement if it is set, otherwise returns `"center"`
94+
* for `ionic` and `ios`, and `"start"` for `md`.
95+
*/
96+
private getTitlePlacement(): 'start' | 'center' | 'end' {
97+
if (this.titlePlacement !== undefined) {
98+
return this.titlePlacement;
99+
}
100+
101+
return getIonTheme(this) === 'ionic' || getIonTheme(this) === 'ios' ? 'center' : 'start';
102+
}
103+
70104
/**
71105
* Updates the CSS custom properties for slot widths
72106
* This ensures that slots shown by their met conditions
@@ -164,7 +198,21 @@ export class Toolbar implements ComponentInterface {
164198
return allMeasurementsSuccessful;
165199
}
166200

201+
/**
202+
* Removes all slot visibility classes and slot width CSS variables.
203+
*/
204+
private removeSlotClasses() {
205+
this.el.classList.remove(...this.slotClasses, ...this.showClasses);
206+
this.slotSizeVars.forEach((cssVar) => this.el.style.removeProperty(cssVar));
207+
}
208+
167209
private updateSlotClasses() {
210+
const titlePlacement = this.getTitlePlacement();
211+
if (titlePlacement !== 'center') {
212+
this.removeSlotClasses();
213+
return;
214+
}
215+
168216
// Check if slots have content
169217
const slots = ['start', 'end', 'primary', 'secondary'];
170218

@@ -250,12 +298,15 @@ export class Toolbar implements ComponentInterface {
250298
Object.assign(childStyles, style);
251299
});
252300

301+
const titlePlacement = this.getTitlePlacement();
302+
253303
return (
254304
<Host
255305
class={{
256306
...createColorClasses(this.color, {
257307
[theme]: true,
258308
'in-toolbar': hostContext('ion-toolbar', this.el),
309+
[`toolbar-title-placement-${titlePlacement}`]: true,
259310
}),
260311
...childStyles,
261312
}}

packages/angular/src/directives/proxies.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,14 +2636,14 @@ This event will not emit when programmatically setting the `checked` property.
26362636

26372637

26382638
@ProxyCmp({
2639-
inputs: ['color', 'mode', 'theme']
2639+
inputs: ['color', 'mode', 'theme', 'titlePlacement']
26402640
})
26412641
@Component({
26422642
selector: 'ion-toolbar',
26432643
changeDetection: ChangeDetectionStrategy.OnPush,
26442644
template: '<ng-content></ng-content>',
26452645
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
2646-
inputs: ['color', 'mode', 'theme'],
2646+
inputs: ['color', 'mode', 'theme', 'titlePlacement'],
26472647
})
26482648
export class IonToolbar {
26492649
protected el: HTMLIonToolbarElement;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,14 +2298,14 @@ Shorthand for ionToastDidDismiss.
22982298

22992299
@ProxyCmp({
23002300
defineCustomElementFn: defineIonToolbar,
2301-
inputs: ['color', 'mode', 'theme']
2301+
inputs: ['color', 'mode', 'theme', 'titlePlacement']
23022302
})
23032303
@Component({
23042304
selector: 'ion-toolbar',
23052305
changeDetection: ChangeDetectionStrategy.OnPush,
23062306
template: '<ng-content></ng-content>',
23072307
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
2308-
inputs: ['color', 'mode', 'theme'],
2308+
inputs: ['color', 'mode', 'theme', 'titlePlacement'],
23092309
standalone: true
23102310
})
23112311
export class IonToolbar {

packages/vue/src/proxies.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,7 @@ export const IonToggle: StencilVueComponent<JSX.IonToggle, JSX.IonToggle["checke
11221122

11231123

11241124
export const IonToolbar: StencilVueComponent<JSX.IonToolbar> = /*@__PURE__*/ defineContainer<JSX.IonToolbar>('ion-toolbar', defineIonToolbar, [
1125-
'color'
1125+
'color',
1126+
'titlePlacement'
11261127
]);
11271128

0 commit comments

Comments
 (0)