From 9a82860897f516e22017c038245c6c7c57ad3051 Mon Sep 17 00:00:00 2001 From: germanocaumo Date: Tue, 2 Jun 2026 12:55:03 -0300 Subject: [PATCH 1/3] feat(buttons): expose button style props in SDK Support configurable plugin button styles Add a shared plugin button style contract with documented size variants for plugin-provided buttons. Thread color, circle, hideLabel, size, and style through NavBarButton, ActionsBarButton, and PresentationToolbarButton constructors so plugins can control their rendered buttons while preserving current defaults. Update the README nav bar example with the new styling props and available button sizes. --- README.md | 5 ++++ .../actions-bar-item/component.ts | 19 +++++++++++++- .../actions-bar-item/types.ts | 4 +-- src/extensible-areas/common/button/index.ts | 1 + src/extensible-areas/common/button/types.ts | 26 +++++++++++++++++++ src/extensible-areas/common/index.ts | 1 + src/extensible-areas/index.ts | 1 + .../nav-bar-item/component.ts | 22 ++++++++++++++++ src/extensible-areas/nav-bar-item/types.ts | 3 ++- .../presentation-toolbar-item/component.ts | 20 +++++++++++++- .../presentation-toolbar-item/types.ts | 4 +-- 11 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 src/extensible-areas/common/button/index.ts create mode 100644 src/extensible-areas/common/button/types.ts diff --git a/README.md b/README.md index d02a49fc..d2a821e9 100644 --- a/README.md +++ b/README.md @@ -315,6 +315,11 @@ useEffect(() => { label: 'Custom Nav Button', tooltip: 'Navigate to custom area', position: NavBarItemPosition.RIGHT, + color: 'primary', + circle: true, + hideLabel: true, + size: 'sm', // Available sizes: 'sm', 'md', 'lg', 'jumbo'. + style: { marginLeft: '4px' }, onClick: () => pluginLogger.info('Nav button clicked'), hasSeparator: true, }), diff --git a/src/extensible-areas/actions-bar-item/component.ts b/src/extensible-areas/actions-bar-item/component.ts index 1b418622..8176d0a3 100644 --- a/src/extensible-areas/actions-bar-item/component.ts +++ b/src/extensible-areas/actions-bar-item/component.ts @@ -11,6 +11,7 @@ import { ActionsBarToggleGroupProps, } from './types'; import { PluginIconType } from '../common/icon'; +import { PluginButtonSize } from '../common/button'; // ActionsBar Extensible Area @@ -48,6 +49,14 @@ export class ActionsBarButton extends ActionsBarItem { color: string; + circle: boolean; + + hideLabel: boolean; + + size: PluginButtonSize; + + style: React.CSSProperties; + /** * Returns object to be used in the setter for action bar. In this case, * a button. @@ -59,12 +68,16 @@ export class ActionsBarButton extends ActionsBarItem { * @param onClick - function to be called when clicking the button * @param position - position that this button will be displayed, see {@link ActionsBarPosition} * @param color - button color variant, defaults to 'primary' + * @param circle - if true, the action bar button will be displayed as a circle + * @param hideLabel - if true, the action bar button label will be visually hidden + * @param size - button size variant, defaults to 'lg' + * @param style - style of the action bar button * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5) */ constructor({ id, icon, tooltip = '', dataTest = '', onClick = () => { }, position = ActionsBarPosition.RIGHT, - color = 'primary', + color = 'primary', circle = true, hideLabel = true, size = 'lg', style = {}, }: ActionsBarButtonProps) { super({ id, type: ActionsBarItemType.BUTTON, position, dataTest, @@ -74,6 +87,10 @@ export class ActionsBarButton extends ActionsBarItem { this.dataTest = dataTest; this.onClick = onClick; this.color = color; + this.circle = circle; + this.hideLabel = hideLabel; + this.size = size; + this.style = style; } } diff --git a/src/extensible-areas/actions-bar-item/types.ts b/src/extensible-areas/actions-bar-item/types.ts index e37244eb..cf4a7e33 100644 --- a/src/extensible-areas/actions-bar-item/types.ts +++ b/src/extensible-areas/actions-bar-item/types.ts @@ -2,6 +2,7 @@ import { ChangeEvent, MouseEvent } from 'react'; import { PluginProvidedUiItemDescriptor } from '../base'; import { ActionsBarItemType, ActionsBarPosition } from './enums'; import { PluginIconType } from '../common/icon'; +import { PluginButtonStyleProps } from '../common/button'; /** * Interface for the generic Actions bar item. (`position` is mandatory) @@ -17,14 +18,13 @@ export interface ActionsBarItemProps { dataTest?: string; } -export interface ActionsBarButtonProps { +export interface ActionsBarButtonProps extends PluginButtonStyleProps { id?: string; icon: PluginIconType; tooltip: string; position: ActionsBarPosition; dataTest?: string; onClick: () => void; - color?: string; } export interface ActionsBarSeparatorProps { diff --git a/src/extensible-areas/common/button/index.ts b/src/extensible-areas/common/button/index.ts new file mode 100644 index 00000000..fcb073fe --- /dev/null +++ b/src/extensible-areas/common/button/index.ts @@ -0,0 +1 @@ +export * from './types'; diff --git a/src/extensible-areas/common/button/types.ts b/src/extensible-areas/common/button/types.ts new file mode 100644 index 00000000..da54eaf6 --- /dev/null +++ b/src/extensible-areas/common/button/types.ts @@ -0,0 +1,26 @@ +import * as React from 'react'; + +/** + * Available size variants for plugin-provided buttons. + */ +export type PluginButtonSize = 'sm' | 'md' | 'lg' | 'jumbo'; + +/** + * Shared style properties for plugin-provided buttons. + */ +export interface PluginButtonStyleProps { + /** Button color variant. */ + color?: string; + + /** Whether the button should be displayed as a circle. */ + circle?: boolean; + + /** Whether the button label should be visually hidden. */ + hideLabel?: boolean; + + /** Button size variant. Available sizes are 'sm', 'md', 'lg', and 'jumbo'. */ + size?: PluginButtonSize; + + /** Custom style properties for the button. */ + style?: React.CSSProperties; +} diff --git a/src/extensible-areas/common/index.ts b/src/extensible-areas/common/index.ts index af77d84e..b841b600 100644 --- a/src/extensible-areas/common/index.ts +++ b/src/extensible-areas/common/index.ts @@ -1 +1,2 @@ export * from './icon'; +export * from './button'; diff --git a/src/extensible-areas/index.ts b/src/extensible-areas/index.ts index c5e318dc..c9ab9897 100644 --- a/src/extensible-areas/index.ts +++ b/src/extensible-areas/index.ts @@ -1,4 +1,5 @@ export * from './common/icon'; +export * from './common/button'; export * from './presentation-toolbar-item'; export * from './user-list-dropdown-item'; export * from './action-button-dropdown-item'; diff --git a/src/extensible-areas/nav-bar-item/component.ts b/src/extensible-areas/nav-bar-item/component.ts index 29b5ae3c..7ee8610e 100644 --- a/src/extensible-areas/nav-bar-item/component.ts +++ b/src/extensible-areas/nav-bar-item/component.ts @@ -4,6 +4,7 @@ import { NavBarInfoProps, } from './types'; import { PluginIconType } from '../common/icon'; +import { PluginButtonSize } from '../common/button'; // NavBar Extensible Area @@ -20,6 +21,16 @@ export class NavBarButton implements NavBarInterface { disabled: boolean; + color: string; + + circle: boolean; + + hideLabel: boolean; + + size: PluginButtonSize; + + style: React.CSSProperties; + dataTest: string; position: NavBarItemPosition; @@ -41,6 +52,11 @@ export class NavBarButton implements NavBarInterface { * @param hasSeparator - boolean indicating whether the navigation bar button has separator * (vertical bar) * @param disabled - if true, the navigation bar button will not be clickable + * @param color - button color variant, defaults to 'primary' + * @param circle - if true, the navigation bar button will be displayed as a circle + * @param hideLabel - if true, the navigation bar button label will be visually hidden + * @param size - button size variant, defaults to 'sm' + * @param style - style of the navigation bar button * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). @@ -48,6 +64,7 @@ export class NavBarButton implements NavBarInterface { constructor({ id, label = '', icon = '', tooltip = '', disabled = true, dataTest = '', onClick = () => { }, position = NavBarItemPosition.RIGHT, hasSeparator = true, + color = 'primary', circle = true, hideLabel = true, size = 'sm', style = {}, }: NavBarButtonProps) { if (id) { this.id = id; @@ -56,6 +73,11 @@ export class NavBarButton implements NavBarInterface { this.icon = icon; this.tooltip = tooltip; this.disabled = disabled; + this.color = color; + this.circle = circle; + this.hideLabel = hideLabel; + this.size = size; + this.style = style; this.dataTest = dataTest; this.onClick = onClick; this.type = NavBarItemType.BUTTON; diff --git a/src/extensible-areas/nav-bar-item/types.ts b/src/extensible-areas/nav-bar-item/types.ts index 42a9614c..6400649d 100644 --- a/src/extensible-areas/nav-bar-item/types.ts +++ b/src/extensible-areas/nav-bar-item/types.ts @@ -1,13 +1,14 @@ import { PluginProvidedUiItemDescriptor } from '../base'; import { NavBarItemPosition } from './enums'; import { PluginIconType } from '../common/icon'; +import { PluginButtonStyleProps } from '../common/button'; export interface NavBarInterface extends PluginProvidedUiItemDescriptor { position: NavBarItemPosition; hasSeparator: boolean; } -export interface NavBarButtonProps { +export interface NavBarButtonProps extends PluginButtonStyleProps { id?: string; label: string; icon: PluginIconType; diff --git a/src/extensible-areas/presentation-toolbar-item/component.ts b/src/extensible-areas/presentation-toolbar-item/component.ts index 750e5ffa..3f6efab8 100644 --- a/src/extensible-areas/presentation-toolbar-item/component.ts +++ b/src/extensible-areas/presentation-toolbar-item/component.ts @@ -2,6 +2,7 @@ import { PresentationToolbarItemType } from './enums'; import { PresentationToolbarInterface, PresentationToolbarButtonProps, } from './types'; +import { PluginButtonSize } from '../common/button'; // PresentationToolbar Extensible Area @@ -14,6 +15,14 @@ export class PresentationToolbarButton implements PresentationToolbarInterface { tooltip: string; + color: string; + + circle: boolean; + + hideLabel: boolean; + + size: PluginButtonSize; + style: React.CSSProperties; dataTest: string; @@ -27,13 +36,18 @@ export class PresentationToolbarButton implements PresentationToolbarInterface { * @param label - label to be displayed in the button * @param tooltip - tooltip to be displayed when hovering the button * @param onClick - function to be called when clicking the button + * @param color - button color variant, defaults to 'default' + * @param circle - if true, the presentation toolbar button will be displayed as a circle + * @param hideLabel - if true, the presentation toolbar button label will be visually hidden + * @param size - button size variant, defaults to 'md' * @param style - style of the button in the presentation toolbar * @param dataTest - data-test attribute for testing purposes * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5) */ constructor({ - id, label = '', tooltip = '', dataTest = '', onClick = () => {}, style = {}, + id, label = '', tooltip = '', dataTest = '', onClick = () => {}, + color = 'default', circle = false, hideLabel = false, size = 'md', style = {}, }: PresentationToolbarButtonProps) { if (id) { this.id = id; @@ -41,6 +55,10 @@ export class PresentationToolbarButton implements PresentationToolbarInterface { this.label = label; this.tooltip = tooltip; this.onClick = onClick; + this.color = color; + this.circle = circle; + this.hideLabel = hideLabel; + this.size = size; this.style = style; this.dataTest = dataTest; this.type = PresentationToolbarItemType.BUTTON; diff --git a/src/extensible-areas/presentation-toolbar-item/types.ts b/src/extensible-areas/presentation-toolbar-item/types.ts index 71660bf7..ce244c80 100644 --- a/src/extensible-areas/presentation-toolbar-item/types.ts +++ b/src/extensible-areas/presentation-toolbar-item/types.ts @@ -1,15 +1,15 @@ import { PluginProvidedUiItemDescriptor } from '../base'; +import { PluginButtonStyleProps } from '../common/button'; /** * Interface for a generic item for presentation toolbar. */ export interface PresentationToolbarInterface extends PluginProvidedUiItemDescriptor {} -export interface PresentationToolbarButtonProps { +export interface PresentationToolbarButtonProps extends PluginButtonStyleProps { id?: string; label: string; tooltip: string; - style: React.CSSProperties; dataTest?: string; onClick: () => void; } From d4868741cdfd5c4c3dfcb66b22c5bc30ceccc16d Mon Sep 17 00:00:00 2001 From: germanocaumo Date: Thu, 4 Jun 2026 07:17:44 -0300 Subject: [PATCH 2/3] fix(extensilbe-area): preserve nav bar button defaults Keep NavBarButton aligned with the HTML5 client's backward-compatible fallback for legacy plugin buttons. Default circle and hideLabel to false, and size to md, matching the previous Button defaults when nav bar plugin buttons did not provide these props. --- src/extensible-areas/nav-bar-item/component.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/extensible-areas/nav-bar-item/component.ts b/src/extensible-areas/nav-bar-item/component.ts index 7ee8610e..d1e3ab5f 100644 --- a/src/extensible-areas/nav-bar-item/component.ts +++ b/src/extensible-areas/nav-bar-item/component.ts @@ -53,9 +53,11 @@ export class NavBarButton implements NavBarInterface { * (vertical bar) * @param disabled - if true, the navigation bar button will not be clickable * @param color - button color variant, defaults to 'primary' - * @param circle - if true, the navigation bar button will be displayed as a circle - * @param hideLabel - if true, the navigation bar button label will be visually hidden - * @param size - button size variant, defaults to 'sm' + * @param circle - if true, the navigation bar button will be displayed as a circle, + * defaults to false + * @param hideLabel - if true, the navigation bar button label will be visually hidden, + * defaults to false + * @param size - button size variant, defaults to 'md' * @param style - style of the navigation bar button * @param dataTest - string attribute to be used for testing * @@ -64,7 +66,7 @@ export class NavBarButton implements NavBarInterface { constructor({ id, label = '', icon = '', tooltip = '', disabled = true, dataTest = '', onClick = () => { }, position = NavBarItemPosition.RIGHT, hasSeparator = true, - color = 'primary', circle = true, hideLabel = true, size = 'sm', style = {}, + color = 'primary', circle = false, hideLabel = false, size = 'md', style = {}, }: NavBarButtonProps) { if (id) { this.id = id; From 587ca7280185d3d7727abca9bd2ea00ac3074585 Mon Sep 17 00:00:00 2001 From: germanocaumo Date: Mon, 8 Jun 2026 08:42:56 -0300 Subject: [PATCH 3/3] fix(ext-areas): support action bar button labels Add an optional label prop to ActionsBarButton so plugins can provide visible button text separately from tooltip text. This keeps tooltip available for hover text while allowing the HTML5 client to render a dedicated label when hideLabel is false. --- src/extensible-areas/actions-bar-item/component.ts | 9 +++++++-- src/extensible-areas/actions-bar-item/types.ts | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/extensible-areas/actions-bar-item/component.ts b/src/extensible-areas/actions-bar-item/component.ts index 8176d0a3..9867e0d2 100644 --- a/src/extensible-areas/actions-bar-item/component.ts +++ b/src/extensible-areas/actions-bar-item/component.ts @@ -41,6 +41,8 @@ class ActionsBarItem implements ActionsBarInterface { } export class ActionsBarButton extends ActionsBarItem { + label: string; + icon: PluginIconType; tooltip: string; @@ -61,6 +63,7 @@ export class ActionsBarButton extends ActionsBarItem { * Returns object to be used in the setter for action bar. In this case, * a button. * + * @param label - label to be displayed in the button * @param icon - icon to be used in the button for the action bar - it can be the iconName * from BigBlueButton or an svg * @param tooltip - tooltip to be displayed when hovering the button @@ -76,12 +79,14 @@ export class ActionsBarButton extends ActionsBarItem { * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5) */ constructor({ - id, icon, tooltip = '', dataTest = '', onClick = () => { }, position = ActionsBarPosition.RIGHT, - color = 'primary', circle = true, hideLabel = true, size = 'lg', style = {}, + id, label = '', icon, tooltip = '', dataTest = '', onClick = () => { }, + position = ActionsBarPosition.RIGHT, color = 'primary', circle = true, hideLabel = true, + size = 'lg', style = {}, }: ActionsBarButtonProps) { super({ id, type: ActionsBarItemType.BUTTON, position, dataTest, }); + this.label = label; this.icon = icon; this.tooltip = tooltip; this.dataTest = dataTest; diff --git a/src/extensible-areas/actions-bar-item/types.ts b/src/extensible-areas/actions-bar-item/types.ts index cf4a7e33..95f380ea 100644 --- a/src/extensible-areas/actions-bar-item/types.ts +++ b/src/extensible-areas/actions-bar-item/types.ts @@ -20,6 +20,7 @@ export interface ActionsBarItemProps { export interface ActionsBarButtonProps extends PluginButtonStyleProps { id?: string; + label?: string; icon: PluginIconType; tooltip: string; position: ActionsBarPosition;