├── ROADMAP.md ├── src ├── test.html ├── styles │ ├── pages │ │ └── pages.css │ ├── layout │ │ ├── _main.css │ │ ├── _scroll-spy.css │ │ ├── layout.css │ │ ├── _header.css │ │ ├── _core.css │ │ └── _header-nav.css │ ├── _code.css │ └── index.css ├── why.html ├── index.html ├── how.html ├── components-chips.html ├── components-details.html ├── components-dialog.html ├── components-select.html ├── components-tooltip.html ├── components.html ├── foundations.html ├── getting-started.html ├── getting-started-integrations.html ├── components-tree-view.html ├── getting-started-css-apis.html ├── components-textarea.html ├── getting-started-quick-start.html ├── components-switch.html ├── components-checkbox.html ├── components-accordion.html ├── foundations-elevations.html ├── foundations-typography.html ├── components-input.html ├── components-radio.html ├── common │ ├── breadcrumbs.html │ ├── header.html │ └── docs-nav.html ├── assets │ └── background-image.svg └── _layout.html ├── .nvmrc ├── CNAME ├── .tool-versions ├── packages ├── css │ ├── foundations │ │ ├── NOTES.md │ │ ├── lib │ │ │ ├── helpers │ │ │ │ ├── index.css │ │ │ │ └── _sr-only.css │ │ │ ├── _radiuses.css │ │ │ ├── _elevations.css │ │ │ ├── _focus.css │ │ │ ├── foundations.css │ │ │ ├── _reset.css │ │ │ └── _spacings.css │ │ ├── README.md │ │ └── package.json │ ├── grid-system │ │ ├── NOTES.md │ │ ├── README.md │ │ ├── lib │ │ │ ├── _variables.css │ │ │ ├── _column.css │ │ │ ├── _row.css │ │ │ ├── _container.css │ │ │ ├── grid-system.css │ │ │ └── _container-breakpoints.css │ │ └── package.json │ ├── iconography │ │ ├── NOTES.md │ │ ├── lib │ │ │ ├── iconography.css │ │ │ └── fonts │ │ │ │ └── wcag-icons │ │ │ │ ├── PNG │ │ │ │ ├── copy.png │ │ │ │ ├── exeen.png │ │ │ │ ├── figma.png │ │ │ │ ├── dev-dojo.png │ │ │ │ ├── github.png │ │ │ │ ├── wcag-ui.png │ │ │ │ ├── checkmark.png │ │ │ │ ├── chevron-up.png │ │ │ │ ├── linked-in.png │ │ │ │ ├── chevron-down.png │ │ │ │ ├── chevron-left.png │ │ │ │ ├── chevron-right.png │ │ │ │ ├── scheme-dark.png │ │ │ │ ├── scheme-light.png │ │ │ │ └── scheme-system.png │ │ │ │ ├── fonts │ │ │ │ ├── wcag-icons.ttf │ │ │ │ └── wcag-icons.woff │ │ │ │ ├── SVG │ │ │ │ ├── chevron-up.svg │ │ │ │ ├── chevron-down.svg │ │ │ │ ├── chevron-left.svg │ │ │ │ ├── chevron-right.svg │ │ │ │ ├── checkmark.svg │ │ │ │ ├── scheme-dark.svg │ │ │ │ ├── scheme-system.svg │ │ │ │ ├── copy.svg │ │ │ │ ├── linked-in.svg │ │ │ │ ├── scheme-light.svg │ │ │ │ ├── github.svg │ │ │ │ ├── dev-dojo.svg │ │ │ │ └── figma.svg │ │ │ │ ├── Read Me.txt │ │ │ │ └── demo-files │ │ │ │ └── demo.js │ │ ├── README.md │ │ └── package.json │ └── typography │ │ ├── lib │ │ ├── fonts │ │ │ ├── fonts.css │ │ │ └── inter │ │ │ │ ├── Inter.woff2 │ │ │ │ ├── Inter-Italic.woff2 │ │ │ │ └── style.css │ │ └── typography.css │ │ ├── README.md │ │ └── package.json ├── components │ ├── dialog │ │ ├── lib │ │ │ ├── styles │ │ │ │ └── dialog.css │ │ │ ├── dialog.events.js │ │ │ ├── dialog.attributes.js │ │ │ └── dialog.js │ │ ├── README.md │ │ └── __tests__ │ │ │ └── dialog.test.js │ ├── input │ │ ├── lib │ │ │ ├── styles │ │ │ │ ├── variants │ │ │ │ │ └── variants.css │ │ │ │ ├── modifiers │ │ │ │ │ └── modifiers.css │ │ │ │ ├── dimensions │ │ │ │ │ ├── dimensions.css │ │ │ │ │ ├── _medium.css │ │ │ │ │ ├── _large.css │ │ │ │ │ └── _small.css │ │ │ │ ├── states │ │ │ │ │ ├── states.css │ │ │ │ │ ├── _hover.css │ │ │ │ │ ├── _active.css │ │ │ │ │ ├── _focus.css │ │ │ │ │ └── _disabled.css │ │ │ │ └── input.css │ │ │ ├── input.attributes.js │ │ │ ├── input.events.js │ │ │ └── input.js │ │ ├── README.md │ │ ├── __tests__ │ │ │ └── input.test.js │ │ └── package.json │ ├── radio │ │ ├── lib │ │ │ ├── styles │ │ │ │ ├── variants │ │ │ │ │ └── variants.css │ │ │ │ ├── modifiers │ │ │ │ │ └── modifiers.css │ │ │ │ ├── dimensions │ │ │ │ │ ├── dimensions.css │ │ │ │ │ ├── _medium.css │ │ │ │ │ ├── _large.css │ │ │ │ │ └── _small.css │ │ │ │ ├── states │ │ │ │ │ ├── states.css │ │ │ │ │ ├── _hover.css │ │ │ │ │ ├── _active.css │ │ │ │ │ ├── _focus.css │ │ │ │ │ └── _disabled.css │ │ │ │ └── radio.css │ │ │ ├── radio.attributes.js │ │ │ ├── radio.events.js │ │ │ └── radio.js │ │ ├── README.md │ │ ├── __tests__ │ │ │ └── radio.test.js │ │ └── package.json │ ├── checkbox │ │ ├── lib │ │ │ ├── styles │ │ │ │ ├── modifiers │ │ │ │ │ └── modifiers.css │ │ │ │ ├── variants │ │ │ │ │ └── variants.css │ │ │ │ ├── dimensions │ │ │ │ │ ├── dimensions.css │ │ │ │ │ ├── _medium.css │ │ │ │ │ ├── _large.css │ │ │ │ │ └── _small.css │ │ │ │ ├── states │ │ │ │ │ ├── states.css │ │ │ │ │ ├── _hover.css │ │ │ │ │ ├── _active.css │ │ │ │ │ ├── _focus.css │ │ │ │ │ └── _disabled.css │ │ │ │ └── checkbox.css │ │ │ ├── checkbox.attributes.js │ │ │ ├── checkbox.events.js │ │ │ └── checkbox.js │ │ ├── README.md │ │ └── __tests__ │ │ │ └── checkbox.test.js │ ├── switch │ │ ├── lib │ │ │ ├── styles │ │ │ │ ├── modifiers │ │ │ │ │ └── modifiers.css │ │ │ │ ├── variants │ │ │ │ │ └── variants.css │ │ │ │ ├── dimensions │ │ │ │ │ ├── dimensions.css │ │ │ │ │ ├── _medium.css │ │ │ │ │ ├── _large.css │ │ │ │ │ └── _small.css │ │ │ │ ├── states │ │ │ │ │ ├── states.css │ │ │ │ │ ├── _hover.css │ │ │ │ │ ├── _active.css │ │ │ │ │ ├── _focus.css │ │ │ │ │ └── _disabled.css │ │ │ │ └── switch.css │ │ │ ├── switch.attributes.js │ │ │ ├── switch.events.js │ │ │ └── switch.js │ │ ├── README.md │ │ └── __tests__ │ │ │ └── switch.test.js │ ├── textarea │ │ ├── lib │ │ │ ├── styles │ │ │ │ ├── modifiers │ │ │ │ │ └── modifiers.css │ │ │ │ ├── variants │ │ │ │ │ └── variants.css │ │ │ │ ├── dimensions │ │ │ │ │ ├── dimensions.css │ │ │ │ │ ├── _medium.css │ │ │ │ │ ├── _large.css │ │ │ │ │ └── _small.css │ │ │ │ ├── states │ │ │ │ │ ├── states.css │ │ │ │ │ ├── _hover.css │ │ │ │ │ ├── _active.css │ │ │ │ │ ├── _focus.css │ │ │ │ │ └── _disabled.css │ │ │ │ └── textarea.css │ │ │ ├── textarea.attributes.js │ │ │ ├── textarea.events.js │ │ │ └── textarea.js │ │ ├── README.md │ │ └── __tests__ │ │ │ └── textarea.test.js │ ├── details │ │ ├── lib │ │ │ ├── details.events.js │ │ │ ├── styles │ │ │ │ ├── details.css │ │ │ │ └── _core.css │ │ │ └── details.attributes.js │ │ ├── README.md │ │ └── __tests__ │ │ │ └── details.test.js │ ├── select │ │ ├── lib │ │ │ ├── select.events.js │ │ │ ├── select.attributes.js │ │ │ ├── styles │ │ │ │ └── select.css │ │ │ └── select.js │ │ ├── README.md │ │ ├── __tests__ │ │ │ └── select.test.js │ │ └── package.json │ ├── tooltip │ │ ├── lib │ │ │ ├── tooltip.events.js │ │ │ ├── tooltip.attributes.js │ │ │ ├── styles │ │ │ │ └── tooltip.css │ │ │ └── tooltip.js │ │ ├── README.md │ │ ├── __tests__ │ │ │ └── tooltip.test.js │ │ └── package.json │ ├── accordion │ │ ├── lib │ │ │ ├── styles │ │ │ │ ├── accordion.css │ │ │ │ └── _core.css │ │ │ ├── accordion.attributes.js │ │ │ ├── accordion.events.js │ │ │ └── accordion.js │ │ └── __tests__ │ │ │ └── accordion.test.js │ ├── tree-view │ │ ├── lib │ │ │ ├── styles │ │ │ │ ├── tree-view.css │ │ │ │ └── _core.css │ │ │ ├── tree-view.events.js │ │ │ ├── tree-view.attributes.js │ │ │ └── tree-view.js │ │ ├── __tests__ │ │ │ └── tree-view.test.js │ │ └── README.md │ ├── scroll-spy │ │ ├── lib │ │ │ ├── styles │ │ │ │ ├── scroll-spy.css │ │ │ │ └── _core.css │ │ │ ├── scroll-spy.attributes.js │ │ │ └── scroll-spy.events.js │ │ ├── README.md │ │ ├── __tests__ │ │ │ └── scroll-spy.test.js │ │ └── package.json │ └── button │ │ ├── lib │ │ ├── styles │ │ │ ├── modifiers │ │ │ │ ├── modifiers.css │ │ │ │ ├── _square.css │ │ │ │ └── _circle.css │ │ │ ├── dimensions │ │ │ │ ├── dimensions.css │ │ │ │ ├── _medium.css │ │ │ │ ├── _large.css │ │ │ │ └── _small.css │ │ │ ├── states │ │ │ │ ├── states.css │ │ │ │ ├── _hover.css │ │ │ │ ├── _active.css │ │ │ │ ├── _focus.css │ │ │ │ └── _disabled.css │ │ │ ├── variants │ │ │ │ └── variants.css │ │ │ ├── button.css │ │ │ └── _core.css │ │ ├── button.attributes.js │ │ ├── button.events.js │ │ └── button.js │ │ ├── README.md │ │ ├── __tests__ │ │ └── button.test.js │ │ └── package.json └── js │ ├── core │ ├── lib │ │ ├── polyfills │ │ │ └── index.js │ │ ├── storage │ │ │ └── index.js │ │ ├── encoding │ │ │ ├── index.js │ │ │ └── _jwt.js │ │ ├── _error.js │ │ ├── events │ │ │ ├── index.js │ │ │ ├── _dispatchComponentEvent.js │ │ │ ├── _cancelEvent.js │ │ │ └── _dispatchCustomEvent.js │ │ ├── helpers │ │ │ ├── index.js │ │ │ ├── _debounce.js │ │ │ ├── _throttle.js │ │ │ └── _files.js │ │ ├── decorator │ │ │ ├── _buildExtendOptions.js │ │ │ ├── _generateIsAttribute.js │ │ │ ├── _exposeComponent.js │ │ │ ├── _assertMetaKey.js │ │ │ ├── _defineCustomElement.js │ │ │ ├── index.js │ │ │ └── _applyMixins.js │ │ └── core.js │ ├── README.md │ ├── __tests__ │ │ └── core.test.js │ └── package.json │ └── dom │ ├── README.md │ ├── __tests__ │ └── dom.test.js │ ├── lib │ ├── _containsHTML.js │ ├── _createFragment.js │ ├── _findNodes.js │ ├── _outerHTML.js │ ├── _ensureElement.js │ ├── _createElement.js │ ├── _insertElement.js │ ├── _wrapElement.js │ ├── _insertHTML.js │ └── dom.js │ └── package.json ├── .husky ├── pre-commit └── pre-push ├── .npmrc ├── scripts ├── templates │ └── component │ │ ├── lib │ │ ├── styles │ │ │ ├── component-name.css │ │ │ └── _core.css │ │ ├── component-name.events.js │ │ ├── component-name.attributes.js │ │ └── component-name.js │ │ ├── __tests__ │ │ └── component-name.test.js │ │ └── README.md ├── _cli-utils.mjs ├── unpublish.mjs └── _template-utils.mjs ├── .posthtmlrc ├── pnpm-workspace.yaml ├── .vscode ├── launch.json └── settings.json ├── .prettierrc ├── jsconfig.json ├── commitlint.config.js ├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── coding-styleguides │ └── a11y.md └── workflows │ └── static.yml ├── LICENSE └── docs └── GETTING-STARTED.md /ROADMAP.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/* 2 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | wcag-ui.com 2 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | nodejs 22.17.1 2 | -------------------------------------------------------------------------------- /packages/css/foundations/NOTES.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/css/grid-system/NOTES.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/css/iconography/NOTES.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | pnpm commitlint 2 | -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | pnpm commitlint 2 | -------------------------------------------------------------------------------- /packages/components/dialog/lib/styles/dialog.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | @wcag-ui:registry=http://localhost:4873/ 2 | -------------------------------------------------------------------------------- /packages/components/input/lib/styles/variants/variants.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/components/radio/lib/styles/variants/variants.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/styles/modifiers/modifiers.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/styles/variants/variants.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/components/input/lib/styles/modifiers/modifiers.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/components/radio/lib/styles/modifiers/modifiers.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/components/switch/lib/styles/modifiers/modifiers.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/components/switch/lib/styles/variants/variants.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/styles/modifiers/modifiers.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/styles/variants/variants.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/components/details/lib/details.events.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/components/select/lib/select.events.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/components/tooltip/lib/tooltip.events.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/js/core/lib/polyfills/index.js: -------------------------------------------------------------------------------- 1 | import './_customElements'; 2 | -------------------------------------------------------------------------------- /packages/components/select/lib/select.attributes.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/components/tooltip/lib/tooltip.attributes.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/css/typography/lib/fonts/fonts.css: -------------------------------------------------------------------------------- 1 | @import './inter/style.css' layer(inter); 2 | -------------------------------------------------------------------------------- /src/styles/pages/pages.css: -------------------------------------------------------------------------------- 1 | @import "./_foundations-colors.css" layer(foundations.colors); 2 | -------------------------------------------------------------------------------- /packages/components/tooltip/lib/styles/tooltip.css: -------------------------------------------------------------------------------- 1 | /* @layer wcag-ui.components.tooltip { 2 | } */ 3 | -------------------------------------------------------------------------------- /src/styles/layout/_main.css: -------------------------------------------------------------------------------- 1 | main { 2 | grid-area: main; 3 | 4 | padding-block: 8rem; 5 | } 6 | -------------------------------------------------------------------------------- /packages/components/details/lib/styles/details.css: -------------------------------------------------------------------------------- 1 | @import "./_core.css" layer(wcag-ui.components.details); 2 | -------------------------------------------------------------------------------- /packages/components/accordion/lib/styles/accordion.css: -------------------------------------------------------------------------------- 1 | @import "./_core.css" layer(wcag-ui.components.accordion); 2 | -------------------------------------------------------------------------------- /packages/components/tree-view/lib/styles/tree-view.css: -------------------------------------------------------------------------------- 1 | @import "./_core.css" layer(wcag-ui.components.tree-view); 2 | -------------------------------------------------------------------------------- /packages/components/scroll-spy/lib/styles/scroll-spy.css: -------------------------------------------------------------------------------- 1 | @import "./_core.css" layer(wcag-ui.components.scroll-spy); 2 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/iconography.css: -------------------------------------------------------------------------------- 1 | @import "./fonts/wcag-icons/style.css" layer(wcag-ui.foundations.iconography); 2 | -------------------------------------------------------------------------------- /scripts/templates/component/lib/styles/component-name.css: -------------------------------------------------------------------------------- 1 | @import "./_core.css" layer(wcag-ui.components.component-name); 2 | -------------------------------------------------------------------------------- /packages/css/foundations/lib/helpers/index.css: -------------------------------------------------------------------------------- 1 | @import "./_flex.css" layer(flex); 2 | @import "./_sr-only.css" layer(sr-only); 3 | -------------------------------------------------------------------------------- /packages/components/accordion/lib/accordion.attributes.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: function () { 3 | this.update(); 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /packages/css/typography/lib/fonts/inter/Inter.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/typography/lib/fonts/inter/Inter.woff2 -------------------------------------------------------------------------------- /packages/components/tree-view/lib/styles/_core.css: -------------------------------------------------------------------------------- 1 | /** biome-ignore-all lint/suspicious/noEmptyBlock: */ 2 | [is="wcag-tree-view"] { 3 | } 4 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/modifiers/modifiers.css: -------------------------------------------------------------------------------- 1 | @import "./_square.css" layer(modifiers.square); 2 | @import "./_circle.css" layer(modifiers.circle); 3 | -------------------------------------------------------------------------------- /scripts/templates/component/lib/styles/_core.css: -------------------------------------------------------------------------------- 1 | /** biome-ignore-all lint/suspicious/noEmptyBlock: */ 2 | [is="wcag-component-name"] { 3 | } 4 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/copy.png -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/exeen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/exeen.png -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/figma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/figma.png -------------------------------------------------------------------------------- /packages/css/typography/lib/fonts/inter/Inter-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/typography/lib/fonts/inter/Inter-Italic.woff2 -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/dev-dojo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/dev-dojo.png -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/github.png -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/wcag-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/wcag-ui.png -------------------------------------------------------------------------------- /packages/components/select/lib/styles/select.css: -------------------------------------------------------------------------------- 1 | /* biome-ignore lint/suspicious/noEmptyBlock: It could be filled in the future */ 2 | @layer wcag-ui.components.select { 3 | } 4 | -------------------------------------------------------------------------------- /packages/css/foundations/lib/_radiuses.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* TODO: ask design for radiuses tokens */ 3 | --wcag-r--s: 4px; 4 | --wcag-r--m: 6px; 5 | --wcag-r--l: 8px; 6 | } 7 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/checkmark.png -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/chevron-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/chevron-up.png -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/linked-in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/linked-in.png -------------------------------------------------------------------------------- /packages/js/dom/README.md: -------------------------------------------------------------------------------- 1 | # `dom` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const dom = require('dom'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/chevron-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/chevron-down.png -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/chevron-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/chevron-left.png -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/chevron-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/chevron-right.png -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/scheme-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/scheme-dark.png -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/scheme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/scheme-light.png -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/PNG/scheme-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/PNG/scheme-system.png -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/fonts/wcag-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/fonts/wcag-icons.ttf -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/fonts/wcag-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devdojo-it/wcag-ui/HEAD/packages/css/iconography/lib/fonts/wcag-icons/fonts/wcag-icons.woff -------------------------------------------------------------------------------- /packages/css/typography/lib/typography.css: -------------------------------------------------------------------------------- 1 | @import "./fonts/fonts.css" layer(wcag-ui.foundations.typography.fonts); 2 | @import "./_core.css" layer(wcag-ui.foundations.typography); 3 | -------------------------------------------------------------------------------- /packages/js/core/README.md: -------------------------------------------------------------------------------- 1 | # `core` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const core = require('core'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/components/button/README.md: -------------------------------------------------------------------------------- 1 | # `button` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const button = require('button'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/components/dialog/README.md: -------------------------------------------------------------------------------- 1 | # `dialog` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const dialog = require('dialog'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/components/input/README.md: -------------------------------------------------------------------------------- 1 | # `input` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const input = require('input'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/components/radio/README.md: -------------------------------------------------------------------------------- 1 | # `radio` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const radio = require('radio'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/components/select/README.md: -------------------------------------------------------------------------------- 1 | # `select` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const select = require('select'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/components/details/README.md: -------------------------------------------------------------------------------- 1 | # `details` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const details = require('details'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/components/tooltip/README.md: -------------------------------------------------------------------------------- 1 | # `tooltip` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const tooltip = require('tooltip'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/components/tree-view/lib/tree-view.events.js: -------------------------------------------------------------------------------- 1 | /** biome-ignore-all lint/correctness/noUnusedImports: */ 2 | import { events } from '@wcag-ui/core'; 3 | 4 | export default {}; 5 | -------------------------------------------------------------------------------- /packages/components/checkbox/README.md: -------------------------------------------------------------------------------- 1 | # `checkbox` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const checkbox = require('checkbox'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/components/switch/README.md: -------------------------------------------------------------------------------- 1 | # `checkbox` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const checkbox = require('checkbox'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/components/textarea/README.md: -------------------------------------------------------------------------------- 1 | # `textarea` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const textarea = require('textarea'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/components/tree-view/lib/tree-view.attributes.js: -------------------------------------------------------------------------------- 1 | /** biome-ignore-all lint/correctness/noUnusedImports: */ 2 | import { events } from '@wcag-ui/core'; 3 | 4 | export default {}; 5 | -------------------------------------------------------------------------------- /packages/css/foundations/README.md: -------------------------------------------------------------------------------- 1 | # `typography` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const typography = require('typography'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/css/grid-system/README.md: -------------------------------------------------------------------------------- 1 | # `typography` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const typography = require('typography'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/css/typography/README.md: -------------------------------------------------------------------------------- 1 | # `typography` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const typography = require('typography'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /scripts/templates/component/lib/component-name.events.js: -------------------------------------------------------------------------------- 1 | /** biome-ignore-all lint/correctness/noUnusedImports: */ 2 | import { events } from '@wcag-ui/core'; 3 | 4 | export default {}; 5 | -------------------------------------------------------------------------------- /src/why.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/components/button/lib/button.attributes.js: -------------------------------------------------------------------------------- 1 | export default { 2 | disabled: function (oldValue, newValue) { 3 | console.log('disabled changed', oldValue, newValue, this.textContent); 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /packages/components/scroll-spy/README.md: -------------------------------------------------------------------------------- 1 | # `scroll-spy` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const scrollSpy = require('scroll-spy'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/css/iconography/README.md: -------------------------------------------------------------------------------- 1 | # `iconography` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const iconography = require('iconography'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /scripts/templates/component/lib/component-name.attributes.js: -------------------------------------------------------------------------------- 1 | /** biome-ignore-all lint/correctness/noUnusedImports: */ 2 | import { events } from '@wcag-ui/core'; 3 | 4 | export default {}; 5 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/dimensions/dimensions.css: -------------------------------------------------------------------------------- 1 | @import "./_medium.css" layer(dimensions.medium); 2 | @import "./_small.css" layer(dimensions.small); 3 | @import "./_large.css" layer(dimensions.large); 4 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/styles/dimensions/dimensions.css: -------------------------------------------------------------------------------- 1 | @import "./_medium.css" layer(dimensions.medium); 2 | @import "./_small.css" layer(dimensions.small); 3 | @import "./_large.css" layer(dimensions.large); 4 | -------------------------------------------------------------------------------- /packages/components/input/lib/styles/dimensions/dimensions.css: -------------------------------------------------------------------------------- 1 | @import "./_medium.css" layer(dimensions.medium); 2 | @import "./_small.css" layer(dimensions.small); 3 | @import "./_large.css" layer(dimensions.large); 4 | -------------------------------------------------------------------------------- /packages/components/radio/lib/styles/dimensions/dimensions.css: -------------------------------------------------------------------------------- 1 | @import "./_medium.css" layer(dimensions.medium); 2 | @import "./_small.css" layer(dimensions.small); 3 | @import "./_large.css" layer(dimensions.large); 4 | -------------------------------------------------------------------------------- /packages/components/scroll-spy/lib/scroll-spy.attributes.js: -------------------------------------------------------------------------------- 1 | export default { 2 | target: (_oldValue, _newValue) => { 3 | // console.log("disabled changed", oldValue, newValue, this.textContent); 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /packages/components/switch/lib/styles/dimensions/dimensions.css: -------------------------------------------------------------------------------- 1 | @import "./_medium.css" layer(dimensions.medium); 2 | @import "./_small.css" layer(dimensions.small); 3 | @import "./_large.css" layer(dimensions.large); 4 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/styles/dimensions/dimensions.css: -------------------------------------------------------------------------------- 1 | @import "./_medium.css" layer(dimensions.medium); 2 | @import "./_small.css" layer(dimensions.small); 3 | @import "./_large.css" layer(dimensions.large); 4 | -------------------------------------------------------------------------------- /src/how.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.posthtmlrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": { 3 | "posthtml-extend": { 4 | "root": "./src" 5 | }, 6 | "posthtml-include": { 7 | "root": "./src" 8 | }, 9 | "posthtml-markdownit": {} 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/css/grid-system/lib/_variables.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-gs--container--size: 100vw; 3 | --wcag-gs--container--gap: 1.5rem; 4 | --wcag-gs--cols: 12; 5 | --wcag-gs--gap: 1.5rem; 6 | --wcag-gs--v-gap: 1.5rem; 7 | } 8 | -------------------------------------------------------------------------------- /packages/js/dom/__tests__/dom.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const dom = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(dom(), 'Hello from dom'); 7 | console.info('dom tests passed'); 8 | -------------------------------------------------------------------------------- /packages/css/grid-system/lib/_column.css: -------------------------------------------------------------------------------- 1 | :where(col, [col]) { 2 | display: flex; 3 | flex-flow: column nowrap; 4 | grid-column: auto / span var(--wcag-gs--cols); 5 | 6 | max-inline-size: var(--wcag-gs--container--size); 7 | } 8 | -------------------------------------------------------------------------------- /packages/js/core/lib/storage/index.js: -------------------------------------------------------------------------------- 1 | import { CookieStorage } from "./_cookieStorage"; 2 | 3 | /** 4 | * Storage utilities bundle. 5 | */ 6 | const storage = { 7 | CookieStorage, 8 | }; 9 | 10 | export { storage }; 11 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - packages/**/* 3 | 4 | onlyBuiltDependencies: 5 | - '@parcel/watcher' 6 | - '@swc/core' 7 | - esbuild 8 | - lightningcss-cli 9 | - lmdb 10 | - msgpackr-extract 11 | - sharp 12 | -------------------------------------------------------------------------------- /packages/js/core/__tests__/core.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const core = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(core(), 'Hello from core'); 7 | console.info('core tests passed'); 8 | -------------------------------------------------------------------------------- /packages/js/dom/lib/_containsHTML.js: -------------------------------------------------------------------------------- 1 | /** 2 | * returns true if the provided string contains HTML tags 3 | * 4 | * @param {string} str 5 | * @return {boolean} 6 | */ 7 | export const containsHTML = (str) => /<[a-z][\s\S]*>/i.test(str); 8 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/modifiers/_square.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-button--m-square--aspect-ratio: 1; 3 | } 4 | 5 | [is="wcag-button"][square] { 6 | --wcag-button--aspect-ratio: var(--wcag-button--m-square--aspect-ratio); 7 | } 8 | -------------------------------------------------------------------------------- /packages/components/input/__tests__/input.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const input = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(input(), 'Hello from input'); 7 | console.info('input tests passed'); 8 | -------------------------------------------------------------------------------- /packages/components/radio/__tests__/radio.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const radio = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(radio(), 'Hello from radio'); 7 | console.info('radio tests passed'); 8 | -------------------------------------------------------------------------------- /packages/components/switch/__tests__/switch.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const sw = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(sw(), 'Hello from switch'); 7 | console.info('switch tests passed'); 8 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/states/states.css: -------------------------------------------------------------------------------- 1 | @import "./_hover.css" layer(states.hover); 2 | @import "./_active.css" layer(states.active); 3 | @import "./_focus.css" layer(states.focus); 4 | @import "./_disabled.css" layer(states.disabled); 5 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/styles/states/states.css: -------------------------------------------------------------------------------- 1 | @import "./_hover.css" layer(states.hover); 2 | @import "./_active.css" layer(states.active); 3 | @import "./_focus.css" layer(states.focus); 4 | @import "./_disabled.css" layer(states.disabled); 5 | -------------------------------------------------------------------------------- /packages/components/input/lib/styles/states/states.css: -------------------------------------------------------------------------------- 1 | @import "./_hover.css" layer(states.hover); 2 | @import "./_active.css" layer(states.active); 3 | @import "./_focus.css" layer(states.focus); 4 | @import "./_disabled.css" layer(states.disabled); 5 | -------------------------------------------------------------------------------- /packages/components/radio/lib/styles/states/states.css: -------------------------------------------------------------------------------- 1 | @import "./_hover.css" layer(states.hover); 2 | @import "./_active.css" layer(states.active); 3 | @import "./_focus.css" layer(states.focus); 4 | @import "./_disabled.css" layer(states.disabled); 5 | -------------------------------------------------------------------------------- /packages/components/switch/lib/styles/states/states.css: -------------------------------------------------------------------------------- 1 | @import "./_hover.css" layer(states.hover); 2 | @import "./_active.css" layer(states.active); 3 | @import "./_focus.css" layer(states.focus); 4 | @import "./_disabled.css" layer(states.disabled); 5 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/styles/states/states.css: -------------------------------------------------------------------------------- 1 | @import "./_hover.css" layer(states.hover); 2 | @import "./_active.css" layer(states.active); 3 | @import "./_focus.css" layer(states.focus); 4 | @import "./_disabled.css" layer(states.disabled); 5 | -------------------------------------------------------------------------------- /packages/components/button/__tests__/button.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const button = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(button(), 'Hello from button'); 7 | console.info('button tests passed'); 8 | -------------------------------------------------------------------------------- /packages/components/button/lib/button.events.js: -------------------------------------------------------------------------------- 1 | export default { 2 | click: function (e) { 3 | console.log('button clicked', this.textContent); 4 | }, 5 | focus: function (e) { 6 | console.log('button focused', this.textContent); 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /packages/components/dialog/__tests__/dialog.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const dialog = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(dialog(), 'Hello from dialog'); 7 | console.info('dialog tests passed'); 8 | -------------------------------------------------------------------------------- /packages/components/select/__tests__/select.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const select = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(select(), 'Hello from select'); 7 | console.info('select tests passed'); 8 | -------------------------------------------------------------------------------- /packages/css/foundations/lib/_elevations.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-e--sm: 0 0.2rem 2rem 0 hsla(248, 28%, 55%, 0.08); 3 | --wcag-e--md: 0 0.4rem 4rem -0.2rem hsla(248, 28%, 55%, 0.1); 4 | --wcag-e--lg: 0 1.8rem 6rem 0.2rem hsla(248, 28%, 55%, 0.1); 5 | } 6 | -------------------------------------------------------------------------------- /src/styles/_code.css: -------------------------------------------------------------------------------- 1 | /* @import 'npm:highlight.js/styles/tomorrow-night-blue.min.css'; */ 2 | @import 'npm:highlight.js/styles/a11y-dark.min.css'; 3 | 4 | .hljs { 5 | background-color: hsl(247, 69%, 14%); 6 | border: 1px solid hsl(245, 93%, 28%); 7 | } 8 | -------------------------------------------------------------------------------- /packages/components/tooltip/__tests__/tooltip.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const tooltip = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(tooltip(), 'Hello from tooltip'); 7 | console.info('tooltip tests passed'); 8 | -------------------------------------------------------------------------------- /packages/components/checkbox/__tests__/checkbox.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const checkbox = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(checkbox(), 'Hello from checkbox'); 7 | console.info('checkbox tests passed'); 8 | -------------------------------------------------------------------------------- /packages/components/textarea/__tests__/textarea.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const textarea = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(textarea(), 'Hello from textarea'); 7 | console.info('textarea tests passed'); 8 | -------------------------------------------------------------------------------- /packages/components/tree-view/__tests__/tree-view.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const treeView = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(treeView(), 'Hello from treeView'); 7 | console.info('treeView tests passed'); 8 | -------------------------------------------------------------------------------- /packages/components/accordion/__tests__/accordion.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const accordion = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(accordion(), 'Hello from accordion'); 7 | console.info('accordion tests passed'); 8 | -------------------------------------------------------------------------------- /packages/components/details/__tests__/details.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const details = require('../lib/details'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(details(), 'Hello from details'); 7 | console.info('details tests passed'); 8 | -------------------------------------------------------------------------------- /src/components-chips.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Details Docs Example

7 |
8 |
9 | -------------------------------------------------------------------------------- /src/components-details.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Details Docs Example

7 |
8 |
9 | -------------------------------------------------------------------------------- /src/components-dialog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Details Docs Example

7 |
8 |
9 | -------------------------------------------------------------------------------- /src/components-select.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Details Docs Example

7 |
8 |
9 | -------------------------------------------------------------------------------- /src/components-tooltip.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Details Docs Example

7 |
8 |
9 | -------------------------------------------------------------------------------- /src/components.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/components/scroll-spy/__tests__/scroll-spy.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const scrollSpy = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(scrollSpy(), 'Hello from scrollSpy'); 7 | console.info('scrollSpy tests passed'); 8 | -------------------------------------------------------------------------------- /src/foundations.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/variants/variants.css: -------------------------------------------------------------------------------- 1 | @import "./_primary.css" layer(variants.primary); 2 | @import "./_secondary.css" layer(variants.secondary); 3 | @import "./_tertiary.css" layer(variants.tertiary); 4 | @import "./_destructive.css" layer(variants.destructive); 5 | -------------------------------------------------------------------------------- /packages/components/dialog/lib/dialog.events.js: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | // click: function (e) { 4 | // console.log("button clicked", this.textContent); 5 | // }, 6 | // focus: function (e) { 7 | // console.log("button focused", this.textContent); 8 | // }, 9 | }; 10 | -------------------------------------------------------------------------------- /scripts/templates/component/__tests__/component-name.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const componentName = require('..'); 4 | const assert = require('node:assert').strict; 5 | 6 | assert.strictEqual(componentName(), 'Hello from componentName'); 7 | console.info('componentName tests passed'); 8 | -------------------------------------------------------------------------------- /src/getting-started.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/css/foundations/lib/helpers/_sr-only.css: -------------------------------------------------------------------------------- 1 | [sr-only] { 2 | position: absolute; 3 | 4 | width: 1px; 5 | height: 1px; 6 | padding: 0; 7 | border: 0; 8 | margin: -1px; 9 | 10 | overflow: hidden; 11 | white-space: nowrap; 12 | 13 | clip: rect(0, 0, 0, 0); 14 | } 15 | -------------------------------------------------------------------------------- /packages/components/scroll-spy/lib/scroll-spy.events.js: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | // click: function (e) { 4 | // console.log("button clicked", this.textContent); 5 | // }, 6 | // focus: function (e) { 7 | // console.log("button focused", this.textContent); 8 | // }, 9 | }; 10 | -------------------------------------------------------------------------------- /packages/js/core/lib/encoding/index.js: -------------------------------------------------------------------------------- 1 | import { base64 } from "./_base64"; 2 | import { jwt } from "./_jwt"; 3 | import { md5 } from "./_md5"; 4 | 5 | /** 6 | * Encoding utilities bundle. 7 | */ 8 | const encoding = { 9 | base64, 10 | jwt, 11 | md5, 12 | }; 13 | 14 | export { encoding }; 15 | -------------------------------------------------------------------------------- /src/styles/layout/_scroll-spy.css: -------------------------------------------------------------------------------- 1 | body > aside[scroll-spy] { 2 | grid-area: scroll-spy; 3 | 4 | [is="wcag-scroll-spy"] { 5 | position: sticky; 6 | inset-block-start: calc(var(--docs--header--min-height) + 3rem); 7 | 8 | inline-size: 19.3rem; 9 | margin: 0 auto 0 2rem; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/components/tree-view/README.md: -------------------------------------------------------------------------------- 1 | # `TreeView` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const treeView = require('@wcag-ui/tree-view'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | 13 | ## HTML before 14 | 15 | ```html 16 | ``` 17 | 18 | ## HTML after 19 | 20 | ```html 21 | ``` 22 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/chevron-up.svg: -------------------------------------------------------------------------------- 1 | 2 | chevron-up 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/chevron-down.svg: -------------------------------------------------------------------------------- 1 | 2 | chevron-down 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/chevron-left.svg: -------------------------------------------------------------------------------- 1 | 2 | chevron-left 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 2 | chevron-right 3 | 4 | 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Usare IntelliSense per informazioni sui possibili attributi. 3 | // Al passaggio del mouse vengono visualizzate le descrizioni degli attributi esistenti. 4 | // Per altre informazioni, visitare: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [] 7 | } 8 | -------------------------------------------------------------------------------- /scripts/templates/component/README.md: -------------------------------------------------------------------------------- 1 | # `ComponentName` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const componentName = require('@wcag-ui/component-name'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | 13 | ## HTML before 14 | 15 | ```html 16 | ``` 17 | 18 | ## HTML after 19 | 20 | ```html 21 | ``` 22 | -------------------------------------------------------------------------------- /src/getting-started-integrations.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/checkmark.svg: -------------------------------------------------------------------------------- 1 | 2 | checkmark 3 | 4 | 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "htmlWhitespaceSensitivity": "ignore", 6 | "proseWrap": "never", 7 | "bracketSameLine": true, 8 | "overrides": [ 9 | { 10 | "files": ["*.js"], 11 | "options": { 12 | "singleQuote": true 13 | } 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "moduleResolution": "Bundler", 5 | "target": "ES2022", 6 | "jsx": "react", 7 | "allowImportingTsExtensions": true, 8 | "checkJs": true, 9 | "strictNullChecks": true, 10 | "strictFunctionTypes": true 11 | }, 12 | "exclude": ["node_modules", "**/node_modules/*"] 13 | } 14 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/modifiers/_circle.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-button--m-circle--aspect-ratio: 1; 3 | --wcag-button--m-circle--border-radius: 50%; 4 | } 5 | 6 | [is="wcag-button"][circle] { 7 | --wcag-button--aspect-ratio: var(--wcag-button--m-circle--aspect-ratio); 8 | --wcag-button--border-radius: var(--wcag-button--m-circle--border-radius); 9 | } 10 | -------------------------------------------------------------------------------- /packages/components/details/lib/details.attributes.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | open: function (_oldValue, newValue) { 5 | const state = newValue === null ? 'close' : 'open'; 6 | this.setAttribute('aria-expanded', state === 'open'); 7 | 8 | events.dispatchComponentEvent.call(this, 'toggle', { state }); 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/components/input/lib/styles/input.css: -------------------------------------------------------------------------------- 1 | @import "./_core.css" layer(wcag-ui.components.input); 2 | @import "./variants/variants.css" layer(wcag-ui.components.input); 3 | @import "./dimensions/dimensions.css" layer(wcag-ui.components.input); 4 | @import "./modifiers/modifiers.css" layer(wcag-ui.components.input); 5 | @import "./states/states.css" layer(wcag-ui.components.input); 6 | -------------------------------------------------------------------------------- /packages/components/radio/lib/styles/radio.css: -------------------------------------------------------------------------------- 1 | @import "./_core.css" layer(wcag-ui.components.radio); 2 | @import "./variants/variants.css" layer(wcag-ui.components.radio); 3 | @import "./dimensions/dimensions.css" layer(wcag-ui.components.radio); 4 | @import "./modifiers/modifiers.css" layer(wcag-ui.components.radio); 5 | @import "./states/states.css" layer(wcag-ui.components.radio); 6 | -------------------------------------------------------------------------------- /packages/components/accordion/lib/accordion.events.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | 'wcag-details.toggle': function (_e) { 5 | // NOTE: this works only with
6 | // because native element doesn't bubble the `toggle` event 7 | 8 | events.dispatchComponentEvent.call(this, 'toggle', {}); 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/button.css: -------------------------------------------------------------------------------- 1 | @import "./_core.css" layer(wcag-ui.components.button); 2 | @import "./variants/variants.css" layer(wcag-ui.components.button); 3 | @import "./dimensions/dimensions.css" layer(wcag-ui.components.button); 4 | @import "./modifiers/modifiers.css" layer(wcag-ui.components.button); 5 | @import "./states/states.css" layer(wcag-ui.components.button); 6 | -------------------------------------------------------------------------------- /packages/components/switch/lib/styles/switch.css: -------------------------------------------------------------------------------- 1 | @import "./_core.css" layer(wcag-ui.components.switch); 2 | @import "./variants/variants.css" layer(wcag-ui.components.switch); 3 | @import "./dimensions/dimensions.css" layer(wcag-ui.components.switch); 4 | @import "./modifiers/modifiers.css" layer(wcag-ui.components.switch); 5 | @import "./states/states.css" layer(wcag-ui.components.switch); 6 | -------------------------------------------------------------------------------- /packages/components/dialog/lib/dialog.attributes.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | open: function (_oldValue, newValue) { 5 | const state = newValue === null ? 'close' : 'open'; 6 | this.setAttribute('aria-expanded', (state === 'open').toString()); 7 | 8 | events.dispatchComponentEvent.call(this, 'toggle', { state }); 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/styles/checkbox.css: -------------------------------------------------------------------------------- 1 | @import "./_core.css" layer(wcag-ui.components.checkbox); 2 | @import "./variants/variants.css" layer(wcag-ui.components.checkbox); 3 | @import "./dimensions/dimensions.css" layer(wcag-ui.components.checkbox); 4 | @import "./modifiers/modifiers.css" layer(wcag-ui.components.checkbox); 5 | @import "./states/states.css" layer(wcag-ui.components.checkbox); 6 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/styles/textarea.css: -------------------------------------------------------------------------------- 1 | @import "./_core.css" layer(wcag-ui.components.textarea); 2 | @import "./variants/variants.css" layer(wcag-ui.components.textarea); 3 | @import "./dimensions/dimensions.css" layer(wcag-ui.components.textarea); 4 | @import "./modifiers/modifiers.css" layer(wcag-ui.components.textarea); 5 | @import "./states/states.css" layer(wcag-ui.components.textarea); 6 | -------------------------------------------------------------------------------- /packages/js/core/lib/_error.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Throws a standardized wcag-ui error. 3 | * 4 | * @param {string} componentName - Component name for context (e.g., "Dialog"). 5 | * @param {string} errorMessage - Error message. 6 | * @returns {never} 7 | */ 8 | export const error = (componentName, errorMessage) => { 9 | throw new Error(`wcag-ui.${componentName} error: ${errorMessage}`); 10 | }; 11 | -------------------------------------------------------------------------------- /packages/js/dom/lib/_createFragment.js: -------------------------------------------------------------------------------- 1 | /** 2 | * create an document fragment, appends the specified children to it and returns it 3 | * 4 | * @param {...ChildNode} children to append 5 | * @return {Element} 6 | */ 7 | export const createFragment = (...children) => { 8 | const fragment = document.createDocumentFragment(); 9 | 10 | fragment.append(...children); 11 | 12 | return fragment; 13 | }; 14 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | // TODO Add Scope Enum Here 5 | // 'scope-enum': [2, 'always', ['yourscope', 'yourscope']], 6 | 'type-enum': [ 7 | 2, 8 | 'always', 9 | ['feat', 'fix', 'docs', 'chore', 'style', 'refactor', 'ci', 'test', 'revert', 'perf', 'build', 'rel'], 10 | ], 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /packages/js/core/lib/events/index.js: -------------------------------------------------------------------------------- 1 | import { cancelEvent } from "./_cancelEvent"; 2 | import { dispatchCustomEvent } from "./_dispatchCustomEvent"; 3 | import { dispatchComponentEvent } from "./_dispatchComponentEvent"; 4 | 5 | /** 6 | * Events utilities bundle. 7 | */ 8 | const events = { 9 | cancelEvent, 10 | dispatchCustomEvent, 11 | dispatchComponentEvent, 12 | }; 13 | 14 | export { events }; 15 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/scheme-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | scheme-dark 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components-tree-view.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

TreeView Docs Example

7 |
8 |

TreeView

9 |

10 |

11 |

12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /src/getting-started-css-apis.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |

Getting Started

8 |

CSS APIs

9 |
10 | 11 |
12 |
13 | -------------------------------------------------------------------------------- /src/styles/layout/layout.css: -------------------------------------------------------------------------------- 1 | @import "./_variables.css" layer(variables); 2 | @import "./_core.css" layer(core); 3 | @import "./_header.css" layer(header); 4 | @import "./_header-nav.css" layer(header.nav); 5 | @import "./_color-scheme.css" layer(color-scheme); 6 | @import "./_aside.css" layer(aside); 7 | @import "./_main.css" layer(main); 8 | @import "./_scroll-spy.css" layer(scroll-spy); 9 | @import "./_footer.css" layer(footer); 10 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/scheme-system.svg: -------------------------------------------------------------------------------- 1 | 2 | scheme-system 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components-textarea.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Textarea Docs Example

7 |
8 |

Textarea

9 |

10 | 11 |

12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /src/getting-started-quick-start.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |

Getting Started

8 |

Quick Start

9 |
10 | 11 |
12 |
13 | -------------------------------------------------------------------------------- /packages/js/core/lib/helpers/index.js: -------------------------------------------------------------------------------- 1 | import { debounce } from './_debounce'; 2 | import { throttle } from './_throttle'; 3 | 4 | import { files } from './_files'; 5 | import { strings } from './_strings'; 6 | import { types } from './_types'; 7 | 8 | /** 9 | * General-purpose helpers bundle (debounce/throttle, string utils, types, files). 10 | */ 11 | const helpers = { 12 | debounce, 13 | throttle, 14 | files, 15 | strings, 16 | types, 17 | }; 18 | 19 | export { helpers }; 20 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/checkbox.attributes.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | 'aria-label': function (_oldValue, newValue) { 5 | if (this.label) { 6 | const textContent = this.label.textContent; 7 | 8 | if (textContent !== newValue) { 9 | this.label.childNodes[0].textContent = newValue; 10 | 11 | events.dispatchComponentEvent.call(this, 'aria-label.change', { label: newValue }); 12 | } 13 | } 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | copy 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/components/input/lib/input.attributes.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | 'aria-label': function (oldValue, newValue) { 5 | if (this.label) { 6 | const textContent = this.label.textContent; 7 | 8 | if (textContent !== newValue) { 9 | this.label.childNodes[0].textContent = newValue; 10 | 11 | events.dispatchComponentEvent.call(this, 'aria-label.change', { value: newValue, oldValue }); 12 | } 13 | } 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/components/radio/lib/radio.attributes.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | 'aria-label': function (oldValue, newValue) { 5 | if (this.label) { 6 | const textContent = this.label.textContent; 7 | 8 | if (textContent !== newValue) { 9 | this.label.childNodes[0].textContent = newValue; 10 | 11 | events.dispatchComponentEvent.call(this, 'aria-label.change', { value: newValue, oldValue }); 12 | } 13 | } 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/components/switch/lib/switch.attributes.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | 'aria-label': function (oldValue, newValue) { 5 | if (this.label) { 6 | const textContent = this.label.textContent; 7 | 8 | if (textContent !== newValue) { 9 | this.label.childNodes[0].textContent = newValue; 10 | 11 | events.dispatchComponentEvent.call(this, 'aria-label.change', { value: newValue, oldValue }); 12 | } 13 | } 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/textarea.attributes.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | 'aria-label': function (oldValue, newValue) { 5 | if (this.label) { 6 | const textContent = this.label.textContent; 7 | 8 | if (textContent !== newValue) { 9 | this.label.childNodes[0].textContent = newValue; 10 | 11 | events.dispatchComponentEvent.call(this, 'aria-label.change', { value: newValue, oldValue }); 12 | } 13 | } 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/css/foundations/lib/_focus.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-f--outline-width: 2px; 3 | --wcag-f--outline-style: solid; 4 | --wcag-f--outline-color: hsl(245, 93%, 38%); 5 | --wcag-f--outline-offset: var(--wcag-f--outline-width); 6 | } 7 | 8 | :where(:focus-visible, :has(> [sr-only]):focus-within) { 9 | outline-width: var(--wcag-f--outline-width); 10 | outline-style: var(--wcag-f--outline-style); 11 | outline-color: var(--wcag-f--outline-color); 12 | outline-offset: var(--wcag-f--outline-offset); 13 | } 14 | -------------------------------------------------------------------------------- /packages/components/input/lib/styles/states/_hover.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 3 | --wcag-input--s-hov--color: ; 4 | --wcag-input--s-hov--background-color: ; 5 | */ 6 | --wcag-input--s-hov--border-color: var(--wcag-c--neutral-600); 7 | } 8 | 9 | [is="wcag-input"]:hover { 10 | /* 11 | --wcag-input--color: var(--wcag-input--s-hov--color); 12 | --wcag-input--background-color: var(--wcag-input--s-hov--background-color); 13 | */ 14 | 15 | --wcag-input--border-color: var(--wcag-input--s-hov--border-color); 16 | } 17 | -------------------------------------------------------------------------------- /packages/components/radio/lib/styles/states/_hover.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 3 | --wcag-radio--s-hov--color: ; 4 | --wcag-radio--s-hov--background-color: ; 5 | */ 6 | --wcag-radio--s-hov--border-color: var(--wcag-c--neutral-600); 7 | } 8 | 9 | [is="wcag-radio"]:hover { 10 | /* 11 | --wcag-radio--color: var(--wcag-radio--s-hov--color); 12 | --wcag-radio--background-color: var(--wcag-radio--s-hov--background-color); 13 | */ 14 | 15 | --wcag-radio--border-color: var(--wcag-radio--s-hov--border-color); 16 | } 17 | -------------------------------------------------------------------------------- /packages/css/grid-system/lib/_row.css: -------------------------------------------------------------------------------- 1 | /* biome-ignore lint/correctness/noUnknownTypeSelector: */ 2 | :where(row, [row]) { 3 | display: grid; 4 | grid-template-columns: repeat(var(--wcag-gs--cols), minmax(0, 1fr)); 5 | grid-template-rows: auto; 6 | grid-auto-flow: row; 7 | /* grid-column-gap: 0; */ 8 | gap: var(--wcag-gs--v-gap) var(--wcag-gs--gap); 9 | 10 | inline-size: 100%; 11 | margin: 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/components-switch.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Switch Docs Example

7 |
8 |

Example

9 |

10 | 11 | 12 |

13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /packages/components/tooltip/lib/tooltip.js: -------------------------------------------------------------------------------- 1 | import { componentDecorator } from '@wcag-ui/core'; 2 | 3 | import attributes from './tooltip.attributes'; 4 | import events from './tooltip.events'; 5 | 6 | export class Tooltip extends HTMLElement { 7 | static extendsElement = 'span'; 8 | static attributes = attributes; 9 | static events = events; 10 | 11 | static { 12 | componentDecorator(this); 13 | } 14 | 15 | constructor() { 16 | super(); 17 | 18 | this.#init(); 19 | } 20 | 21 | #init() {} 22 | } 23 | -------------------------------------------------------------------------------- /packages/components/switch/lib/styles/states/_hover.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 3 | --wcag-switch--s-hov--color: ; 4 | --wcag-switch--s-hov--background-color: ; 5 | */ 6 | --wcag-switch--s-hov--border-color: var(--wcag-c--neutral-600); 7 | } 8 | 9 | [is="wcag-switch"]:hover { 10 | /* 11 | --wcag-switch--color: var(--wcag-switch--s-hov--color); 12 | --wcag-switch--background-color: var(--wcag-switch--s-hov--background-color); 13 | */ 14 | 15 | --wcag-switch--border-color: var(--wcag-switch--s-hov--border-color); 16 | } 17 | -------------------------------------------------------------------------------- /src/components-checkbox.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Checkbox Docs Example

7 |
8 |

Example

9 |

10 | 11 | 12 |

13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /packages/css/foundations/lib/foundations.css: -------------------------------------------------------------------------------- 1 | @layer wcag-ui.core, wcag-ui.foundations, wcag-ui.components; 2 | 3 | @import "./_reset.css" layer(wcag-ui.core.reset); 4 | @import "./helpers/index.css" layer(wcag-ui.core.helpers); 5 | @import "./_focus.css" layer(wcag-ui.core.focus); 6 | @import "./_colors.css" layer(wcag-ui.foundations.colors); 7 | @import "./_elevations.css" layer(wcag-ui.foundations.elevations); 8 | @import "./_spacings.css" layer(wcag-ui.foundations.spacings); 9 | @import "./_radiuses.css" layer(wcag-ui.foundations.radiuses); 10 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/styles/states/_hover.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 3 | --wcag-checkbox--s-hov--color: ; 4 | --wcag-checkbox--s-hov--background-color: ; 5 | */ 6 | --wcag-checkbox--s-hov--border-color: var(--wcag-c--neutral-600); 7 | } 8 | 9 | [is="wcag-checkbox"]:hover { 10 | /* 11 | --wcag-checkbox--color: var(--wcag-checkbox--s-hov--color); 12 | --wcag-checkbox--background-color: var(--wcag-checkbox--s-hov--background-color); 13 | */ 14 | 15 | --wcag-checkbox--border-color: var(--wcag-checkbox--s-hov--border-color); 16 | } 17 | -------------------------------------------------------------------------------- /packages/components/input/lib/styles/states/_active.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 3 | --wcag-input--s-act--color: ; 4 | --wcag-input--s-act--background-color: ; 5 | */ 6 | 7 | --wcag-input--s-act--border-color: var(--wcag-c--neutral-600); 8 | } 9 | 10 | [is="wcag-input"]:where(:active, [aria-pressed="true"]) { 11 | /* 12 | --wcag-input--color: var(--wcag-input--s-act--color); 13 | --wcag-input--background-color: var(--wcag-input--s-act--background-color); 14 | */ 15 | --wcag-input--border-color: var(--wcag-input--s-act--border-color); 16 | } 17 | -------------------------------------------------------------------------------- /packages/components/radio/lib/styles/states/_active.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 3 | --wcag-radio--s-act--color: ; 4 | --wcag-radio--s-act--background-color: ; 5 | */ 6 | 7 | --wcag-radio--s-act--border-color: var(--wcag-c--neutral-600); 8 | } 9 | 10 | [is="wcag-radio"]:where(:active, [aria-pressed="true"]) { 11 | /* 12 | --wcag-radio--color: var(--wcag-radio--s-act--color); 13 | --wcag-radio--background-color: var(--wcag-radio--s-act--background-color); 14 | */ 15 | --wcag-radio--border-color: var(--wcag-radio--s-act--border-color); 16 | } 17 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/styles/states/_hover.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 3 | --wcag-textarea--s-hov--color: ; 4 | --wcag-textarea--s-hov--background-color: ; 5 | */ 6 | --wcag-textarea--s-hov--border-color: var(--wcag-c--neutral-600); 7 | } 8 | 9 | [is="wcag-textarea"]:hover { 10 | /* 11 | --wcag-textarea--color: var(--wcag-textarea--s-hov--color); 12 | --wcag-textarea--background-color: var(--wcag-textarea--s-hov--background-color); 13 | */ 14 | 15 | --wcag-textarea--border-color: var(--wcag-textarea--s-hov--border-color); 16 | } 17 | -------------------------------------------------------------------------------- /packages/css/grid-system/lib/_container.css: -------------------------------------------------------------------------------- 1 | /* biome-ignore lint/correctness/noUnknownTypeSelector: */ 2 | :where(container, [container]) { 3 | display: flex; 4 | flex-flow: column nowrap; 5 | gap: var(--wcag-gs--container--gap); 6 | 7 | inline-size: var(--wcag-gs--container--size); 8 | block-size: auto; 9 | padding: 0; 10 | margin: 0 auto; 11 | 12 | &:where([fluid]) { 13 | --wcag-gs--container--size: 100%; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/components/switch/lib/styles/states/_active.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 3 | --wcag-switch--s-act--color: ; 4 | --wcag-switch--s-act--background-color: ; 5 | */ 6 | 7 | --wcag-switch--s-act--border-color: var(--wcag-c--neutral-600); 8 | } 9 | 10 | [is="wcag-switch"]:where(:active, [aria-pressed="true"]) { 11 | /* 12 | --wcag-switch--color: var(--wcag-switch--s-act--color); 13 | --wcag-switch--background-color: var(--wcag-switch--s-act--background-color); 14 | */ 15 | --wcag-switch--border-color: var(--wcag-switch--s-act--border-color); 16 | } 17 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/states/_hover.css: -------------------------------------------------------------------------------- 1 | /* 2 | :root { 3 | --wcag-button--s-hov--color: ; 4 | --wcag-button--s-hov--background-color: ; 5 | --wcag-button--s-hov--border-color: ; 6 | } 7 | */ 8 | 9 | [is="wcag-button"]:hover { 10 | --wcag-button--color: var(--wcag-button--s-hov--color); 11 | --wcag-button--background-color: var(--wcag-button--s-hov--background-color); 12 | --wcag-button--border-color: var(--wcag-button--s-hov--border-color); 13 | 14 | --wcag-button--text-decoration: var(--wcag-button--s-hov--text-decoration); 15 | } 16 | -------------------------------------------------------------------------------- /packages/components/scroll-spy/lib/styles/_core.css: -------------------------------------------------------------------------------- 1 | [is="wcag-scroll-spy"] { 2 | align-self: flex-start; 3 | 4 | display: block; 5 | width: 250px; 6 | 7 | nav { 8 | ul { 9 | list-style: none; 10 | padding: 0; 11 | 12 | li { 13 | margin-bottom: 10px; 14 | 15 | a { 16 | text-decoration: none; 17 | color: #333; 18 | } 19 | 20 | &.active { 21 | a { 22 | font-weight: bold; 23 | color: #007bff; 24 | } 25 | } 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/styles/states/_active.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 3 | --wcag-checkbox--s-act--color: ; 4 | --wcag-checkbox--s-act--background-color: ; 5 | */ 6 | 7 | --wcag-checkbox--s-act--border-color: var(--wcag-c--neutral-600); 8 | } 9 | 10 | [is="wcag-checkbox"]:where(:active, [aria-pressed="true"]) { 11 | /* 12 | --wcag-checkbox--color: var(--wcag-checkbox--s-act--color); 13 | --wcag-checkbox--background-color: var(--wcag-checkbox--s-act--background-color); 14 | */ 15 | --wcag-checkbox--border-color: var(--wcag-checkbox--s-act--border-color); 16 | } 17 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/styles/states/_active.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 3 | --wcag-textarea--s-act--color: ; 4 | --wcag-textarea--s-act--background-color: ; 5 | */ 6 | 7 | --wcag-textarea--s-act--border-color: var(--wcag-c--neutral-600); 8 | } 9 | 10 | [is="wcag-textarea"]:where(:active, [aria-pressed="true"]) { 11 | /* 12 | --wcag-textarea--color: var(--wcag-textarea--s-act--color); 13 | --wcag-textarea--background-color: var(--wcag-textarea--s-act--background-color); 14 | */ 15 | --wcag-textarea--border-color: var(--wcag-textarea--s-act--border-color); 16 | } 17 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/states/_active.css: -------------------------------------------------------------------------------- 1 | /* 2 | :root { 3 | --wcag-button--s-act--color: ; 4 | --wcag-button--s-act--background-color: ; 5 | --wcag-button--s-act--border-color: ; 6 | } 7 | */ 8 | 9 | [is="wcag-button"]:where(:active, [aria-pressed="true"]) { 10 | --wcag-button--color: var(--wcag-button--s-act--color); 11 | --wcag-button--background-color: var(--wcag-button--s-act--background-color); 12 | --wcag-button--border-color: var(--wcag-button--s-act--border-color); 13 | 14 | --wcag-button--text-decoration: var(--wcag-button--s-act--text-decoration); 15 | } 16 | -------------------------------------------------------------------------------- /packages/css/grid-system/lib/grid-system.css: -------------------------------------------------------------------------------- 1 | @import "./_variables.css" layer(wcag-ui.foundations.grid-system.variables); 2 | @import "./_container.css" layer(wcag-ui.foundations.grid-system.container); 3 | @import "./_container-breakpoints.css" layer(wcag-ui.foundations.grid-system.container.breakpoints); 4 | @import "./_row.css" layer(wcag-ui.foundations.grid-system.row); 5 | @import "./_column.css" layer(wcag-ui.foundations.grid-system.column); 6 | @import "./_column-sizes.css" layer(wcag-ui.foundations.grid-system.column.sizes); 7 | @import "./_column-offsets.css" layer(wcag-ui.foundations.grid-system.column.offsets); 8 | -------------------------------------------------------------------------------- /packages/js/core/lib/decorator/_buildExtendOptions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the `extends` option for Custom Elements when the component 3 | * targets a built-in element extension (e.g., `{ extends: 'button' }`). 4 | * 5 | * If `component.extendsElement` is falsy, returns `undefined`. 6 | * 7 | * @param {{ extendsElement?: string }} component - Component static metadata. 8 | * @returns {{ extends: string }|undefined} The extend options (or `undefined`). 9 | */ 10 | export function buildExtendOptions(component) { 11 | return component.extendsElement ? { extends: component.extendsElement } : undefined; 12 | } 13 | -------------------------------------------------------------------------------- /src/components-accordion.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Accordion Docs Example

7 |
8 |
9 | Details group 1 10 | Details content 1 11 |
12 |
13 | Details group 2 14 | Details content 2 15 |
16 |
17 |
18 |
19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # testing 9 | coverage 10 | 11 | # build 12 | dist 13 | *.min.css 14 | *.min.js 15 | 16 | # misc 17 | *.pem 18 | 19 | # cache 20 | .parcel-cache 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | lerna-debug.log* 28 | 29 | #lock files 30 | package-lock.json 31 | yarn.lock 32 | 33 | # local env files 34 | .env.* 35 | *.env 36 | 37 | # OS/IDE files 38 | .DS_Store 39 | .idea 40 | .obsidian 41 | 42 | -------------------------------------------------------------------------------- /packages/components/accordion/lib/styles/_core.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-accordion--display: flex; 3 | --wcag-accordion--flex-flow: column nowrap; 4 | --wcag-accordion--place-content: center space-between; 5 | --wcag-accordion--gap: var(--wcag-s--200); 6 | 7 | --wcag-accordion--border-radius: var(--wcag-r--s); 8 | } 9 | 10 | [is="wcag-accordion"] { 11 | display: var(--wcag-accordion--display); 12 | flex-flow: var(--wcag-accordion--flex-flow); 13 | place-content: var(--wcag-accordion--place-content); 14 | gap: var(--wcag-accordion--gap); 15 | 16 | border-radius: var(--wcag-accordion--border-radius); 17 | } 18 | -------------------------------------------------------------------------------- /packages/js/core/lib/decorator/_generateIsAttribute.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Converts a component name (PascalCase or camelCase) 3 | * into the "wcag-kebab-case" format for the `is` attribute. 4 | * 5 | * @param {string} name - Component name (e.g., "TreeView", "Button", "ScrollSpy") 6 | * @returns {string} - Formatted name for `is` (e.g., "wcag-tree-view") 7 | */ 8 | export function generateIsAttribute(name) { 9 | return `wcag-${name 10 | .replace(/([a-z0-9])([A-Z])/g, '$1-$2') // split camelCase/PascalCase 11 | .replace(/([A-Z])([A-Z][a-z])/g, '$1-$2') // handle acronyms like HTMLParser 12 | .toLowerCase()}`; 13 | } 14 | -------------------------------------------------------------------------------- /packages/js/core/lib/decorator/_exposeComponent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Exposes the component constructor on the global namespace: 3 | * `self.wcagUI[ComponentName] = Component`. 4 | * 5 | * This allows programmatic usage like: `new wcagUI.Button()`. 6 | * The function is idempotent and merges with the existing `wcagUI` bag. 7 | * 8 | * @param {CustomElementConstructor & { name: string }} component - The component class to expose. 9 | * @returns {void} 10 | */ 11 | export function exposeComponent(component) { 12 | Object.assign(self, { wcagUI: { ...self.wcagUI, [component.name]: component } }); 13 | } 14 | 15 | // usage example: new wcagUI.Button(); 16 | -------------------------------------------------------------------------------- /packages/css/typography/lib/fonts/inter/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | src: 3 | url("./lib/fonts/inter/Inter.woff2") format("woff2 supports variations"), 4 | url("./lib/fonts/inter/Inter.woff2") format("woff2-variations"); 5 | font-family: Inter; 6 | font-style: normal; 7 | font-weight: 100 900; 8 | font-display: block; 9 | } 10 | 11 | @font-face { 12 | src: 13 | url("./lib/fonts/inter/Inter-Italic.woff2") format("woff2 supports variations"), 14 | url("./lib/fonts/inter/Inter-Italic.woff2") format("woff2-variations"); 15 | font-family: Inter; 16 | font-style: italic; 17 | font-weight: 100 900; 18 | font-display: block; 19 | } 20 | -------------------------------------------------------------------------------- /packages/css/foundations/lib/_reset.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | :where(menu, dir) { 6 | margin-inline: 0; 7 | padding-inline: 0; 8 | } 9 | 10 | :where(ul, ol, li, menu, dir) { 11 | margin-block: 0; 12 | padding-block: 0; 13 | } 14 | 15 | /* rem reset 1rem = 10px */ 16 | html { 17 | font-size: 0.625em; /* 10px/16px */ 18 | overscroll-behavior: none; 19 | } 20 | 21 | body { 22 | margin: 0; 23 | } 24 | 25 | hr { 26 | display: block; 27 | 28 | inline-size: 50%; 29 | block-size: 0; 30 | 31 | margin: 6em auto; 32 | 33 | border: 1px solid color-mix(in srgb, CanvasText, transparent 90%); 34 | border-radius: 1.5px; 35 | } 36 | -------------------------------------------------------------------------------- /packages/js/core/lib/decorator/_assertMetaKey.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Asserts that a required static meta key exists on the component constructor. 3 | * 4 | * Throws a descriptive error if the key is missing. 5 | * 6 | * @param {Record} component - Component constructor (or its static bag). 7 | * @param {string} key - The required key to verify (e.g., 'events', 'attributes'). 8 | * @returns {void} 9 | * @throws {Error} If the key is not present on the component. 10 | */ 11 | export function assertMetaKey(component, key) { 12 | if (!component[key]) { 13 | throw new Error(`The meta ${key} is required for the wcagUI component: ${component}`); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/js/dom/lib/_findNodes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * finds nodes in a given node by using the query parameter for querying the textContent 3 | * 4 | * @param {string} query - the namespace of the event 5 | * @param {Node} node - the given node 6 | * @return {Node[]} 7 | */ 8 | export const findNodes = (query, node) => { 9 | if (!node.textContent?.toLowerCase().includes(query.toLowerCase())) { 10 | return []; 11 | } 12 | 13 | if (![...node.childNodes].length) { 14 | return [node]; 15 | } 16 | 17 | const foundNodes = []; 18 | 19 | for (const child of [...node.childNodes]) { 20 | foundNodes.push(...findNodes(query, child)); 21 | } 22 | 23 | return foundNodes; 24 | }; 25 | -------------------------------------------------------------------------------- /packages/components/input/lib/styles/states/_focus.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-input--s-foc--outline-width: var(--wcag-f--outline-width); 3 | --wcag-input--s-foc--outline-style: solid; 4 | --wcag-input--s-foc--outline-color: var(--wcag-f--outline-color); 5 | --wcag-input--s-foc--outline-offset: var(--wcag-f--outline-width); 6 | } 7 | 8 | [is="wcag-input"]:where(:focus, :focus-visible) { 9 | --wcag-input--outline-width: var(--wcag-input--s-foc--outline-width); 10 | --wcag-input--outline-style: var(--wcag-input--s-foc--outline-style); 11 | --wcag-input--outline-color: var(--wcag-input--s-foc--outline-color); 12 | --wcag-input--outline-offset: var(--wcag-input--s-foc--outline-offset); 13 | } 14 | -------------------------------------------------------------------------------- /packages/components/radio/lib/styles/states/_focus.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-radio--s-foc--outline-width: var(--wcag-f--outline-width); 3 | --wcag-radio--s-foc--outline-style: solid; 4 | --wcag-radio--s-foc--outline-color: var(--wcag-f--outline-color); 5 | --wcag-radio--s-foc--outline-offset: var(--wcag-f--outline-width); 6 | } 7 | 8 | [is="wcag-radio"]:where(:focus, :focus-visible) { 9 | --wcag-radio--outline-width: var(--wcag-radio--s-foc--outline-width); 10 | --wcag-radio--outline-style: var(--wcag-radio--s-foc--outline-style); 11 | --wcag-radio--outline-color: var(--wcag-radio--s-foc--outline-color); 12 | --wcag-radio--outline-offset: var(--wcag-radio--s-foc--outline-offset); 13 | } 14 | -------------------------------------------------------------------------------- /src/foundations-elevations.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |
box-shadow: 0px 2px 40px -2px var(--ColorShadowS); hsla(248, 28%, 55%, 0.08)
9 |
box-shadow: 0px 8px 40px -2px var(--ColorShadowM); hsla(248, 28%, 55%, 0.1)
10 |
box-shadow: 0px 18px 60px 2px var(--ColorShadowM); hsla(248, 28%, 55%, 0.1)
11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /src/foundations-typography.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |

Foundations

8 |

Typography

9 |
10 |
11 |

Type Scale

12 |
13 |

Heading 1

14 |

Heading 2

15 |

Heading 3

16 |

Heading 4

17 |
Heading 5
18 |
Heading 6
19 |

Paragraph

20 |
21 |
22 |
23 |
24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/states/_focus.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-button--s-foc--outline-width: var(--wcag-f--outline-width); 3 | --wcag-button--s-foc--outline-style: solid; 4 | --wcag-button--s-foc--outline-color: var(--wcag-f--outline-color); 5 | --wcag-button--s-foc--outline-offset: var(--wcag-f--outline-width); 6 | } 7 | 8 | [is="wcag-button"]:where(:focus, :focus-visible) { 9 | --wcag-button--outline-width: var(--wcag-button--s-foc--outline-width); 10 | --wcag-button--outline-style: var(--wcag-button--s-foc--outline-style); 11 | --wcag-button--outline-color: var(--wcag-button--s-foc--outline-color); 12 | --wcag-button--outline-offset: var(--wcag-button--s-foc--outline-offset); 13 | } 14 | -------------------------------------------------------------------------------- /packages/components/switch/lib/styles/states/_focus.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-switch--s-foc--outline-width: var(--wcag-f--outline-width); 3 | --wcag-switch--s-foc--outline-style: solid; 4 | --wcag-switch--s-foc--outline-color: var(--wcag-f--outline-color); 5 | --wcag-switch--s-foc--outline-offset: var(--wcag-f--outline-width); 6 | } 7 | 8 | [is="wcag-switch"]:where(:focus, :focus-visible) { 9 | --wcag-switch--outline-width: var(--wcag-switch--s-foc--outline-width); 10 | --wcag-switch--outline-style: var(--wcag-switch--s-foc--outline-style); 11 | --wcag-switch--outline-color: var(--wcag-switch--s-foc--outline-color); 12 | --wcag-switch--outline-offset: var(--wcag-switch--s-foc--outline-offset); 13 | } 14 | -------------------------------------------------------------------------------- /src/components-input.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Input Docs Example

7 |
8 |

Input

9 |

10 | 11 | 12 | 13 |

14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /src/components-radio.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Radio Docs Example

7 |
8 |

Example

9 |

10 | 11 | 12 | 13 | 14 |

15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /packages/js/core/lib/helpers/_debounce.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates a debounced version of a callback that delays invocation 3 | * until after `threshold` milliseconds have elapsed since the last call. 4 | * 5 | * @template {(...args: any[]) => any} F 6 | * @param {F} callback - Function to debounce. 7 | * @param {number} [threshold=300] - Delay in milliseconds. 8 | * @returns {(this: ThisType, ...args: Parameters) => void} Debounced function. 9 | */ 10 | export function debounce(callback, threshold = 300) { 11 | let debounce; 12 | 13 | return (...args) => { 14 | clearTimeout(debounce); 15 | 16 | debounce = setTimeout(() => { 17 | callback.apply(this, args); 18 | }, threshold); 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/styles/states/_focus.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-checkbox--s-foc--outline-width: var(--wcag-f--outline-width); 3 | --wcag-checkbox--s-foc--outline-style: solid; 4 | --wcag-checkbox--s-foc--outline-color: var(--wcag-f--outline-color); 5 | --wcag-checkbox--s-foc--outline-offset: var(--wcag-f--outline-width); 6 | } 7 | 8 | [is="wcag-checkbox"]:where(:focus, :focus-visible) { 9 | --wcag-checkbox--outline-width: var(--wcag-checkbox--s-foc--outline-width); 10 | --wcag-checkbox--outline-style: var(--wcag-checkbox--s-foc--outline-style); 11 | --wcag-checkbox--outline-color: var(--wcag-checkbox--s-foc--outline-color); 12 | --wcag-checkbox--outline-offset: var(--wcag-checkbox--s-foc--outline-offset); 13 | } 14 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/styles/states/_focus.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-textarea--s-foc--outline-width: var(--wcag-f--outline-width); 3 | --wcag-textarea--s-foc--outline-style: solid; 4 | --wcag-textarea--s-foc--outline-color: var(--wcag-f--outline-color); 5 | --wcag-textarea--s-foc--outline-offset: var(--wcag-f--outline-width); 6 | } 7 | 8 | [is="wcag-textarea"]:where(:focus, :focus-visible) { 9 | --wcag-textarea--outline-width: var(--wcag-textarea--s-foc--outline-width); 10 | --wcag-textarea--outline-style: var(--wcag-textarea--s-foc--outline-style); 11 | --wcag-textarea--outline-color: var(--wcag-textarea--s-foc--outline-color); 12 | --wcag-textarea--outline-offset: var(--wcag-textarea--s-foc--outline-offset); 13 | } 14 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/states/_disabled.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 3 | --wcag-button--s-dis--color: ; 4 | --wcag-button--s-dis--background-color: ; 5 | --wcag-button--s-dis--border-color: ; 6 | */ 7 | 8 | --wcag-button--s-dis--cursor: not-allowed; 9 | } 10 | 11 | [is="wcag-button"]:where([disabled], :disabled, [aria-disabled="true"]) { 12 | --wcag-button--color: var(--wcag-button--s-dis--color); 13 | --wcag-button--background-color: var(--wcag-button--s-dis--background-color); 14 | --wcag-button--border-color: var(--wcag-button--s-dis--border-color); 15 | 16 | --wcag-button--text-decoration: var(--wcag-button--s-dis--text-decoration); 17 | 18 | --wcag-button--cursor: var(--wcag-button--s-dis--cursor); 19 | } 20 | -------------------------------------------------------------------------------- /packages/js/core/lib/helpers/_throttle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates a throttled function that only invokes `callback` at most once 3 | * every `threshold` milliseconds. 4 | * 5 | * @template {(...args: any[]) => any} F 6 | * @param {F} callback - Function to throttle. 7 | * @param {number} [threshold=300] - Minimum delay between calls. 8 | * @returns {(this: ThisType, ...args: Parameters) => void} Throttled function. 9 | */ 10 | export function throttle(callback, threshold = 300) { 11 | let throttlePause; 12 | 13 | return (...args) => { 14 | if (throttlePause) return; 15 | 16 | throttlePause = true; 17 | 18 | setTimeout(() => { 19 | callback.apply(this, args); 20 | throttlePause = false; 21 | }, threshold); 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /src/common/breadcrumbs.html: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /packages/components/input/lib/styles/states/_disabled.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-input--s-dis--color: var(--wcag-c--neutral-50); 3 | --wcag-input--s-dis--background-color: var(--wcag-c--light); 4 | --wcag-input--s-dis--border-color: var(--wcag-c--neutral-100); 5 | 6 | --wcag-input--s-dis--cursor: not-allowed; 7 | } 8 | 9 | [is="wcag-input"]:where([disabled], :disabled, [aria-disabled="true"]) { 10 | --wcag-input--color: var(--wcag-input--s-dis--color); 11 | --wcag-input--background-color: var(--wcag-input--s-dis--background-color); 12 | --wcag-input--border-color: var(--wcag-input--s-dis--border-color); 13 | 14 | --wcag-input--text-decoration: var(--wcag-input--s-dis--text-decoration); 15 | 16 | --wcag-input--cursor: var(--wcag-input--s-dis--cursor); 17 | } 18 | -------------------------------------------------------------------------------- /packages/components/radio/lib/styles/states/_disabled.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-radio--s-dis--color: var(--wcag-c--neutral-50); 3 | --wcag-radio--s-dis--background-color: var(--wcag-c--light); 4 | --wcag-radio--s-dis--border-color: var(--wcag-c--neutral-100); 5 | 6 | --wcag-radio--s-dis--cursor: not-allowed; 7 | } 8 | 9 | [is="wcag-radio"]:where([disabled], :disabled, [aria-disabled="true"]) { 10 | --wcag-radio--color: var(--wcag-radio--s-dis--color); 11 | --wcag-radio--background-color: var(--wcag-radio--s-dis--background-color); 12 | --wcag-radio--border-color: var(--wcag-radio--s-dis--border-color); 13 | 14 | --wcag-radio--text-decoration: var(--wcag-radio--s-dis--text-decoration); 15 | 16 | --wcag-radio--cursor: var(--wcag-radio--s-dis--cursor); 17 | } 18 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[markdown]": { 3 | "editor.defaultFormatter": "esbenp.prettier-vscode" 4 | }, 5 | "[yaml]": { 6 | "editor.defaultFormatter": "esbenp.prettier-vscode" 7 | }, 8 | "[html]": { 9 | "editor.defaultFormatter": "esbenp.prettier-vscode" 10 | }, 11 | "[css]": { 12 | "editor.defaultFormatter": "esbenp.prettier-vscode" 13 | }, 14 | "[javascript]": { 15 | "editor.defaultFormatter": "esbenp.prettier-vscode" 16 | }, 17 | "[json]": { 18 | "editor.defaultFormatter": "esbenp.prettier-vscode" 19 | }, 20 | "[jsonc]": { 21 | "editor.defaultFormatter": "biomejs.biome" 22 | }, 23 | "[svg]": { 24 | "editor.defaultFormatter": "jock.svg" 25 | }, 26 | "files.exclude": { 27 | "**/.vscode": false 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/js/dom/lib/_outerHTML.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the outer HTML of an element, with an option to exclude the element's content. 3 | * 4 | * @param {HTMLElement} element The target element from which to get the outer HTML. 5 | * @param {boolean} [excludeContent=false] A boolean flag indicating whether to exclude the content between the opening and closing tags. 6 | * If set to true, the content will be removed from the resulting HTML. 7 | * @return {string} The outer HTML of the element, optionally without its content. 8 | */ 9 | 10 | export const outerHTML = (element, excludeContent = false) => { 11 | if (!excludeContent) { 12 | return element.outerHTML; 13 | } 14 | 15 | return element.outerHTML.replaceAll('\n', '').replace(/(?<=<.*?>).*(?=<\/.*>)/gm, ''); 16 | }; 17 | -------------------------------------------------------------------------------- /packages/components/switch/lib/styles/states/_disabled.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-switch--s-dis--color: var(--wcag-c--neutral-50); 3 | --wcag-switch--s-dis--background-color: var(--wcag-c--light); 4 | --wcag-switch--s-dis--border-color: var(--wcag-c--neutral-100); 5 | 6 | --wcag-switch--s-dis--cursor: not-allowed; 7 | } 8 | 9 | [is="wcag-switch"]:where([disabled], :disabled, [aria-disabled="true"]) { 10 | --wcag-switch--color: var(--wcag-switch--s-dis--color); 11 | --wcag-switch--background-color: var(--wcag-switch--s-dis--background-color); 12 | --wcag-switch--border-color: var(--wcag-switch--s-dis--border-color); 13 | 14 | --wcag-switch--text-decoration: var(--wcag-switch--s-dis--text-decoration); 15 | 16 | --wcag-switch--cursor: var(--wcag-switch--s-dis--cursor); 17 | } 18 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/linked-in.svg: -------------------------------------------------------------------------------- 1 | 2 | linked-in 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/components/dialog/lib/dialog.js: -------------------------------------------------------------------------------- 1 | import { componentDecorator } from '@wcag-ui/core'; 2 | 3 | import attributes from './dialog.attributes'; 4 | import events from './dialog.events'; 5 | 6 | /** 7 | * wcagUI Dialog class 8 | * 9 | * @export 10 | * @class Dialog 11 | * @extends {HTMLDialogElement} 12 | */ 13 | export class Dialog extends HTMLDialogElement { 14 | static extendsElement = 'dialog'; 15 | static attributes = attributes; 16 | static events = events; 17 | 18 | /** 19 | * static initialization 20 | * 21 | * @static 22 | * @memberof Dialog 23 | */ 24 | static { 25 | componentDecorator(this); 26 | } 27 | 28 | constructor() { 29 | super(); 30 | 31 | this.#init(); 32 | } 33 | 34 | #init() {} 35 | } 36 | 37 | // import "@wcag-ui/dialog"; 38 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/Read Me.txt: -------------------------------------------------------------------------------- 1 | Open *demo.html* to see a list of all the glyphs in your font along with their codes/ligatures. 2 | 3 | To use the generated font in desktop programs, you can install the TTF font. In order to copy the character associated with each icon, refer to the text box at the bottom right corner of each glyph in demo.html. The character inside this text box may be invisible; but it can still be copied. See this guide for more info: https://icomoon.io/docs/#local-fonts 4 | 5 | You won't need any of the files located under the *demo-files* directory when including the generated font in your own projects. 6 | 7 | You can import *selection.json* back to the IcoMoon app using the *Import Icons* button (or via Main Menu → Manage Projects) to retrieve your icon selection. 8 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/styles/states/_disabled.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-checkbox--s-dis--color: var(--wcag-c--neutral-50); 3 | --wcag-checkbox--s-dis--background-color: var(--wcag-c--light); 4 | --wcag-checkbox--s-dis--border-color: var(--wcag-c--neutral-100); 5 | 6 | --wcag-checkbox--s-dis--cursor: not-allowed; 7 | } 8 | 9 | [is="wcag-checkbox"]:where([disabled], :disabled, [aria-disabled="true"]) { 10 | --wcag-checkbox--color: var(--wcag-checkbox--s-dis--color); 11 | --wcag-checkbox--background-color: var(--wcag-checkbox--s-dis--background-color); 12 | --wcag-checkbox--border-color: var(--wcag-checkbox--s-dis--border-color); 13 | 14 | --wcag-checkbox--text-decoration: var(--wcag-checkbox--s-dis--text-decoration); 15 | 16 | --wcag-checkbox--cursor: var(--wcag-checkbox--s-dis--cursor); 17 | } 18 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/styles/states/_disabled.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-textarea--s-dis--color: var(--wcag-c--neutral-50); 3 | --wcag-textarea--s-dis--background-color: var(--wcag-c--light); 4 | --wcag-textarea--s-dis--border-color: var(--wcag-c--neutral-100); 5 | 6 | --wcag-textarea--s-dis--cursor: not-allowed; 7 | } 8 | 9 | [is="wcag-textarea"]:where([disabled], :disabled, [aria-disabled="true"]) { 10 | --wcag-textarea--color: var(--wcag-textarea--s-dis--color); 11 | --wcag-textarea--background-color: var(--wcag-textarea--s-dis--background-color); 12 | --wcag-textarea--border-color: var(--wcag-textarea--s-dis--border-color); 13 | 14 | --wcag-textarea--text-decoration: var(--wcag-textarea--s-dis--text-decoration); 15 | 16 | --wcag-textarea--cursor: var(--wcag-textarea--s-dis--cursor); 17 | } 18 | -------------------------------------------------------------------------------- /packages/js/core/lib/encoding/_jwt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Minimal JWT helpers. 3 | */ 4 | const jwt = { 5 | /** 6 | * Parses a JWT token string and returns the payload as an object. 7 | * 8 | * Note: This does not verify the signature. Intended for non-sensitive cases. 9 | * 10 | * @param {string} token - JWT in the form header.payload.signature 11 | * @returns {object} 12 | */ 13 | parse: (token) => { 14 | var base64Url = token.split('.')[1]; 15 | var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); 16 | var jsonPayload = decodeURIComponent( 17 | atob(base64) 18 | .split('') 19 | .map((c) => `%${(`00${c.charCodeAt(0).toString(16)}`).slice(-2)}`) 20 | .join(''), 21 | ); 22 | 23 | return JSON.parse(jsonPayload); 24 | }, 25 | }; 26 | 27 | export { jwt }; 28 | -------------------------------------------------------------------------------- /packages/js/dom/lib/_ensureElement.js: -------------------------------------------------------------------------------- 1 | import { createElement } from './_createElement'; 2 | 3 | /** 4 | * create an element and return it 5 | * 6 | * @param {Element|TElementOptions} elementOrOptions - instance of an element or options 7 | * @return {boolean} true, if the parameter is an Element 8 | */ 9 | function isElement(elementOrOptions) { 10 | return elementOrOptions instanceof HTMLElement || elementOrOptions instanceof DocumentFragment; 11 | } 12 | 13 | /** 14 | * checks if the parameter is an element or creates it 15 | * 16 | * @param {Element|TElementOptions} elementOrOptions - the element or the options for building it 17 | * @return {Element} 18 | */ 19 | export const ensureElement = (elementOrOptions) => { 20 | return isElement(elementOrOptions) ? elementOrOptions : createElement(elementOrOptions); 21 | }; 22 | -------------------------------------------------------------------------------- /packages/js/core/lib/decorator/_defineCustomElement.js: -------------------------------------------------------------------------------- 1 | import { buildExtendOptions } from './_buildExtendOptions'; 2 | 3 | /** 4 | * Defines the component as a Custom Element if not already registered. 5 | * 6 | * - Skips definition if `customElements` is not available. 7 | * - Skips if the tag is already defined. 8 | * - Uses `extends` option when `component.extendsElement` is provided. 9 | * 10 | * @param {CustomElementConstructor & { extendsElement?: string }} component - Component class. 11 | * @param {string} isAttribute - Custom element tag to register (e.g., "wcag-tree-view"). 12 | * @returns {void} 13 | */ 14 | export function defineCustomElement(component, isAttribute) { 15 | !!customElements && 16 | !customElements.get(isAttribute) && 17 | customElements.define(isAttribute, component, buildExtendOptions(component)); 18 | } 19 | -------------------------------------------------------------------------------- /packages/components/input/lib/styles/dimensions/_medium.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-input--md--gap: 1.2rem; 3 | 4 | --wcag-input--md--height: 4.4rem; 5 | --wcag-input--md--padding-inline: 2rem; 6 | --wcag-input--md--padding-block: 0; 7 | --wcag-input--md--border-width: 1px; 8 | --wcag-input--md--border-radius: 0.4rem; 9 | 10 | --wcag-input--md--font-size: 1.6rem; 11 | } 12 | 13 | [is="wcag-input"] { 14 | --wcag-input--gap: var(--wcag-input--md--gap); 15 | 16 | --wcag-input--height: var(--wcag-input--md--height); 17 | --wcag-input--padding-inline: var(--wcag-input--md--padding-inline); 18 | --wcag-input--padding-block: var(--wcag-input--md--padding-block); 19 | --wcag-input--border-width: var(--wcag-input--md--border-width); 20 | --wcag-input--border-radius: var(--wcag-input--md--border-radius); 21 | 22 | --wcag-input--font-size: var(--wcag-input--md--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/radio/lib/styles/dimensions/_medium.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-radio--md--gap: 1.2rem; 3 | 4 | --wcag-radio--md--height: 4.4rem; 5 | --wcag-radio--md--padding-inline: 2rem; 6 | --wcag-radio--md--padding-block: 0; 7 | --wcag-radio--md--border-width: 1px; 8 | --wcag-radio--md--border-radius: 0.4rem; 9 | 10 | --wcag-radio--md--font-size: 1.6rem; 11 | } 12 | 13 | [is="wcag-radio"] { 14 | --wcag-radio--gap: var(--wcag-radio--md--gap); 15 | 16 | --wcag-radio--height: var(--wcag-radio--md--height); 17 | --wcag-radio--padding-inline: var(--wcag-radio--md--padding-inline); 18 | --wcag-radio--padding-block: var(--wcag-radio--md--padding-block); 19 | --wcag-radio--border-width: var(--wcag-radio--md--border-width); 20 | --wcag-radio--border-radius: var(--wcag-radio--md--border-radius); 21 | 22 | --wcag-radio--font-size: var(--wcag-radio--md--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/scheme-light.svg: -------------------------------------------------------------------------------- 1 | 2 | scheme-light 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/js/dom/lib/_createElement.js: -------------------------------------------------------------------------------- 1 | import { sanitizeHTML } from './_sanitizeHTML'; 2 | 3 | /** 4 | * create an element and return it 5 | * 6 | * @param {TElementOptions} options of the element to create 7 | * @return {Element} 8 | */ 9 | export const createElement = (options) => { 10 | if (!options.tag) { 11 | throw new Error(`wcag-ui.core.createElement error: no tag provided`); 12 | } 13 | 14 | const element = document.createElement(options.tag); 15 | 16 | options.classes && element.classList.add(...options.classes); 17 | 18 | for (const [key, value] of Object.entries(options.attributes ?? {})) { 19 | element.setAttribute(key, value); 20 | } 21 | 22 | const fragment = document.createDocumentFragment(); 23 | fragment.append(...sanitizeHTML(options.content, true)); 24 | 25 | options.content && element.append(fragment); 26 | 27 | return element; 28 | }; 29 | -------------------------------------------------------------------------------- /.github/coding-styleguides/a11y.md: -------------------------------------------------------------------------------- 1 | # a11y-standards 2 | 3 | The place for all the A11y standards, best practices, naming conventions and other amenities 4 | 5 | A screen reader is a technology that helps people who have difficulty seeing access and interact with digital content, like websites or applications via audio or touch or keyboard. The main users of screen readers are people who are blind or have very limited vision. 6 | 7 | This is one of the most important websites for accessibility: 8 | https://www.w3.org/WAI/ARIA/apg/patterns/ 9 | it has definitions of keyboard interactions, aria attributes and rules for properly implementing visual patterns for accessibility. 10 | 11 | Here are some other useful accessibility links: 12 | https://medium.com/weekly-webtips/10-accessibility-best-practices-cb66b666fa0f 13 | https://dev.to/brittneypostma/accessibility-best-practices-for-html-css-d51?s=09 14 | -------------------------------------------------------------------------------- /packages/components/input/lib/styles/dimensions/_large.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-input--lg--gap: 1.6rem; 3 | 4 | --wcag-input--lg--height: 5.6rem; 5 | --wcag-input--lg--padding-inline: 2rem; 6 | --wcag-input--lg--padding-block: 0; 7 | --wcag-input--lg--border-width: 1px; 8 | --wcag-input--lg--border-radius: 0.5rem; 9 | 10 | --wcag-input--lg--font-size: 1.8rem; 11 | } 12 | 13 | [is="wcag-input"][lg] { 14 | --wcag-input--gap: var(--wcag-input--lg--gap); 15 | 16 | --wcag-input--height: var(--wcag-input--lg--height); 17 | --wcag-input--padding-inline: var(--wcag-input--lg--padding-inline); 18 | --wcag-input--padding-block: var(--wcag-input--lg--padding-block); 19 | --wcag-input--border-width: var(--wcag-input--lg--border-width); 20 | --wcag-input--border-radius: var(--wcag-input--lg--border-radius); 21 | 22 | --wcag-input--font-size: var(--wcag-input--lg--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/input/lib/styles/dimensions/_small.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-input--sm--gap: 0.8rem; 3 | 4 | --wcag-input--sm--height: 4rem; 5 | --wcag-input--sm--padding-inline: 1.2rem; 6 | --wcag-input--sm--padding-block: 0; 7 | --wcag-input--sm--border-width: 1px; 8 | --wcag-input--sm--border-radius: 0.35rem; 9 | 10 | --wcag-input--sm--font-size: 1.4rem; 11 | } 12 | 13 | [is="wcag-input"][sm] { 14 | --wcag-input--gap: var(--wcag-input--sm--gap); 15 | 16 | --wcag-input--height: var(--wcag-input--sm--height); 17 | --wcag-input--padding-inline: var(--wcag-input--sm--padding-inline); 18 | --wcag-input--padding-block: var(--wcag-input--sm--padding-block); 19 | --wcag-input--border-width: var(--wcag-input--sm--border-width); 20 | --wcag-input--border-radius: var(--wcag-input--sm--border-radius); 21 | 22 | --wcag-input--font-size: var(--wcag-input--sm--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/radio/lib/styles/dimensions/_large.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-radio--lg--gap: 1.6rem; 3 | 4 | --wcag-radio--lg--height: 5.6rem; 5 | --wcag-radio--lg--padding-inline: 2rem; 6 | --wcag-radio--lg--padding-block: 0; 7 | --wcag-radio--lg--border-width: 1px; 8 | --wcag-radio--lg--border-radius: 0.5rem; 9 | 10 | --wcag-radio--lg--font-size: 1.8rem; 11 | } 12 | 13 | [is="wcag-radio"][lg] { 14 | --wcag-radio--gap: var(--wcag-radio--lg--gap); 15 | 16 | --wcag-radio--height: var(--wcag-radio--lg--height); 17 | --wcag-radio--padding-inline: var(--wcag-radio--lg--padding-inline); 18 | --wcag-radio--padding-block: var(--wcag-radio--lg--padding-block); 19 | --wcag-radio--border-width: var(--wcag-radio--lg--border-width); 20 | --wcag-radio--border-radius: var(--wcag-radio--lg--border-radius); 21 | 22 | --wcag-radio--font-size: var(--wcag-radio--lg--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/radio/lib/styles/dimensions/_small.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-radio--sm--gap: 0.8rem; 3 | 4 | --wcag-radio--sm--height: 4rem; 5 | --wcag-radio--sm--padding-inline: 1.2rem; 6 | --wcag-radio--sm--padding-block: 0; 7 | --wcag-radio--sm--border-width: 1px; 8 | --wcag-radio--sm--border-radius: 0.35rem; 9 | 10 | --wcag-radio--sm--font-size: 1.4rem; 11 | } 12 | 13 | [is="wcag-radio"][sm] { 14 | --wcag-radio--gap: var(--wcag-radio--sm--gap); 15 | 16 | --wcag-radio--height: var(--wcag-radio--sm--height); 17 | --wcag-radio--padding-inline: var(--wcag-radio--sm--padding-inline); 18 | --wcag-radio--padding-block: var(--wcag-radio--sm--padding-block); 19 | --wcag-radio--border-width: var(--wcag-radio--sm--border-width); 20 | --wcag-radio--border-radius: var(--wcag-radio--sm--border-radius); 21 | 22 | --wcag-radio--font-size: var(--wcag-radio--sm--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/tree-view/lib/tree-view.js: -------------------------------------------------------------------------------- 1 | /** biome-ignore-all lint/correctness/noUnusedImports: */ 2 | import { componentDecorator, helpers } from '@wcag-ui/core'; 3 | import { DOM } from '@wcag-ui/dom'; 4 | 5 | import attributes from './tree-view.attributes'; 6 | import events from './tree-view.events'; 7 | 8 | /** 9 | * wcagUI treeView class 10 | * 11 | * @export 12 | * @class treeView 13 | * @extends {HTMLElement} 14 | */ 15 | export class TreeView extends HTMLElement { 16 | static extendsElement = 'section'; 17 | static attributes = attributes; 18 | static events = events; 19 | 20 | /** 21 | * static initialization 22 | * 23 | * @static 24 | * @memberof treeView 25 | */ 26 | static { 27 | componentDecorator(this); 28 | } 29 | 30 | constructor() { 31 | super(); 32 | 33 | this.#init(); 34 | } 35 | 36 | #init() {} 37 | } 38 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/dimensions/_medium.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-button--md--gap: 1.2rem; 3 | 4 | --wcag-button--md--height: 4.4rem; 5 | --wcag-button--md--padding-inline: 2rem; 6 | --wcag-button--md--padding-block: 0; 7 | --wcag-button--md--border-width: 1px; 8 | --wcag-button--md--border-radius: 0.4rem; 9 | 10 | --wcag-button--md--font-size: 1.6rem; 11 | } 12 | 13 | [is="wcag-button"] { 14 | --wcag-button--gap: var(--wcag-button--md--gap); 15 | 16 | --wcag-button--height: var(--wcag-button--md--height); 17 | --wcag-button--padding-inline: var(--wcag-button--md--padding-inline); 18 | --wcag-button--padding-block: var(--wcag-button--md--padding-block); 19 | --wcag-button--border-width: var(--wcag-button--md--border-width); 20 | --wcag-button--border-radius: var(--wcag-button--md--border-radius); 21 | 22 | --wcag-button--font-size: var(--wcag-button--md--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/switch/lib/styles/dimensions/_medium.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-switch--md--gap: 1.2rem; 3 | 4 | --wcag-switch--md--height: 4.4rem; 5 | --wcag-switch--md--padding-inline: 2rem; 6 | --wcag-switch--md--padding-block: 0; 7 | --wcag-switch--md--border-width: 1px; 8 | --wcag-switch--md--border-radius: 0.4rem; 9 | 10 | --wcag-switch--md--font-size: 1.6rem; 11 | } 12 | 13 | [is="wcag-switch"] { 14 | --wcag-switch--gap: var(--wcag-switch--md--gap); 15 | 16 | --wcag-switch--height: var(--wcag-switch--md--height); 17 | --wcag-switch--padding-inline: var(--wcag-switch--md--padding-inline); 18 | --wcag-switch--padding-block: var(--wcag-switch--md--padding-block); 19 | --wcag-switch--border-width: var(--wcag-switch--md--border-width); 20 | --wcag-switch--border-radius: var(--wcag-switch--md--border-radius); 21 | 22 | --wcag-switch--font-size: var(--wcag-switch--md--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/dimensions/_large.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-button--lg--gap: 1.6rem; 3 | 4 | --wcag-button--lg--height: 5.6rem; 5 | --wcag-button--lg--padding-inline: 2rem; 6 | --wcag-button--lg--padding-block: 0; 7 | --wcag-button--lg--border-width: 1px; 8 | --wcag-button--lg--border-radius: 0.5rem; 9 | 10 | --wcag-button--lg--font-size: 1.8rem; 11 | } 12 | 13 | [is="wcag-button"][lg] { 14 | --wcag-button--gap: var(--wcag-button--lg--gap); 15 | 16 | --wcag-button--height: var(--wcag-button--lg--height); 17 | --wcag-button--padding-inline: var(--wcag-button--lg--padding-inline); 18 | --wcag-button--padding-block: var(--wcag-button--lg--padding-block); 19 | --wcag-button--border-width: var(--wcag-button--lg--border-width); 20 | --wcag-button--border-radius: var(--wcag-button--lg--border-radius); 21 | 22 | --wcag-button--font-size: var(--wcag-button--lg--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/button/lib/styles/dimensions/_small.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-button--sm--gap: 0.8rem; 3 | 4 | --wcag-button--sm--height: 4rem; 5 | --wcag-button--sm--padding-inline: 1.2rem; 6 | --wcag-button--sm--padding-block: 0; 7 | --wcag-button--sm--border-width: 1px; 8 | --wcag-button--sm--border-radius: 0.35rem; 9 | 10 | --wcag-button--sm--font-size: 1.4rem; 11 | } 12 | 13 | [is="wcag-button"][sm] { 14 | --wcag-button--gap: var(--wcag-button--sm--gap); 15 | 16 | --wcag-button--height: var(--wcag-button--sm--height); 17 | --wcag-button--padding-inline: var(--wcag-button--sm--padding-inline); 18 | --wcag-button--padding-block: var(--wcag-button--sm--padding-block); 19 | --wcag-button--border-width: var(--wcag-button--sm--border-width); 20 | --wcag-button--border-radius: var(--wcag-button--sm--border-radius); 21 | 22 | --wcag-button--font-size: var(--wcag-button--sm--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/switch/lib/styles/dimensions/_large.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-switch--lg--gap: 1.6rem; 3 | 4 | --wcag-switch--lg--height: 5.6rem; 5 | --wcag-switch--lg--padding-inline: 2rem; 6 | --wcag-switch--lg--padding-block: 0; 7 | --wcag-switch--lg--border-width: 1px; 8 | --wcag-switch--lg--border-radius: 0.5rem; 9 | 10 | --wcag-switch--lg--font-size: 1.8rem; 11 | } 12 | 13 | [is="wcag-switch"][lg] { 14 | --wcag-switch--gap: var(--wcag-switch--lg--gap); 15 | 16 | --wcag-switch--height: var(--wcag-switch--lg--height); 17 | --wcag-switch--padding-inline: var(--wcag-switch--lg--padding-inline); 18 | --wcag-switch--padding-block: var(--wcag-switch--lg--padding-block); 19 | --wcag-switch--border-width: var(--wcag-switch--lg--border-width); 20 | --wcag-switch--border-radius: var(--wcag-switch--lg--border-radius); 21 | 22 | --wcag-switch--font-size: var(--wcag-switch--lg--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/switch/lib/styles/dimensions/_small.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-switch--sm--gap: 0.8rem; 3 | 4 | --wcag-switch--sm--height: 4rem; 5 | --wcag-switch--sm--padding-inline: 1.2rem; 6 | --wcag-switch--sm--padding-block: 0; 7 | --wcag-switch--sm--border-width: 1px; 8 | --wcag-switch--sm--border-radius: 0.35rem; 9 | 10 | --wcag-switch--sm--font-size: 1.4rem; 11 | } 12 | 13 | [is="wcag-switch"][sm] { 14 | --wcag-switch--gap: var(--wcag-switch--sm--gap); 15 | 16 | --wcag-switch--height: var(--wcag-switch--sm--height); 17 | --wcag-switch--padding-inline: var(--wcag-switch--sm--padding-inline); 18 | --wcag-switch--padding-block: var(--wcag-switch--sm--padding-block); 19 | --wcag-switch--border-width: var(--wcag-switch--sm--border-width); 20 | --wcag-switch--border-radius: var(--wcag-switch--sm--border-radius); 21 | 22 | --wcag-switch--font-size: var(--wcag-switch--sm--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/js/core/lib/events/_dispatchComponentEvent.js: -------------------------------------------------------------------------------- 1 | import { dispatchCustomEvent } from './_dispatchCustomEvent'; 2 | 3 | /** 4 | * Dispatches a namespaced custom event for a wcag-ui component instance. 5 | * 6 | * Uses `this.componentName` as the namespace and `${componentName}.${eventName}` as final event type. 7 | * 8 | * @param {string} eventName - Event name (e.g., "open", "close"). 9 | * @param {object} details - Data to include in `event.detail`. 10 | * @param {Event} [originalEvent=undefined] - Optional originating DOM event. 11 | * @returns {void} 12 | */ 13 | export const dispatchComponentEvent = function (eventName, details, originalEvent = undefined) { 14 | const componentName = this.componentName; 15 | 16 | dispatchCustomEvent.call( 17 | this, 18 | componentName, 19 | eventName, 20 | details, 21 | originalEvent ?? new Event(`${componentName}.${eventName}`) 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /scripts/templates/component/lib/component-name.js: -------------------------------------------------------------------------------- 1 | /** biome-ignore-all lint/correctness/noUnusedImports: */ 2 | import { componentDecorator, helpers } from '@wcag-ui/core'; 3 | import { DOM } from '@wcag-ui/dom'; 4 | 5 | import attributes from './component-name.attributes'; 6 | import events from './component-name.events'; 7 | 8 | /** 9 | * wcagUI ComponentName class 10 | * 11 | * @export 12 | * @class ComponentName 13 | * @extends {HTMLElement} 14 | */ 15 | export class ComponentName extends HTMLElement { 16 | static extendsElement = 'section'; 17 | static attributes = attributes; 18 | static events = events; 19 | 20 | /** 21 | * static initialization 22 | * 23 | * @static 24 | * @memberof ComponentName 25 | */ 26 | static { 27 | componentDecorator(this); 28 | } 29 | 30 | constructor() { 31 | super(); 32 | 33 | this.#init(); 34 | } 35 | 36 | #init() {} 37 | } 38 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/styles/dimensions/_medium.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-checkbox--md--gap: 1.2rem; 3 | 4 | --wcag-checkbox--md--height: 4.4rem; 5 | --wcag-checkbox--md--padding-inline: 2rem; 6 | --wcag-checkbox--md--padding-block: 0; 7 | --wcag-checkbox--md--border-width: 1px; 8 | --wcag-checkbox--md--border-radius: 0.4rem; 9 | 10 | --wcag-checkbox--md--font-size: 1.6rem; 11 | } 12 | 13 | [is="wcag-checkbox"] { 14 | --wcag-checkbox--gap: var(--wcag-checkbox--md--gap); 15 | 16 | --wcag-checkbox--height: var(--wcag-checkbox--md--height); 17 | --wcag-checkbox--padding-inline: var(--wcag-checkbox--md--padding-inline); 18 | --wcag-checkbox--padding-block: var(--wcag-checkbox--md--padding-block); 19 | --wcag-checkbox--border-width: var(--wcag-checkbox--md--border-width); 20 | --wcag-checkbox--border-radius: var(--wcag-checkbox--md--border-radius); 21 | 22 | --wcag-checkbox--font-size: var(--wcag-checkbox--md--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/styles/dimensions/_medium.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-textarea--md--gap: 1.2rem; 3 | 4 | --wcag-textarea--md--height: 4.4rem; 5 | --wcag-textarea--md--padding-inline: 2rem; 6 | --wcag-textarea--md--padding-block: 0; 7 | --wcag-textarea--md--border-width: 1px; 8 | --wcag-textarea--md--border-radius: 0.4rem; 9 | 10 | --wcag-textarea--md--font-size: 1.6rem; 11 | } 12 | 13 | [is="wcag-textarea"] { 14 | --wcag-textarea--gap: var(--wcag-textarea--md--gap); 15 | 16 | --wcag-textarea--height: var(--wcag-textarea--md--height); 17 | --wcag-textarea--padding-inline: var(--wcag-textarea--md--padding-inline); 18 | --wcag-textarea--padding-block: var(--wcag-textarea--md--padding-block); 19 | --wcag-textarea--border-width: var(--wcag-textarea--md--border-width); 20 | --wcag-textarea--border-radius: var(--wcag-textarea--md--border-radius); 21 | 22 | --wcag-textarea--font-size: var(--wcag-textarea--md--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/styles/dimensions/_large.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-checkbox--lg--gap: 1.6rem; 3 | 4 | --wcag-checkbox--lg--height: 5.6rem; 5 | --wcag-checkbox--lg--padding-inline: 2rem; 6 | --wcag-checkbox--lg--padding-block: 0; 7 | --wcag-checkbox--lg--border-width: 1px; 8 | --wcag-checkbox--lg--border-radius: 0.5rem; 9 | 10 | --wcag-checkbox--lg--font-size: 1.8rem; 11 | } 12 | 13 | [is="wcag-checkbox"][lg] { 14 | --wcag-checkbox--gap: var(--wcag-checkbox--lg--gap); 15 | 16 | --wcag-checkbox--height: var(--wcag-checkbox--lg--height); 17 | --wcag-checkbox--padding-inline: var(--wcag-checkbox--lg--padding-inline); 18 | --wcag-checkbox--padding-block: var(--wcag-checkbox--lg--padding-block); 19 | --wcag-checkbox--border-width: var(--wcag-checkbox--lg--border-width); 20 | --wcag-checkbox--border-radius: var(--wcag-checkbox--lg--border-radius); 21 | 22 | --wcag-checkbox--font-size: var(--wcag-checkbox--lg--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/styles/dimensions/_small.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-checkbox--sm--gap: 0.8rem; 3 | 4 | --wcag-checkbox--sm--height: 4rem; 5 | --wcag-checkbox--sm--padding-inline: 1.2rem; 6 | --wcag-checkbox--sm--padding-block: 0; 7 | --wcag-checkbox--sm--border-width: 1px; 8 | --wcag-checkbox--sm--border-radius: 0.35rem; 9 | 10 | --wcag-checkbox--sm--font-size: 1.4rem; 11 | } 12 | 13 | [is="wcag-checkbox"][sm] { 14 | --wcag-checkbox--gap: var(--wcag-checkbox--sm--gap); 15 | 16 | --wcag-checkbox--height: var(--wcag-checkbox--sm--height); 17 | --wcag-checkbox--padding-inline: var(--wcag-checkbox--sm--padding-inline); 18 | --wcag-checkbox--padding-block: var(--wcag-checkbox--sm--padding-block); 19 | --wcag-checkbox--border-width: var(--wcag-checkbox--sm--border-width); 20 | --wcag-checkbox--border-radius: var(--wcag-checkbox--sm--border-radius); 21 | 22 | --wcag-checkbox--font-size: var(--wcag-checkbox--sm--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/styles/dimensions/_large.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-textarea--lg--gap: 1.6rem; 3 | 4 | --wcag-textarea--lg--height: 5.6rem; 5 | --wcag-textarea--lg--padding-inline: 2rem; 6 | --wcag-textarea--lg--padding-block: 0; 7 | --wcag-textarea--lg--border-width: 1px; 8 | --wcag-textarea--lg--border-radius: 0.5rem; 9 | 10 | --wcag-textarea--lg--font-size: 1.8rem; 11 | } 12 | 13 | [is="wcag-textarea"][lg] { 14 | --wcag-textarea--gap: var(--wcag-textarea--lg--gap); 15 | 16 | --wcag-textarea--height: var(--wcag-textarea--lg--height); 17 | --wcag-textarea--padding-inline: var(--wcag-textarea--lg--padding-inline); 18 | --wcag-textarea--padding-block: var(--wcag-textarea--lg--padding-block); 19 | --wcag-textarea--border-width: var(--wcag-textarea--lg--border-width); 20 | --wcag-textarea--border-radius: var(--wcag-textarea--lg--border-radius); 21 | 22 | --wcag-textarea--font-size: var(--wcag-textarea--lg--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/styles/dimensions/_small.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wcag-textarea--sm--gap: 0.8rem; 3 | 4 | --wcag-textarea--sm--height: 4rem; 5 | --wcag-textarea--sm--padding-inline: 1.2rem; 6 | --wcag-textarea--sm--padding-block: 0; 7 | --wcag-textarea--sm--border-width: 1px; 8 | --wcag-textarea--sm--border-radius: 0.35rem; 9 | 10 | --wcag-textarea--sm--font-size: 1.4rem; 11 | } 12 | 13 | [is="wcag-textarea"][sm] { 14 | --wcag-textarea--gap: var(--wcag-textarea--sm--gap); 15 | 16 | --wcag-textarea--height: var(--wcag-textarea--sm--height); 17 | --wcag-textarea--padding-inline: var(--wcag-textarea--sm--padding-inline); 18 | --wcag-textarea--padding-block: var(--wcag-textarea--sm--padding-block); 19 | --wcag-textarea--border-width: var(--wcag-textarea--sm--border-width); 20 | --wcag-textarea--border-radius: var(--wcag-textarea--sm--border-radius); 21 | 22 | --wcag-textarea--font-size: var(--wcag-textarea--sm--font-size); 23 | } 24 | -------------------------------------------------------------------------------- /packages/js/dom/lib/_insertElement.js: -------------------------------------------------------------------------------- 1 | import { ensureElement } from './_ensureElement'; 2 | 3 | /** 4 | * @typedef TInsertPositions 5 | * @type {'before'|'prepend'|'append'|'after'} 6 | */ 7 | 8 | export const EInsertPositions = Object.freeze({ 9 | before: 'beforebegin', 10 | prepend: 'afterbegin', 11 | append: 'beforeend', 12 | after: 'afterend', 13 | }); 14 | 15 | /** 16 | * insert an element in a certain position respect to another element 17 | * 18 | * @param {Element|TElementOptions} elementOrOptions - the element to insert or the options of it 19 | * @param {Element} target - the target element 20 | * @param {TInsertPositions} position - where insert the element 21 | * @return {Element} the element 22 | */ 23 | export const insertElement = (elementOrOptions, target, position) => { 24 | const element = ensureElement(elementOrOptions); 25 | 26 | target.insertAdjacentElement(EInsertPositions[position], element); 27 | 28 | return element; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/css/grid-system/lib/_container-breakpoints.css: -------------------------------------------------------------------------------- 1 | 2 | /* iphone max */ 3 | @media screen and (width >= 414px) { 4 | :root { 5 | --wcag-gs--container--size: 375px; 6 | } 7 | } 8 | 9 | /* xs */ 10 | @media screen and (width >= 576px) { 11 | :root { 12 | --wcag-gs--container--size: 540px; 13 | } 14 | } 15 | 16 | /* sm */ 17 | @media screen and (width >= 768px) { 18 | :root { 19 | --wcag-gs--container--size: 720px; 20 | } 21 | } 22 | 23 | /* md */ 24 | @media screen and (width >= 1024px) { 25 | :root { 26 | --wcag-gs--container--size: 960px; 27 | } 28 | } 29 | 30 | /* lg */ 31 | @media screen and (width >= 1366px) { 32 | :root { 33 | --wcag-gs--container--size: 1200px; 34 | } 35 | } 36 | 37 | /* xl */ 38 | @media screen and (width >= 1600px) { 39 | :root { 40 | --wcag-gs--container--size: 1366px; 41 | } 42 | } 43 | 44 | /* xxl */ 45 | @media screen and (width >= 1920px) { 46 | :root { 47 | --wcag-gs--container--size: 1600px; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/js/core/lib/helpers/_files.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Normalizes an array of File or a FileList into a FileList instance. 3 | * 4 | * @param {File[] | FileList} fileArrayOrList 5 | * @returns {FileList} 6 | */ 7 | const buildFileList = (fileArrayOrList) => { 8 | if (fileArrayOrList instanceof FileList) { 9 | return fileArrayOrList; 10 | } 11 | 12 | const dataTransfer = new DataTransfer(); 13 | 14 | for (const file of fileArrayOrList) { 15 | dataTransfer.items.add(file); 16 | } 17 | 18 | return dataTransfer.files; 19 | }; 20 | 21 | /** 22 | * Normalizes an array of File or a FileList into a File[] array. 23 | * 24 | * @param {File[] | FileList} fileArrayOrList 25 | * @returns {File[]} 26 | */ 27 | const buildFileArray = (fileArrayOrList) => { 28 | if (Array.isArray(fileArrayOrList)) { 29 | return fileArrayOrList; 30 | } 31 | 32 | return Array.from(fileArrayOrList); 33 | }; 34 | 35 | const files = { 36 | buildFileList, 37 | buildFileArray, 38 | }; 39 | 40 | export { files }; 41 | -------------------------------------------------------------------------------- /scripts/_cli-utils.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Parses command line arguments in the format --key=value or --key. 3 | * Returns an object with key-value pairs. 4 | * 5 | * @example Parse CLI arguments 6 | * const args = parseArgs(process.argv); 7 | * // args = { foo: 'bar', dryRun: true } 8 | * 9 | * @export 10 | * @param {string[]} argv - Array of CLI arguments (usually process.argv) 11 | * @returns {Object} Parsed arguments as key-value pairs 12 | */ 13 | export function parseArgs(argv) { 14 | const args = {}; 15 | 16 | // Iterate over CLI arguments, skipping the first two (node and script path) 17 | for (const token of argv.slice(2)) { 18 | // Match --key or --key=value 19 | const m = token.match(/^--([^=\s]+)(?:=(.*))?$/); 20 | 21 | if (!m) { 22 | continue; 23 | } 24 | 25 | const key = m[1]; 26 | // If no value is provided, treat as boolean true 27 | const val = m[2] === undefined ? true : m[2]; 28 | args[key] = val; 29 | } 30 | 31 | return args; 32 | } 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /packages/js/dom/lib/_wrapElement.js: -------------------------------------------------------------------------------- 1 | import { ensureElement } from './_ensureElement'; 2 | import { insertElement } from './_insertElement'; 3 | /** 4 | * insert an element in a certain position respect to another element 5 | * 6 | * @param {Element|TElementOptions} elementOrOptions - the element to be wrapped or the options to build it 7 | * @param {Element|TElementOptions} wrapperElementOrOptions - the wrapperElement or the options to build it 8 | * @return {Element} the wrapper element 9 | */ 10 | export const wrapElement = (elementOrOptions, wrapperElementOrOptions) => { 11 | const element = ensureElement(elementOrOptions); 12 | const wrapperElement = ensureElement(wrapperElementOrOptions); 13 | 14 | // checks if the wrapperElement isConnected or not to the DOM, 15 | // if not the wrapperElement will be put before begin the element 16 | !wrapperElement.isConnected && insertElement(wrapperElement, element, 'before'); 17 | 18 | insertElement(element, wrapperElement, 'append'); 19 | 20 | return wrapperElement; 21 | }; 22 | -------------------------------------------------------------------------------- /src/common/header.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 15 | 16 | 21 | 26 | 31 | 32 |
33 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/github.svg: -------------------------------------------------------------------------------- 1 | 2 | github 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/js/core/lib/events/_cancelEvent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Cancels a DOM event by optionally calling preventDefault, stopPropagation, 3 | * and stopImmediatePropagation. 4 | * 5 | * Returns `false` for ergonomic usage inside handlers (e.g., `return cancelEvent(e)`). 6 | * If no event is provided, returns `undefined`. 7 | * 8 | * @param {Event} e - The DOM event to cancel. 9 | * @param {boolean} [preventDefault=true] - Whether to call `e.preventDefault()`. 10 | * @param {boolean} [stopPropagation=true] - Whether to call `e.stopPropagation()`. 11 | * @param {boolean} [stopImmediatePropagation=true] - Whether to call `e.stopImmediatePropagation()`. 12 | * @returns {false|undefined} 13 | */ 14 | export const cancelEvent = ( 15 | e, 16 | preventDefault = true, 17 | stopPropagation = true, 18 | stopImmediatePropagation = true 19 | ) => { 20 | if (!e) { 21 | return; 22 | } 23 | 24 | !!preventDefault && e.preventDefault(); 25 | !!stopPropagation && e.stopPropagation(); 26 | !!stopImmediatePropagation && e.stopImmediatePropagation(); 27 | 28 | return false; 29 | }; 30 | -------------------------------------------------------------------------------- /src/assets/background-image.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/js/core/lib/core.js: -------------------------------------------------------------------------------- 1 | import './polyfills'; 2 | 3 | import { componentDecorator } from './decorator'; 4 | import { encoding } from './encoding'; 5 | import { events } from './events'; 6 | import { helpers } from './helpers'; 7 | 8 | /** 9 | * Core global stylesheet used to declare CSS cascade layers for wcag-ui. 10 | * 11 | * Declares three layers in order: `wcag-ui.core`, `wcag-ui.foundations`, `wcag-ui.components`. 12 | * Consumers can import their own CSS within these layers to control precedence. 13 | */ 14 | export const coreStyleSheet = new CSSStyleSheet(); 15 | coreStyleSheet.replaceSync('@layer wcag-ui.core, wcag-ui.foundations, wcag-ui.components;'); 16 | 17 | // Attach the stylesheet using Constructable Stylesheets API. 18 | // Note: add a feature detection or fallback if you need to support older browsers. 19 | // Example: 20 | // if ('adoptedStyleSheets' in Document.prototype) { document.adoptedStyleSheets.push(coreStyleSheet); } 21 | document.adoptedStyleSheets.push(coreStyleSheet); 22 | 23 | // Public surface of the core package 24 | export { componentDecorator, encoding, events, helpers }; 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024-2025 Dev Dojo IT 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/demo-files/demo.js: -------------------------------------------------------------------------------- 1 | if (!('boxShadow' in document.body.style)) { 2 | document.body.setAttribute('class', 'noBoxShadow'); 3 | } 4 | 5 | document.body.addEventListener("click", (e) => { 6 | var target = e.target; 7 | if (target.tagName === "INPUT" && 8 | target.getAttribute('class').indexOf('liga') === -1) { 9 | target.select(); 10 | } 11 | }); 12 | 13 | ((() => { 14 | var fontSize = document.getElementById('fontSize'), 15 | testDrive = document.getElementById('testDrive'), 16 | testText = document.getElementById('testText'); 17 | function updateTest() { 18 | testDrive.innerHTML = testText.value || String.fromCharCode(160); 19 | if (window.icomoonLiga) { 20 | window.icomoonLiga(testDrive); 21 | } 22 | } 23 | function updateSize() { 24 | testDrive.style.fontSize = fontSize.value + 'px'; 25 | } 26 | fontSize.addEventListener('change', updateSize, false); 27 | testText.addEventListener('input', updateTest, false); 28 | testText.addEventListener('change', updateTest, false); 29 | updateSize(); 30 | })()); 31 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/dev-dojo.svg: -------------------------------------------------------------------------------- 1 | 2 | dev-dojo 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/components/input/lib/input.events.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | input: function (e) { 5 | console.log('input emitted input', this.ariaLabel); 6 | 7 | // style :user-invalid or :user-valid 8 | 9 | events.dispatchComponentEvent.call(this, 'input', { value: this.value }, e); 10 | }, 11 | change: function (e) { 12 | console.log('input emitted change', this.ariaLabel); 13 | 14 | // style :user-invalid or :user-valid 15 | 16 | events.dispatchComponentEvent.call(this, 'change', { value: this.value }, e); 17 | }, 18 | focus: function (e) { 19 | console.log('input emitted focus', this.ariaLabel); 20 | 21 | events.dispatchComponentEvent.call(this, 'focus', { value: this.value }, e); 22 | }, 23 | blur: function (e) { 24 | console.log('input emitted blur', this.ariaLabel); 25 | 26 | events.dispatchComponentEvent.call(this, 'blur', { value: this.value }, e); 27 | }, 28 | invalid: function (e) { 29 | console.log('input emitted invalid', this.ariaLabel); 30 | 31 | // style :user-invalid or :user-valid 32 | 33 | events.dispatchComponentEvent.call(this, 'invalid', { value: this.value }, e); 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /packages/components/radio/lib/radio.events.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | input: function (e) { 5 | console.log('radio emitted input', this.ariaLabel); 6 | 7 | // style :user-invalid or :user-valid 8 | 9 | events.dispatchComponentEvent.call(this, 'input', { value: this.value }, e); 10 | }, 11 | change: function (e) { 12 | console.log('radio emitted change', this.ariaLabel); 13 | 14 | // style :user-invalid or :user-valid 15 | 16 | events.dispatchComponentEvent.call(this, 'change', { value: this.value }, e); 17 | }, 18 | focus: function (e) { 19 | console.log('radio emitted focus', this.ariaLabel); 20 | 21 | events.dispatchComponentEvent.call(this, 'focus', { value: this.value }, e); 22 | }, 23 | blur: function (e) { 24 | console.log('radio emitted blur', this.ariaLabel); 25 | 26 | events.dispatchComponentEvent.call(this, 'blur', { value: this.value }, e); 27 | }, 28 | invalid: function (e) { 29 | console.log('radio emitted invalid', this.ariaLabel); 30 | 31 | // style :user-invalid or :user-valid 32 | 33 | events.dispatchComponentEvent.call(this, 'invalid', { value: this.value }, e); 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /packages/css/iconography/lib/fonts/wcag-icons/SVG/figma.svg: -------------------------------------------------------------------------------- 1 | 2 | figma 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/components/switch/lib/switch.events.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | input: function (e) { 5 | console.log('switch emitted input', this.ariaLabel); 6 | 7 | // style :user-invalid or :user-valid 8 | 9 | events.dispatchComponentEvent.call(this, 'input', { value: this.value }, e); 10 | }, 11 | change: function (e) { 12 | console.log('switch emitted change', this.ariaLabel); 13 | 14 | // style :user-invalid or :user-valid 15 | 16 | events.dispatchComponentEvent.call(this, 'change', { value: this.value }, e); 17 | }, 18 | focus: function (e) { 19 | console.log('switch emitted focus', this.ariaLabel); 20 | 21 | events.dispatchComponentEvent.call(this, 'focus', { value: this.value }, e); 22 | }, 23 | blur: function (e) { 24 | console.log('switch emitted blur', this.ariaLabel); 25 | 26 | events.dispatchComponentEvent.call(this, 'blur', { value: this.value }, e); 27 | }, 28 | invalid: function (e) { 29 | console.log('switch emitted invalid', this.ariaLabel); 30 | 31 | // style :user-invalid or :user-valid 32 | 33 | events.dispatchComponentEvent.call(this, 'invalid', { value: this.value }, e); 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /packages/components/checkbox/lib/checkbox.events.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | input: function (e) { 5 | console.log('checkbox emitted input', this.ariaLabel); 6 | 7 | // style :user-invalid or :user-valid 8 | 9 | events.dispatchComponentEvent.call(this, 'input', { value: this.value }, e); 10 | }, 11 | change: function (e) { 12 | console.log('checkbox emitted change', this.ariaLabel); 13 | 14 | // style :user-invalid or :user-valid 15 | 16 | events.dispatchComponentEvent.call(this, 'change', { value: this.value }, e); 17 | }, 18 | focus: function (e) { 19 | console.log('checkbox emitted focus', this.ariaLabel); 20 | 21 | events.dispatchComponentEvent.call(this, 'focus', { value: this.value }, e); 22 | }, 23 | blur: function (e) { 24 | console.log('checkbox emitted blur', this.ariaLabel); 25 | 26 | events.dispatchComponentEvent.call(this, 'blur', { value: this.value }, e); 27 | }, 28 | invalid: function (e) { 29 | console.log('checkbox emitted invalid', this.ariaLabel); 30 | 31 | // style :user-invalid or :user-valid 32 | 33 | events.dispatchComponentEvent.call(this, 'invalid', { value: this.value }, e); 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /packages/components/textarea/lib/textarea.events.js: -------------------------------------------------------------------------------- 1 | import { events } from '@wcag-ui/core'; 2 | 3 | export default { 4 | input: function (e) { 5 | console.log('textarea emitted input', this.ariaLabel); 6 | 7 | // style :user-invalid or :user-valid 8 | 9 | events.dispatchComponentEvent.call(this, 'input', { value: this.value }, e); 10 | }, 11 | change: function (e) { 12 | console.log('textarea emitted change', this.ariaLabel); 13 | 14 | // style :user-invalid or :user-valid 15 | 16 | events.dispatchComponentEvent.call(this, 'change', { value: this.value }, e); 17 | }, 18 | focus: function (e) { 19 | console.log('textarea emitted focus', this.ariaLabel); 20 | 21 | events.dispatchComponentEvent.call(this, 'focus', { value: this.value }, e); 22 | }, 23 | blur: function (e) { 24 | console.log('textarea emitted blur', this.ariaLabel); 25 | 26 | events.dispatchComponentEvent.call(this, 'blur', { value: this.value }, e); 27 | }, 28 | invalid: function (e) { 29 | console.log('textarea emitted invalid', this.ariaLabel); 30 | 31 | // style :user-invalid or :user-valid 32 | 33 | events.dispatchComponentEvent.call(this, 'invalid', { value: this.value }, e); 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /packages/js/core/lib/events/_dispatchCustomEvent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dispatches a namespaced CustomEvent. 3 | * 4 | * Event name format: `${eventNamespace}.${eventName}` (bubbling, cancelable). 5 | * 6 | * @param {string} eventNamespace - Namespace (e.g., component name/tag). 7 | * @param {string} eventName - Event name (e.g., "open", "close"). 8 | * @param {object} [detail={}] - Data to pass in `event.detail`. 9 | * @param {Event} [originalEvent=undefined] - Original DOM event to include in detail. 10 | * @param {EventTarget} [dispatcher=undefined] - Optional custom dispatcher (defaults to `this` or `self`). 11 | * @returns {void} 12 | */ 13 | export const dispatchCustomEvent = function ( 14 | eventNamespace, 15 | eventName, 16 | detail = {}, 17 | originalEvent = undefined, 18 | dispatcher = undefined 19 | ) { 20 | dispatcher = dispatcher ?? this ?? self; 21 | 22 | const event = new CustomEvent(`${eventNamespace}.${eventName}`, { 23 | bubbles: true, 24 | cancelable: true, 25 | detail: { 26 | ...detail, 27 | ...(originalEvent && { originalEvent }), 28 | }, 29 | }); 30 | 31 | // Optional: instrument here if you need debug logs for emitted events. 32 | 33 | dispatcher.dispatchEvent(event); 34 | }; 35 | -------------------------------------------------------------------------------- /src/styles/layout/_header.css: -------------------------------------------------------------------------------- 1 | body > header { 2 | --wcag-t--font-size: var(--docs--header--font-size); 3 | 4 | grid-area: header; 5 | 6 | position: sticky; 7 | inset-block-start: 0; 8 | z-index: 3; 9 | 10 | display: flex; 11 | place-content: space-between; 12 | place-items: center; 13 | gap: 2rem; 14 | flex-flow: column nowrap; 15 | 16 | color: var(--docs--header--color); 17 | background-color: var(--docs--header--background-color); 18 | box-shadow: var(--docs--header--box-shadow); 19 | 20 | min-block-size: var(--docs--header--min-height); 21 | padding-inline: var(--docs--header--padding-inline); 22 | padding-block: 0 1.5rem; 23 | 24 | @media screen and (width >= 1024px) { 25 | flex-flow: row nowrap; 26 | 27 | padding-block: 0; 28 | } 29 | 30 | a { 31 | --wcag-t--text-decoration: none; 32 | 33 | &[logo] { 34 | --wcag-t--font-size: var(--docs--header--logo--height); 35 | 36 | display: inline-block; 37 | inline-size: 14.6rem; 38 | block-size: 6.5rem; 39 | 40 | padding-inline: 0.5rem; 41 | border-radius: var(--docs--header--menu--border-radius); 42 | 43 | color: var(--docs--header--logo--color); 44 | } 45 | } 46 | 47 | i { 48 | display: inline-block; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /scripts/unpublish.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import { execSync } from 'node:child_process'; 3 | import fs from 'node:fs'; 4 | import path from 'node:path'; 5 | import { collectPackageJson } from './_package-utils.mjs'; 6 | 7 | const root = process.cwd(); 8 | 9 | /** 10 | * Unpublishes all local packages found in the packages directory. 11 | * Uses npm unpublish with --force for each package and logs the result. 12 | * 13 | * @example Unpublish all local packages 14 | * // Run this script from the project root 15 | */ 16 | const packageJsonPaths = collectPackageJson(path.join(root, 'packages')); 17 | 18 | for (const file of packageJsonPaths) { 19 | const { name, version } = JSON.parse(fs.readFileSync(file, 'utf8')); 20 | try { 21 | console.log(`\u23F4 Unpublish ${name}@${version}`); 22 | execSync(`npm unpublish ${name}@${version} --force`, { stdio: 'inherit' }); 23 | } catch (err) { 24 | console.error(`⚠️ Impossible to unpublish ${name}@${version}:`, err.message); 25 | } 26 | } 27 | 28 | // Optionally, remove associated git tag for the version just unpublished: 29 | // const tag = `v${JSON.parse(fs.readFileSync(packageJsonPaths[0], 'utf8')).version}`; 30 | // execSync(`git tag -d ${tag}`); 31 | // execSync(`git push origin :refs/tags/${tag}`); 32 | -------------------------------------------------------------------------------- /packages/js/dom/lib/_insertHTML.js: -------------------------------------------------------------------------------- 1 | import { sanitizeHTML } from './_sanitizeHTML'; 2 | 3 | /** 4 | * Inserts a sanitized HTML code in a certain position relative to another element. 5 | * 6 | * @param {string} html - the HTML code to be inserted in the targetElement 7 | * @param {HTMLElement} targetElement - the target element where the insertion will happen 8 | * @param {TInsertPositions} position - the position where to insert the element (before='beforebegin', prepend='afterbegin', append='beforeend', after='afterend') 9 | * @param {boolean} [emptyTarget=false] - specifies if the targetElement should be emptied before insertion 10 | * @return {NodeList} The inserted elements NodeList 11 | */ 12 | export const insertHTML = (html, targetElement, position, emptyTarget = false) => { 13 | emptyTarget && (targetElement.innerHTML = ''); 14 | 15 | const sanitizedDOM = sanitizeHTML(html, true); 16 | 17 | const fragment = document.createDocumentFragment(); 18 | fragment.append(...sanitizedDOM); 19 | 20 | // position === 'beforebegin' && target.before(fragment); 21 | // position === 'afterbegin' && target.prepend(fragment); 22 | // position === 'beforeend' && target.append(fragment); 23 | // position === 'afterend' && target.after(fragment); 24 | targetElement[position ?? 'append'](fragment); 25 | 26 | return sanitizedDOM; 27 | }; 28 | -------------------------------------------------------------------------------- /src/styles/layout/_core.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: "InterVariable", sans-serif; 3 | font-optical-sizing: auto; 4 | font-weight: var(--wcag-t--variant--weight); 5 | font-variation-settings: 6 | "opsz" var(--wcag-t--variant--opsz), 7 | "wght" var(--wcag-t--variant--weight); 8 | } 9 | 10 | html { 11 | inline-size: 100vw; 12 | min-block-size: 100vh; 13 | } 14 | 15 | body { 16 | display: grid; 17 | grid-template-columns: var(--docs--aside--width) 1fr var(--docs--scroll-spy--width); 18 | grid-template-rows: auto 1fr auto; 19 | grid-template-areas: 20 | "header header header" 21 | "aside main -" 22 | "footer footer footer"; 23 | 24 | background-color: var(--docs--background-color); 25 | background-image: url("../../assets/background-image.svg"); 26 | background-size: 100vw auto; 27 | background-repeat: repeat-y; 28 | 29 | inline-size: 100vw; 30 | min-block-size: 100vh; 31 | } 32 | 33 | @media screen and (width >= 1366px) { 34 | body { 35 | grid-template-rows: var(--docs--header--min-height) 1fr var(--docs--footer--min-height); 36 | 37 | grid-template-areas: 38 | "header header header" 39 | "aside main scroll-spy" 40 | "footer footer footer"; 41 | } 42 | } 43 | 44 | a { 45 | --wcag-f--outline-offset: calc(var(--wcag-f--outline-width) * 2); 46 | 47 | border-radius: 0.4rem; 48 | } 49 | -------------------------------------------------------------------------------- /src/_layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | wcagUI - {{title}} 8 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 33 |
34 | 35 |
36 | 37 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /packages/components/button/lib/button.js: -------------------------------------------------------------------------------- 1 | import { componentDecorator } from '@wcag-ui/core'; 2 | 3 | import attributes from './button.attributes'; 4 | import events from './button.events'; 5 | 6 | /** 7 | * wcagUI Button class 8 | * 9 | * @export 10 | * @class Button 11 | * @extends {HTMLButtonElement} 12 | */ 13 | export class Button extends HTMLButtonElement { 14 | static extendsElement = 'button'; 15 | static attributes = attributes; 16 | static events = events; 17 | 18 | /** 19 | * static initialization block 20 | * 21 | * @static 22 | * @memberof Button 23 | */ 24 | static { 25 | componentDecorator(this); 26 | } 27 | 28 | constructor() { 29 | super(); 30 | 31 | this.#init(); 32 | } 33 | 34 | #init() { 35 | !this.hasAttribute('type') && this.setAttribute('type', 'button'); 36 | // !this.hasAttribute("role") && this.setAttribute("role", "button"); 37 | } 38 | } 39 | 40 | // 48 | // 49 | 50 | // import '@wcag-ui/button'; 51 | // import '@wcag-ui/button/button.css'; 52 | 53 | // before: