├── .babelrc
├── .eslintrc.cjs
├── .gitignore
├── .npmrc
├── .prettierrc
├── LICENSE.md
├── README.md
├── jest.config.ts
├── package-lock.json
├── package.json
├── package
├── .gitignore
├── Accordion.svelte
├── Accordion.svelte.d.ts
├── Accordion
│ ├── AccordionButton.svelte
│ ├── AccordionButton.svelte.d.ts
│ ├── AccordionHeader.svelte
│ ├── AccordionHeader.svelte.d.ts
│ ├── AccordionItem.svelte
│ ├── AccordionItem.svelte.d.ts
│ ├── AccordionPanel.svelte
│ ├── AccordionPanel.svelte.d.ts
│ ├── AccordionTypes.d.ts
│ └── AccordionTypes.js
├── Button.svelte
├── Button.svelte.d.ts
├── Checkbox.svelte
├── Checkbox.svelte.d.ts
├── Meter.svelte
├── Meter.svelte.d.ts
├── NavBar.svelte
├── NavBar.svelte.d.ts
├── NavBar
│ ├── NavBarHeader.svelte
│ ├── NavBarHeader.svelte.d.ts
│ ├── NavBarLists.svelte
│ ├── NavBarLists.svelte.d.ts
│ ├── NavBarOptions.svelte
│ ├── NavBarOptions.svelte.d.ts
│ ├── NavBarTypes.d.ts
│ └── NavBarTypes.js
├── README.md
├── Table.svelte
├── Table.svelte.d.ts
├── TextInput.svelte
├── TextInput.svelte.d.ts
└── package.json
├── src
├── __tests__
│ ├── Accordion.spec.js
│ ├── Button.spec.js
│ ├── Checkbox.spec.js
│ ├── Meter.spec.js
│ ├── NavBar.spec.js
│ ├── Radio.spec.js
│ ├── Table.spec.js
│ └── TextInput.spec.js
├── app.d.ts
├── app.html
├── app.scss
├── components
│ ├── NavBar-website.svelte
│ └── about-info.svelte
├── images
│ ├── Github-logo-circle-purple.png
│ ├── Github-logo-white.png
│ ├── Github-logo.png
│ ├── LinkedIn-logo-circle-purple.png
│ ├── LinkedIn-logo-white-circle.png
│ ├── LinkedIn-logo.png
│ ├── bekFancy.png
│ ├── paulFancy.png
│ ├── simonFancy.png
│ ├── svve11-logo-cropped-blue.png
│ ├── svve11-logo-cropped-purple-transparent.png
│ ├── svve11-logo-notext.png
│ ├── svve11-logo-square-purple.jpg
│ ├── svve11-logo-white-transparent-cropped.png
│ ├── svve11-logo-white.png
│ ├── tech-icons
│ │ ├── Firefox_logo_2019.svg
│ │ ├── JAWS-screenreader-logo.png
│ │ ├── Microsoft_Edge_logo_(2019).svg
│ │ ├── Safari_browser_logo.svg
│ │ ├── chrome-logo.svg
│ │ ├── jest-logo-F9901EBBF7-seeklogo.com.png
│ │ ├── nvda_200x200.png
│ │ └── voiceover_logo.png
│ └── timFancy.png
├── lib
│ ├── Accordion.svelte
│ ├── Accordion
│ │ ├── AccordionButton.svelte
│ │ ├── AccordionHeader.svelte
│ │ ├── AccordionItem.svelte
│ │ ├── AccordionPanel.svelte
│ │ └── AccordionTypes.ts
│ ├── Button.svelte
│ ├── Checkbox.svelte
│ ├── Meter.svelte
│ ├── NavBar.svelte
│ ├── NavBar
│ │ ├── NavBarHeader.svelte
│ │ ├── NavBarLists.svelte
│ │ ├── NavBarOptions.svelte
│ │ └── NavBarTypes.ts
│ ├── Table.svelte
│ └── TextInput.svelte
├── pending
│ ├── ImageLink.svelte
│ └── RadioButton.svelte
├── routes
│ ├── __layout.svelte
│ ├── about.svelte
│ ├── index.svelte
│ └── pages
│ │ ├── accordion.svelte
│ │ ├── button.svelte
│ │ ├── checkbox.svelte
│ │ ├── meter.svelte
│ │ ├── navbar.svelte
│ │ ├── radiobutton.svelte
│ │ ├── table.svelte
│ │ ├── tableStyles.js
│ │ └── textinput.svelte
└── stylesheets
│ └── variables.scss
├── static
└── favicon.png
├── svelte.config.js
└── tsconfig.json
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [["@babel/preset-env", { "targets": { "node": "current" } }]]
3 | }
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: '@typescript-eslint/parser',
4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
5 | plugins: ['svelte3', '@typescript-eslint'],
6 | ignorePatterns: ['*.cjs'],
7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
8 | settings: {
9 | 'svelte3/typescript': () => require('typescript')
10 | },
11 | parserOptions: {
12 | sourceType: 'module',
13 | ecmaVersion: 2020
14 | },
15 | env: {
16 | browser: true,
17 | es2017: true,
18 | node: true
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | .env
6 | .env.*
7 | !.env.example
8 | /coverage
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true;
2 | global=false;
3 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "useTabs": true,
3 | "singleQuote": true,
4 | "trailingComma": "none",
5 | "printWidth": 100
6 | }
7 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Simon H Lee
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 |
--------------------------------------------------------------------------------
/jest.config.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | transform: {
3 | "^.+\\.js$": "babel-jest",
4 | "^.+\\.svelte$": ["svelte-jester", { preprocess: true }],
5 | "^.+\\.ts$": "ts-jest",
6 | },
7 | moduleFileExtensions: [
8 | "js",
9 | "ts",
10 | "svelte"
11 | ],
12 | verbose: true,
13 | moduleNameMapper: {
14 | "^\\$lib/(.*)": "./src/lib/$1",
15 | },
16 | collectCoverage: true,
17 | coverageDirectory: "coverage",
18 | testEnvironment: "jsdom",
19 | };
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svve11",
3 | "version": "1.1.0",
4 | "scripts": {
5 | "dev": "svelte-kit dev",
6 | "build": "svelte-kit build",
7 | "package": "svelte-kit package",
8 | "preview": "svelte-kit preview",
9 | "prepare": "svelte-kit sync",
10 | "check": "svelte-check --tsconfig ./tsconfig.json",
11 | "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
12 | "lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
13 | "format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. .",
14 | "test": "jest"
15 | },
16 | "exports": {
17 | ".": "./src/lib"
18 | },
19 | "devDependencies": {
20 | "@babel/preset-env": "^7.18.0",
21 | "@sveltejs/adapter-auto": "next",
22 | "@sveltejs/kit": "next",
23 | "@testing-library/jest-dom": "^5.16.4",
24 | "@testing-library/svelte": "^3.1.1",
25 | "@testing-library/user-event": "^14.2.0",
26 | "@typescript-eslint/eslint-plugin": "^5.10.1",
27 | "@typescript-eslint/parser": "^5.10.1",
28 | "babel-jest": "^28.1.0",
29 | "eslint": "^8.12.0",
30 | "eslint-config-prettier": "^8.3.0",
31 | "eslint-plugin-svelte3": "^4.0.0",
32 | "jest": "^28.1.0",
33 | "jest-environment-jsdom": "^28.1.0",
34 | "prettier": "^2.5.1",
35 | "prettier-plugin-svelte": "^2.5.0",
36 | "sass": "^1.52.1",
37 | "svelte": "^3.44.0",
38 | "svelte-check": "^2.2.6",
39 | "svelte-jester": "^2.3.2",
40 | "svelte-preprocess": "^4.10.6",
41 | "svelte2tsx": "^0.5.10",
42 | "ts-jest": "^28.0.2",
43 | "ts-node": "^10.8.0",
44 | "tslib": "^2.3.1",
45 | "typescript": "~4.6.2"
46 | },
47 | "type": "module",
48 | "dependencies": {
49 | "svve11": "^0.0.1"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/package/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | .env
6 | .env.*
7 | !.env.example
8 | /coverage
--------------------------------------------------------------------------------
/package/Accordion.svelte:
--------------------------------------------------------------------------------
1 |
65 |
66 |
83 |
84 |
86 |
91 |
97 | {#each options.panelInfo as info, i}
98 |
105 | {/each}
106 |
107 |
108 |
109 |
119 |
--------------------------------------------------------------------------------
/package/Accordion.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | import type { optionsTypes } from './Accordion/AccordionTypes';
3 | declare const __propDef: {
4 | props: {
5 | options?: optionsTypes | undefined;
6 | };
7 | events: {
8 | [evt: string]: CustomEvent;
9 | };
10 | slots: {};
11 | };
12 | export declare type AccordionProps = typeof __propDef.props;
13 | export declare type AccordionEvents = typeof __propDef.events;
14 | export declare type AccordionSlots = typeof __propDef.slots;
15 | /**
16 | * Props are passed in through the options object which contains the following properties:
17 | * ```tsx
18 | * panelInfo: array of objects (required)
19 | * Each object in the array contains:
20 | * - id: number (required)
21 | * - panelContent: string (required)
22 | * - headerTitle: string (required)
23 | * headerLevel: number (required)
24 | * styles: an object with (4) properties (optional)
25 | * - accordionHeaderStyle: string (optional)
26 | * - accordionPanelStyle: string (optional)
27 | * - accordionItemStyle: string (optional)
28 | * - overallAccordionStyle: string (optional)
29 | * multiselectable:boolean (optional)
30 | * ```
31 | */
32 | export default class Accordion extends SvelteComponentTyped {
33 | }
34 | export {};
35 |
--------------------------------------------------------------------------------
/package/Accordion/AccordionButton.svelte:
--------------------------------------------------------------------------------
1 |
19 |
20 |
25 |
37 |
38 |
50 |
--------------------------------------------------------------------------------
/package/Accordion/AccordionButton.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | declare const __propDef: {
3 | props: {
4 | headerTitle: string;
5 | controls: string;
6 | id: string;
7 | customStyles: accordionStylesObject;
8 | textToRead: string;
9 | isOpen: boolean;
10 | };
11 | events: {
12 | updatePanelStates: CustomEvent<{
13 | target: string;
14 | }>;
15 | } & {
16 | [evt: string]: CustomEvent;
17 | };
18 | slots: {};
19 | };
20 | export declare type AccordionButtonProps = typeof __propDef.props;
21 | export declare type AccordionButtonEvents = typeof __propDef.events;
22 | export declare type AccordionButtonSlots = typeof __propDef.slots;
23 | export default class AccordionButton extends SvelteComponentTyped {
24 | }
25 | export {};
26 |
--------------------------------------------------------------------------------
/package/Accordion/AccordionHeader.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
16 |
33 |
34 |
40 |
--------------------------------------------------------------------------------
/package/Accordion/AccordionHeader.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | declare const __propDef: {
3 | props: {
4 | headerLevel?: number | undefined;
5 | headerTitle: string;
6 | controls?: string | undefined;
7 | customStyles: accordionStylesObject;
8 | textToRead?: string | undefined;
9 | id: string;
10 | isOpen: boolean;
11 | };
12 | events: {
13 | updatePanelStates: CustomEvent<{
14 | target: string;
15 | }>;
16 | } & {
17 | [evt: string]: CustomEvent;
18 | };
19 | slots: {};
20 | };
21 | export declare type AccordionHeaderProps = typeof __propDef.props;
22 | export declare type AccordionHeaderEvents = typeof __propDef.events;
23 | export declare type AccordionHeaderSlots = typeof __propDef.slots;
24 | export default class AccordionHeader extends SvelteComponentTyped {
25 | }
26 | export {};
27 |
--------------------------------------------------------------------------------
/package/Accordion/AccordionItem.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
16 |
17 |
26 |
36 |
37 |
43 |
50 |
51 |
52 |
53 |
59 |
--------------------------------------------------------------------------------
/package/Accordion/AccordionItem.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | import type { panelInfoTypes, accordionStylesObjectTypes } from './AccordionTypes';
3 | declare const __propDef: {
4 | props: {
5 | options: panelInfoTypes;
6 | headerLevel?: number | undefined;
7 | customStyles: accordionStylesObjectTypes;
8 | isOpen: boolean;
9 | };
10 | events: {
11 | updatePanelStates: CustomEvent<{
12 | target: string;
13 | }>;
14 | } & {
15 | [evt: string]: CustomEvent;
16 | };
17 | slots: {};
18 | };
19 | export declare type AccordionItemProps = typeof __propDef.props;
20 | export declare type AccordionItemEvents = typeof __propDef.events;
21 | export declare type AccordionItemSlots = typeof __propDef.slots;
22 | export default class AccordionItem extends SvelteComponentTyped {
23 | }
24 | export {};
25 |
--------------------------------------------------------------------------------
/package/Accordion/AccordionPanel.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
14 |
22 |
23 | {#if isOpen}
24 |
{panelContent}
25 | {/if}
26 |
27 |
28 |
29 |
43 |
--------------------------------------------------------------------------------
/package/Accordion/AccordionPanel.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | declare const __propDef: {
3 | props: {
4 | panelContent?: string | undefined;
5 | isOpen: boolean;
6 | panelID: string;
7 | labeledBy: string;
8 | style?: string | undefined;
9 | };
10 | events: {
11 | [evt: string]: CustomEvent;
12 | };
13 | slots: {};
14 | };
15 | export declare type AccordionPanelProps = typeof __propDef.props;
16 | export declare type AccordionPanelEvents = typeof __propDef.events;
17 | export declare type AccordionPanelSlots = typeof __propDef.slots;
18 | export default class AccordionPanel extends SvelteComponentTyped {
19 | }
20 | export {};
21 |
--------------------------------------------------------------------------------
/package/Accordion/AccordionTypes.d.ts:
--------------------------------------------------------------------------------
1 | export declare type panelInfoTypes = {
2 | id: number | string;
3 | panelContent: string;
4 | headerTitle: string;
5 | };
6 | export declare type optionsTypes = {
7 | multiselectable: boolean;
8 | headerLevel: (number | undefined);
9 | panelInfo: panelInfoTypes[];
10 | styles?: accordionStylesObjectTypes;
11 | };
12 | export declare type accordionStylesObjectTypes = {
13 | accordionHeaderStyle?: string;
14 | accordionPanelStyle?: string;
15 | accordionItemStyle?: string;
16 | overallAccordionStyle?: string;
17 | };
18 |
--------------------------------------------------------------------------------
/package/Accordion/AccordionTypes.js:
--------------------------------------------------------------------------------
1 | export {};
2 |
--------------------------------------------------------------------------------
/package/Button.svelte:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
20 |
21 |
22 |
25 |
26 |
27 |
35 |
--------------------------------------------------------------------------------
/package/Button.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | declare const __propDef: {
3 | props: {
4 | options?: {
5 | handleClick: () => void;
6 | content: string | null;
7 | label: string | null;
8 | id?: string | null | undefined;
9 | style?: string | null | undefined;
10 | } | undefined;
11 | };
12 | events: {
13 | [evt: string]: CustomEvent;
14 | };
15 | slots: {};
16 | };
17 | export declare type ButtonProps = typeof __propDef.props;
18 | export declare type ButtonEvents = typeof __propDef.events;
19 | export declare type ButtonSlots = typeof __propDef.slots;
20 | /**
21 | * Props are passed in through the options object which contains the following properties:
22 | * ```tsx
23 | * label: string (required)
24 | * content: string (required)
25 | * handleClick: function (required)
26 | * id: string (optional)
27 | * style: string (optional)
28 | * ```
29 | */
30 | export default class Button extends SvelteComponentTyped {
31 | }
32 | export {};
33 |
--------------------------------------------------------------------------------
/package/Checkbox.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
28 |
29 |
30 |
40 |
41 |
42 |
45 |
46 |
48 |
--------------------------------------------------------------------------------
/package/Checkbox.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | declare const __propDef: {
3 | props: {
4 | options?: {
5 | checkBoxLabel: string | null;
6 | id: string | null;
7 | checked: boolean;
8 | checkBoxStyle?: string | null | undefined;
9 | checkBoxLabelStyle?: string | null | undefined;
10 | name?: string | null | undefined;
11 | value?: string | null | undefined;
12 | } | undefined;
13 | defaultStyle?: string | undefined;
14 | };
15 | events: {
16 | [evt: string]: CustomEvent;
17 | };
18 | slots: {};
19 | };
20 | export declare type CheckboxProps = typeof __propDef.props;
21 | export declare type CheckboxEvents = typeof __propDef.events;
22 | export declare type CheckboxSlots = typeof __propDef.slots;
23 | /**
24 | * Props are passed in through the options object which contains the following properties:
25 | * ```tsx
26 | * id: string (required)
27 | * checkBoxLabel: string (required)
28 | *
29 | * checkBoxStyle: number (string)
30 | * checked: boolean (optional)
31 | * checkBoxLabelStyle: string (optional)
32 | * name: string (optional)
33 | * value: string (optional)
34 | * ```
35 | */
36 | export default class Checkbox extends SvelteComponentTyped {
37 | }
38 | export {};
39 |
--------------------------------------------------------------------------------
/package/Meter.svelte:
--------------------------------------------------------------------------------
1 |
48 |
49 |
69 |
70 |
78 |
79 |
96 |
97 |
99 |
--------------------------------------------------------------------------------
/package/Meter.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | declare const __propDef: {
3 | props: {
4 | options?: {
5 | maxValue: number;
6 | minValue: number;
7 | meterLabel: string | null;
8 | id: string | number | null;
9 | lowValue?: number | null | undefined;
10 | highValue?: number | null | undefined;
11 | optimumValue?: number | null | undefined;
12 | valueText?: string | null | undefined;
13 | displayDecimal?: boolean | undefined;
14 | units?: string | null | undefined;
15 | meterStyle?: string | null | undefined;
16 | labelStyle?: string | null | undefined;
17 | } | undefined;
18 | value: number;
19 | };
20 | events: {
21 | [evt: string]: CustomEvent;
22 | };
23 | slots: {};
24 | };
25 | export declare type MeterProps = typeof __propDef.props;
26 | export declare type MeterEvents = typeof __propDef.events;
27 | export declare type MeterSlots = typeof __propDef.slots;
28 | /**
29 | * Props are passed in through an options object, except for the value which is a separate attribute.
30 | * Options should be defined by an object containing the following properties
31 | * ```tsx
32 | * value: number (required) - Passed as separate attribute
33 | * maxValue: number (required)
34 | * minValue: number (required)
35 | * meterLabel: string (required)
36 | * id: number (required)
37 | *
38 | * lowValue: number (optional)
39 | * highValue : number (optional)
40 | * optimumValue : number (optional)
41 | * valueText : string (optional)
42 | * displayDecimal : boolean (optional)
43 | * units : string (optional)
44 | * meterStyle : string (optional)
45 | * labelStyle : string (optional)
46 | * ```
47 | */
48 | export default class Meter extends SvelteComponentTyped {
49 | }
50 | export {};
51 |
--------------------------------------------------------------------------------
/package/NavBar.svelte:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
27 |
28 |
29 |
30 |
34 |
35 |
36 |
38 |
--------------------------------------------------------------------------------
/package/NavBar.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | import type { optionsTypes } from './NavBar/NavBarTypes';
3 | declare const __propDef: {
4 | props: {
5 | options?: optionsTypes | undefined;
6 | };
7 | events: {
8 | [evt: string]: CustomEvent;
9 | };
10 | slots: {};
11 | };
12 | export declare type NavBarProps = typeof __propDef.props;
13 | export declare type NavBarEvents = typeof __propDef.events;
14 | export declare type NavBarSlots = typeof __propDef.slots;
15 | /**
16 | * Props are passed in through the options object which contains the following properties:
17 | * ```tsx
18 | * contentInfo : array of objects (required)
19 | * Each object in the array contains:
20 | * - subheading: string (optional)
21 | * - option: an array of strings (required)
22 | * - links: array (required)
23 | *
24 | * id: string (optional)
25 | * header: string (optional)
26 | * imgSrc: string (optional)
27 | * imgClass: string (optional)
28 | * imgAlt: string (optional)
29 | * ```
30 | */
31 | export default class NavBar extends SvelteComponentTyped {
32 | }
33 | export {};
34 |
--------------------------------------------------------------------------------
/package/NavBar/NavBarHeader.svelte:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 | {#if header}
16 |
17 | {/if}
18 |
19 | >
20 | {#if imgSrc}
21 |
22 | {/if}
23 |
24 |
25 |
27 |
--------------------------------------------------------------------------------
/package/NavBar/NavBarHeader.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | declare const __propDef: {
3 | props: {
4 | header: string;
5 | imgSrc: string;
6 | imgClass: string;
7 | imgAlt: string;
8 | };
9 | events: {
10 | [evt: string]: CustomEvent;
11 | };
12 | slots: {};
13 | };
14 | export declare type NavBarHeaderProps = typeof __propDef.props;
15 | export declare type NavBarHeaderEvents = typeof __propDef.events;
16 | export declare type NavBarHeaderSlots = typeof __propDef.slots;
17 | export default class NavBarHeader extends SvelteComponentTyped {
18 | }
19 | export {};
20 |
--------------------------------------------------------------------------------
/package/NavBar/NavBarLists.svelte:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 | {#if subheading}
13 |
14 | {/if}
15 |
16 |
17 |
18 | {#each options as option, i}
19 | -
20 | {option}
21 |
22 | {/each}
23 |
24 |
25 |
26 |
28 |
--------------------------------------------------------------------------------
/package/NavBar/NavBarLists.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | declare const __propDef: {
3 | props: {
4 | subheading: string;
5 | options?: string[] | undefined;
6 | links?: string[] | undefined;
7 | };
8 | events: {
9 | [evt: string]: CustomEvent;
10 | };
11 | slots: {};
12 | };
13 | export declare type NavBarListsProps = typeof __propDef.props;
14 | export declare type NavBarListsEvents = typeof __propDef.events;
15 | export declare type NavBarListsSlots = typeof __propDef.slots;
16 | export default class NavBarLists extends SvelteComponentTyped {
17 | }
18 | export {};
19 |
--------------------------------------------------------------------------------
/package/NavBar/NavBarOptions.svelte:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 | {#each contentInfo as content, i}
12 |
13 | {/each}
14 |
15 |
16 |
21 |
--------------------------------------------------------------------------------
/package/NavBar/NavBarOptions.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | import type { sectionTypes } from './NavBarTypes';
3 | declare const __propDef: {
4 | props: {
5 | contentInfo?: sectionTypes[] | undefined;
6 | };
7 | events: {
8 | [evt: string]: CustomEvent;
9 | };
10 | slots: {};
11 | };
12 | export declare type NavBarOptionsProps = typeof __propDef.props;
13 | export declare type NavBarOptionsEvents = typeof __propDef.events;
14 | export declare type NavBarOptionsSlots = typeof __propDef.slots;
15 | export default class NavBarOptions extends SvelteComponentTyped {
16 | }
17 | export {};
18 |
--------------------------------------------------------------------------------
/package/NavBar/NavBarTypes.d.ts:
--------------------------------------------------------------------------------
1 | export declare type optionsTypes = {
2 | id?: string;
3 | header?: string;
4 | imgSrc?: string;
5 | imgClass?: string;
6 | imgAlt?: string;
7 | contentInfo: sectionTypes[];
8 | };
9 | export declare type sectionTypes = {
10 | subheading?: string;
11 | options: string[];
12 | links: string[];
13 | };
14 |
--------------------------------------------------------------------------------
/package/NavBar/NavBarTypes.js:
--------------------------------------------------------------------------------
1 | export {};
2 |
--------------------------------------------------------------------------------
/package/Table.svelte:
--------------------------------------------------------------------------------
1 |
2 |
29 |
30 |
31 |
50 |
51 |
58 |
59 |
64 | {ariaDescription}
65 |
66 |
67 |
68 |
69 |
75 |
76 |
77 |
78 | {#each rowsContent as rowContent, i}
79 |
80 |
81 | {#each rowContent as cellContent}
82 |
83 | {cellContent} |
92 | {/each}
93 |
94 | {/each}
95 |
96 |
97 |
98 |
99 |
100 |
111 |
--------------------------------------------------------------------------------
/package/Table.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | declare const __propDef: {
3 | props: {
4 | options?: {
5 | id: string;
6 | ariaLabel: string;
7 | ariaDescription: string;
8 | columnNames: string[];
9 | rowsContent: string[][];
10 | styles?: {
11 | overallStyles?: string | undefined;
12 | titleStyles?: string | undefined;
13 | headersRowStyles?: string | undefined;
14 | generalRowStyles?: string | undefined;
15 | oddRowStyles?: string | undefined;
16 | evenRowStyles?: string | undefined;
17 | } | undefined;
18 | } | undefined;
19 | };
20 | events: {
21 | [evt: string]: CustomEvent;
22 | };
23 | slots: {};
24 | };
25 | export declare type TableProps = typeof __propDef.props;
26 | export declare type TableEvents = typeof __propDef.events;
27 | export declare type TableSlots = typeof __propDef.slots;
28 | /**
29 | * https://svve11.io/pages/table
30 | *
31 | * Props are passed in through the options object that contains the following properties:
32 | * ```tsx
33 | * id: string (required)
34 | * ariaLabel: string (required)
35 | * ariaDescription: string (required)
36 | * columnNames: array of string (required)
37 | * rowsContent: array of arrays of strings (required)
38 | * styles: object (optional)
39 | * - overallStyles:string (optional)
40 | * - titleStyles:string (optional)
41 | * - headersRowStyles:string (optional)
42 | * - generalRowStyles:string (optional)
43 | * - oddRowStyles:string (optional)
44 | * - evenRowStyles:string (optional)
45 | * ```
46 | */
47 | export default class Table extends SvelteComponentTyped {
48 | }
49 | export {};
50 |
--------------------------------------------------------------------------------
/package/TextInput.svelte:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
22 |
23 |
26 |
43 |
44 |
45 |
47 |
--------------------------------------------------------------------------------
/package/TextInput.svelte.d.ts:
--------------------------------------------------------------------------------
1 | import { SvelteComponentTyped } from "svelte";
2 | declare const __propDef: {
3 | props: {
4 | options?: {
5 | label: string | null;
6 | placeholder: string | null;
7 | id: string | null;
8 | type: ("" | "number" | "date" | "datetime-local" | "email" | "month" | "password" | "tel" | "text" | "time" | "url" | "week") | null;
9 | max?: number | null | undefined;
10 | min?: number | null | undefined;
11 | maxlength?: number | null | undefined;
12 | size?: number | null | undefined;
13 | step?: number | null | undefined;
14 | inputStyle?: string | null | undefined;
15 | labelStyle?: string | null | undefined;
16 | autocomplete?: boolean | undefined;
17 | disabled?: boolean | undefined;
18 | multiple?: boolean | undefined;
19 | readonly?: boolean | undefined;
20 | required?: boolean | undefined;
21 | } | undefined;
22 | };
23 | events: {
24 | [evt: string]: CustomEvent;
25 | };
26 | slots: {};
27 | };
28 | export declare type TextInputProps = typeof __propDef.props;
29 | export declare type TextInputEvents = typeof __propDef.events;
30 | export declare type TextInputSlots = typeof __propDef.slots;
31 | /**
32 | * Props are passed in through the options object which contains the following properties:
33 | * ```tsx
34 | * label: string (required)
35 | * placeholder: string (required)
36 | * id: string (required)
37 | * type: string (required)
38 | * inputStyle: string (optional)
39 | * labelStyle: string (optional)
40 | * ```
41 | */
42 | export default class TextInput extends SvelteComponentTyped {
43 | }
44 | export {};
45 |
--------------------------------------------------------------------------------
/package/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svve11",
3 | "version": "1.2.0",
4 | "exports": {
5 | "./package.json": "./package.json",
6 | ".": "./src/lib",
7 | "./Accordion/AccordionButton.svelte": "./Accordion/AccordionButton.svelte",
8 | "./Accordion/AccordionHeader.svelte": "./Accordion/AccordionHeader.svelte",
9 | "./Accordion/AccordionItem.svelte": "./Accordion/AccordionItem.svelte",
10 | "./Accordion/AccordionPanel.svelte": "./Accordion/AccordionPanel.svelte",
11 | "./Accordion/AccordionTypes": "./Accordion/AccordionTypes.js",
12 | "./Accordion.svelte": "./Accordion.svelte",
13 | "./Button.svelte": "./Button.svelte",
14 | "./Checkbox.svelte": "./Checkbox.svelte",
15 | "./Meter.svelte": "./Meter.svelte",
16 | "./NavBar/NavBarHeader.svelte": "./NavBar/NavBarHeader.svelte",
17 | "./NavBar/NavBarLists.svelte": "./NavBar/NavBarLists.svelte",
18 | "./NavBar/NavBarOptions.svelte": "./NavBar/NavBarOptions.svelte",
19 | "./NavBar/NavBarTypes": "./NavBar/NavBarTypes.js",
20 | "./NavBar.svelte": "./NavBar.svelte",
21 | "./Table.svelte": "./Table.svelte",
22 | "./TextInput.svelte": "./TextInput.svelte"
23 | },
24 | "devDependencies": {
25 | "@babel/preset-env": "^7.18.0",
26 | "@sveltejs/adapter-auto": "next",
27 | "@sveltejs/kit": "next",
28 | "@testing-library/jest-dom": "^5.16.4",
29 | "@testing-library/svelte": "^3.1.1",
30 | "@testing-library/user-event": "^14.2.0",
31 | "@typescript-eslint/eslint-plugin": "^5.10.1",
32 | "@typescript-eslint/parser": "^5.10.1",
33 | "babel-jest": "^28.1.0",
34 | "eslint": "^8.12.0",
35 | "eslint-config-prettier": "^8.3.0",
36 | "eslint-plugin-svelte3": "^4.0.0",
37 | "jest": "^28.1.0",
38 | "jest-environment-jsdom": "^28.1.0",
39 | "prettier": "^2.5.1",
40 | "prettier-plugin-svelte": "^2.5.0",
41 | "sass": "^1.52.1",
42 | "svelte": "^3.44.0",
43 | "svelte-check": "^2.2.6",
44 | "svelte-jester": "^2.3.2",
45 | "svelte-preprocess": "^4.10.6",
46 | "svelte2tsx": "^0.5.10",
47 | "ts-jest": "^28.0.2",
48 | "ts-node": "^10.8.0",
49 | "tslib": "^2.3.1",
50 | "typescript": "~4.6.2"
51 | },
52 | "type": "module",
53 | "dependencies": {
54 | "svve11": "^0.0.1"
55 | },
56 | "svelte": "./src/lib"
57 | }
--------------------------------------------------------------------------------
/src/__tests__/Accordion.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 | import '@testing-library/jest-dom';
3 | import { render } from '@testing-library/svelte';
4 | import userEvent from '@testing-library/user-event';
5 |
6 | import Accordion from '../lib/Accordion.svelte';
7 |
8 | // List of Accordion Parts:
9 | // - Accordion: contains accordion item(s)
10 | // - Accordion Item: contains header and panel
11 | // - Accordion Header: contains button
12 | // - Accordion Button: labels header
13 | // - Accordion Panel: contains contents
14 |
15 | describe('Accessible Accordion Unit Tests', () => {
16 | const options = {
17 | multiselectable: true,
18 | headerLevel: 4,
19 | styles: {
20 | accordionHeaderStyle: 'Header styles string',
21 | accordionPanelStyle: 'Panel styles string;',
22 | accordionItemStyle: 'Item styles string',
23 | overallAccordionStyle: 'Accordion styles string'
24 | },
25 | panelInfo: [
26 | {
27 | id: 1,
28 | panelContent:
29 | 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus suspendisse faucibus interdum posuere lorem ipsum dolor sit amet. Cursus eget nunc scelerisque viverra mauris. Lacus laoreet non curabitur gravida arcu ac tortor dignissim. Proin fermentum leo vel orci porta non pulvinar neque laoreet. Nisl vel pretium lectus quam id. Ultrices eros in cursus turpis massa. Mauris pharetra et ultrices neque. Tristique senectus et netus et malesuada fames ac turpis. Turpis tincidunt id aliquet risus feugiat in ante metus. Pellentesque habitant morbi tristique senectus et netus et malesuada.',
30 | headerTitle: 'First Section'
31 | },
32 | {
33 | id: 2,
34 | panelContent:
35 | 'Et sollicitudin ac orci phasellus egestas tellus rutrum tellus. Ut enim blandit volutpat maecenas volutpat blandit. Mi ipsum faucibus vitae aliquet nec. Dui ut ornare lectus sit amet est placerat in. Convallis convallis tellus id interdum. Vitae aliquet nec ullamcorper sit amet risus. Eu mi bibendum neque egestas congue quisque egestas diam in. Fermentum iaculis eu non diam phasellus vestibulum lorem sed risus. Ullamcorper a lacus vestibulum sed. Vitae purus faucibus ornare suspendisse. Curabitur gravida arcu ac tortor dignissim convallis. Viverra ipsum nunc aliquet bibendum enim facilisis gravida. Dolor magna eget est lorem ipsum dolor sit amet consectetur. Id leo in vitae turpis massa sed. Faucibus interdum posuere lorem ipsum dolor.',
36 | headerTitle: 'Second Section'
37 | }
38 | ]
39 | };
40 |
41 | describe('Button Unit Tests', () => {
42 | let buttons, button, user;
43 | beforeEach(() => {
44 | const { getAllByRole, getByText } = render(Accordion, { options });
45 | buttons = getAllByRole('button');
46 | button = getByText('First Section');
47 | user = userEvent.setup();
48 | });
49 |
50 | it('should have a role attribute set to button', () => {
51 | expect(buttons.length).toEqual(options.panelInfo.length);
52 | });
53 |
54 | it('should have no siblings', () => {
55 | expect(button.nextElementSibling).toEqual(null);
56 | });
57 |
58 | it('should have an attribute aria-expanded initialized to false', () => {
59 | expect(button.getAttribute('aria-expanded')).toEqual('false');
60 | });
61 |
62 | it('should toggle aria-expanded when clicked', async () => {
63 | expect(button.getAttribute('aria-expanded')).toEqual('false');
64 | await user.click(button);
65 | expect(button.getAttribute('aria-expanded')).toEqual('true');
66 | await user.click(button);
67 | expect(button.getAttribute('aria-expanded')).toEqual('false');
68 | });
69 |
70 | it('should have an attribute aria-label that toggles between an empty string and panel contents when clicked', async () => {
71 | expect(button.getAttribute('aria-label')).toEqual('');
72 | await user.click(button);
73 | expect(button.getAttribute('aria-label')).toEqual(options.panelInfo[0].panelContent);
74 | await user.click(button);
75 | expect(button.getAttribute('aria-label')).toEqual('');
76 | });
77 |
78 | it('should have a class name set to header-button', () => {
79 | expect(button.getAttribute('class')).toContain('sv-accordion-button');
80 | });
81 |
82 | it('should habe an id attribute set to button and the id number', () => {
83 | expect(button.getAttribute('id')).toEqual(`button${options.panelInfo[0].id}`);
84 | });
85 |
86 | it('should have an attribute aria-controls set to the panel it controls', () => {
87 | expect(button.getAttribute('aria-controls')).toEqual(`panel${options.panelInfo[0].id}`);
88 | });
89 |
90 | it('should be passed the styles string in the accordionHeaderStyle of the styles property in options object', () => {
91 | expect(button.getAttribute('style')).toEqual(options.styles.accordionHeaderStyle);
92 | });
93 |
94 | it('should be able to have focus', () => {
95 | user.tab();
96 | expect(button).toHaveFocus();
97 | });
98 |
99 | it('should expand/collapse when space key is pressed', async () => {
100 | user.tab();
101 | expect(button.getAttribute('aria-expanded')).toEqual('false');
102 | expect(button).toHaveFocus();
103 | expect(button.getAttribute('aria-label')).toEqual('');
104 | await user.keyboard(' ');
105 | expect(button.getAttribute('aria-expanded')).toEqual('true');
106 | expect(button.getAttribute('aria-label')).toEqual(options.panelInfo[0].panelContent);
107 | await user.keyboard('{enter}');
108 | expect(button.getAttribute('aria-expanded')).toEqual('false');
109 | expect(button.getAttribute('aria-label')).toEqual('');
110 | });
111 |
112 | it('should expand/collapse when enter key is pressed', async () => {
113 | user.tab();
114 | expect(button.getAttribute('aria-expanded')).toEqual('false');
115 | expect(button).toHaveFocus();
116 | expect(button.getAttribute('aria-label')).toEqual('');
117 | await user.keyboard('{enter}');
118 | expect(button.getAttribute('aria-expanded')).toEqual('true');
119 | expect(button.getAttribute('aria-label')).toEqual(options.panelInfo[0].panelContent);
120 | await user.keyboard('{enter}');
121 | expect(button.getAttribute('aria-expanded')).toEqual('false');
122 | expect(button.getAttribute('aria-label')).toEqual('');
123 | });
124 | });
125 |
126 | describe('Header Unit Tests', () => {
127 | let headers, heading, button;
128 | beforeEach(() => {
129 | const { getAllByRole, getByText } = render(Accordion, { options });
130 | headers = getAllByRole('heading');
131 | heading = getAllByRole('heading')[0];
132 | button = getByText('First Section');
133 | });
134 |
135 | it('should have a role attribute set to heading', () => {
136 | expect(headers.length).toEqual(options.panelInfo.length);
137 | });
138 |
139 | it('should have a class attribute set to accordion-header', () => {
140 | expect(heading.getAttribute('class')).toContain('accordion-header');
141 | });
142 |
143 | it('should have a child that is a button', () => {
144 | expect(heading.firstChild).toBe(button);
145 | });
146 |
147 | it('should have an aria-level attribute set to appropriate header level number', () => {
148 | expect(heading.getAttribute('aria-level')).toEqual(options.headerLevel.toString());
149 | });
150 |
151 | it('should be passed the styles string in the 0th index of the styles array', () => {
152 | expect(heading.getAttribute('style')).toEqual(options.styles.accordionHeaderStyle);
153 | });
154 | });
155 |
156 | describe('Panel Unit Tests', () => {
157 | let panels, panel;
158 |
159 | beforeEach(() => {
160 | const { getAllByRole } = render(Accordion, { options });
161 | panels = getAllByRole('region');
162 | panel = panels[0];
163 | });
164 |
165 | it('should have a role attribute set to region', () => {
166 | expect(panels.length).toEqual(options.panelInfo.length);
167 | });
168 |
169 | it('should have an id attribute set to panel and the appropriate id number', () => {
170 | expect(panel.getAttribute('id')).toEqual(`panel${options.panelInfo[0].id}`);
171 | });
172 |
173 | it('should have an aria-labelledby attribute set to the button labeling it', () => {
174 | expect(panel.getAttribute('aria-labelledby')).toEqual(`button${options.panelInfo[0].id}`);
175 | });
176 |
177 | it('should have a class attribute set to accordion-panel', () => {
178 | expect(panel.getAttribute('class')).toContain('accordion-panel');
179 | });
180 |
181 | it('should be passed the appropriate styles', () => {
182 | expect(panel.getAttribute('style')).toEqual(options.styles.accordionPanelStyle);
183 | });
184 | });
185 |
186 | describe('Item Unit Tests', () => {
187 | let items, item, button, panel, header, user;
188 | beforeEach(() => {
189 | const { getByText, getAllByRole } = render(Accordion, { options });
190 | items = document.getElementsByClassName('sv-accordion-item');
191 | item = items[0];
192 | button = document.querySelector('.sv-accordion-button');
193 | panel = document.querySelector('.sv-accordion-panel');
194 | header = document.querySelectorAll('.sv-accordion-header')[0];
195 | user = userEvent.setup();
196 | });
197 |
198 | it('should render one item for each panelInfo in options object', () => {
199 | expect(items.length).toEqual(options.panelInfo.length);
200 | });
201 |
202 | it('should have a data-state attribute set to collapsed initially, and should toggle to expanded when corresponding button is clicked', async () => {
203 | expect(item.getAttribute('data-state')).toBe('collapsed');
204 | await user.click(button);
205 | expect(item.getAttribute('data-state')).toBe('expanded');
206 | });
207 |
208 | it('should have two children, the first being the button and the second the panel', () => {
209 | expect(item.firstChild).toBe(header);
210 | expect(item.firstChild.firstChild).toBe(button);
211 | expect(item.firstChild.nextElementSibling).toBe(panel);
212 | expect(item.firstChild.nextElementSibling.nextElementSibling).toEqual(null);
213 | });
214 | });
215 |
216 | describe('Accordion Unit Tests', () => {
217 | it('should have an aria-multiselectable attribute corresponding to that passed into the options object', () => {
218 | const {} = render(Accordion, { options });
219 | const accordion = document.getElementsByClassName('sv-accordion-main')[0];
220 | expect(accordion.getAttribute('aria-multiselectable')).toEqual(`${options.multiselectable}`);
221 | });
222 | });
223 | });
224 |
--------------------------------------------------------------------------------
/src/__tests__/Button.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 |
3 | import '@testing-library/jest-dom';
4 | import { render } from '@testing-library/svelte';
5 | // import '@testing-library/svelte';
6 | import userEvent from '@testing-library/user-event';
7 | import Button from '../lib/Button.svelte';
8 |
9 | let user;
10 | let button;
11 | const options = {
12 | content: 'test descriptive content',
13 | id: 'test-button',
14 | label: 'accessible-button',
15 | handleClick: (e) => (e.target.textContent = 'clicked')
16 | };
17 |
18 | // before each test runs run,
19 | beforeEach(() => {
20 | // set up a user to dispatch events
21 | user = userEvent.setup();
22 |
23 | // render a Button for testing
24 | const { getByText } = render(Button, { options });
25 | button = getByText('test descriptive content');
26 | });
27 |
28 | describe('Running accessible Button tests', () => {
29 | describe('WAI-ARIA Roles, States, Properties tests', () => {
30 | test('It has an accessible label', () => {
31 | expect(button).toHaveAttribute('aria-label');
32 | });
33 |
34 | test('It has an accessible name', () => {
35 | expect(button).toHaveAccessibleName('accessible-button');
36 | });
37 |
38 | test('Its content is unique and descriptive', () => {
39 | expect(button).toHaveTextContent('test descriptive content');
40 | });
41 |
42 | test('It is not autofocused', () => {
43 | expect(document.activeElement).not.toBe(button);
44 | });
45 |
46 | test('It can can be be activated with a click', async () => {
47 | await user.click(button);
48 | expect(button).toHaveTextContent('clicked');
49 | });
50 |
51 | test('It triggers an event or action', async () => {
52 | await user.click(button);
53 | expect(button).toHaveTextContent('clicked');
54 | });
55 | });
56 |
57 | describe('Keyboard interaction tests', () => {
58 | test('It can be focused by pressing tab', async () => {
59 | await user.tab();
60 | expect(document.activeElement).toBe(button);
61 | });
62 |
63 | test('It can can be be activated by pressing space', async () => {
64 | // focus the button
65 | user.tab();
66 | // press space
67 | await user.keyboard(' ');
68 | expect(button).toHaveTextContent('clicked');
69 | });
70 |
71 | test('It can can be be activated by pressing enter', async () => {
72 | // focus the button
73 | user.tab();
74 | // press enter
75 | await user.keyboard('{enter}');
76 | expect(button).toHaveTextContent('clicked');
77 | });
78 |
79 | test('Keys that are not space or enter do not activate the button', async () => {
80 | user.tab();
81 | await user.keyboard('`1234567890qwertyuiopasdfghjklzxcvbnm');
82 | expect(button).toHaveTextContent('test descriptive content');
83 | });
84 | });
85 | });
86 |
87 | /**
88 | * Tests:
89 | * ----------------------------------------------------------
90 | * WAI-ARIA Roles, States, Properties:
91 | * ----------------------------------------------------------
92 | * - has a role of button
93 | * - its content is unique and descriptive
94 | * - it cannot be autofocused
95 | * - has an accessible label
96 | * - default: computed from any text content inside btn elmt
97 | * - can also be provided by aria-labelledby or aria-label
98 | * - if it has a description
99 | * - aria-describedby is set to ID of elmt containing the description
100 | * - aria-disabled is set to true when action associated w/ btn is unavailable
101 | * - all of its descendants are presentational
102 | *
103 | * If Toggle button...
104 | * - it has an aria-pressed attribute
105 | * - aria-pressed is set to true when btn toggled on
106 | * - aria-pressed is set to false when btn toggled off
107 | *
108 | * If Menu button...
109 | * - it has an aria-haspopup attribute
110 | * - aria-haspopup is set to either menu OR true
111 | * - You should be able to focus the button
112 | * - and then it should activate
113 | * - on Click events
114 | * - on pressing Space
115 | * - on pressing Enter
116 | * - It should not be activated by any other events
117 | *
118 | * - Does it trigger the desired event or action?
119 | * e.g. submit a form, open a dialog, perform a delete operation
120 | * - it should either be...
121 | * - a button element
122 | * - a input element with type = "button"
123 | * - if anything else:
124 | * - should be focusable
125 | * - should have event handlers for click events
126 | * - should have event handlers for keydown events
127 | *
128 | * ----------------------------------------------------------
129 | * Keyboard interaction tests:
130 | * ----------------------------------------------------------
131 | * - after button activation, it focus should be set correctly depending on button action
132 | * - if activation does NOT dismiss current context:
133 | * focus typ. returns to button
134 | * - opens a dialog:
135 | * focus moves inside the dialog
136 | * - closes a dialog:
137 | * focus typ. returns to button that opened the dialog
138 | * - action indicates a context change
139 | * focus typ. moves to starting point for that action
140 | * - if btn activated w/ a shortcut key
141 | * typ. remains in context from which shortcut ky was activated
142 | * e.g. if Alt + U were assigned to an "Up" button that moves
143 | * the currently focused item in a list one position higher in the list,
144 | * pressing Alt + U when the focus is in the list
145 | * would not move the focus from the list.
146 | *
147 | * ----------------------------------------------------------
148 | * Other:
149 | * ----------------------------------------------------------
150 | * - its [text] content has minimum 4.5:1 contrast ratio to its background
151 | * - if it has a border
152 | * - its border color has minimum 3:1 contrast ratio to its surrounding context elmts
153 | * - if it doesn't have a border
154 | * - its background color has minimum 3:1 contrast ratio to its surrounding context elmts
155 | * - OR its background color is the same as its surrounding context
156 | * - it has a different style for when it's focused
157 | * - if btn can be disabled, aria-disabled set to true when disabled, false when active
158 | */
159 |
--------------------------------------------------------------------------------
/src/__tests__/Checkbox.spec.js:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom';
2 | import { render } from '@testing-library/svelte';
3 | import userEvent from '@testing-library/user-event';
4 | import Checkbox from '../lib/Checkbox.svelte';
5 |
6 | let user;
7 | let checkbox;
8 | const options = {
9 | checkBoxLabel: 'This is checkbox value',
10 | id: 'checkBoxOne',
11 | checked: false,
12 | defaultStyle: 'display: inline-block; user-select: none;'
13 | };
14 |
15 | beforeEach(() => {
16 | user = userEvent.setup();
17 | const { component } = render(Checkbox, { options });
18 | checkbox = document.getElementById('checkBoxOne');
19 | });
20 |
21 | describe('Accessible Checkbox Testing Unit Tests', () => {
22 | test('checking for aria-label', () => {
23 | expect(checkbox).toHaveAttribute('aria-label');
24 | });
25 |
26 | test('checking for id', () => {
27 | expect(checkbox).toHaveAttribute('id');
28 | });
29 |
30 | test('checking for type', () => {
31 | expect(checkbox).toHaveAttribute('type');
32 | });
33 |
34 | test('testing if the checkbox is starting off as not checked', () => {
35 | expect(checkbox.getAttribute('checked')).toBeFalsy();
36 | });
37 |
38 | test('checking for type to equal checkbox', () => {
39 | expect(checkbox.getAttribute('type')).toEqual('checkbox');
40 | });
41 |
42 | test('checking if check box name is accessible', () => {
43 | // expect(checkbox.getAttribute('name')).toEqual('accessible-checkbox');
44 | });
45 |
46 | test('checking if check box name is accessible', () => {
47 | // expect(checkbox.getAttribute('value')).toEqual('box');
48 | });
49 |
50 | // test('checking for checkbox display styling', () => {
51 | // expect(checkbox.getAttribute('style')).toEqual(props.styles[0]);
52 | // });
53 |
54 | // test('checking for checkbox user-select styling', () => {
55 | // expect(checkbox.getAttribute('style').toEqual(props.styles[1]));
56 | // });
57 | });
58 |
59 | // describe('Accessible button key press testing', () => {
60 | // test('checking it on/off when space press', async () => {
61 | // user.tab();
62 | // await user.keyboard(' ');
63 | // expect(checkbox.getAttribute('checked')).toBeTruthy();
64 | // });
65 | // });
66 |
--------------------------------------------------------------------------------
/src/__tests__/Meter.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 | import '@testing-library/jest-dom';
3 | import { render } from '@testing-library/svelte';
4 | import { get } from 'svelte/store';
5 | // import userEvent from '@testing-library/user-event';
6 |
7 | import Meter from '../lib/Meter.svelte';
8 |
9 | describe('Meter Unit Tests', () => {
10 | const options = {
11 | maxValue: 100,
12 | minValue: 0,
13 | meterLabel: "Test Meter",
14 | id: 1,
15 | optimumValue: 80,
16 | lowValue: 20,
17 | highValue: 85,
18 | }
19 |
20 | let meter, label, meters, meterDiv
21 |
22 | beforeEach(() => {
23 | const {getByTestId, getByText} = render(Meter, {options: options, value: 60})
24 | meters = document.getElementsByTagName('meter')
25 | meter = getByTestId('meter-test')
26 | label = getByText('Test Meter: 60%')
27 | })
28 |
29 | it('should have two children, a label and meter', () => {
30 | expect(label).toBeInTheDocument()
31 | expect(label.nextElementSibling).toBeInTheDocument()
32 | expect(label.nextElementSibling).toBe(meter)
33 | })
34 |
35 | it('should have a role set to meter', () => {
36 | expect(meters.length).toEqual(1)
37 | })
38 |
39 | it('should have a meter with accessible attributes', () => {
40 | expect(meter).toHaveAttribute('aria-valuenow')
41 | expect(meter.getAttribute('aria-valuenow')).toEqual('60')
42 | expect(meter).toHaveAttribute('aria-valuemax')
43 | expect(meter.getAttribute('aria-valuemax')).toEqual(options.maxValue.toString())
44 | expect(meter).toHaveAttribute('aria-valuemin')
45 | expect(meter.getAttribute('aria-valuemin')).toEqual(options.minValue.toString())
46 | expect(meter).toHaveAttribute('aria-labelledby')
47 | expect(meter.getAttribute('aria-labelledby')).toEqual('meter-label-1')
48 | expect(meter).toHaveAttribute('aria-valuetext')
49 | expect(meter.getAttribute('aria-valuetext')).toEqual('')
50 | })
51 |
52 | it('should have a meter with attributes defined by props', () => {
53 | expect(meter).toHaveAttribute('id')
54 | expect(meter.getAttribute('id')).toEqual('meter-1')
55 | expect(meter).toHaveAttribute('min')
56 | expect(meter.getAttribute('min')).toEqual(options.minValue.toString())
57 | expect(meter).toHaveAttribute('max')
58 | expect(meter.getAttribute('max')).toEqual(options.maxValue.toString())
59 | expect(meter).toHaveAttribute('low')
60 | expect(meter.getAttribute('low')).toEqual(options.lowValue.toString())
61 | expect(meter).toHaveAttribute('high')
62 | expect(meter.getAttribute('high')).toEqual(options.highValue.toString())
63 | expect(meter).toHaveAttribute('optimum')
64 | expect(meter.getAttribute('optimum')).toEqual(options.optimumValue.toString())
65 | expect(meter).toHaveAttribute('value')
66 | expect(meter.getAttribute('value')).toEqual('60')
67 | expect(meter).toHaveAttribute('style')
68 | expect(meter.getAttribute('style')).toEqual('')
69 | })
70 |
71 | it('should have a label with accessible attributes', () => {
72 | expect(label).toHaveAttribute('for')
73 | expect(label.getAttribute('for')).toEqual('meter-1')
74 | expect(label).toHaveAttribute('id')
75 | expect(label.getAttribute('id')).toEqual('meter-label-1')
76 | expect(label).toHaveAttribute('style')
77 | expect(label.getAttribute('style')).toEqual('')
78 | })
79 |
80 | })
--------------------------------------------------------------------------------
/src/__tests__/NavBar.spec.js:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom';
2 | import { render } from '@testing-library/svelte';
3 | import userEvent from '@testing-library/user-event';
4 | import NavBar from '../lib/NavBar.svelte';
5 |
6 | let user;
7 | let header;
8 | let subheading;
9 | let option1;
10 | let option2;
11 |
12 | const options = {
13 | id: 'testnav',
14 | header: 'Menu',
15 | contentInfo: [
16 | {
17 | subheading: 'Components',
18 | options: ['Button', 'Accordion'],
19 | links: ['../routes/pages/button.svelte', '../routes/pages/accordion.svelte']
20 | }
21 | ],
22 | imgSrc: '../images/svve11-logo-white-transparent-cropped.png',
23 | imgClass: 'navbar-logo',
24 | imgAlt: 'company logo'
25 | };
26 |
27 | // before each test runs run,
28 | beforeEach(() => {
29 | // set up a user to dispatch events
30 | user = userEvent.setup();
31 |
32 | // render a Button for testing
33 | const { getByText } = render(NavBar, { options });
34 | //header = getByText('Menu');
35 | console.log(document.body);
36 | subheading = getByText('Components');
37 | option1 = getByText('Button');
38 | option2 = getByText('Accordion');
39 | });
40 |
41 | describe('Running accessible NavBar tests', () => {
42 | describe('Keyboard interaction tests', () => {
43 | test('Can go down list of options using tab', async () => {
44 | await user.tab();
45 | // console.log('current active element:', document.activeElement);
46 | expect(document.activeElement).toBe(option1);
47 | await user.tab();
48 | expect(document.activeElement).toBe(option2);
49 | });
50 | test('Each option is paired with the appropriate link', async () => {
51 | await user.tab();
52 | const optionA = document.activeElement;
53 | expect(optionA).toHaveAttribute('href', '../routes/pages/button.svelte');
54 |
55 | await user.tab();
56 | const optionB = document.activeElement;
57 | expect(optionB).toHaveAttribute('href', '../routes/pages/accordion.svelte');
58 | });
59 | });
60 | });
61 |
--------------------------------------------------------------------------------
/src/__tests__/Radio.spec.js:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom';
2 | import { render } from '@testing-library/svelte';
3 | import userEvent from '@testing-library/user-event';
4 | import RadioButton from '../pending/RadioButton.svelte';
5 |
6 | const options = {
7 | radioButtonLabel: 'Radio Button',
8 | id: 'first',
9 | checked: false,
10 | radioButtonStyle: 'styling for buton',
11 | radioButtonLabelStyle: 'styling for label',
12 | name: 'groupOne',
13 | value: 'group'
14 | };
15 |
16 | let user;
17 | // beforeEach(() => {
18 | user = userEvent.setup();
19 | const { component } = render(RadioButton, { options });
20 | let radioButton = document.getElementById('first');
21 | // });
22 |
23 | describe('Accessible testing for radioButton', () => {
24 | test('checking if aria-label is being used', () => {
25 | expect(radioButton).toHaveAttribute('aria-label');
26 | });
27 |
28 | test('checking if id is being used', () => {
29 | expect(radioButton).toHaveAttribute('id');
30 | });
31 |
32 | test('checking if type is being defined', () => {
33 | expect(radioButton).toHaveAttribute('type');
34 | });
35 |
36 | test('checking if radio-button unselected by default', () => {
37 | expect(radioButton.getAttribute('checked')).toBeFalsy();
38 | });
39 |
40 | test('checking if the type is being defined as a radio button', () => {
41 | expect(radioButton.getAttribute('type')).toEqual('radio');
42 | });
43 |
44 | test('checking if name is being defined', () => {
45 | expect(radioButton).toHaveAttribute('name');
46 | });
47 |
48 | });
49 |
50 | describe('Accessing by keyboard functionality', () => {
51 | test('It can be focused by pressing tab', async () => {
52 | await user.tab();
53 | // expect(document.activeElement).toHaveValue('group');
54 | });
55 | });
56 |
--------------------------------------------------------------------------------
/src/__tests__/Table.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 | import '@testing-library/jest-dom';
3 | import { render } from '@testing-library/svelte';
4 | import userEvent from '@testing-library/user-event';
5 |
6 | import Table from './../lib/Table.svelte';
7 |
8 | let user;
9 | let table;
10 |
11 | const options = {
12 | id: 'test-table',
13 | ariaLabel: 'test',
14 | ariaDescription: 'Table Component for Testing',
15 | columnNames: ['Name', 'Age', 'Favorite Color'],
16 | rowsContent: [
17 | ['Nurbek', '19', 'White'],
18 | ['Paul', '26', 'Red'],
19 | ['Tim', '29', 'Blue'],
20 | ['Simon', '26', 'Green']
21 | ],
22 | styles: {
23 | overallStyles: 'background-color: powderblue',
24 | titleStyles: 'text-align: left;',
25 | headersRowStyles: 'background-color: grey',
26 | generalRowStyles: 'font-weight: lighter',
27 | oddRowStyles: 'background-color: white',
28 | evenRowStyles: 'background-color: lightgrey'
29 | }
30 | };
31 |
32 | beforeEach(() => {
33 | // set up a user to dispatch events
34 | user = userEvent.setup();
35 |
36 | // render a Table for testing
37 | const { component } = render(Table, { options });
38 | table = document.getElementById('test-table');
39 | });
40 |
41 | describe('Running accessible Table tests', () => {
42 | describe('WAI-ARIA Roles, States, Properties tests', () => {
43 | test('It has a role table', () => {
44 | expect(table);
45 | });
46 |
47 | test('It has an accessible label', () => {
48 | expect(table).toHaveAttribute('aria-label');
49 | expect(table).toHaveAccessibleName('test');
50 | });
51 |
52 | test('It has an accessible description', () => {
53 | expect(table).toHaveAccessibleDescription('Table Component for Testing');
54 | });
55 | });
56 |
57 | describe('a11y checklist tests', () => {
58 | test('The table should have a caption element', () => {
59 | const caption = document.getElementById('test_table_desc');
60 | console.log('table caption:', caption);
61 | expect(table).toContainElement(caption);
62 | });
63 |
64 | test('Its caption element should provide a title for the table', () => {
65 | const caption = document.getElementById('test_table_desc');
66 | expect(caption.textContent).toBe('Table Component for Testing');
67 | });
68 | });
69 |
70 | describe('Keyboard interaction tests', () => {
71 | test('It can be focused by pressing tab', async () => {
72 | // press tab
73 | await user.tab();
74 | expect(document.activeElement).toHaveAccessibleName('test');
75 | });
76 | });
77 | });
78 |
--------------------------------------------------------------------------------
/src/__tests__/TextInput.spec.js:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom';
2 | import TextInput from "../lib/TextInput.svelte";
3 | import { render } from "@testing-library/svelte";
4 | import userEvent from '@testing-library/user-event';
5 |
6 | let user;
7 | let input;
8 | let label;
9 |
10 | const options = {
11 | label: "This is a test",
12 | placeholder: "Test",
13 | id: "testInputText",
14 | type: "text"
15 | }
16 |
17 | beforeEach(() => {
18 | // // set up a user to dispatch events
19 | user = userEvent.setup();
20 |
21 | // render a Button for testing
22 | const { component, getByText, getByLabelText } = render(TextInput, { options });
23 | input = getByLabelText('This is a test');
24 | label = getByText('This is a test');
25 | });
26 |
27 | describe('Running accessible TextInput tests', () => {
28 | describe('Check that all attributes have been passed down properly', () => {
29 | test(' has correct placeholder attribute', () => {
30 | expect(input).toHaveAttribute('placeholder', 'Test');
31 | });
32 |
33 | test(' has correct type attribute', () => {
34 | expect(input).toHaveAttribute('type', 'text');
35 | });
36 |
37 | test(' and