Currently, the following implementations of a button component exist:
- [[https://github.com/wikimedia/wvui/blob/master/src/components/button/Button.vue|WVUI]] (used in Vector search, NearbyPages, GlobalWatchlist)
- [[https://github.com/wikimedia/mediawiki-extensions-WikibaseMediaInfo/blob/master/resources/mediasearch-vue/components/base/Button.vue|WikibaseMediaInfo]] ([[https://github.com/wikimedia/mediawiki-extensions-WikibaseMediaInfo/blob/master/resources/mediasearch-vue/components/base/Button.less|styles]]; copy used in WikiLambda)
- [[https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/Wikibase/+/refs/heads/master/client/data-bridge/src/presentation/components/EventEmittingButton.vue|Wikidata bridge]]
Some of the differences between these implementations are:
**Primary style**: The WBMI button allows progressive/destructive buttons to be primary (white text on blue/red background) or non-primary (blue/red text on white background). The WVUI button is always non-primary. The CX button is primary by default, but it supports the non-primary style through `type="text"`. The Wikit button styles primary buttons exactly as prescribed in the [[https://design.wikimedia.org/style-guide/components/buttons.html|design style guide]], but it ignores `type="progressive"` or `type="destructive"` if the button doesn't also have `variant="primary"` or `variant="quiet"`. The Wikidata Bridge button is always primary when it is progressive.
**Setting the action type and quietness**: The Wikit button takes a `type` prop that can be set to `neutral`, `progressive` or `destructive`, and a variant prop that can be set to `normal`, `primary` or `quiet`. Even though Wikit is written in TypeScript, it doesn't use TypeScript types for these, they just take a string and use a validator. The WVUI button takes an `action` prop that can be set to `default`, `progressive` or `destructive`, and [[https://github.com/wikimedia/wvui/blob/master/src/actions/PrimaryAction.ts|defines a TypeScript enum]] for this; `quiet` is a boolean prop, and there is no way to make a button primary. The CX button takes `progressive` and `destructive` as boolean props; it doesn't have quiet buttons as such, but buttons with `type="text"` or `type="icon"` look similar (there is also an `outlined` prop but I'm not sure what it does). Similarly, WBMI takes `progressive`, `destructive`, and `primary` as boolean props, as well as a boolean `frameless` prop (which appears to be the same concept as "quiet"). Wikidata Bridge takes `type="primaryProgressive"`, and does not support destructive (or non-primary progressive); it supports something similar to quiet buttons with `type="link"` (and `type="close" and `type="back"` are icon-only quiet buttons).
**Other display modes**: The CX button takes `type="icon"` to make a button quiet and icon-only, `type="text"` to make it quiet and text-only, `type="toggle"` (which doesn't seem to do anything); it also takes a boolean prop `large` to make it bigger, and boolean `outlined` and `depressed` props whose behavior is unclear to me. The Wikit button takes an `icon-only` prop. Wikidata Bridge takes a `size` prop (set to M, L or XL) and a `squary` prop (unclear what that does). WVUI and WBMI don't have additional display modes.
**Which HTML tag to use / link support**: WVUI, WBMI and Wikit always use `<button>`. CX uses an `<a>` if the `href` prop is set, and a `<span>` otherwise. Wikidata Bridge always uses an `<a>` with a `<span>` inside it, and takes an `href` prop and and props to make the link open in a new tab (`opens-in-new-tab`) or prevent the href from being followed (`prevent-default`).
**Setting the disabled state**: The CX, and Wikidata Bridge implementations have a `disabled` prop, and set a CSS class on the button when it's disabled, in order to style it differently. The WVUI and Wikit implementations don't have a `disabled` prop, so setting them to `disabled` sets the native attribute on the `<button>`, which they then style through the `:disabled` selector. WBMI does have a `disabled` prop, but it's superfluous since it's only used to set the native attribute.
**How content is injected**: WVUI allows any content to be injected through a slot, and does not have explicit support for icons; a button with an icon can be made by manually passing in an icon as part of the slot content. Wikit works the same way, but it also takes an `icon-only` prop that styles the button differently. WBMI accepts arbitrary content via a slot, but also takes an `icon` prop that adds the specified icon before the slot content. Wikidata Bridge only accepts text, through the `message` prop; it does not support arbitrary content, and support for icons is limited (`type="back"` and `type="close"` make the button icon-only with a pre-set icon). CX renders an icon, a plain text label and an indicator (smaller secondary icon) by default, but allows arbitrary content to be injected through a slot, which overrides all of that.
**How the icon color is controlled**: CX's Icon component uses inline SVG with `fill="currentColor"`, so setting the text color (to blue for progressive, red for destructive, or white for primary) also changes the icon color. Wikit and WBMI do the same thing. WVUI's Icon component doesn't do this, and its button doesn't manage icons explicitly, so color-coordinating the icons is left up to the caller. WDB's button doesn't support changing the color of the icon.
**Invisible label text**: WBMI takes an `invisibleLabel` prop that causes the label to be rendered but hidden (this is desirable for icon-only buttons, for accessibility reasons). WDB does this automatically when `type="back"` or `type="close"` are used (both result in an icon-only button). WVUI and Wikit don't put in their own icons or labels, so this feature isn't relevant for them. CX doesn't have this feature, the label isn't rendered at all for icon-only buttons.