chore(StoryBook): add Colors page
- gives an overview of all the `Theme.palette.foo` colors - the color name/code can be copied to clipboard - light/dark variant supported via storybook's "Dark mode" switch - integrated search (both the color name and value)
This commit is contained in:
parent
26b875ea16
commit
bbd0e71fd6
|
@ -0,0 +1,278 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import StatusQ 0.1
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Core.Theme 0.1
|
||||||
|
|
||||||
|
import Storybook 1.0
|
||||||
|
|
||||||
|
import SortFilterProxyModel 0.2
|
||||||
|
|
||||||
|
SplitView {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
orientation: Qt.Vertical
|
||||||
|
|
||||||
|
component ColorRectangle: Rectangle {
|
||||||
|
id: colorRectangle
|
||||||
|
property alias text: textLabel.text
|
||||||
|
|
||||||
|
implicitWidth: 120
|
||||||
|
implicitHeight: 60
|
||||||
|
Column {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
Row {
|
||||||
|
spacing: 4
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
Text {
|
||||||
|
id: textLabel
|
||||||
|
}
|
||||||
|
ToolButton {
|
||||||
|
focusPolicy: Qt.NoFocus
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 16
|
||||||
|
height: 16
|
||||||
|
padding: 0
|
||||||
|
text: "📋"
|
||||||
|
font.pixelSize: 10
|
||||||
|
onClicked: QClipboardProxy.copyTextToClipboard(textLabel.text)
|
||||||
|
ToolTip.text: "Copy color name"
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row {
|
||||||
|
spacing: 4
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
Text {
|
||||||
|
id: colorLabel
|
||||||
|
color: textLabel.color
|
||||||
|
text: colorRectangle.color.toString()
|
||||||
|
}
|
||||||
|
ToolButton {
|
||||||
|
focusPolicy: Qt.NoFocus
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 16
|
||||||
|
height: 16
|
||||||
|
padding: 0
|
||||||
|
text: "📋"
|
||||||
|
font.pixelSize: 10
|
||||||
|
onClicked: QClipboardProxy.copyTextToClipboard(colorLabel.text)
|
||||||
|
ToolTip.text: "Copy color value"
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component ColorFlow: ColumnLayout {
|
||||||
|
id: colorFlow
|
||||||
|
|
||||||
|
property string title
|
||||||
|
property var model
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: listModel
|
||||||
|
Component.onCompleted: {
|
||||||
|
append(Object.entries(colorFlow.model))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.topMargin: 8
|
||||||
|
//visible: colorRepeater.count
|
||||||
|
font.weight: Font.Medium
|
||||||
|
text: "%1 (%2)".arg(colorFlow.title).arg(colorRepeater.count)
|
||||||
|
}
|
||||||
|
Flow {
|
||||||
|
Layout.preferredWidth: scrollview.availableWidth
|
||||||
|
spacing: 5
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: colorRepeater
|
||||||
|
model: SortFilterProxyModel {
|
||||||
|
sourceModel: listModel
|
||||||
|
proxyRoles: [
|
||||||
|
ExpressionRole {
|
||||||
|
name: "name"
|
||||||
|
expression: model[0]
|
||||||
|
},
|
||||||
|
ExpressionRole {
|
||||||
|
name: "color"
|
||||||
|
expression: model[1]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
filters: FastExpressionFilter {
|
||||||
|
expression: {
|
||||||
|
searchField.searchText
|
||||||
|
return (!!model.name && model.name.toLowerCase().includes(searchField.searchText)) ||
|
||||||
|
(!!model.color && model.color.toLowerCase().includes(searchField.searchText))
|
||||||
|
}
|
||||||
|
enabled: searchField.searchText !== ""
|
||||||
|
expectedRoles: ["name", "color"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegate: ColorRectangle {
|
||||||
|
text: model.name
|
||||||
|
color: model.color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: searchField.forceActiveFocus()
|
||||||
|
|
||||||
|
ScrollView {
|
||||||
|
id: scrollview
|
||||||
|
contentWidth: availableWidth
|
||||||
|
SplitView.fillHeight: true
|
||||||
|
padding: 8
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
RowLayout {
|
||||||
|
Label {
|
||||||
|
text: "Search"
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
readonly property string searchText: text.toLowerCase()
|
||||||
|
id: searchField
|
||||||
|
}
|
||||||
|
ToolButton {
|
||||||
|
focusPolicy: Qt.NoFocus
|
||||||
|
text: "❌"
|
||||||
|
enabled: searchField.searchText !== ""
|
||||||
|
onClicked: searchField.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "Base"
|
||||||
|
model: {
|
||||||
|
"baseColor1": Theme.palette.baseColor1.toString(),
|
||||||
|
"baseColor2": Theme.palette.baseColor2.toString(),
|
||||||
|
"baseColor3": Theme.palette.baseColor3.toString(),
|
||||||
|
"baseColor4": Theme.palette.baseColor4.toString(),
|
||||||
|
"baseColor5": Theme.palette.baseColor5.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "Primary"
|
||||||
|
model: {
|
||||||
|
"primaryColor1": Theme.palette.primaryColor1.toString(),
|
||||||
|
"primaryColor2": Theme.palette.primaryColor2.toString(),
|
||||||
|
"primaryColor3": Theme.palette.primaryColor3.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "Danger"
|
||||||
|
model: {
|
||||||
|
"dangerColor1": Theme.palette.dangerColor1.toString(),
|
||||||
|
"dangerColor2": Theme.palette.dangerColor2.toString(),
|
||||||
|
"dangerColor3": Theme.palette.dangerColor3.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "Warning"
|
||||||
|
model: {
|
||||||
|
"warningColor1": Theme.palette.warningColor1.toString(),
|
||||||
|
"warningColor2": Theme.palette.warningColor2.toString(),
|
||||||
|
"warningColor3": Theme.palette.warningColor3.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "Success"
|
||||||
|
model: {
|
||||||
|
"successColor1": Theme.palette.successColor1.toString(),
|
||||||
|
"successColor2": Theme.palette.successColor2.toString(),
|
||||||
|
"successColor3": Theme.palette.successColor3.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "Direct"
|
||||||
|
model: {
|
||||||
|
"directColor1": Theme.palette.directColor1.toString(),
|
||||||
|
"directColor2": Theme.palette.directColor2.toString(),
|
||||||
|
"directColor3": Theme.palette.directColor3.toString(),
|
||||||
|
"directColor4": Theme.palette.directColor4.toString(),
|
||||||
|
"directColor5": Theme.palette.directColor5.toString(),
|
||||||
|
"directColor6": Theme.palette.directColor6.toString(),
|
||||||
|
"directColor7": Theme.palette.directColor7.toString(),
|
||||||
|
"directColor8": Theme.palette.directColor8.toString(),
|
||||||
|
"directColor9": Theme.palette.directColor9.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "Indirect"
|
||||||
|
model: {
|
||||||
|
"indirectColor1": Theme.palette.indirectColor1.toString(),
|
||||||
|
"indirectColor2": Theme.palette.indirectColor2.toString(),
|
||||||
|
"indirectColor3": Theme.palette.indirectColor3.toString(),
|
||||||
|
"indirectColor4": Theme.palette.indirectColor4.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "Mention"
|
||||||
|
model: {
|
||||||
|
"mentionColor1": Theme.palette.mentionColor1.toString(),
|
||||||
|
"mentionColor2": Theme.palette.mentionColor2.toString(),
|
||||||
|
"mentionColor3": Theme.palette.mentionColor3.toString(),
|
||||||
|
"mentionColor4": Theme.palette.mentionColor4.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "Pin"
|
||||||
|
model: {
|
||||||
|
"pinColor1": Theme.palette.pinColor1.toString(),
|
||||||
|
"pinColor2": Theme.palette.pinColor2.toString(),
|
||||||
|
"pinColor3": Theme.palette.pinColor3.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "Misc"
|
||||||
|
model: {
|
||||||
|
"miscColor1": Theme.palette.miscColor1.toString(),
|
||||||
|
"miscColor2": Theme.palette.miscColor2.toString(),
|
||||||
|
"miscColor3": Theme.palette.miscColor3.toString(),
|
||||||
|
"miscColor4": Theme.palette.miscColor4.toString(),
|
||||||
|
"miscColor5": Theme.palette.miscColor5.toString(),
|
||||||
|
"miscColor6": Theme.palette.miscColor6.toString(),
|
||||||
|
"miscColor7": Theme.palette.miscColor7.toString(),
|
||||||
|
"miscColor8": Theme.palette.miscColor8.toString(),
|
||||||
|
"miscColor9": Theme.palette.miscColor9.toString(),
|
||||||
|
"miscColor10": Theme.palette.miscColor10.toString(),
|
||||||
|
"miscColor11": Theme.palette.miscColor11.toString(),
|
||||||
|
"miscColor12": Theme.palette.miscColor12.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "User customization"
|
||||||
|
model: Theme.palette.userCustomizationColors
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "Identicon ring colors"
|
||||||
|
model: Theme.palette.identiconRingColors
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorFlow {
|
||||||
|
title: "Status colors"
|
||||||
|
model: StatusColors.colors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// category: Core
|
|
@ -54,6 +54,7 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE bool isValidImageUrl(const QUrl &url, const QStringList &acceptedExtensions) const;
|
Q_INVOKABLE bool isValidImageUrl(const QUrl &url, const QStringList &acceptedExtensions) const;
|
||||||
Q_INVOKABLE qint64 getFileSize(const QUrl &url) const;
|
Q_INVOKABLE qint64 getFileSize(const QUrl &url) const;
|
||||||
|
Q_INVOKABLE void copyTextToClipboard(const QString& text);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void contentChanged();
|
void contentChanged();
|
||||||
|
|
|
@ -59,7 +59,7 @@ QString QClipboardProxy::imageBase64() const
|
||||||
QByteArray byteArray;
|
QByteArray byteArray;
|
||||||
QBuffer buffer(&byteArray);
|
QBuffer buffer(&byteArray);
|
||||||
img.save(&buffer, "JPG");
|
img.save(&buffer, "JPG");
|
||||||
return QStringLiteral("data:image/jpeg;base64,") + byteArray.toBase64();
|
return QByteArrayLiteral("data:image/jpeg;base64,") + byteArray.toBase64();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QClipboardProxy::hasUrls() const
|
bool QClipboardProxy::hasUrls() const
|
||||||
|
@ -87,3 +87,8 @@ qint64 QClipboardProxy::getFileSize(const QUrl& url) const
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QClipboardProxy::copyTextToClipboard(const QString &text)
|
||||||
|
{
|
||||||
|
m_clipboard->setText(text);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue