diff --git a/src/button-groups.ts b/src/button-groups.ts index 655d88a..46da804 100644 --- a/src/button-groups.ts +++ b/src/button-groups.ts @@ -1,4 +1,5 @@ import { StacksCommonOptions } from "./index"; +import { Buttons } from "./index"; export type GroupButton = { /** Button text (HTML allowed) */ @@ -9,6 +10,8 @@ export type GroupButton = { count?: number; /** Whether to wrap the button in a `
` element */ form?: boolean; + /** The type of the button (outlined and muted by default) */ + types?: Omit[]; }; export type StacksButtonGroupOptions = StacksCommonOptions; @@ -36,12 +39,14 @@ export const makeStacksButtonGroup = ( selected = false, count, form = false, + types = [] } = buttonConfig; - const button = document.createElement("button"); - button.classList.add("s-btn", "s-btn__muted", "s-btn__outlined"); - button.setAttribute("role", "button"); - button.append(text); + const button = Buttons.makeStacksButton( + "", + text, + { type: ["muted", "outlined", ...(types as Buttons.ButtonType[])] } + ); if (selected) { button.classList.add("is-selected"); @@ -61,7 +66,6 @@ export const makeStacksButtonGroup = ( if (form) { const formContainer = document.createElement("form"); - formContainer.classList.add("s-btn-group--container"); formContainer.append(button); container.append(formContainer); diff --git a/src/buttons/index.ts b/src/buttons/index.ts index 6d8b5a3..9a5c5ff 100644 --- a/src/buttons/index.ts +++ b/src/buttons/index.ts @@ -54,7 +54,7 @@ export type StacksIconButtonOptions = StacksCommonOptions & { */ export const makeStacksButton = ( id: string, - text: string, + text: string | HTMLElement, options: StacksIconButtonOptions = {} ): HTMLButtonElement => { const { @@ -72,17 +72,26 @@ export const makeStacksButton = ( } = options; const btn = document.createElement("button"); - btn.id = id; - btn.textContent = text; + if (id !== "") { + btn.id = id; + } + btn.classList.add( "s-btn", ...type.map((name) => `s-btn__${name}`), ...classes ); + btn.append(text); btn.type = "button"; btn.setAttribute("role", "button"); - btn.setAttribute("aria-label", title || text); + + const ariaLabel = title || ( + text instanceof HTMLElement + ? text.textContent || "" + : text + ); + btn.setAttribute("aria-label", ariaLabel); if (primary) { btn.classList.add("s-btn__filled"); diff --git a/test/button-groups.spec.ts b/test/button-groups.spec.ts new file mode 100644 index 0000000..28b79c1 --- /dev/null +++ b/test/button-groups.spec.ts @@ -0,0 +1,41 @@ +import { expect } from "chai"; +import { appendScript, getSample } from "./index.spec"; +import { makeStacksButtonGroup, GroupButton } from "../src/button-groups"; +import { makeStacksButton } from "../src/buttons"; +import { JSDOM } from "jsdom"; + +describe("Button groups", function() { + const buttonGroups = getSample(this.title.toLowerCase().replace(" ", "-")); + + let window: JSDOM["window"]; + + beforeEach(() => { + window = new JSDOM("", { runScripts: "dangerously" }).window; + appendScript(window, { makeStacksButtonGroup, makeStacksButton, Buttons: "{ makeStacksButton }" }); + }); + + it("should correctly generate button groups", () => { + const group = window.makeStacksButtonGroup as typeof makeStacksButtonGroup; + + ( + [ + [ + { text: "Newest" }, + { text: "Frequent" }, + { text: "Votes", form: true, selected: true }, + { text: "Active" }, + { text: "Unanswered", form: true }, + ], + [ + { text: "Active", count: 197 }, + { text: "Inactive", count: 37, types: [ "dropdown" ], selected: true }, + { text: "All", count: 234 } + ] + ] as GroupButton[][] + ).forEach((data, index) => { + const el = group(data); + + expect(el.outerHTML).to.equal(buttonGroups[index].outerHTML); + }); + }); +}); \ No newline at end of file diff --git a/test/sample/button-groups.html b/test/sample/button-groups.html new file mode 100644 index 0000000..eab0be5 --- /dev/null +++ b/test/sample/button-groups.html @@ -0,0 +1,2 @@ +
+
\ No newline at end of file