You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@royale.apache.org by GitBox <gi...@apache.org> on 2018/09/10 14:49:11 UTC

[GitHub] carlosrovira closed pull request #292: new component snackbar

carlosrovira closed pull request #292: new component snackbar
URL: https://github.com/apache/royale-asjs/pull/292
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/examples/royale/JewelExample/src/main/royale/FormsValidationPlayGround.mxml b/examples/royale/JewelExample/src/main/royale/FormsValidationPlayGround.mxml
index 12204903e..f500ae574 100644
--- a/examples/royale/JewelExample/src/main/royale/FormsValidationPlayGround.mxml
+++ b/examples/royale/JewelExample/src/main/royale/FormsValidationPlayGround.mxml
@@ -49,7 +49,7 @@ limitations under the License.
 
 		<j:Form>
 			<j:beads>
-				<j:FormValidator trigger="{btn}" triggerEvent="click"/>
+				<j:FormValidator trigger="{btn}" triggerEvent="click" requiredFieldError="There are invalid data, please check it."/>
 			</j:beads>
 			
 			<html:H4 text="Your name"/>
diff --git a/examples/royale/JewelExample/src/main/royale/MainContent.mxml b/examples/royale/JewelExample/src/main/royale/MainContent.mxml
index 06547b83b..71c216de1 100644
--- a/examples/royale/JewelExample/src/main/royale/MainContent.mxml
+++ b/examples/royale/JewelExample/src/main/royale/MainContent.mxml
@@ -119,7 +119,7 @@ limitations under the License.
         <local:ButtonPlayGround id="button_panel"/>
         <local:NumericStepperPlayGround id="numericstepper_panel"/>
         <local:DateComponentsPlayGround id="datecomponents_panel"/>
-        <local:DropDownListPlayGround id="dropdownlist_panel"/>
+        <local:ComboBoxPlayGround id="combobox_panel"/>
         <local:CheckBoxPlayGround id="checkbox_panel"/>
         <local:MiscelaneaPlayGound id="miscelanea_panel"/>
         <local:HeadingsAndText id="text_panel"/>
@@ -132,6 +132,8 @@ limitations under the License.
         <local:CardPlayGround id="card_panel"/>
         <local:TablePlayGround id="tables_panel"/>
         <local:FormsValidationPlayGround id="form_validation_panel"/>
+        <local:DropDownListPlayGround id="dropdownlist_panel"/>
+        <local:SnackbarPlayGround id="snackbar_panel"/>
     </j:ApplicationMainContent>
     
 </j:ApplicationResponsiveView>
diff --git a/examples/royale/JewelExample/src/main/royale/SnackbarPlayGround.mxml b/examples/royale/JewelExample/src/main/royale/SnackbarPlayGround.mxml
new file mode 100644
index 000000000..4a9d733e0
--- /dev/null
+++ b/examples/royale/JewelExample/src/main/royale/SnackbarPlayGround.mxml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<j:SectionContent xmlns:fx="http://ns.adobe.com/mxml/2009"
+		xmlns:j="library://ns.apache.org/royale/jewel"
+		xmlns:html="library://ns.apache.org/royale/html"
+		xmlns:js="library://ns.apache.org/royale/basic">
+	<fx:Script>
+		<![CDATA[
+			import org.apache.royale.jewel.Snackbar;
+
+			// Event handler function uses a static method to show
+            // a snackbar with the message, and requested action.        
+            private function clickHandler(event:MouseEvent):void {
+                var snackbar:Snackbar = Snackbar.show("Do you want to save your changes?", 0, "Save Changes");
+				snackbar.addEventListener(Snackbar.ACTION, actionClickHandler);
+            }
+
+            private function clickHandler2(event:MouseEvent):void {
+                Snackbar.show("This example shows long message in Snackbar that will disappear after 10 seconds, or you can click other button to show another Snackbar immediately. <i>There is only one Snackbar can be displayed</i> in the application.", 10000, "DISMISS");
+            }
+
+			// Event handler function for displaying the action button.
+            private function actionClickHandler(event:Event):void {
+                status.text="You clicked Save Changes";
+            }
+		]]>
+	</fx:Script>
+	<j:beads>
+        <js:ContainerDataBinding/>
+    </j:beads>
+	<j:Grid gap="true" itemsVerticalAlign="itemsSameHeight">
+		<j:GridCell desktopNumerator="1" desktopDenominator="2"
+					tabletNumerator="1" tabletDenominator="1"
+					phoneNumerator="1" phoneDenominator="1">
+			<j:Card>
+				<html:H3 text="Jewel Snackbar"/>
+				
+				<!-- Alert 1-->
+				<j:Label text="Click the button below to display a simple Snackbar"
+						multiline="true"/>
+				<j:Button text="Click Me" click="Snackbar.show('This is an Snackbar component example that shows a message')"/>
+
+				<!-- Alert 2-->
+				<j:Label text="Click the button below to display an Snackbar and capture the action pressed by the user."
+						multiline="true"/>
+				<j:Button text="Click Me" click="clickHandler(event)"/>
+
+				<j:Label id="status"/>
+				
+				<!-- Alert 3 (Long Message)-->
+				<j:Label text="This is long message example just for demonstration. Do not use long message and 'DISMISS' action in Snackbar, because it automatically disappear after a timeout."
+						multiline="true"/>
+				<j:Button text="Click Me" click="clickHandler2(event)"/>
+			</j:Card>
+		</j:GridCell>
+		<j:GridCell desktopNumerator="1" desktopDenominator="2"
+					tabletNumerator="1" tabletDenominator="1"
+					phoneNumerator="1" phoneDenominator="1">
+			<j:Card>
+				<html:H3 text="Snackbar with emphasis"/>
+				<j:Label text="Click the button below to display Snackbar with different emphasis"
+						multiline="true"/>
+				<j:VGroup gap="8">
+					<j:Button text="Default" id="button" click="Snackbar.show('This is Default')"/>
+					<j:Button text="Primary" emphasis="{Button.PRIMARY}"
+							click="{Snackbar.show('This is Primary').emphasis = Button.PRIMARY}"/>
+					<j:Button text="Secondary" emphasis="{Button.SECONDARY}"
+							click="{Snackbar.show('Secondary with ACTION',4000,'ACTION').emphasis = Button.SECONDARY}"/>
+					<j:Button text="Emphasized" emphasis="{Button.EMPHASIZED}"
+							click="{Snackbar.show('This is Emphasized with some message').emphasis = Button.EMPHASIZED}"/>
+				</j:VGroup>
+			</j:Card>
+		</j:GridCell>
+	</j:Grid>
+</j:SectionContent>
diff --git a/examples/royale/JewelExample/src/main/royale/models/MainNavigationModel.as b/examples/royale/JewelExample/src/main/royale/models/MainNavigationModel.as
index 64d49860c..ac05d7f0b 100644
--- a/examples/royale/JewelExample/src/main/royale/models/MainNavigationModel.as
+++ b/examples/royale/JewelExample/src/main/royale/models/MainNavigationModel.as
@@ -29,7 +29,7 @@ package models
             new NavigationLinkVO("Button", "button_panel", MaterialIconType.CROP_7_5),
             new NavigationLinkVO("NumericStepper", "numericstepper_panel", MaterialIconType.UNFOLD_MORE),
             new NavigationLinkVO("Date Components", "datecomponents_panel", MaterialIconType.DATE_RANGE),
-            new NavigationLinkVO("DropDownList/ComboBox", "dropdownlist_panel", MaterialIconType.CREDIT_CARD),
+            new NavigationLinkVO("ComboBox", "combobox_panel", MaterialIconType.CREDIT_CARD),
             new NavigationLinkVO("CheckBox", "checkbox_panel", MaterialIconType.CHECK_BOX),
             new NavigationLinkVO("Icon", "miscelanea_panel", MaterialIconType.FACE),
             new NavigationLinkVO("Label", "label_panel", MaterialIconType.LABEL),
@@ -38,11 +38,12 @@ package models
             new NavigationLinkVO("Slider", "slider_panel", MaterialIconType.STORAGE),
             new NavigationLinkVO("Text", "text_panel", MaterialIconType.SUBJECT),
             new NavigationLinkVO("TextInput", "textinput_panel", MaterialIconType.TEXT_FIELDS),
-            new NavigationLinkVO("Forms & Validation", "form_validation_panel", MaterialIconType.ASSIGNMENT_TURNED_IN)
+            new NavigationLinkVO("Forms & Validation", "form_validation_panel", MaterialIconType.ASSIGNMENT_TURNED_IN),
+            new NavigationLinkVO("DropDownList", "dropdownlist_panel", MaterialIconType.CREDIT_CARD),
 
             // new NavigationLinkVO("Menu", "menus_panel"),
             // new NavigationLinkVO("Loading", "loading_panel"),
-            // new NavigationLinkVO("Snackbar", "snackbar_panel"),
+            new NavigationLinkVO("Snackbar", "snackbar_panel", MaterialIconType.VIDEO_LABEL)
             // new NavigationLinkVO("Tables", "tables_panel"),
             
         ]);
diff --git a/frameworks/projects/Jewel/src/main/resources/defaults.css b/frameworks/projects/Jewel/src/main/resources/defaults.css
index ba0581b72..7142c6c29 100644
--- a/frameworks/projects/Jewel/src/main/resources/defaults.css
+++ b/frameworks/projects/Jewel/src/main/resources/defaults.css
@@ -3352,4 +3352,50 @@ j|ApplicationMainContent {
   IViewportModel: ClassReference("org.apache.royale.html.beads.models.ViewportModel");
 }
 
+j|Snackbar {
+    IBeadModel: ClassReference("org.apache.royale.jewel.beads.models.SnackbarModel");
+    IBeadController: ClassReference("org.apache.royale.jewel.beads.controllers.SnackbarController");
+    IBeadView: ClassReference("org.apache.royale.jewel.beads.views.SnackbarView");
+}
+
+.jewel.snackbar {
+    bottom: 0;
+    position: fixed;
+    width: 100%;
+}
+
+.jewel.snackbar-content {
+    background: #2C3E50;
+    border-radius: 3px;
+    max-width: 568px;
+    min-width: 288px;
+    padding: 6px; 
+    position: relative;
+}
+
+.jewel.snackbar-message {
+    color: #fff;
+    float: left;
+    margin: 10px;
+}
+
+.jewel.snackbar-action {
+    color: #FFD740;
+    cursor: pointer;
+    float: right;
+    padding: 10px;
+}
+
+.jewel.snackbar-action:hover {
+    background-color: #3C4E60;
+}
+
+@media (max-width: 992px) {
+    .jewel.snackbar-content {
+        max-width: 100%;
+        width: 100%;
+        border-radius: 0px;
+    }
+}
+
 /*# sourceMappingURL=defaults.css.map */
diff --git a/frameworks/projects/Jewel/src/main/resources/jewel-manifest.xml b/frameworks/projects/Jewel/src/main/resources/jewel-manifest.xml
index b177818b6..4d6b4b221 100644
--- a/frameworks/projects/Jewel/src/main/resources/jewel-manifest.xml
+++ b/frameworks/projects/Jewel/src/main/resources/jewel-manifest.xml
@@ -65,6 +65,7 @@
     
     <component id="Form" class="org.apache.royale.jewel.Form"/>
     <component id="ErrorTip" class="org.apache.royale.jewel.ErrorTip"/>
+	<component id="Snackbar" class="org.apache.royale.jewel.Snackbar"/>
 
     <component id="Validator" class="org.apache.royale.jewel.beads.validators.Validator"/>
     <component id="FormValidator" class="org.apache.royale.jewel.beads.validators.FormValidator"/>
diff --git a/frameworks/projects/Jewel/src/main/royale/JewelClasses.as b/frameworks/projects/Jewel/src/main/royale/JewelClasses.as
index 3db51db95..4a9a8a5a2 100644
--- a/frameworks/projects/Jewel/src/main/royale/JewelClasses.as
+++ b/frameworks/projects/Jewel/src/main/royale/JewelClasses.as
@@ -36,6 +36,7 @@ package
         import org.apache.royale.jewel.beads.models.DateChooserModel; DateChooserModel;
         import org.apache.royale.jewel.beads.models.DataProviderModel; DataProviderModel;
         import org.apache.royale.jewel.beads.models.ComboBoxModel; ComboBoxModel;
+		import org.apache.royale.jewel.beads.models.SnackbarModel; SnackbarModel;
 
         import org.apache.royale.jewel.beads.controllers.SpinnerMouseController; SpinnerMouseController;
         import org.apache.royale.jewel.beads.controllers.SliderMouseController; SliderMouseController;
@@ -46,6 +47,7 @@ package
         import org.apache.royale.jewel.beads.controllers.ListSingleSelectionMouseController; ListSingleSelectionMouseController;
         import org.apache.royale.jewel.beads.controllers.TableCellSelectionMouseController; TableCellSelectionMouseController;
         import org.apache.royale.jewel.beads.controllers.ComboBoxController; ComboBoxController;
+		import org.apache.royale.jewel.beads.controllers.SnackbarController; SnackbarController;
         
         import org.apache.royale.jewel.beads.views.ImageView; ImageView;
         import org.apache.royale.jewel.beads.views.SpinnerView; SpinnerView;
@@ -60,6 +62,7 @@ package
         import org.apache.royale.jewel.beads.views.DateChooserView; DateChooserView;
         import org.apache.royale.jewel.beads.views.TableView; TableView;
         import org.apache.royale.jewel.beads.views.ComboBoxView; ComboBoxView;
+		import org.apache.royale.jewel.beads.views.SnackbarView; SnackbarView;
 
         
         COMPILE::SWF
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/Snackbar.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/Snackbar.as
new file mode 100644
index 000000000..b33b8c0e3
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/Snackbar.as
@@ -0,0 +1,223 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.jewel
+{
+    import org.apache.royale.core.IPopUp;
+    import org.apache.royale.core.StyledUIBase;
+    import org.apache.royale.core.UIBase;
+    import org.apache.royale.jewel.beads.models.SnackbarModel;
+
+    COMPILE::JS
+    {
+		import org.apache.royale.core.WrappedHTMLElement;
+		import org.apache.royale.html.util.addElementToWrapper;
+    }
+
+    [Event(name="action", type="org.apache.royale.events.Event")]
+	/**
+	 *  The Snackbar class is a component that provide brief messages
+     *  about app processes at the bottom that pops up over all other controls.
+     *  The Snackbar component uses the SnackbarView bead to display messages
+     *  and can contain a single action which configured through the action property.
+     *  Because Snackbar disappear automatically, the action shouldn’t be “Dismiss” or “Cancel.”
+	 *  The Snackbar component uses the following beads:
+	 * 
+	 *  org.apache.royale.core.IBeadModel: the data model for the Snackbar.
+	 *  org.apache.royale.core.IBeadView: the bead used to create the parts of the Snackbar.
+	 *  org.apache.royale.core.IBeadController: the bead used to handle disappear automatically.
+	 *  
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.2
+	 *  @playerversion AIR 2.6
+	 *  @productversion Royale 0.9.4
+	 */
+	public class Snackbar extends StyledUIBase implements IPopUp
+	{
+		/**
+		 *  constructor.
+         * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.2
+		 *  @playerversion AIR 2.6
+		 *  @productversion Royale 0.9.4
+		 */
+		public function Snackbar()
+		{
+			super();
+			
+			typeNames = "jewel snackbar layout itemsCenter";
+		}
+
+		/**
+		 *  Action event name.
+         * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.2
+		 *  @playerversion AIR 2.6
+		 *  @productversion Royale 0.9.4
+		 */
+		public static const ACTION:String = "action";
+
+		private var _emphasis:String;
+
+		public function get emphasis():String
+		{
+			return _emphasis;
+		}
+
+		public function set emphasis(value:String):void
+		{
+			if (_emphasis != value)
+            {
+                if(_emphasis)
+                {
+                    classSelectorList.toggle(_emphasis, false);
+                }
+                _emphasis = value;
+
+                classSelectorList.toggle(_emphasis, value);
+            }
+		}
+
+		/**
+		 *  The number of milliseconds to show the Snackbar.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.2
+		 *  @playerversion AIR 2.6
+		 *  @productversion Royale 0.9.4
+		 */
+		public function get duration():int
+		{
+			return SnackbarModel(model).duration;
+		}
+
+		public function set duration(value:int):void
+		{
+			SnackbarModel(model).duration = value;
+		}
+
+		/**
+		 *  The text message to display in the Snackbar.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.2
+		 *  @playerversion AIR 2.6
+		 *  @productversion Royale 0.9.4
+		 */
+		public function get message():String
+		{
+			return SnackbarModel(model).message;
+		}
+
+		public function set message(value:String):void
+		{
+			SnackbarModel(model).message = value;
+		}
+
+		/**
+		 *  The action to display on the Snackbar.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.2
+		 *  @playerversion AIR 2.6
+		 *  @productversion Royale 0.9.4
+		 */
+		public function get action():String
+		{
+			return SnackbarModel(model).action;
+		}
+
+		public function set action(value:String):void
+		{
+			SnackbarModel(model).action = value;
+		}
+
+        /**
+          *  This static method is a convenience function to quickly create and display an Snackbar. The
+          *  message paramters are required, the others will default.
+          *
+          *  @param String message The message content of the Snackbar.
+          *  @param int duration How long to show the Snackbar for.
+		  *  @param String actionText The action text of the Snackbar.
+          *  @param Object parent The object that hosts the pop-up.
+          *
+          *  @langversion 3.0
+          *  @playerversion Flash 10.2
+          *  @playerversion AIR 2.6
+          *  @productversion Royale 0.9.4
+          */
+        static public function show(message:String, duration:int = 4000, actionText:String = null, parent:Object = null) : Snackbar
+		{
+            var snackbar:Snackbar = new Snackbar();
+            snackbar.message = message;
+			snackbar.duration = duration;
+			snackbar.action = actionText;
+           	snackbar.show(parent);
+			return snackbar;
+		}
+
+		
+		/**
+		 *  Shows the Snackbar anchored to a root component such
+		 *  as body
+		 * 
+		 *  @param Object parent The object that hosts the pop-up.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.2
+		 *  @playerversion AIR 2.6
+		 *  @productversion Royale 0.9.4
+		 */
+		public function show(parent:Object = null) : void
+		{
+            COMPILE::JS
+			{
+				var body:HTMLElement = document.getElementsByTagName('body')[0];
+				body.appendChild(element);
+				addedToParent();
+			}
+
+            COMPILE::SWF
+			{
+				parent.addElement(this);
+			}
+		}
+
+        /**
+		 *  Dismiss the snackbar.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.2
+		 *  @playerversion AIR 2.6
+		 *  @productversion Royale 0.9.4
+		 */
+		public function dismiss(event:Event = null):void
+		{
+			COMPILE::JS
+			{
+				removeAllListeners();
+
+				var body:HTMLElement = document.getElementsByTagName('body')[0];
+				body.removeChild(element);
+			}
+		}
+	}
+}
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controllers/SnackbarController.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controllers/SnackbarController.as
new file mode 100644
index 000000000..be0f54f66
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controllers/SnackbarController.as
@@ -0,0 +1,149 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.jewel.beads.controllers
+{
+    import org.apache.royale.core.IBeadController;
+    import org.apache.royale.core.IStrand;
+    import org.apache.royale.events.Event;
+    import org.apache.royale.jewel.Snackbar;
+    import org.apache.royale.jewel.beads.models.SnackbarModel;
+    import org.apache.royale.utils.Timer;
+
+    /**
+	 *  The SnackbarController class bead handles duration of the Snackbar
+     *  How long to show the Snackbar for.
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.2
+	 *  @playerversion AIR 2.6
+	 *  @productversion Royale 0.9.4
+	 */
+	public class SnackbarController implements IBeadController
+	{
+		/**
+		 *  constructor.
+		 *  
+	     *  @langversion 3.0
+	     *  @playerversion Flash 10.2
+	     *  @playerversion AIR 2.6
+	     *  @productversion Royale 0.9.4
+		 */
+		public function SnackbarController()
+		{
+		}
+		
+        /**
+		 * Ensure only one snackbar is created.
+		 */
+		private static var _singletonInstance:Snackbar;
+
+        /**
+         *  IStrand
+         *   
+	     *  @langversion 3.0
+	     *  @playerversion Flash 10.2
+	     *  @playerversion AIR 2.6
+	     *  @productversion Royale 0.9.4
+         */
+		private var _strand:IStrand;
+
+		/**
+		 *  @copy org.apache.royale.core.IBead#strand
+		 *  
+	     *  @langversion 3.0
+	     *  @playerversion Flash 10.2
+	     *  @playerversion AIR 2.6
+	     *  @productversion Royale 0.9.4
+		 */
+		public function set strand(value:IStrand):void
+		{
+			_strand = value;
+             // set duration = -1 to dismiss previous snackbar immediately
+            if (_singletonInstance) _singletonInstance.duration = -1;
+
+            _singletonInstance = (value as Snackbar);
+
+            COMPILE::JS {
+                // start the timer for dismiss
+                durationChangeHandler(null);
+
+                var model:SnackbarModel = _strand.getBeadByType(SnackbarModel) as SnackbarModel;
+                model.addEventListener("durationChange", durationChangeHandler);
+            }
+		}
+
+        /**
+         *  Control how long to show the Snackbar base on duration.
+         *  
+	     *  @langversion 3.0
+	     *  @playerversion Flash 10.2
+	     *  @playerversion AIR 2.6
+	     *  @productversion Royale 0.9.4
+         */
+        private var _timer:Timer;
+
+        /**
+         *  Reset the timer for displaying when duration changed
+         *  
+	     *  @langversion 3.0
+	     *  @playerversion Flash 10.2
+	     *  @playerversion AIR 2.6
+	     *  @productversion Royale 0.9.4
+         */
+		COMPILE::JS
+        private function durationChangeHandler(event:Event):void
+        {
+            if (_timer) {
+				_timer.reset();
+			}
+
+            var model:SnackbarModel = _strand.getBeadByType(SnackbarModel) as SnackbarModel;
+            if (model.duration < 0) {
+                timerHandler(null);
+			} else if (model.duration > 0) {
+				if (_timer) {
+					_timer.delay = model.duration;
+				} else {
+					_timer = new Timer(model.duration);
+					_timer.addEventListener(Timer.TIMER, timerHandler);
+				}
+				_timer.start();
+			}
+        }
+
+        /**
+         *  Dismiss snackbar after duration matching.
+         *  
+	     *  @langversion 3.0
+	     *  @playerversion Flash 10.2
+	     *  @playerversion AIR 2.6
+	     *  @productversion Royale 0.9.4
+         */
+        COMPILE::JS
+        private function timerHandler(event:Event):void {
+            _singletonInstance = null;
+            if (_timer) {
+                _timer.stop();
+                _timer.removeAllListeners();
+                _timer = null;
+            }
+            (_strand as Snackbar).dismiss();
+        }
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/models/SnackbarModel.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/models/SnackbarModel.as
new file mode 100644
index 000000000..bb75766f9
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/models/SnackbarModel.as
@@ -0,0 +1,143 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.jewel.beads.models
+{	
+	import org.apache.royale.core.IBead;
+	import org.apache.royale.core.IBeadModel;
+	import org.apache.royale.core.IStrand;
+	import org.apache.royale.events.Event;
+	import org.apache.royale.events.EventDispatcher;
+		
+	/**
+	 *  The SnackbarModel class bead defines the data associated with an org.apache.royale.jewel.Snackbar
+	 *  component. This includes a message, the action and duration - how long to show the view for.
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.2
+	 *  @playerversion AIR 2.6
+	 *  @productversion Royale 0.9.4
+	 */
+	public class SnackbarModel extends EventDispatcher implements IBead, IBeadModel
+	{
+        /**
+         *  Constructor.
+         *  
+	     *  @langversion 3.0
+	     *  @playerversion Flash 10.2
+	     *  @playerversion AIR 2.6
+	     *  @productversion Royale 0.9.4
+         */
+		public function SnackbarModel()
+		{
+            super();
+		}
+
+		private var _strand:IStrand;
+		
+        /**
+         *  @copy org.apache.royale.core.IBead#strand
+         *  
+         *  @langversion 3.0
+         *  @playerversion Flash 10.2
+         *  @playerversion AIR 2.6
+         *  @productversion Royale 0.9.4
+         */
+		public function set strand(value:IStrand):void
+		{
+			_strand = value;
+		}
+
+		private var _message:String;
+
+        [Bindable("messageChange")]
+        public function get message():String
+		{
+			return _message;
+		}
+		
+        /**
+         *  Set message to be displayed.
+         *  
+         *  @langversion 3.0
+         *  @playerversion Flash 10.2
+         *  @playerversion AIR 2.6
+         *  @productversion Royale 0.9.4
+         */
+		public function set message(value:String):void
+		{
+            if (value == null)
+                value = "";
+			if (value != _message)
+			{
+				_message = value;
+				dispatchEvent(new Event("messageChange"));
+			}
+		}
+		
+		private var _action:String;
+        
+        [Bindable("actionChange")]
+		public function get action():String
+		{
+			return _action;
+		}
+		
+        /**
+         *  Set action to be displayed.
+         *  
+         *  @langversion 3.0
+         *  @playerversion Flash 10.2
+         *  @playerversion AIR 2.6
+         *  @productversion Royale 0.9.4
+         */
+		public function set action(value:String):void
+		{
+			if (value != _action)
+			{
+				_action = value;
+				dispatchEvent(new Event("actionChange"));
+			}
+		}
+
+        private var _duration:int = 4000;
+
+        [Bindable("durationChange")]
+		public function get duration():int
+		{
+			return _duration;
+		}
+		
+        /**
+         *  Set how long to show the view for.
+         *  
+         *  @langversion 3.0
+         *  @playerversion Flash 10.2
+         *  @playerversion AIR 2.6
+         *  @productversion Royale 0.9.4
+         */
+		public function set duration(value:int):void
+		{
+			if (value != _duration)
+			{
+				_duration = value;
+				dispatchEvent(new Event("durationChange"));
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/validators/FormValidator.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/validators/FormValidator.as
index 4173124b2..5cc6b2502 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/validators/FormValidator.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/validators/FormValidator.as
@@ -22,6 +22,7 @@ package org.apache.royale.jewel.beads.validators
 	import org.apache.royale.events.Event;
 	import org.apache.royale.events.IEventDispatcher;
 	import org.apache.royale.jewel.Group;
+    import org.apache.royale.jewel.Snackbar;
 	import org.apache.royale.core.IChild;
 
 	/**
@@ -127,6 +128,7 @@ package org.apache.royale.jewel.beads.validators
 			_isError = false;
 			validateAll(hostComponent as Group);
 			if (isError) {
+                if (requiredFieldError) Snackbar.show(requiredFieldError);
 				hostComponent.dispatchEvent(new Event("invalid"));
 			} else {
 				hostComponent.dispatchEvent(new Event("valid"));
@@ -150,4 +152,4 @@ package org.apache.royale.jewel.beads.validators
 			}
 		}
 	}
-}
+}
\ No newline at end of file
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/SnackbarView.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/SnackbarView.as
new file mode 100644
index 000000000..418dbfffa
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/SnackbarView.as
@@ -0,0 +1,135 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.jewel.beads.views
+{
+    import org.apache.royale.core.BeadViewBase;
+    import org.apache.royale.core.IStrand;
+    import org.apache.royale.events.Event;
+    import org.apache.royale.jewel.Snackbar;
+    import org.apache.royale.jewel.beads.models.SnackbarModel;
+
+    /**
+	 *  The SnackbarView class creates the visual elements of the org.apache.royale.jewel.Snackbar 
+	 *  component. The job of the view bead is to put together the parts of the Snackbar such as the message
+	 *  text and action clicked dispatches action event on behalf of the Snackbar.
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.2
+	 *  @playerversion AIR 2.6
+	 *  @productversion Royale 0.9.4
+	 */
+	public class SnackbarView extends BeadViewBase
+	{
+		/**
+		 *  constructor.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.2
+		 *  @playerversion AIR 2.6
+		 *  @productversion Royale 0.9.4
+		 */
+		public function SnackbarView()
+		{
+            super();
+		}
+
+        /**
+		 * The Snackbar component
+		 */
+        protected var host:Snackbar;
+
+        /**
+		 * The action element that parents the action
+		 */
+        COMPILE::JS
+		protected var actionElement:Element;
+		
+        /**
+         *  @copy org.apache.royale.core.IBead#strand
+         *  
+         *  @langversion 3.0
+         *  @playerversion Flash 10.2
+         *  @playerversion AIR 2.6
+         *  @productversion Royale 0.9.4
+         */
+		override public function set strand(value:IStrand):void
+		{
+			super.strand = value;
+
+            host = value as Snackbar;
+            var model:SnackbarModel = host.model as SnackbarModel;
+
+			var messageElement:Element = document.createElement("div");
+			messageElement.className = "jewel snackbar-message";
+            messageElement.innerHTML = model.message;
+
+			var contentElement:Element = document.createElement("div");
+			contentElement.className = "jewel snackbar-content";
+			contentElement.appendChild(messageElement);
+
+            model.addEventListener("messageChange", messageChangeHandler);
+            model.addEventListener("actionChange", actionChangeHandler);
+
+            host.element.appendChild(contentElement);
+
+            if (model.action) actionChangeHandler(null);
+        }
+
+
+        /**
+         *  Update the text when message changed. 
+         */
+        private function messageChangeHandler(event:Event):void {
+            Element(host.element.firstChild.firstChild).innerHTML = SnackbarModel(host.model).message;
+        }
+
+        /**
+         *  Show the action element or remove it, based on action text.
+         */
+        private function actionChangeHandler(event:Event):void {
+            var model:SnackbarModel = host.model as SnackbarModel;
+
+            if (model.action) {
+				if (!actionElement) {
+					actionElement = document.createElement("div");
+					actionElement.className = "jewel snackbar-action";
+					actionElement.addEventListener("click", actionClickHandler);
+					host.element.firstChild.appendChild(actionElement);
+				}
+				actionElement.innerText = model.action;
+			} else {
+				if (actionElement) {
+					actionElement.removeEventListener("click", actionClickHandler);
+					host.element.firstChild.removeChild(actionElement);
+					actionElement = null;
+				}
+			}
+        }
+
+        /**
+         *  Trigger event and dismiss the host when action clicked.
+         */
+        private function actionClickHandler(event:Event):void {
+            actionElement.removeEventListener("click", actionClickHandler);
+            host.dispatchEvent(new Event(Snackbar.ACTION));
+            SnackbarModel(host.model).duration = -1; // set -1 to dismiss
+        }
+
+    }
+}
diff --git a/frameworks/projects/Jewel/src/main/sass/components/_snackbar.sass b/frameworks/projects/Jewel/src/main/sass/components/_snackbar.sass
new file mode 100644
index 000000000..4569e263b
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/sass/components/_snackbar.sass
@@ -0,0 +1,60 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+j|Snackbar
+    IBeadModel: ClassReference("org.apache.royale.jewel.beads.models.SnackbarModel");
+    IBeadController: ClassReference("org.apache.royale.jewel.beads.controllers.SnackbarController");
+    IBeadView: ClassReference("org.apache.royale.jewel.beads.views.SnackbarView");
+
+.jewel.snackbar
+    bottom: 0;
+    position: fixed;
+    width: 100%;
+
+
+.jewel.snackbar-content
+    background: #2C3E50;
+    border-radius: 3px;
+    max-width: 568px;
+    min-width: 288px;
+    padding: 6px; 
+    position: relative;
+
+
+.jewel.snackbar-message
+    color: #fff;
+    float: left;
+    margin: 10px;
+
+
+.jewel.snackbar-action
+    color: #FFD740;
+    cursor: pointer;
+    float: right;
+    padding: 10px;
+    
+    &:hover
+        background-color: #3C4E60;
+
+
+@media (max-width: $desktop)
+   .jewel.snackbar-content
+        max-width: 100%;
+        width: 100%;
+        border-radius: 0px;
diff --git a/frameworks/projects/Jewel/src/main/sass/defaults.sass b/frameworks/projects/Jewel/src/main/sass/defaults.sass
index e17e52a33..a3af19f0c 100644
--- a/frameworks/projects/Jewel/src/main/sass/defaults.sass
+++ b/frameworks/projects/Jewel/src/main/sass/defaults.sass
@@ -52,4 +52,4 @@
 @import "components/tooltip"
 @import "components/topappbar"
 @import "components/applicationmaincontent"
-
+@import "components/snackbar"
diff --git a/frameworks/themes/JewelTheme/src/main/sass/components-emphasized/_snackbar.sass b/frameworks/themes/JewelTheme/src/main/sass/components-emphasized/_snackbar.sass
new file mode 100644
index 000000000..ea9cb3ace
--- /dev/null
+++ b/frameworks/themes/JewelTheme/src/main/sass/components-emphasized/_snackbar.sass
@@ -0,0 +1,38 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Jewel Snackbar
+
+// Snackbar variables
+$snackbar-border-radius: 3px
+
+.jewel.snackbar.emphasized
+	.jewel.snackbar-content
+		+jewel-bg-border("normal", $emphasized-color, $snackbar-border-radius)
+	
+	.jewel.snackbar-message
+		color: $font-theme-color
+
+	.jewel.snackbar-action
+		color: $yellow
+	
+		&:hover
+			+jewel-bg-border("hover", $emphasized-color)
+			@if $flat == false
+				border: none
\ No newline at end of file
diff --git a/frameworks/themes/JewelTheme/src/main/sass/components-primary/_snackbar.sass b/frameworks/themes/JewelTheme/src/main/sass/components-primary/_snackbar.sass
new file mode 100644
index 000000000..2aaa863da
--- /dev/null
+++ b/frameworks/themes/JewelTheme/src/main/sass/components-primary/_snackbar.sass
@@ -0,0 +1,38 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Jewel Snackbar
+
+// Snackbar variables
+$snackbar-border-radius: 3px
+
+.jewel.snackbar.primary
+	.jewel.snackbar-content
+		+jewel-bg-border("normal", $primary-color, $snackbar-border-radius)
+	
+	.jewel.snackbar-message
+		color: $font-theme-color
+
+	.jewel.snackbar-action
+		color: $yellow
+	
+		&:hover
+			+jewel-bg-border("hover", $primary-color)
+			@if $flat == false
+				border: none
\ No newline at end of file
diff --git a/frameworks/themes/JewelTheme/src/main/sass/components-secondary/_snackbar.sass b/frameworks/themes/JewelTheme/src/main/sass/components-secondary/_snackbar.sass
new file mode 100644
index 000000000..07132bdaa
--- /dev/null
+++ b/frameworks/themes/JewelTheme/src/main/sass/components-secondary/_snackbar.sass
@@ -0,0 +1,38 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Jewel Snackbar
+
+// Snackbar variables
+$snackbar-border-radius: 3px
+
+.jewel.snackbar.secondary
+	.jewel.snackbar-content
+		+jewel-bg-border("normal", $secondary-color, $snackbar-border-radius)
+	
+	.jewel.snackbar-message
+		color: $font-theme-color
+
+	.jewel.snackbar-action
+		color: $yellow
+	
+		&:hover
+			+jewel-bg-border("hover", $secondary-color)
+			@if $flat == false
+				border: none
\ No newline at end of file
diff --git a/frameworks/themes/JewelTheme/src/main/sass/defaults.sass b/frameworks/themes/JewelTheme/src/main/sass/defaults.sass
index f1edfd754..3df7469aa 100644
--- a/frameworks/themes/JewelTheme/src/main/sass/defaults.sass
+++ b/frameworks/themes/JewelTheme/src/main/sass/defaults.sass
@@ -52,6 +52,7 @@
 @import "components-primary/togglebutton"
 @import "components-primary/tooltip"
 @import "components-primary/topappbar"
+@import "components-primary/snackbar"
 
 @import "components-secondary/alert"    
 @import "components-secondary/button"
@@ -67,6 +68,7 @@
 @import "components-secondary/text"
 @import "components-secondary/textinput"
 @import "components-secondary/titlebar"
+@import "components-secondary/snackbar"
 
 @import "components-emphasized/alert"    
 @import "components-emphasized/button"
@@ -82,3 +84,4 @@
 @import "components-emphasized/text"
 @import "components-emphasized/textinput"
 @import "components-emphasized/titlebar"
+@import "components-emphasized/snackbar"


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services