Fluid 1.3.0
Material Design for QtQuick and Qml
Loading...
Searching...
No Matches
FAB.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 QtQuick.Templates as T
8import Fluid as MD
9import "../core/UiMetrics.js" as UiMetrics
10import "../internal/MotionAnimation.js" as MotionAnimation
11
26T.ToolButton {
27 id: control
28
30 enum Size {
31 Default,
32 Medium,
33 Large
34 }
35
37 enum Variant {
38 Surface,
39 Primary,
40 Secondary,
41 Tertiary
42 }
43
45 property int size: FAB.Size.Default
46
48 property int variant: FAB.Variant.Primary
49
51 property bool lowered: false
52
60 property bool expanded: true
61
63 property MD.typescale typescale: UiMetrics.fabTypescale(control)
64
66 property bool mirrorIconInRtl: false
67
69 readonly property bool hasIcon: icon.name.length > 0
70
72 property color containerColor: {
73 switch (variant) {
74 case FAB.Variant.Surface:
75 return lowered ? control.MD.Style.surfaceContainerLowColor : control.MD.Style.surfaceContainerHighColor;
76 case FAB.Variant.Primary:
77 return control.MD.Style.primaryContainerColor;
78 case FAB.Variant.Secondary:
79 return control.MD.Style.secondaryContainerColor;
80 case FAB.Variant.Tertiary:
81 return control.MD.Style.tertiaryContainerColor;
82 }
83 }
84
86 property color contentColor: {
87 switch (variant) {
88 case FAB.Variant.Surface:
89 return control.MD.Style.primaryColor;
90 case FAB.Variant.Primary:
91 return control.MD.Style.onPrimaryContainerColor;
92 case FAB.Variant.Secondary:
93 return control.MD.Style.onSecondaryContainerColor;
94 case FAB.Variant.Tertiary:
95 return control.MD.Style.onTertiaryContainerColor;
96 }
97 }
98
100 readonly property color effectiveContentColor: state.contentColor
101
103 readonly property color effectiveContainerColor: state.containerColor
104
106 readonly property real effectiveElevation: state.elevation
107
109 readonly property string effectiveIconName: icon.name
110
112 readonly property url effectiveIconSource: icon.source
113
115 readonly property color effectiveIconColor: icon.color.a > 0 ? icon.color : effectiveContentColor
116
118 readonly property bool effectiveIconMirrored: mirrorIconInRtl && mirrored
119
121 readonly property bool _effectiveExpanded: expanded || !hasIcon
122
124 readonly property real _collapsedWidth: UiMetrics.fabContainerWidth(control)
125
127 readonly property real _expandedWidth: Math.max(_collapsedWidth,
128 state.expandedLeadingSpace
129 + contentItem.implicitWidth
130 + state.expandedTrailingSpace)
131
133 readonly property real _layoutProgress: {
134 const distance = _expandedWidth - _collapsedWidth;
135 if (distance <= 0)
136 return _effectiveExpanded ? 1 : 0;
137 return Math.max(0, Math.min(1, (state.containerWidth - _collapsedWidth) / distance));
138 }
139
141 readonly property real _leadingPadding: state.collapsedIconPadding
142 + (state.expandedLeadingSpace
143 - state.collapsedIconPadding)
144 * _layoutProgress
145
147 readonly property real _trailingPadding: state.collapsedIconPadding
148 + (state.expandedTrailingSpace
149 - state.collapsedIconPadding)
150 * _layoutProgress
151
152 icon.width: state.iconSize
153 icon.height: state.iconSize
154
155 implicitWidth: state.containerWidth
156 implicitHeight: state.containerHeight
157
158 leftInset: 0
159 rightInset: 0
160 topInset: 0
161 bottomInset: 0
162 leftPadding: mirrored ? _trailingPadding : _leadingPadding
163 rightPadding: mirrored ? _leadingPadding : _trailingPadding
164 topPadding: 0
165 bottomPadding: 0
166 spacing: state.iconLabelSpacing
167
168 hoverEnabled: true
169 focusPolicy: Qt.StrongFocus
170
171 Accessible.name: text
172 Accessible.role: Accessible.Button
173
174 QtObject {
175 id: state
176
177 readonly property real containerHeight: UiMetrics.fabContainerHeight(control)
178 readonly property MD.shapeValue containerShape: UiMetrics.fabContainerShape(control)
179 readonly property real iconSize: UiMetrics.fabIconSize(control)
180 readonly property real expandedLeadingSpace: UiMetrics.fabLeadingSpace(control)
181 readonly property real expandedTrailingSpace: UiMetrics.fabTrailingSpace(control)
182 readonly property real iconLabelSpacing: UiMetrics.fabSpacing(control)
183 readonly property real collapsedIconPadding: (control._collapsedWidth - iconSize) / 2
184
185 property real containerWidth: control._effectiveExpanded ? control._expandedWidth : control._collapsedWidth
186 property color containerColor: control.containerColor
187 property color contentColor: control.contentColor
188 property color stateLayerColor: "transparent"
189
190 property real elevation: control.lowered ? MD.Tokens.fab.loweredContainerElevation : MD.Tokens.fab.containerElevation
191 property real stateLayerOpacity: 0
192
193 Behavior on containerWidth {
194 enabled: control.text.length > 0
195
196 NumberAnimation {
197 // qmllint disable unresolved-type
198 easing.type: Easing.BezierSpline
199 easing.bezierCurve: MotionAnimation.expressiveFastSpatialCurve
200 duration: MotionAnimation.expressiveFastSpatialDuration
201 // qmllint enable unresolved-type
202 }
203 }
204 }
205
206 states: [
207 State {
208 name: "pressed"
209 when: control.down && control.enabled
210
211 PropertyChanges {
212 state.elevation: control.lowered ? MD.Tokens.fab.loweredPressedContainerElevation : MD.Tokens.fab.pressedContainerElevation
213 state.stateLayerColor: control.effectiveIconColor
214 state.stateLayerOpacity: MD.Tokens.fab.pressedStateLayerOpacity
215 }
216 },
217 State {
218 name: "focused"
219 when: control.visualFocus && control.enabled
220
221 PropertyChanges {
222 state.elevation: control.lowered ? MD.Tokens.fab.loweredFocusContainerElevation : MD.Tokens.fab.focusContainerElevation
223 state.stateLayerColor: control.effectiveIconColor
224 state.stateLayerOpacity: MD.Tokens.fab.focusStateLayerOpacity
225 }
226 },
227 State {
228 name: "hovered"
229 when: control.hovered && control.enabled
230
231 PropertyChanges {
232 state.elevation: control.lowered ? MD.Tokens.fab.loweredHoverContainerElevation : MD.Tokens.fab.hoverContainerElevation
233 state.stateLayerColor: control.effectiveIconColor
234 state.stateLayerOpacity: MD.Tokens.fab.hoverStateLayerOpacity
235 }
236 }
237 ]
238
239 contentItem: MD.IconLabel {
240 id: iconLabel
241 objectName: "fabContent"
242
243 clip: true
244 text: control.text
245 display: MD.IconLabel.TextBesideIcon
246 mirrored: control.mirrored
247 mirrorIconInRtl: control.mirrorIconInRtl
248 spacing: state.iconLabelSpacing
249 typescale: control.typescale
250 color: control.effectiveContentColor
251 textOpacity: control._effectiveExpanded ? 1 : 0
252 icon.name: control.effectiveIconName
253 icon.source: control.effectiveIconSource
254 icon.width: state.iconSize
255 icon.height: state.iconSize
256 icon.color: control.effectiveIconColor
257
258 Behavior on textOpacity {
259 NumberAnimation {
260 // qmllint disable unresolved-type
261 easing.type: Easing.BezierSpline
262 easing.bezierCurve: MotionAnimation.expressiveFastEffectsCurve
263 duration: MotionAnimation.expressiveFastEffectsDuration
264 // qmllint enable unresolved-type
265 }
266 }
267 }
268
269 background: MD.ElevationRectangle {
270 implicitWidth: state.containerWidth
271 implicitHeight: state.containerHeight
272 topLeftRadius: UiMetrics.resolveShapeRadius(state.containerShape.topLeft, width, height)
273 topRightRadius: UiMetrics.resolveShapeRadius(state.containerShape.topRight, width, height)
274 bottomLeftRadius: UiMetrics.resolveShapeRadius(state.containerShape.bottomLeft, width, height)
275 bottomRightRadius: UiMetrics.resolveShapeRadius(state.containerShape.bottomRight, width,
276 height)
277 color: state.containerColor
278 elevation: state.elevation
279
280 MD.Ripple {
281 objectName: "fabRipple"
282 anchors.fill: parent
283 topLeftRadius: parent.topLeftRadius
284 topRightRadius: parent.topRightRadius
285 bottomLeftRadius: parent.bottomLeftRadius
286 bottomRightRadius: parent.bottomRightRadius
287 pressed: control.pressed
288 pressX: control.pressX
289 pressY: control.pressY
290 stateOpacity: state.stateLayerOpacity
291 color: state.stateLayerColor
292 }
293 }
294}
A rectangle that casts a Material 3 elevation shadow.
A Material Design 3 Expressive floating action button.
Definition FAB.qml:20
Material Design 3 design tokens.
Definition tokens.h:68
Lays out an icon and text as a single reusable visual.
Definition IconLabel.qml:16
Material Design 3 Expressive button tokens.
Definition button.h:22