Module:Clickable button

Lua

CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules

Generates wikitext for clickable Codex button. Renders the button component from the Codex design system for Wikimedia. Includes helper functions for URL parsing and cleaning, adding tracking categories. Intended for use in templates and other modules. Implements Template:Clickable button and others. Supports legacy parameters.

For more information on appropriate usage of UI buttons, see the Codex documentation.

Usage in wikitextUsage in wikitext

Some arguments are case-insensitive.

{{#invoke:Clickable button|main
| 1        = <!-- Alias for wikilink -->
| 2        = <!-- Alias for label -->
| label    = <!-- Button visible text label -->
| link     = <!-- Target wikilink -->
| url      = <!-- Target external URL -->
<!-- Inputs action, weight, size, and icon are case-insensitive -->
| action   = <!-- progressive | destructive | default: default. -->
| weight   = <!-- primary | quiet | default: normal. -->
| size     = <!-- small | large | default: medium. Automatically chooses size based on line-height and device. -->
| icon     = <!-- Name of icon, stored in [[Module:Clickable button/icons.css]] e.g., search  -->
| disabled = <!-- `true` or any other true value like `1` or `yes`. -->
| aria-label = <!-- [[w:ARIA]] label for accessibility DOM tree. -->
| nocat      = <!-- `true` to not auto-categorize. -->
<!-- Others -->
| category = <!-- Category name e.g., Category:Name or Name or [[Category:Name]] -->
| class    = <!-- Custom CSS class without quotation marks -->
| style    = <!-- Custom CSS styling without quotation marks -->
<!-- Legacy arguments -->
| color    = <!-- blue | red --> 
}}

Usage in other modulesUsage in other modules

Ensure you know what to expect from the function you call from another module.

To call p.main() for example, use:

local createButton = require( 'Module:Clickable button/sandbox' )
buttonWikitext = createButton.main( {
    link = 'South Africa',
    label = 'Go to South Africa',
    action = 'progressive'
    weight = 'default',
    size = 'medium',
    icon = 'link-external',
} ) 
return buttonWikitext

and the value of buttonWikitext would be:

<<templatestyles src="Module:Cdx-button/styles.css" /><templatestyles src="Module:Cdx-button/icons.css" /><span class="cdx-button cdx-button--fake-button cdx-button--action-progressive cdx-button--weight-quiet cdx-button--size-medium" role="button" aria-disabled="false"><span class="cdx-button__icon cdx-demo-css-icon--link-external" aria-hidden="true"></span>Go to South Africa</span>

Function _main would output:

<span class="cdx-button cdx-button--fake-button cdx-button--action-progressive cdx-button--weight-quiet cdx-button--size-medium" role="button" aria-disabled="false"><span class="cdx-button__icon cdx-demo-css-icon--link-external" aria-hidden="true"></span>Go to South Africa</span>

As a result, unless a CSS file is added to give the appropriate class an icon, the icon will not render.

ImplementationImplementation

Length of visible label Length of visible label

See the Codex button component documentation.


Code

--------------------------------------------------------------------------------
--- @module 'CodexClickableButton'
--- Generates wikitext for clickable Codex button.
--- 
--- Outputs wikitext to render the (button component)[mdoc:codex/latest/components/demos/button.html]
--- from the (Codex design system for Wikimedia)[https://doc.wikimedia.org/codex/latest].
---- Options to include an icon or create an icon-only button.
---- Target a URL or a wikilink
---- Set the weight, size and state of the button (enabled or disabled).
---- Dummy button creation can be disabled.
---
--- Includes helper functions for URL parsing and cleaning, and adding tracking 
--- categories. Intended for use in templates and other modules.
--- Supports legacy parameters. To add icons, see CSS link in constants below.
---
--- @author [[User:Waddie96]]
--- @license CC-BY-SA-4.0/GFDL
--- @class CodexClickableButton extends ClickableButton
---  Table containing arguments for the button.
--- @class args table
--- @field label? string The button's visible text label.
--- @field link? string|'no' The target wikilink for the button.
--- @field url? string The target external URL for the button.
--- @field icon? string The name of the icon to display found in CSS file.
--- @field color? 'blue'|'green'|'red'|string Legacy color parameter.
--- @field class? string Custom CSS classes for the button.
--- @field weight? 'quiet'|'normal'|'primary' The visual weight of the button.
--- @field size? 'small'|'medium'|'large' The size of the button.
--- @field action? 'progressive'|'destructive'|'default'|string The action type of the button.
--- @field disabled? boolean|'1'|string Whether the button is disabled/greyed out. `disabled` is `true` if: `link` = `'no'` or `false` or `disabled` = `'1'` or `true`.
--- @field style? string Custom inline CSS styles.
--- @field nocat? boolean|string If `true`, suppresses tracking categories.
--- @field category? string An additional category to add.
--- @field aria-label? string The ARIA label for accessibility.
--- @field arialabel? string (alias for aria-label)
--- @field aria_label? string (alias for aria-label)
--- @field [1]? string Positional argument 1 (alias for link/label).
--- @field [2]? string Positional argument 2 (alias for label).
--- @var categories? string|boolean Additional categories to add.
--- @var ariaDisabled? boolean Internal flag indicating if the button is functionally disabled for ARIA.
--- @var oldClassMatched string|boolean Internal flag for outdated classes.
--- @var isUrl boolean Whether the link is a URL.
--- @var errorText string|nil 
--- @var tblClasses table Classes for the button span tag.
--- @var pageTitle mw.title Title of the current page.
--- @todo [[Module:Neturl]] [[Module:Check for unknown parameters]]

local yesno = require('Module:Yesno')
local delink = require('Module:Delink')._delink

local p = {}

function p.main(frame)
	local getArgs = require('Module:Arguments').getArgs
	local args = getArgs(frame)
	return p._main(args)
end

function p._main(args)
	-- If first arg or a url is not provided,
	-- but we have a second arg, make a button.
	-- Otherwise, return nothing.
	args.originalInput = args[1]
	args[1] = delink({args[1]})
	if args[1] == "" then
		args[1] = nil
	end

	if not args[1] and not args.url then
		if args[2] then
			p.nolink = true
		else
			return ''
		end
	end

	local data = p.makeLinkData(args)
	local link = p.renderLink(args.originalInput, data)
	local trackingCategories = p.renderTrackingCategories(args)
	return link .. trackingCategories
end

function p.makeLinkData(args)
	local data = {}

	-- Get the link and display values,
	-- and find whether we are outputting
	-- a wikilink or a URL.
	if args.url then
		data.isUrl = true
		data.link = args.url
		if args[1] then
			data.display = args[1]
		elseif args[2] then
			data.display = args[2]
		else
			data.display = args.url
			p.urlisdisplay = true
		end
	else
		data.isUrl = false
		p.urlisdisplay = false
		data.link = args[1]
		if args[2] then
			data.display = args[2]
		else
			data.display = args[1]
		end
		if args[1] and args[1]:find('http') then
			data.isUrl = true
		end
	end
	
	if yesno(args.link) == false then
		p.nolink = true
	end

	-- Colours
	-- For the merge with {{clickable button}}
	local colour = args.color and args.color:lower()

	-- Classes
	local class = args.class and args.class:lower()
	data.classes = {}
	if class == 'ui-button-green'
		or class == 'ui-button-blue'
		or class == 'ui-button-red'
	then
		table.insert(
			data.classes,
			'submit ui-button ui-widget ui-state-default ui-corner-all'
				.. ' ui-button-text-only ui-button-text'
		)
	else
		table.insert(data.classes, 'mw-ui-button')
	end
	
	--If class is unset,
	--then let color determine class
	if not class then
		if colour == 'blue' then
			class = 'mw-ui-progressive'
		elseif colour == 'red' then
			class = 'mw-ui-destructive'
		elseif colour == 'green' then
			class = 'mw-ui-constructive'
		end
	end
	
	if class then
		table.insert(data.classes, class)
	end

	-- Styles
	do
		--[[
		-- Check whether we are on the same page as we have specified in
		-- args[1], but not if we are using a URL link, as then args[1] is only
		-- a display value. If we are currently on the page specified in
		-- args[1] make the button colour darker so that it stands out from
		-- other buttons on the page.
		--]]
		local success, linkTitle, currentTitle
		if not data.isUrl then
			currentTitle = mw.title.getCurrentTitle()
			success, linkTitle = pcall(mw.title.new, args[1])
		elseif p.urlisdisplay then
			currentTitle = mw.title.getCurrentTitle()
		end
		if success
			and linkTitle
			and mw.title.equals(currentTitle, linkTitle)
			and not p.urlisdisplay
		then
			if class == 'ui-button-blue'
				or class == 'mw-ui-progressive'
				or class == 'mw-ui-constructive'
			then
				data.backgroundColor = '#2962CB'
				data.color = '#fff'
			elseif class == 'ui-button-green' then
				data.backgroundColor = '#008B6D'
			elseif class == 'ui-button-red' or class == 'mw-ui-destructive' then
				data.backgroundColor = '#A6170F'
			else
				data.backgroundColor = '#CCC'
				data.color = '#666'
			end
		elseif p.urlisdisplay then
			data.dummyLink = tostring(currentTitle)
		end
		-- Add user-specified styles.
		data.style = args.style
	end
	return data
end

function p.renderLink(originalInput, data)
	-- Render the display span tag.
	local display
	do
		local displaySpan = mw.html.create('span')
		for i, class in ipairs(data.classes or {}) do
			displaySpan:addClass(class)
		end

		displaySpan
			:css{
				['background-color'] = data.backgroundColor,
				color = data.color
			}
		if data.style then
			displaySpan:cssText(data.style)
		end
		displaySpan:wikitext(data.display)
		display = tostring(displaySpan)
	end

	-- Render the link
	local link
	if originalInput and originalInput:find('|') then
		link = string.format('[[%s|%s]]', delink({originalInput, wikilinks = 'target'}), display)
	elseif p.nolink then
		if p.urlisdisplay then
			link = string.format('[[%s|%s]]', data.dummyLink, display)
		else
			link = string.format('%s', display)
		end
	else
		if data.isUrl then
			link = string.format('[%s %s]', data.link, display)
		else
			link = string.format('[[%s |%s]]', data.link, display)
		end
	end

	return string.format('<span class="plainlinks clickbutton">%s</span>', link)
end

function p.renderTrackingCategories(args)
	if yesno(args.category) == false then
		return ''
	end
	local class = args.class and args.class:lower()
	if class == 'ui-button-green'
		or class == 'ui-button-blue'
		or class == 'ui-button-red'
	then
		return '[[Category:Pages using old style ui-button-color]]'
	else
		return ''
	end
end

return p
Category:Modules in beta Category:Pages with content copied from English Wikipedia Category:Templates using TemplateStyles