Module:Box

From Puella Magi Wiki
Jump to navigation Jump to search

Generic box with automatic dark mode based on tint colors.

Functions

Self-Contained Box

{{#invoke:Box|main
|background=false
|body=Body
|compact=false
|outer=false
|tintColor=#f8f2fb
|vfill=false
|vspace=false
}}

Use main if you want a self-contained box.

background (default: false)
Whether to set tint color as a background color.
body (default: empty)
Set the body text. Inline wikitext can be used. For block wikitext (e.g., header), use open and close.
compact (default: false)
Whether to make the box more compact. This should be set to true if box is used for layout purposes.
outer (default: false)
Whether to use the "outer border" styling (see example below)
tintColor (default: #999999)
Set the tint color. This should be set to the lightest color of the element (e.g., background). Border color and dark mode colors will derive from this value. In particular, border will use a darkened value of the tint color, and dark mode will use a brightness-inverted value of the respective light tint.
vfill (default: false)
Fill 100% of the height (intended to be used with Module:Layout)
vspace (default: false)
Whether to add a small space after the box. Useful when box is used for notices, etc.

Open/Close Box

{{#invoke:Box|open
|background=false
|compact=false
|outer=false
|tintColor=#f8f2fb
|vfill=false
|vspace=false
}}

Body

{{#invoke:Box|close
|outer=false
}}

Use open and close if you want to use the box for layout purposes.

background (default: false)
Whether to set tint color as a background color.
compact (default: false)
Whether to make the box more compact. This should be set to true if box is used for layout purposes.
outer (default: false)
Whether to use the "outer border" styling (see example below). see example below). Note that this should be set to the same value in both open and close.
tintColor (default: #999999)
Set the tint color. This should be set to the lightest color of the element (e.g., background). Border color and dark mode colors will derive from this value. In particular, border will use a darkened value of the tint color, and dark mode will use a brightness-inverted value of the respective light tint.
vfill (default: false)
Fill 100% of the height (intended to be used with Module:Layout)
vspace (default: false)
Whether to add a small space after the box. Useful when box is used for notices, etc.

Examples

Plain Box

{{#invoke:Box|main|body=Body}}
Body
{{#invoke:Box|main|body=Body|tintColor=#f8f2fb}}
Body
{{#invoke:Box|main|body=Body|tintColor=#e4efff}}
Body
{{#invoke:Box|open|tintColor=#e4efff|compact=true}}
{{#invoke:Box|main|body=Title|background=true|tintColor=#e4efff}}
Body
{{#invoke:Box|close}}
Title

Body

Outer Box

{{#invoke:Box|main|body=Body|outer=true}}
Body
{{#invoke:Box|main|body=Body|outer=true|tintColor=#f8f2fb}}
Body
{{#invoke:Box|main|body=Body|outer=true|tintColor=#e4efff}}
Body
{{#invoke:Box|open|tintColor=#e4efff|outer=true|compact=true}}
{{#invoke:Box|main|body=Title|background=true|tintColor=#e4efff}}
Body
{{#invoke:Box|close}}
Title

Body


local getArgs = require('Module:Arguments').getArgs
local toBoolean = require('Module:Boolean').toBoolean
local color = require('Module:Color')
local p = {}

--------------------------------------------------------------------------------
-- PRIVATE HELPER FUNCTIONS
--------------------------------------------------------------------------------

-- Builds the opening HTML tags.
local function buildOpeningHtml(args, frame)
	local tintColor = args.tintColor
	if tintColor == nil or tintColor == "" then	tintColor = "#dddddd" end
	local borderColor = color.darken(tintColor)

	local htmlParts = {}
	table.insert(htmlParts, tostring(
		frame:extensionTag{
			name = 'templatestyles',
			args = { src = 'Module:Box/base.css' }
		}
	))

	-- Root
	local boxClasses = {}
	table.insert(boxClasses, 'pm-box')
	if toBoolean(args.vfill) then
		table.insert(boxClasses, 'pm-box--vfill')
	end
	if toBoolean(args.vspace) then
		table.insert(boxClasses, 'pm-box--vspace')
	end
	table.insert(htmlParts, string.format(
		'<div class="%s">',
		table.concat(boxClasses, ' ')
	))

	-- Outer
	if toBoolean(args.outer) then
		local outerClasses = {}
		table.insert(outerClasses, 'pm-box__outer')
		if toBoolean(args.vfill) then
			table.insert(outerClasses, 'pm-box__outer--vfill')
		end

		table.insert(htmlParts, string.format(
			'<div class="%s" style="%s">',
			table.concat(outerClasses, ' '),
			string.format(
				'border-color: light-dark(%s, %s);',
				tintColor,
				color.lighten(color.invert(tintColor), 3)
			)
		))
	end

	-- Inner
	local innerClasses = {}
	table.insert(innerClasses, 'pm-box__inner');
	if toBoolean(args.compact) then
		table.insert(innerClasses, 'pm-box__inner--compact')
	end
	if toBoolean(args.vfill) then
		table.insert(innerClasses, 'pm-box__inner--vfill')
	end

	local innerStyles = {}
	table.insert(innerStyles, string.format(
		'border-color: light-dark(%s, %s);',
		borderColor,
		color.invert(borderColor)
	))
	if toBoolean(args.background) then
		table.insert(innerStyles, string.format(
			'background-color: light-dark(%s, %s);',
			tintColor,
			color.invert(tintColor)
		))
	end

	table.insert(htmlParts, string.format(
		'<div class="%s" style="%s">',
		table.concat(innerClasses, ' '),
		table.concat(innerStyles, ' ')
	))

	-- Body
	table.insert(htmlParts, '<div class="pm-box__body">')

	-- Return
	return table.concat(htmlParts, '')
end

-- Builds the closing HTML tags.
local function buildClosingHtml(args)
	if toBoolean(args.outer) then
		return '</div></div></div></div>' -- Closes body, inner, outer, root
	else
		return '</div></div></div>' -- Closes body, inner, root
	end
end

--------------------------------------------------------------------------------
-- PUBLIC FUNCTIONS
--------------------------------------------------------------------------------

-- Self-contained boxes: {{#invoke:Box|main|...}}
function p.main(frame)
	local args = getArgs(frame)
	return buildOpeningHtml(args, frame) ..	(args.body or "") .. buildClosingHtml(args)
end

-- Open a box for wrapping: {{#invoke:Box|open|...}}
function p.open(frame)
	local args = getArgs(frame)
	return buildOpeningHtml(args, frame)
end

-- Close a box: {{#invoke:Box|close|...}}
function p.close(frame)
	local args = getArgs(frame)
	return buildClosingHtml(args)
end

return p