Page MenuHomePhabricator

Create button component(s)
Open, Needs TriagePublic


A common need in apps is to have a button to let the user do things. Both Termbox and (copied from the first) Data Bridge have a dedicated button component, more or less in the look of OOUI. Tainted references is very likely going to need a button as well.

NOTE: While the current API and scope of these components is suitable for an internal component in a single project as they currently are, this doesn't necessarily scale to the needs of a component in a shared component library and should be reevaluated.

Related Objects


Event Timeline

Michael created this task.Fri, Oct 18, 10:20 AM
tl;dr: In my opinion, we need two button components, and we should start with both of them from the beginning.

One or Two components?

We should have two components, one ActionLink component for (overloaded) links and one ActionButton component for pure (submit) buttons.


1: Different no-JS SSR Fallback

If the js doesn't load, we want to provide the user a server-rendered version of many apps that still has basic usability. For buttons that usually handled by javascript this could mean one of two things:

  1. Provide a link to a form that does the thing that would otherwise be handled by the vue app. For this to work the "button" needs to be a HTML <a> tag with the url as the href attribute
  2. Submit an HTML form to the server. For this to work the button needs to be a HTML <button> tag with the type attribute to be submit.
2: Separation of responsibilities

The current EventEmittingButton combines two responsibilities into one component. For a shared component library it makes sense to split it into two, one for each responsibility:

  1. the button is actually a link and only styled as button (e.g. the progressive button in the Termbox anon edit warning) or overloads a link with a vuejs app, e.g. the Termbox edit pens on an Item page. Both of these cases require a link target.
  2. the button is only rendered dynamically within the vuejs app and never needs fallback, e.g. the save button in the data-bridge app. These buttons never need a link target and are always handled purely in js. I.e. This is just a pure button.


These two button components need to share their look and feel, but differ in some of their behavior. Thus, the API regarding the design should be completely shared, whereas the API controlling behavior can only be partly shared.

specific behavior API for ActionLink component

  • href, required, if there is no sensible href for this button, use an ActionButton
  • callback, optional. If it is not there, the component acts as a pure link. If it is provided, then the default action of opening the link is suppressed and the callback executed instead.

specific behavior API for ActionButton component

  • type, optional, can be submit, reset or button, button is the default
  • callback, optional if type is submit or reset, otherwise required.

shared behavior API between ActionLink and ActionButton components

  • disabled, optional, default is false

shared presentational API between ActionLink and ActionButton components

  • purpose, optional, can be normal, progressive or destructive, default is normal
  • progressive, optional, binary, default is false, can only be true if purpose is not normal
  • frameless, optional, binary, default is false, whether to show a border or not
  • icon, optional, name of an icon that is added to the button. The available icons and their names should be the same as for OOUI
  • icononly, optional, binary, default is false, doesn't show the button label, needs the icon option to be set


Hopefully, this approach will provide use with a more SOLID, future ready implementation that scales to upcoming projects without becoming a convoluted mess or breaking existing implementations every other week when another piece of functionality is added. Distinguishing between these two button types should ideally be obvious by design.

We might not want to implement all the functionality outlined above right from the start, especially as the component library is for now only intended for internal use. However, we should ensure that we implement this component in a way that is strictly forward compatible. That means that adding more API functionality doesn't represent a breaking change for the existing usage of the button.

Also, in the future we may want to extend this concept/API to include the indicator visual and the ToggleButton use case and OOUI design.