To introduce a new Button component for YUI 3 that addresses the following user stories
- "I want buttons on my site to look consistent & attractive."
- "I want to be able to programmatically control buttons in my application."
- "I want to my buttons to be intelligent and interact with one another in groups."
- "I want my application to be able to dynamically generate buttons."
- ARIA / Accessibility
- Modern styles (using CSS3), but degrades well to legacy browsers
- Customizable colors with minimal fuss
- Something lighter than Y.Widget, but similar in features to YUI2 buttons
- cssbuttons (CSS) - Some lite CSS skins to give the buttons a nice look & feel. This is ideal for someone who just wants a nice looking button, without needing programatic control.
- button-base (JS) - A
Y.Attribute
-driven wrapper around a button-like DOM node, and some helper utilities - button-group (JS) - A manager that listens for Y.Button events and can fire notifications when the selection has changed
Buttons can be used in many different ways. Some users just want the buttons to be aesthetically pleasing, others want to listen for clicks/events, others want to programmatically control them, and some will use them for core navigation groups. Because of these variety of use cases, it's important to have functionality logically and modularly separate, while keeping them simple to use & control.
The lightest possible implementation is just including the button stylesheet and adding the yui3-button
class to any element you would like to be a button. As requirements start to increase, you can start adding on JS modules to provide the required functionality. The JS portion of Button is very Y.Attribute
-driven. The idea is that it that Y.Button
is basically a wrapper around a DOM node that fills in missing functionality and keeps the UI in sync with the button state. Y.ButtonGroup
is also Y.Attribute
driven that knows about groups of Y.Button
instances and manages them as a whole.
Y.Button
- The Y.Attribute-driven Button objectY.Buttons
- A way to generate an array of Y.Button instances given a NodeListY.ButtonGenerator
- A way to dynamically generate a Y.Button instance with an unattached DOM node
Y.ButtonGroup
- A way to connect Y.Button instances together and has a memory of selection states
- onClick
- getDOMNode
- _colorToHex (static)
- _getContrastYIQ (static)
- type - specifies the type of button (push/toggle)
- disabled - a setter for the node's 'disabled' attribute
- selected - a setter that handles the node's 'selected' state
- backgroundColor - The background color for the button
- typeChange
- selectedChange
- backgroundColorChange
- disabledChange
- yui3-button
- yui3-button:hover
- yui3-button:active
- yui3-button-selected
- yui3-button-focused
- yui3-button-disabled
- type - The type of group (default:push/radio/checkbox)
- buttons - An array of
Y.Button
instances that are in this group - selection - The array of
Y.Button
instances that are currently selected
- role=button
- aria-pressed
- aria-selected
I haven't come up with a good reason for making ARIA support optional (like YUI 2 Button), so it's just baked in for the time being.
You can find some demos here.
-
Y.Button
- Add sugar & properties to not require users to use .get() & .set() all the time. This will improve usability & performance. -
Y.Button
- Support aria-label/aria-labeledby -
Y.Button
- Support icons & image buttons -
Y.Button
- Determine if the color contrast calculation should belong inY.Button
, or elsewhere -
Y.Buttons
- Combine with Y.Button? -
Y.ButtonGenerator
- Allow an optionalcontainer
element that the node is appended to? -
Y.ButtonGroup
- Support aria-multiselectable for radio groups -
Y.ButtonGroup
- Possibly support aria-owns ifY.Button
instance relationship is not parent-children -
Y.ButtonGroup
- 'selection' is probably inefficient. -
cssbuttons
- Add basic Sam & Night skins -
Allow using selector strings as opposed to requiring a Node/NodeList to instantiate.
-
Investigate state on legacy browsers
-
Investigate state on tablets
-
Investigate lazy attributes
-
Use the
event-touch
module to be more responsive on touchscreen devicesY.all('.yui3-button').on(['touchstart' /* <- if applicable */, 'click'], function (e) { e.halt(); // Stop event propagation // do something });
@derek I think the goals are right on target, and I really like how the examples are looking.
My gut reaction to seeing the list of
Y.Button
attributes was thatY.Button
s do not need to exist as instance objects;Y.Node
instances seem like they will represent buttons just fine, and almost everything is covered by standard DOM attributes. I think a specific button's state can be driven by the combination of CSS classes and usingY.Node
'sgetData
/setData
support.So what I see is something more like a
Y.button
object with static utility methods.Y.button.create()
can generate a newY.Node
instance for the button, or take an existingY.Node
instance and modify it by adding the ARIA attributes and updating whatever else was passed into the config.I could also see more utility methods for things like:
Y.button.select()
Y.button.unselect()
Y.button.disable()
Y.button.enable()
These methods could have some sugar and also accept
Y.NodeList
s. They could be implemented by either toggling CSS classes on the node instance, or usinggetData
/setData
for things which aren't well expressed as CSS classes. This way the API is nicer than having people remember which CSS classes to add and remove, etc.@derek and @lsmith I found your discussion about adding things to
Y.Node.prototype
interesting.Y.Transition
does this; and I don't think it would be crazy to add the aboveY.button
utility functions on to theY.Node.prototype
name-spaced underY.Node.prototype.button
orY.Node.prototype.btn
. This would be similar to howY.DOM
's static methods are added toY.Node.prototype
viaY.Node.importMethod()
;What about something like this?
I think if people want more fancy with their buttons they will probably use
Y.ButtonGroup
, I think this should be a widget that interacts with the buttonY.Node
instances as I described above, and be the things that maintains the shared state like which button in the group isselected
.The touch even support stuff is a really interesting problem-space that would be great to address. @davglass has been working on some Loader stuff that might make it easier to do some conditional loading of the
event-touch
modules; but that's the extend of what I know about Loader's conditional module support :)I profiled the code in the generate example with 10 buttons and saw: 19.4ms, 6,866 fn calls which is really high, imo.