This is an automated email from the ASF dual-hosted git repository.
yishayw pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
The following commit(s) were added to refs/heads/develop by this push:
new e11c6904d3 Added tabs
new 96cf785c9c Merge branch 'develop' of
https://github.com/apache/royale-asjs into develop
e11c6904d3 is described below
commit e11c6904d34dd54e99d8523da75913c07e96dd16
Author: Yishay Weiss <[email protected]>
AuthorDate: Tue Apr 14 15:22:28 2026 +0300
Added tabs
---
.../projects/Style/src/main/resources/defaults.css | 8 ++
.../Style/src/main/resources/style-manifest.xml | 4 +
.../src/main/royale/org/apache/royale/style/Tab.as | 153 +++++++++++++++++++++
.../main/royale/org/apache/royale/style/TabBar.as | 140 +++++++++++++++++++
.../org/apache/royale/style/skins/ITabSkin.as | 27 ++++
.../org/apache/royale/style/skins/TabBarSkin.as | 76 ++++++++++
.../org/apache/royale/style/skins/TabSkin.as | 151 ++++++++++++++++++++
7 files changed, 559 insertions(+)
diff --git a/frameworks/projects/Style/src/main/resources/defaults.css
b/frameworks/projects/Style/src/main/resources/defaults.css
index f4f028200b..77162e985b 100644
--- a/frameworks/projects/Style/src/main/resources/defaults.css
+++ b/frameworks/projects/Style/src/main/resources/defaults.css
@@ -59,6 +59,14 @@ Dropdown
{
IStyleSkin:
ClassReference("org.apache.royale.style.skins.DropdownSkin");
}
+Tab
+{
+ IStyleSkin: ClassReference("org.apache.royale.style.skins.TabSkin");
+}
+TabBar
+{
+ IStyleSkin: ClassReference("org.apache.royale.style.skins.TabBarSkin");
+}
Toggle
{
IStyleSkin: ClassReference("org.apache.royale.style.skins.ToggleSkin");
diff --git a/frameworks/projects/Style/src/main/resources/style-manifest.xml
b/frameworks/projects/Style/src/main/resources/style-manifest.xml
index 0bc6f3cc71..36ad8784ad 100644
--- a/frameworks/projects/Style/src/main/resources/style-manifest.xml
+++ b/frameworks/projects/Style/src/main/resources/style-manifest.xml
@@ -30,6 +30,8 @@
<component id="CheckBox" class="org.apache.royale.style.CheckBox"/>
<component id="Divider" class="org.apache.royale.style.Divider"/>
<component id="Dropdown" class="org.apache.royale.style.Dropdown"/>
+ <component id="Tab" class="org.apache.royale.style.Tab"/>
+ <component id="TabBar" class="org.apache.royale.style.TabBar"/>
<component id="Toggle" class="org.apache.royale.style.Toggle"/>
<component id="FlexContainer" class="org.apache.royale.style.FlexContainer"/>
<component id="GridContainer" class="org.apache.royale.style.GridContainer"/>
@@ -326,6 +328,8 @@
<component id="AccordionSectionSkin"
class="org.apache.royale.style.skins.AccordionSectionSkin"/>
<component id="AccordionContentSkin"
class="org.apache.royale.style.skins.AccordionContentSkin"/>
<component id="ListRendererSkin"
class="org.apache.royale.style.skins.ListRendererSkin"/>
+ <component id="TabSkin" class="org.apache.royale.style.skins.TabSkin"/>
+ <component id="TabBarSkin" class="org.apache.royale.style.skins.TabBarSkin"/>
<component id="ToggleSkin" class="org.apache.royale.style.skins.ToggleSkin"/>
</componentPackage>
diff --git
a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/Tab.as
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/Tab.as
new file mode 100644
index 0000000000..530e741a27
--- /dev/null
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/Tab.as
@@ -0,0 +1,153 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.style
+{
+ COMPILE::JS{
+ import org.apache.royale.core.WrappedHTMLElement;
+ }
+ import org.apache.royale.events.Event;
+ import org.apache.royale.style.elements.Span;
+ import org.apache.royale.style.skins.ITabSkin;
+
+ /**
+ * Dispatched when the user clicks on the tab.
+ */
+ [Event(name="itemClicked", type="org.apache.royale.events.Event")]
+
+ public class Tab extends StyleUIBase
+ {
+
+ public function Tab()
+ {
+ super();
+ }
+
+ private var labelSpan:Span;
+
+ override protected function getTag():String
+ {
+ return "button";
+ }
+
+ COMPILE::JS
+ override protected function createElement():WrappedHTMLElement
+ {
+ var elem:WrappedHTMLElement = super.createElement();
+ elem.setAttribute("role", "tab");
+ elem.setAttribute("type", "button");
+ elem.onclick = elementClicked;
+
+ return elem;
+ }
+
+ COMPILE::JS
+ private function elementClicked():void
+ {
+ dispatchEvent(new Event("itemClicked"));
+ }
+
+ private var _text:String = "";
+
+ public function get text():String
+ {
+ return _text;
+ }
+
+ public function set text(value:String):void
+ {
+ if(_text != value)
+ {
+ _text = value;
+ if(!labelSpan)
+ {
+ labelSpan = new Span();
+ addElement(labelSpan);
+ if(_stylesLoaded)
+ {
+ applyLabelSkin();
+ }
+ }
+ labelSpan.text = value;
+ }
+ }
+
+ private var _selected:Boolean;
+
+ public function get selected():Boolean
+ {
+ return _selected;
+ }
+
+ public function set selected(value:Boolean):void
+ {
+ if(value != _selected)
+ {
+ _selected = value;
+ toggleAttribute("data-selected", value);
+ COMPILE::JS
+ {
+ element.setAttribute("aria-selected",
value ? "true" : "false");
+ }
+ }
+ }
+
+ private var _disabled:Boolean;
+
+ public function get disabled():Boolean
+ {
+ return _disabled;
+ }
+
+ public function set disabled(value:Boolean):void
+ {
+ if(value != _disabled)
+ {
+ _disabled = value;
+ toggleAttribute("data-disabled", value);
+ COMPILE::JS
+ {
+ (element as HTMLButtonElement).disabled
= value;
+ }
+ }
+ }
+
+ /**
+ * @royaleignorecoercion org.apache.royale.style.skins.ITabSkin
+ */
+ override protected function applySkin():void
+ {
+ applyLabelSkin();
+ }
+
+ /**
+ * @royaleignorecoercion org.apache.royale.style.skins.ITabSkin
+ */
+ private function applyLabelSkin():void
+ {
+ if(!labelSpan) return;
+ var tabSkin:ITabSkin = skin as ITabSkin;
+ labelSpan.setStyles(tabSkin.labelStyles, true);
+ }
+
+ override public function getWrapperStyle():String
+ {
+ return 'tab';
+ }
+ }
+}
diff --git
a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/TabBar.as
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/TabBar.as
new file mode 100644
index 0000000000..1d9c60d3fa
--- /dev/null
+++
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/TabBar.as
@@ -0,0 +1,140 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.style
+{
+ COMPILE::JS{
+ import org.apache.royale.core.WrappedHTMLElement;
+ }
+ import org.apache.royale.events.Event;
+ import org.apache.royale.events.ValueChangeEvent;
+
+ /**
+ * Dispatched when the selected tab changes.
+ */
+ [Event(name="change", type="org.apache.royale.events.Event")]
+
+ [DefaultProperty("tabs")]
+
+ public class TabBar extends StyleUIBase
+ {
+
+ public function TabBar()
+ {
+ super();
+ }
+
+ COMPILE::JS
+ override protected function createElement():WrappedHTMLElement
+ {
+ var elem:WrappedHTMLElement = super.createElement();
+ elem.setAttribute("role", "tablist");
+ return elem;
+ }
+
+ public function get tabs():Array
+ {
+ var result:Array = [];
+ for(var i:int = 0; i < numElements; i++)
+ result.push(getElementAt(i));
+ return result;
+ }
+
+ /**
+ * @royaleignorecoercion org.apache.royale.style.Tab
+ */
+ public function set tabs(value:Array):void
+ {
+ while(numElements > 0)
+ {
+ var oldTab:Tab = getElementAt(0) as Tab;
+ oldTab.removeEventListener("itemClicked",
itemClickedHandler);
+ removeElement(oldTab);
+ }
+ if(value)
+ {
+ for each(var tab:Tab in value)
+ {
+ tab.addEventListener("itemClicked",
itemClickedHandler);
+ addElement(tab);
+ }
+ if(_selectedIndex >= 0 && _selectedIndex <
value.length)
+ value[_selectedIndex].selected = true;
+ }
+ }
+
+ private var _selectedIndex:int = -1;
+
+
[Bindable(event='valueChange',type='org.apache.royale.events.ValueChangeEvent')]
+ public function get selectedIndex():int
+ {
+ return _selectedIndex;
+ }
+
+ public function set selectedIndex(value:int):void
+ {
+ if(value != _selectedIndex)
+ {
+ var oldValue:int = _selectedIndex;
+ selectTab(value);
+
dispatchEvent(ValueChangeEvent.createUpdateEvent(this, 'selectedIndex',
oldValue, value));
+ dispatchEvent(new Event("change"));
+ }
+ }
+
+ /**
+ * @royaleignorecoercion org.apache.royale.style.Tab
+ */
+ public function get selectedTab():Tab
+ {
+ if(_selectedIndex >= 0 && _selectedIndex < numElements)
+ return getElementAt(_selectedIndex) as Tab;
+ return null;
+ }
+
+ private function itemClickedHandler(event:Event):void
+ {
+ var tab:Tab = event.target as Tab;
+ for(var i:int = 0; i < numElements; i++)
+ {
+ if(getElementAt(i) == tab)
+ {
+ selectedIndex = i;
+ return;
+ }
+ }
+ }
+
+ /**
+ * @royaleignorecoercion org.apache.royale.style.Tab
+ */
+ private function selectTab(index:int):void
+ {
+ for(var i:int = 0; i < numElements; i++)
+ {
+ (getElementAt(i) as Tab).selected = (i ==
index);
+ }
+ _selectedIndex = index;
+ }
+
+ override public function getWrapperStyle():String
+ {
+ return 'tab-bar';
+ }
+ }
+}
diff --git
a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/ITabSkin.as
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/ITabSkin.as
new file mode 100644
index 0000000000..39f549af80
--- /dev/null
+++
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/ITabSkin.as
@@ -0,0 +1,27 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.style.skins
+{
+ import org.apache.royale.style.IStyleSkin;
+
+ public interface ITabSkin extends IStyleSkin
+ {
+ function get labelStyles():Array;
+ }
+}
diff --git
a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/TabBarSkin.as
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/TabBarSkin.as
new file mode 100644
index 0000000000..9ffea098bc
--- /dev/null
+++
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/TabBarSkin.as
@@ -0,0 +1,76 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.style.skins
+{
+ import org.apache.royale.style.StyleSkin;
+ import org.apache.royale.style.TabBar;
+ import org.apache.royale.core.IStrand;
+ import org.apache.royale.style.colors.ColorSwatch;
+ import org.apache.royale.style.colors.ThemeColorSet;
+ import org.apache.royale.style.util.ThemeManager;
+ import org.apache.royale.style.stylebeads.layout.Display;
+ import org.apache.royale.style.stylebeads.flexgrid.AlignItems;
+ import org.apache.royale.style.stylebeads.flexgrid.FlexWrap;
+ import org.apache.royale.style.stylebeads.border.Border;
+ import org.apache.royale.style.stylebeads.border.BorderWidth;
+
+ public class TabBarSkin extends StyleSkin
+ {
+ public function TabBarSkin()
+ {
+ super();
+ }
+
+ /**
+ * @royaleignorecoercion org.apache.royale.style.TabBar
+ */
+ private function get host():TabBar
+ {
+ return _strand as TabBar;
+ }
+
+ override public function set strand(value:IStrand):void
+ {
+ super.strand = value;
+ applyStyles();
+ }
+
+ private function applyStyles():void
+ {
+ var colorSet:ThemeColorSet =
ThemeManager.instance.activeTheme.themeColorSet;
+ var borderColor:ColorSwatch =
colorSet.getSwatch(ThemeColorSet.BASE, 200);
+
+ var border:Border = new Border();
+ border.bottomColor = borderColor.colorSpecifier;
+ border.bottomStyle = "solid";
+
+ var borderWidth:BorderWidth = new BorderWidth();
+ borderWidth.bottom = 1;
+
+ _styles = [
+ new Display("flex"),
+ new AlignItems("end"),
+ new FlexWrap("wrap"),
+ borderWidth,
+ border
+ ];
+ host.setStyles(_styles);
+ }
+ }
+}
diff --git
a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/TabSkin.as
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/TabSkin.as
new file mode 100644
index 0000000000..03a3a04639
--- /dev/null
+++
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/TabSkin.as
@@ -0,0 +1,151 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.style.skins
+{
+ import org.apache.royale.style.StyleSkin;
+ import org.apache.royale.style.Tab;
+ import org.apache.royale.core.IStrand;
+ import org.apache.royale.style.colors.ColorSwatch;
+ import org.apache.royale.style.colors.ThemeColorSet;
+ import org.apache.royale.style.util.ThemeManager;
+ import org.apache.royale.style.stylebeads.interact.Cursor;
+ import org.apache.royale.style.stylebeads.interact.UserSelect;
+ import org.apache.royale.style.stylebeads.background.BackgroundColor;
+ import org.apache.royale.style.stylebeads.border.Border;
+ import org.apache.royale.style.stylebeads.border.BorderWidth;
+ import org.apache.royale.style.stylebeads.border.Outline;
+ import org.apache.royale.style.stylebeads.spacing.Padding;
+ import org.apache.royale.style.stylebeads.anim.Transition;
+ import org.apache.royale.style.stylebeads.typography.FontSize;
+ import org.apache.royale.style.stylebeads.typography.TextColor;
+ import org.apache.royale.style.stylebeads.states.attribute.DataState;
+ import org.apache.royale.style.stylebeads.states.FocusVisibleState;
+
+ public class TabSkin extends StyleSkin implements ITabSkin
+ {
+ public function TabSkin()
+ {
+ super();
+ }
+
+ /**
+ * @royaleignorecoercion org.apache.royale.style.Tab
+ */
+ private function get host():Tab
+ {
+ return _strand as Tab;
+ }
+
+ override public function set strand(value:IStrand):void
+ {
+ super.strand = value;
+ applyStyles();
+ }
+
+ private function applyStyles():void
+ {
+ var colorSet:ThemeColorSet =
ThemeManager.instance.activeTheme.themeColorSet;
+ var primaryColor:ColorSwatch =
colorSet.getSwatch(ThemeColorSet.PRIMARY, 500);
+ var disabledColor:ColorSwatch =
colorSet.getSwatch(ThemeColorSet.BASE, 300, 50);
+
+ var size:Number = 16 * getMultiplier();
+ var paddingH:String = computeSize(size * 0.75,
host.unit);
+ var paddingV:String = computeSize(size * 0.5,
host.unit);
+
+ var outline:Outline = new Outline();
+ outline.unit = host.unit;
+ outline.width = 0.5;
+ outline.style = "solid";
+ outline.color = primaryColor.getVariant(NaN,
40).colorSpecifier;
+ outline.offset = 0.5;
+
+ var padding:Padding = new Padding();
+ padding.left = paddingH;
+ padding.right = paddingH;
+ padding.top = paddingV;
+ padding.bottom = paddingV;
+
+ var borderWidth:BorderWidth = new BorderWidth();
+ borderWidth.bottom = 2;
+
+ var defaultBorder:Border = new Border();
+ defaultBorder.bottomColor = "transparent";
+ defaultBorder.bottomStyle = "solid";
+
+ var selectedBorder:Border = new Border();
+ selectedBorder.bottomColor =
primaryColor.colorSpecifier;
+
+ _styles = [
+ new BackgroundColor("transparent"),
+ padding,
+ borderWidth,
+ defaultBorder,
+ new Cursor("pointer"),
+ new UserSelect("none"),
+ new Transition(),
+ new DataState("selected", [
+ selectedBorder,
+ new TextColor(primaryColor)
+ ]),
+ new DataState("disabled", [
+ new TextColor(disabledColor),
+ new Cursor("default")
+ ]),
+ new FocusVisibleState([outline])
+ ];
+ host.setStyles(_styles);
+ }
+
+ private function getMultiplier():Number
+ {
+ switch(host.size)
+ {
+ case "sm":
+ return 0.875;
+ case "md":
+ return 1;
+ case "lg":
+ return 1.125;
+ case "xl":
+ return 1.25;
+ default:
+ return 1;
+ }
+ }
+
+ private var _labelStyles:Array;
+
+ public function get labelStyles():Array
+ {
+ if(!_labelStyles)
+ createLabelStyles();
+ return _labelStyles;
+ }
+
+ private function createLabelStyles():void
+ {
+ var size:Number = 16 * getMultiplier();
+ var fontSize:String = computeSize(size, host.unit);
+
+ _labelStyles = [
+ new FontSize(fontSize)
+ ];
+ }
+ }
+}