Skip to content

Commit

Permalink
Merge pull request #1087 from arturv2000/UI-Button_AllowColor
Browse files Browse the repository at this point in the history
UI-Button: Add Background, text and icon color option
  • Loading branch information
joepavitt authored Jul 23, 2024
2 parents 57c9384 + e1568b9 commit feaeafc
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 23 deletions.
18 changes: 18 additions & 0 deletions docs/nodes/widgets/ui-button.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ props:
Label:
description: The text shown within the button. If not provided, then the button will only render the icon.
dynamic: true
Button Color:
description: Button Color. If not provided, default theme color will be used.
dynamic: true
Text Color:
description: Text (Label) color. If not provided calculated automatically based on Button color to be Black or White.
dynamic: true
Icon Color:
description: Icon color. If not provided, will have the same color as text / label.
dynamic: true
Emulate Button Click: If enabled, any received message will trigger a button click, emitting the relevant payload and topic.
controls:
enabled:
Expand All @@ -27,6 +36,15 @@ dynamic:
Label:
payload: msg.ui_update.label
structure: ["String"]
Button Color:
payload: msg.ui_update.buttonColor
structure: ["String"]
Text Color:
payload: msg.ui_update.textColor
structure: ["String"]
Icon Color:
payload: msg.ui_update.iconColor
structure: ["String"]
Class:
payload: msg.ui_update.class
structure: ["String"]
Expand Down
8 changes: 4 additions & 4 deletions docs/user/migration/ui_button.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@
},
{
"property": "color",
"changes": -1,
"notes": "<a href='https://github.com/FlowFuse/node-red-dashboard/issues/375' target='_blank'>Issue #375</a>"
"changes": "improved",
"notes": "Separated property for text color and icon color"
},
{
"property": "background",
"changes": -1,
"notes": "<a href='https://github.com/FlowFuse/node-red-dashboard/issues/375' target='_blank'>Issue #375</a>"
"changes": null,
"notes": null
},
{
"property": "payload",
Expand Down
24 changes: 23 additions & 1 deletion nodes/widgets/locales/en-US/ui_button.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,32 @@
Clicking the button generates a message with <code>msg.payload</code>
set to the <b>Payload</b> field, and <code>msg.topic</code> to the <b>Topic</b> field.
</p>
<h3>HTML Content</h3>
<p>
The text field can also be used to set HTML content in the user interface.
This can be done by setting the <code>msg.ui_update.label</code> to a string of HTML.
This can be useful for displaying images, links, or other HTML elements.
</p>
<p>
You can also use Node-RED's built-in "template" node to generate the HTML you want to display if
you want to render <code>msg</code>, <code>flow</code> or <code>global</code> content.
</p>
<h3>Properties</h3>
<dl class="message-properties">
<dt>Icon <span class="property-type">string</span></dt>
<dd>Renders a Material Design icon within the button. We use the Material Design Icons, you can see a full list of the available icons <a href="https://pictogrammers.com/library/mdi/">here</a>. There is no need to include the "mdi-" prefix, just the name of the icon.</dd>
<dt>Icon Position<span class="property-type">left | right</span></dt>
<dd>If "Icon" is defined, this property controls which side of the "Label" the icon will render on</dd>
<dt>Label <span class="property-type">string</span></dt>
<dd>The text shown within the button. If not provided, then the button will only render the icon</dd>
<dd>The text shown within the button. If not provided, then the button will only render the icon. It supports HTML content</dd>
<dt>Emulate Button Click <span class="property-type">bool</span></dt>
<dd>If enabled, any received message will trigger a button click, emitting the relevant payload and topic</dd>
<dt>Background Color<span class="property-type">string</span></dt>
<dd>Background color for the button, valid values as <b>green</b>/<b>#a5a5a5</b>/<b>rgb(165,165,165)</b>/<b>green-darken-2</b>, check <a href="https://vuetifyjs.com/en/styles/colors/#material-colors"> Vuetify Colors</a> for help, send empty string to use default theme color</dd>
<dt>Text Color<span class="property-type">string</span></dt>
<dd>Color the text on the Button, valid values as <b>green</b>/<b>#a5a5a5</b>/<b>rgb(165,165,165)</b>, send empty string to use default theme color.
<dt>Icon Color<span class="property-type">string</span></dt>
<dd>Color for the Icon on the Button (if Icon configured), valid values as <b>green</b>/<b>#a5a5a5</b>/<b>rgb(165,165,165)</b>/<b>green-darken-2</b>, check <a href="https://vuetifyjs.com/en/styles/colors/#material-colors"> Vuetify Colors</a> for help, send empty string to use default theme color</dd>
</dl>
<h3>Dynamic Properties (Inputs)</h3>
<p>Any of the following can be appended to a <code>msg.ui_update</code> in order to override or set properties on this node at runtime.</p>
Expand All @@ -24,6 +40,12 @@ <h3>Dynamic Properties (Inputs)</h3>
<dd>Override the icon defined in the initial configuration</dd>
<dt class="optional">iconPosition <span class="property-type">'left' | 'right'</span></dt>
<dd>Change which side of the label the icon renders</dd>
<dt class="optional">buttonColor <span class="property-type">string</span></dt>
<dd>Override the default button color</dd>
<dt class="optional">textColor <span class="property-type">string</span></dt>
<dd>Override the button text default color</dd>
<dt class="optional">iconColor <span class="property-type">string</span></dt>
<dd>Override the icon (if present) default color</dd>
<dt class="optional">class <span class="property-type">string</span></dt>
<dd>Add a CSS class, or more, to the Button at runtime.</dd>
</dl>
Expand Down
8 changes: 7 additions & 1 deletion nodes/widgets/locales/en-US/ui_button.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@
"whenClicked": "When clicked, send:",
"payload": "Payload",
"topic": "Topic",
"emulateClick": "If msg arrives on input, emulate a button click:"
"emulateClick": "If msg arrives on input, emulate a button click:",
"buttonColor": "Background",
"optionalButtonColor": "(Optional) e.g. 'green'/'#a5a5a5'",
"textColor": "Text",
"optionalTextColor": "(Optional) e.g. 'green'/'#a5a5a5'",
"iconColor": "Icon",
"optionalIconColor": "(Optional) e.g. 'green'/'#a5a5a5'"
}
}
}
32 changes: 21 additions & 11 deletions nodes/widgets/ui_button.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@
payload: { value: '', validate: (hasProperty(RED.validators, 'typedInput') ? RED.validators.typedInput('payloadType') : function (v) { return true }) },
payloadType: { value: 'str' },
topic: { value: 'topic', validate: (hasProperty(RED.validators, 'typedInput') ? RED.validators.typedInput('topicType') : function (v) { return true }) },
topicType: { value: 'msg' }
topicType: { value: 'msg' },
buttonColor: { value: '' },
textColor: { value: '' },
iconColor: { value: '' }
},
inputs: 1,
outputs: 1,
Expand Down Expand Up @@ -97,6 +100,10 @@
</script>

<script type="text/html" data-template-name="ui-button">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
</div>
<div class="form-row">
<label for="node-input-group"><i class="fa fa-table"></i> <span data-i18n="ui-button.label.group"></label>
<input type="text" id="node-input-group">
Expand Down Expand Up @@ -143,14 +150,6 @@
<!--<div class="form-row">
<label for="node-input-tooltip"><i class="fa fa-info-circle"></i> <span data-i18n="ui-button.label.tooltip"></label>
<input type="text" id="node-input-tooltip" data-i18n="[placeholder]ui-button.label.optionalTooltip">
</div>
<div class="form-row">
<label for="node-input-color"><i class="fa fa-tint"></i> <span data-i18n="ui-button.label.color"></label>
<input type="text" id="node-input-color" data-i18n="[placeholder]ui-button.label.optionalColor">
</div>
<div class="form-row">
<label for="node-input-bgcolor"><i class="fa fa-tint"></i> <span data-i18n="ui-button.label.background"></label>
<input type="text" id="node-input-bgcolor" data-i18n="[placeholder]ui-button.label.optionalBackgroundColor">
</div>-->
<div class="form-row">
<label style="width:auto" for="node-input-payload"><i class="fa fa-envelope-o"></i> <span data-i18n="ui-button.label.whenClicked"></label>
Expand All @@ -170,7 +169,18 @@
<input type="checkbox" id="node-input-emulateClick" style="display:inline-block; width:auto; vertical-align:top;">
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
<h4>Custom Styling</h4>
</div>
<div class="form-row">
<label for="node-input-buttonColor"><i class="fa fa-tint"></i> <span data-i18n="ui-button.label.buttonColor"></label>
<input type="text" id="node-input-buttonColor" data-i18n="[placeholder]ui-button.label.optionalButtonColor">
</div>
<div class="form-row">
<label for="node-input-textColor"><i class="fa fa-tint"></i> <span data-i18n="ui-button.label.textColor"></label>
<input type="text" id="node-input-textColor" data-i18n="[placeholder]ui-button.label.optionalTextColor">
</div>
<div class="form-row">
<label for="node-input-iconColor"><i class="fa fa-tint"></i> <span data-i18n="ui-button.label.iconColor"></label>
<input type="text" id="node-input-iconColor" data-i18n="[placeholder]ui-button.label.optionalIconColor">
</div>
</script>
16 changes: 14 additions & 2 deletions nodes/widgets/ui_button.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,25 @@ module.exports = function (RED) {
statestore.set(group.getBase(), node, msg, 'label', updates.label)
}
if (typeof updates.icon !== 'undefined') {
// dynamically set "label" property
// dynamically set "icon" property
statestore.set(group.getBase(), node, msg, 'icon', updates.icon)
}
if (typeof updates.iconPosition !== 'undefined') {
// dynamically set "label" property
// dynamically set "iconPosition" property
statestore.set(group.getBase(), node, msg, 'iconPosition', updates.iconPosition)
}
if (typeof updates.buttonColor !== 'undefined') {
// dynamically set "buttonColor" property
statestore.set(group.getBase(), node, msg, 'buttonColor', updates.buttonColor)
}
if (typeof updates.textColor !== 'undefined') {
// dynamically set "textColor" property
statestore.set(group.getBase(), node, msg, 'textColor', updates.textColor)
}
if (typeof updates.iconColor !== 'undefined') {
// dynamically set "iconColor" property
statestore.set(group.getBase(), node, msg, 'iconColor', updates.iconColor)
}
}

if (!error) {
Expand Down
39 changes: 35 additions & 4 deletions ui/src/widgets/ui-button/UIButton.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
<template>
<v-btn
block variant="flat" :disabled="!state.enabled" :prepend-icon="prependIcon"
:append-icon="appendIcon" :class="{'nrdb-ui-button--icon': iconOnly}"
:style="{'min-width': icon ?? 'auto'}" @click="action"
block variant="flat" :disabled="!state.enabled" :prepend-icon="prependIcon" :append-icon="appendIcon"
:class="{ 'nrdb-ui-button--icon': iconOnly }" :color="buttonColor" :style="{ 'min-width': iconOnly ?? 'auto' }"
@click="action"
>
{{ label }}
<template v-if="prependIcon" #prepend>
<v-icon :color="iconColor" />
</template>
<template v-if="appendIcon" #append>
<v-icon :color="iconColor" />
</template>
<span v-if="label" :style="{'color': textColor}" v-html="label" />

Check warning on line 13 in ui/src/widgets/ui-button/UIButton.vue

View workflow job for this annotation

GitHub Actions / build / Build on 18

'v-html' directive can lead to XSS attack
</v-btn>
</template>

Expand All @@ -25,6 +31,9 @@ export default {
dynamic: {
label: null,
icon: null,
buttonColor: null,
textColor: null,
iconColor: null,
iconPosition: null
}
}
Expand All @@ -49,6 +58,15 @@ export default {
},
iconOnly () {
return this.getPropertyValue('icon') && !this.getPropertyValue('label')
},
buttonColor () {
return this.getPropertyValue('buttonColor')
},
iconColor () {
return this.getPropertyValue('iconColor')
},
textColor () {
return this.getPropertyValue('textColor')
}
},
created () {
Expand Down Expand Up @@ -83,6 +101,15 @@ export default {
if (typeof updates.iconPosition !== 'undefined') {
this.dynamic.iconPosition = updates.iconPosition
}
if (typeof updates.buttonColor !== 'undefined') {
this.dynamic.buttonColor = updates.buttonColor
}
if (typeof updates.textColor !== 'undefined') {
this.dynamic.textColor = updates.textColor
}
if (typeof updates.iconColor !== 'undefined') {
this.dynamic.iconColor = updates.iconColor
}
},
getPropertyValue (property) {
return this.dynamic[property] !== null ? this.dynamic[property] : this.props[property]
Expand All @@ -94,14 +121,18 @@ export default {
<style>
.nrdb-ui-button--icon .v-btn__append {
margin-left: 0;
margin-inline: initial;
}
.nrdb-ui-button--icon .v-btn__prepend {
margin-right: 0;
margin-inline: initial;
}
.nrdb-ui-button .v-btn .v-icon {
--v-icon-size-multiplier: 1;
}
.nrdb-ui-button .nrdb-ui-button--icon .v-icon {
--v-icon-size-multiplier: 1.1;
}
Expand Down

0 comments on commit feaeafc

Please sign in to comment.