Fluid 1.3.0
Material Design for QtQuick and Qml
Loading...
Searching...
No Matches
AppBar.qml
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
2// SPDX-License-Identifier: MPL-2.0
3
4pragma ComponentBehavior: Bound
5
6import QtQuick
7import Fluid as MD
8
48MD.BaseAppBar {
49 id: control
50
51 Accessible.role: Accessible.ToolBar
52 Accessible.name: title
53 Accessible.description: subtitle
54
62 enum Variant {
63 Small,
64 MediumFlexible,
65 LargeFlexible
66 }
67
74 enum TitleAlignment {
75 Start,
76 Center
77 }
78
80 property int variant: AppBar.Small
81
83 property string title
84
86 property string subtitle
87
89 property int titleAlignment: AppBar.Start
90
97 property int titleMaximumLineCount: variant === AppBar.Small ? 1 : 2
98
104 property int subtitleMaximumLineCount: 1
105
107 property real _expandedTextHeight: 0
108
110 property real _titleImplicitWidth: 0
111
113 readonly property bool _centeredTitle: titleAlignment !== 0
114
116 readonly property bool _hasSubtitle: subtitle.length > 0
117
119 readonly property real _tokenExpandedHeight: {
120 switch (variant) {
121 case AppBar.MediumFlexible:
122 return _hasSubtitle ? MD.Tokens.appBar.mediumFlexibleContainerHeightWithSubtitle : MD.Tokens.appBar.mediumFlexibleContainerHeight;
123 case AppBar.LargeFlexible:
124 return _hasSubtitle ? MD.Tokens.appBar.largeFlexibleContainerHeightWithSubtitle : MD.Tokens.appBar.largeFlexibleContainerHeight;
125 default:
126 return collapsedHeight;
127 }
128 }
129
131 readonly property real _expandedTitleLineHeight: variant === AppBar.LargeFlexible ? MD.Tokens.typescale.displaySmall.lineHeight : MD.Tokens.typescale.headlineMedium.lineHeight
132
134 readonly property real _expandedSubtitleLineHeight: _hasSubtitle ? (variant === AppBar.LargeFlexible ? MD.Tokens.typescale.titleMedium.lineHeight : MD.Tokens.typescale.labelLarge.lineHeight) : 0
135
137 readonly property real _expandedGap: _hasSubtitle ? (variant === AppBar.LargeFlexible ? MD.Tokens.appBar.largeTitleSubtitleGap : MD.Tokens.appBar.mediumTitleSubtitleGap) : 0
138
140 readonly property real _defaultExpandedTextHeight: _expandedTitleLineHeight + _expandedGap + _expandedSubtitleLineHeight
141
143 readonly property real _bottomPadding: variant === AppBar.LargeFlexible ? MD.Tokens.appBar.largeTitleBottomPadding : MD.Tokens.appBar.mediumTitleBottomPadding
144
145 collapsedHeight: MD.Tokens.appBar.smallContainerHeight
146 expandedHeight: variant === AppBar.Small ? collapsedHeight : _tokenExpandedHeight + Math.max(0, _expandedTextHeight - _defaultExpandedTextHeight)
147 scrollBehavior: variant === AppBar.Small ? MD.BaseAppBar.Pinned : MD.BaseAppBar.ExitUntilCollapsed
148 minimumCenterWidth: Math.max(MD.Tokens.appBar.titleInset * 2, Math.min(barContentWidth, _titleImplicitWidth + MD.Tokens.appBar.titleInset * 2))
149
150 centerContent: Component {
151 Item {
152 id: titleArea
153 objectName: "titleArea"
154
155 readonly property real fraction: control.variant === AppBar.Small ? 1 : control.collapsedFraction
156 readonly property bool collapsedTypography: fraction >= 0.5
157 readonly property real physicalLeadingWidth: control.layoutMirrored ? control.trailingWidth : control.leadingWidth
158 readonly property real physicalTrailingWidth: control.layoutMirrored ? control.leadingWidth : control.trailingWidth
159 readonly property real collapsedSide: Math.max(physicalLeadingWidth, physicalTrailingWidth) + MD.Tokens.appBar.titleInset
160 readonly property real collapsedStartX: control._centeredTitle ? collapsedSide : physicalLeadingWidth + MD.Tokens.appBar.titleInset
161 readonly property real collapsedEndX: control._centeredTitle ? width - collapsedSide : width - physicalTrailingWidth - MD.Tokens.appBar.titleInset
162 readonly property real expandedStartX: MD.Tokens.appBar.titleInset
163 readonly property real expandedEndX: width - MD.Tokens.appBar.titleInset
164 readonly property real targetStartX: expandedStartX + (collapsedStartX - expandedStartX) * fraction
165 readonly property real targetEndX: expandedEndX + (collapsedEndX - expandedEndX) * fraction
166 readonly property real collapsedY: (control.collapsedHeight - titleColumn.implicitHeight) / 2
167 readonly property real expandedY: control.currentContainerHeight - control._bottomPadding - titleColumn.implicitHeight
168
169 // Measure the fully expanded text independently from the animated
170 // title column. The latter changes width as collapsedFraction
171 // changes, so using its implicit height to calculate expandedHeight
172 // would make the container height depend on itself.
173 MD.Label {
174 id: expandedTitleMetrics
175
176 visible: false
177 width: Math.max(0, titleArea.width - MD.Tokens.appBar.titleInset * 2)
178 text: control.title
179 typescale: control.variant === AppBar.LargeFlexible ? MD.Tokens.typescale.displaySmall : MD.Tokens.typescale.headlineMedium
180 maximumLineCount: Math.max(1, control.titleMaximumLineCount)
181 wrapMode: Text.Wrap
182 elide: Text.ElideRight
183 Accessible.ignored: true
184 }
185
186 MD.Label {
187 id: expandedSubtitleMetrics
188
189 visible: false
190 width: expandedTitleMetrics.width
191 text: control.subtitle
192 typescale: control.variant === AppBar.LargeFlexible ? MD.Tokens.typescale.titleMedium : MD.Tokens.typescale.labelLarge
193 maximumLineCount: Math.max(1, control.subtitleMaximumLineCount)
194 wrapMode: Text.Wrap
195 elide: Text.ElideRight
196 Accessible.ignored: true
197 }
198
199 Binding {
200 target: control
201 property: "_expandedTextHeight"
202 value: expandedTitleMetrics.implicitHeight + (control._hasSubtitle ? control._expandedGap + expandedSubtitleMetrics.implicitHeight : 0)
203 }
204
205 Binding {
206 target: control
207 property: "_titleImplicitWidth"
208 value: titleLabel.implicitWidth
209 }
210
211 Column {
212 id: titleColumn
213
214 x: titleArea.targetStartX
215 y: titleArea.expandedY + (titleArea.collapsedY - titleArea.expandedY) * titleArea.fraction
216 width: Math.max(0, titleArea.targetEndX - titleArea.targetStartX)
217 spacing: control._hasSubtitle ? (titleArea.collapsedTypography ? MD.Tokens.appBar.mediumTitleSubtitleGap : control._expandedGap) : 0
218
219 MD.Label {
220 id: titleLabel
221 objectName: "titleLabel"
222
223 width: parent.width
224 text: control.title
225 color: control.titleColor
226 typescale: titleArea.collapsedTypography ? MD.Tokens.typescale.titleLarge : control.variant === AppBar.LargeFlexible ? MD.Tokens.typescale.displaySmall : MD.Tokens.typescale.headlineMedium
227 maximumLineCount: titleArea.collapsedTypography ? 1 : Math.max(1, control.titleMaximumLineCount)
228 wrapMode: Text.Wrap
229 elide: Text.ElideRight
230 horizontalAlignment: control._centeredTitle ? Text.AlignHCenter : control.layoutMirrored ? Text.AlignRight : Text.AlignLeft
231 Accessible.ignored: true
232 }
233
234 MD.Label {
235 id: subtitleLabel
236 width: parent.width
237 objectName: "subtitleLabel"
238 text: control.subtitle
239 color: control.subtitleColor
240 typescale: titleArea.collapsedTypography ? MD.Tokens.typescale.labelMedium : control.variant === AppBar.LargeFlexible ? MD.Tokens.typescale.titleMedium : MD.Tokens.typescale.labelLarge
241 maximumLineCount: titleArea.collapsedTypography ? 1 : Math.max(1, control.subtitleMaximumLineCount)
242 wrapMode: Text.Wrap
243 elide: Text.ElideRight
244 horizontalAlignment: control._centeredTitle ? Text.AlignHCenter : control.layoutMirrored ? Text.AlignRight : Text.AlignLeft
245 visible: control._hasSubtitle
246 Accessible.ignored: true
247 }
248 }
249 }
250 }
251}
Material Design 3 design tokens.
Definition tokens.h:65
Displays text using a selectable Material 3 type scale.
Definition Label.qml:15
qreal largeFlexibleContainerHeightWithSubtitle READ largeFlexibleContainerHeightWithSubtitle
Definition appbar.h:40