diff --git a/.changeset/ten-teachers-appear.md b/.changeset/ten-teachers-appear.md
new file mode 100644
index 0000000000..362cefa739
--- /dev/null
+++ b/.changeset/ten-teachers-appear.md
@@ -0,0 +1,5 @@
+---
+'@baloise/ds-core': minor
+---
+
+**option**: new child component of option-list. Option list component will be used by drop-down, combobox and autocomplete.
diff --git a/.gitignore b/.gitignore
index d9084d5e31..2b8586d5dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,8 +68,8 @@ libs/output-targets-vue/CHANGELOG.md
e2e/generated
e2e/downloads
e2e/reg.json
-e2e/cypress/snapshots
-!e2e/cypress/snapshots/base
+e2e/cypress/snapshots/actual
+e2e/cypress/snapshots/diff
resources/data
!resources/data/tags.json
diff --git a/docs/stories/components/bal-option/testing.md b/docs/stories/components/bal-option/testing.md
new file mode 100644
index 0000000000..98d460be9e
--- /dev/null
+++ b/docs/stories/components/bal-option/testing.md
@@ -0,0 +1,12 @@
+## Testing
+
+The Baloise Design System provides a collection of custom cypress commands for the components. Moreover, some basic cypress commands like `should` or `click` have been overridden to work with the components.
+
+Go to testing guide
+
+
+
+
+
+
+
diff --git a/docs/stories/components/bal-option/theming.md b/docs/stories/components/bal-option/theming.md
new file mode 100644
index 0000000000..a3fa61a158
--- /dev/null
+++ b/docs/stories/components/bal-option/theming.md
@@ -0,0 +1,32 @@
+## Theming
+
+The component can be customization by changing the CSS variables.
+
+Go to theming guide
+
+
+
+
+
+
+
+### Variables​
+
+| Variable |
+| ------------------------------------------ |
+| `--bal-option-padding-x` |
+| `--bal-option-min-height` |
+| `--bal-option-background` |
+| `--bal-option-background-hovered` |
+| `--bal-option-background-selected` |
+| `--bal-option-background-selected-hovered` |
+| `--bal-option-background-invalid` |
+| `--bal-option-background-invalid-hovered` |
+| `--bal-option-border-width` |
+| `--bal-option-border-color` |
+| `--bal-option-font-family` |
+| `--bal-option-font-weight` |
+| `--bal-option-line-height` |
+| `--bal-option-text-hovered` |
+| `--bal-option-text-pressed` |
+| `--bal-option-text-disabled` |
diff --git a/e2e/cypress/e2e/a11y/bal-option.a11y.cy.ts b/e2e/cypress/e2e/a11y/bal-option.a11y.cy.ts
new file mode 100644
index 0000000000..7fbfd18a0b
--- /dev/null
+++ b/e2e/cypress/e2e/a11y/bal-option.a11y.cy.ts
@@ -0,0 +1,13 @@
+describe('bal-option', () => {
+ context('a11y', () => {
+ beforeEach(() => cy.platform('desktop').pageA11y('/components/bal-option/test/bal-option.a11y.html'))
+
+ describe('have the AA standard', () => {
+ it('basic', () => cy.getByTestId('basic').testA11y())
+ it('selected', () => cy.getByTestId('selected').testA11y())
+ it('focused', () => cy.getByTestId('focused').testA11y())
+ it('invalid', () => cy.getByTestId('invalid').testA11y())
+ it('disabled', () => cy.getByTestId('disabled').testA11y())
+ })
+ })
+})
diff --git a/e2e/cypress/e2e/visual/bal-option.visual.cy.ts b/e2e/cypress/e2e/visual/bal-option.visual.cy.ts
new file mode 100644
index 0000000000..c606b784be
--- /dev/null
+++ b/e2e/cypress/e2e/visual/bal-option.visual.cy.ts
@@ -0,0 +1,17 @@
+describe('bal-option', () => {
+ describe('basic', () => {
+ beforeEach(() => cy.visit('/components/bal-option/test/bal-option.visual.html').waitForDesignSystem())
+
+ it('basic component', () => {
+ cy.getByTestId('basic').testVisual('option-basic')
+ })
+
+ it('listbox', () => {
+ cy.getByTestId('listbox').testVisual('option-listbox')
+ })
+
+ it('listbox-with-checkboxes', () => {
+ cy.getByTestId('listbox-checkbox').testVisual('option-listbox-checkbox')
+ })
+ })
+})
diff --git a/e2e/cypress/snapshots/base/visual/bal-option.visual.cy.ts/option-basic.png b/e2e/cypress/snapshots/base/visual/bal-option.visual.cy.ts/option-basic.png
new file mode 100644
index 0000000000..8b08496f1a
Binary files /dev/null and b/e2e/cypress/snapshots/base/visual/bal-option.visual.cy.ts/option-basic.png differ
diff --git a/e2e/cypress/snapshots/base/visual/bal-option.visual.cy.ts/option-listbox-checkbox.png b/e2e/cypress/snapshots/base/visual/bal-option.visual.cy.ts/option-listbox-checkbox.png
new file mode 100644
index 0000000000..0964e2627d
Binary files /dev/null and b/e2e/cypress/snapshots/base/visual/bal-option.visual.cy.ts/option-listbox-checkbox.png differ
diff --git a/e2e/cypress/snapshots/base/visual/bal-option.visual.cy.ts/option-listbox.png b/e2e/cypress/snapshots/base/visual/bal-option.visual.cy.ts/option-listbox.png
new file mode 100644
index 0000000000..08e3003efd
Binary files /dev/null and b/e2e/cypress/snapshots/base/visual/bal-option.visual.cy.ts/option-listbox.png differ
diff --git a/e2e/cypress/support/lib/visuals/command.ts b/e2e/cypress/support/lib/visuals/command.ts
index 30b61e6aec..56001854fa 100644
--- a/e2e/cypress/support/lib/visuals/command.ts
+++ b/e2e/cypress/support/lib/visuals/command.ts
@@ -35,6 +35,10 @@ export type CypressConfigEnv = {
/** Add custom cypress command to compare image snapshots of an element or the window. */
function addCompareSnapshotCommand(screenshotOptions?: ScreenshotOptions): void {
+ console.log('')
+ console.log('visualRegressionType => ', Cypress.env('visualRegressionType'))
+ console.log('')
+
Cypress.Commands.add(
'testVisual',
{ prevSubject: 'optional' },
diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts
index 49461c5925..2f7c6d15e5 100644
--- a/packages/core/src/components.d.ts
+++ b/packages/core/src/components.d.ts
@@ -2080,6 +2080,48 @@ export namespace Components {
*/
"value"?: number;
}
+ interface BalOption {
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ "checkbox": boolean;
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ "disabled": boolean;
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ "focused": boolean;
+ /**
+ * If `true`, the option is hidden.
+ */
+ "hidden": boolean;
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ "invalid": boolean;
+ /**
+ * Label will be shown in the input element when it got selected
+ */
+ "label": string;
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ "multiline": boolean;
+ /**
+ * Selects or deselects the option and informs other components
+ */
+ "select": (selected?: boolean) => Promise;
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ "selected": boolean;
+ /**
+ * The value of the select option. This value will be returned by the parent `` element.
+ */
+ "value": string;
+ }
interface BalPagination {
/**
* Align the buttons to start, center or end
@@ -3332,6 +3374,10 @@ export interface BalNumberInputCustomEvent extends CustomEvent {
detail: T;
target: HTMLBalNumberInputElement;
}
+export interface BalOptionCustomEvent extends CustomEvent {
+ detail: T;
+ target: HTMLBalOptionElement;
+}
export interface BalPaginationCustomEvent extends CustomEvent {
detail: T;
target: HTMLBalPaginationElement;
@@ -4208,6 +4254,24 @@ declare global {
prototype: HTMLBalNumberInputElement;
new (): HTMLBalNumberInputElement;
};
+ interface HTMLBalOptionElementEventMap {
+ "balOptionChange": BalEvents.BalOptionChangeDetail;
+ "balOptionFocus": BalEvents.BalOptionFocusDetail;
+ }
+ interface HTMLBalOptionElement extends Components.BalOption, HTMLStencilElement {
+ addEventListener(type: K, listener: (this: HTMLBalOptionElement, ev: BalOptionCustomEvent) => any, options?: boolean | AddEventListenerOptions): void;
+ addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
+ addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
+ removeEventListener(type: K, listener: (this: HTMLBalOptionElement, ev: BalOptionCustomEvent) => any, options?: boolean | EventListenerOptions): void;
+ removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
+ removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
+ }
+ var HTMLBalOptionElement: {
+ prototype: HTMLBalOptionElement;
+ new (): HTMLBalOptionElement;
+ };
interface HTMLBalPaginationElementEventMap {
"balChange": BalEvents.BalPaginationChangeDetail;
}
@@ -4704,6 +4768,7 @@ declare global {
"bal-notices": HTMLBalNoticesElement;
"bal-notification": HTMLBalNotificationElement;
"bal-number-input": HTMLBalNumberInputElement;
+ "bal-option": HTMLBalOptionElement;
"bal-pagination": HTMLBalPaginationElement;
"bal-popover": HTMLBalPopoverElement;
"bal-popover-content": HTMLBalPopoverContentElement;
@@ -6902,6 +6967,49 @@ declare namespace LocalJSX {
*/
"value"?: number;
}
+ interface BalOption {
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ "checkbox"?: boolean;
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ "disabled"?: boolean;
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ "focused"?: boolean;
+ /**
+ * If `true`, the option is hidden.
+ */
+ "hidden"?: boolean;
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ "invalid"?: boolean;
+ /**
+ * Label will be shown in the input element when it got selected
+ */
+ "label"?: string;
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ "multiline"?: boolean;
+ /**
+ * Emitted when the option gets selected or unselected
+ */
+ "onBalOptionChange"?: (event: BalOptionCustomEvent) => void;
+ "onBalOptionFocus"?: (event: BalOptionCustomEvent) => void;
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ "selected"?: boolean;
+ /**
+ * The value of the select option. This value will be returned by the parent `` element.
+ */
+ "value"?: string;
+ }
interface BalPagination {
/**
* Align the buttons to start, center or end
@@ -8156,6 +8264,7 @@ declare namespace LocalJSX {
"bal-notices": BalNotices;
"bal-notification": BalNotification;
"bal-number-input": BalNumberInput;
+ "bal-option": BalOption;
"bal-pagination": BalPagination;
"bal-popover": BalPopover;
"bal-popover-content": BalPopoverContent;
@@ -8275,6 +8384,7 @@ declare module "@stencil/core" {
"bal-notices": LocalJSX.BalNotices & JSXBase.HTMLAttributes;
"bal-notification": LocalJSX.BalNotification & JSXBase.HTMLAttributes;
"bal-number-input": LocalJSX.BalNumberInput & JSXBase.HTMLAttributes;
+ "bal-option": LocalJSX.BalOption & JSXBase.HTMLAttributes;
"bal-pagination": LocalJSX.BalPagination & JSXBase.HTMLAttributes;
"bal-popover": LocalJSX.BalPopover & JSXBase.HTMLAttributes;
"bal-popover-content": LocalJSX.BalPopoverContent & JSXBase.HTMLAttributes;
diff --git a/packages/core/src/components/bal-option/bal-option.interfaces.ts b/packages/core/src/components/bal-option/bal-option.interfaces.ts
new file mode 100644
index 0000000000..b3f9dbcdd5
--- /dev/null
+++ b/packages/core/src/components/bal-option/bal-option.interfaces.ts
@@ -0,0 +1,28 @@
+/* eslint-disable no-unused-vars */
+/* eslint-disable @typescript-eslint/no-unused-vars */
+// eslint-disable-next-line @typescript-eslint/triple-slash-reference
+///
+
+namespace BalProps {}
+
+namespace BalEvents {
+ export interface BalOptionCustomEvent extends CustomEvent {
+ detail: T
+ target: HTMLBalOptionElement
+ }
+
+ export interface BalOption {
+ value: string
+ label: string
+ selected: boolean
+ }
+
+ export type BalOptionFocusDetail = BalOption
+ export type BalOptionFocus = BalOptionCustomEvent
+
+ export type BalOptionBlurDetail = FocusEvent
+ export type BalOptionBlur = BalOptionCustomEvent
+
+ export type BalOptionChangeDetail = BalOption
+ export type BalOptionChange = BalOptionCustomEvent
+}
diff --git a/packages/core/src/components/bal-option/bal-option.sass b/packages/core/src/components/bal-option/bal-option.sass
new file mode 100644
index 0000000000..5a56349627
--- /dev/null
+++ b/packages/core/src/components/bal-option/bal-option.sass
@@ -0,0 +1,111 @@
+@import '@baloise/ds-styles/sass/mixins'
+@import './bal-option.vars'
+
+// Option
+// --------------------------------------------------
+.bal-option
+ font-size: 16px
+ +unselectable
+ position: relative
+ display: block
+ list-style: none
+ cursor: pointer
+ border-bottom-width: var(--bal-option-border-width)
+ border-bottom-color: var(--bal-option-border-color)
+ border-bottom-style: solid
+ background: var(--bal-option-background)
+ padding-left: var(--bal-option-padding-x)
+ padding-right: var(--bal-option-padding-x)
+ min-height: var(--bal-option-min-height)
+ & > bal-stack
+ min-height: var(--bal-option-min-height)
+ &:last-child
+ border-bottom: none
+ &::-moz-focus-inner
+ border: none
+ &--hidden
+ display: none
+ visibility: hidden
+
+// Option Content
+// --------------------------------------------------
+
+.bal-option__inner
+ font-family: var(--bal-option-font-family)
+ font-weight: var(--bal-option-font-weight)
+ line-height: var(--bal-option-line-height)
+ word-break: break-word
+ white-space: normal
+ hyphens: auto
+ overflow: hidden
+ text-overflow: ellipsis
+ white-space: nowrap
+ flex: 1
+
+.bal-option__inner--multiline
+ white-space: normal
+
+// Focused Option
+// --------------------------------------------------
+.bal-option--focused
+ background: var(--bal-option-background-hovered)
+
+.bal-option
+ +hover
+ &:hover
+ background: var(--bal-option-background-hovered)
+ color: var(--bal-option-text-hovered)
+ &:active
+ background: var(--bal-option-background-hovered)
+ color: var(--bal-option-text-pressed)
+
+// Selected Option
+// --------------------------------------------------
+.bal-option--selected
+ background: var(--bal-option-background-selected)
+ +hover
+ &:hover
+ background: var(--bal-option-background-selected-hovered)
+ &:active
+ background: var(--bal-option-background-selected-hovered)
+
+.bal-option--selected .bal-option__inner
+ font-weight: var(--bal-font-weight-bold)
+
+.bal-option--selected.bal-option--focused
+ background: var(--bal-option-background-selected-hovered)
+ .bal-option__inner
+ font-weight: var(--bal-font-weight-bold)
+
+// Invalid Option
+// --------------------------------------------------
+.bal-option--invalid
+ background: var(--bal-option-background-invalid)
+ +hover
+ &:hover
+ background: var(--bal-option-background-invalid-hovered)
+ &:active
+ background: var(--bal-option-background-invalid-hovered)
+
+.bal-option--invalid.bal-option--focused
+ background: var(--bal-option-background-invalid-hovered)
+
+.bal-option--invalid .bal-option__inner
+ color: var(--bal-color-text-danger-hovered)
+
++hover
+ .bal-option--invalid:hover .bal-option__inner
+ color: var(--bal-color-text-danger-hovered)
+
+.bal-option--invalid:active .bal-option__inner
+ color: var(--bal-color-text-danger-pressed)
+
+// Disbaled Option
+// --------------------------------------------------
+.bal-option--disabled,
+.bal-option--disabled.bal-option--focused
+ background: var(--bal-option-background) !important
+ color: var(--bal-option-text-disabled) !important
+ cursor: default !important
+ &:hover
+ background: var(--bal-option-background) !important
diff --git a/packages/core/src/components/bal-option/bal-option.tsx b/packages/core/src/components/bal-option/bal-option.tsx
new file mode 100644
index 0000000000..69326118fa
--- /dev/null
+++ b/packages/core/src/components/bal-option/bal-option.tsx
@@ -0,0 +1,228 @@
+import {
+ Component,
+ h,
+ ComponentInterface,
+ Host,
+ Element,
+ Prop,
+ Listen,
+ Event,
+ EventEmitter,
+ Method,
+ State,
+} from '@stencil/core'
+import { BEM } from '../../utils/bem'
+import { Loggable, Logger, LogInstance } from '../../utils/log'
+import { ariaBooleanToString } from '../../utils/aria'
+import { BalElementStateInfo, BalElementStateObserver, ListenToElementStates } from '../../utils/element-states'
+import { stopEventBubbling } from '../../utils/form-input'
+import { BalElementStateListener } from '../../utils/element-states/element-states.listener'
+
+@Component({
+ tag: 'bal-option',
+ styleUrl: 'bal-option.sass',
+ shadow: false,
+})
+export class Option implements ComponentInterface, Loggable, BalElementStateObserver {
+ private id = `bal-option-${balOptionIds++}`
+
+ @Element() el!: HTMLElement
+
+ log!: LogInstance
+
+ @Logger('bal-option')
+ createLogger(log: LogInstance) {
+ this.log = log
+ }
+
+ @State() interactionState: BalElementStateInfo = BalElementStateListener.DefaultState
+
+ /**
+ * PUBLIC PROPERTY API
+ * ------------------------------------------------------
+ */
+
+ /**
+ * Label will be shown in the input element when it got selected
+ */
+ @Prop({ reflect: true }) label = ''
+
+ /**
+ * The value of the select option. This value will be returned by the parent `` element.
+ */
+ @Prop({ reflect: true }) value = ''
+
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ @Prop({ reflect: true }) disabled = false
+
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ @Prop({ reflect: true }) multiline = false
+
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ @Prop({ reflect: true }) invalid = false
+
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ @Prop({ reflect: true, mutable: true }) selected = false
+
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ @Prop({ reflect: true, mutable: true }) focused = false
+
+ /**
+ * If `true`, the user cannot interact with the option.
+ */
+ @Prop({ reflect: true }) checkbox = false
+
+ /**
+ * If `true`, the option is hidden.
+ */
+ @Prop({ reflect: true }) hidden = false
+
+ /**
+ * Emitted when the option gets selected or unselected
+ */
+ @Event() balOptionChange!: EventEmitter
+
+ /**
+ * @internal
+ * Emitted when a option gets focused.
+ */
+ @Event() balOptionFocus!: EventEmitter
+
+ /**
+ * LISTENERS
+ * ------------------------------------------------------
+ */
+
+ @Listen('mouseenter')
+ listenToMouseEnter() {
+ const { label, value, selected, disabled, hidden } = this
+ if (!hidden && !disabled) {
+ this.balOptionFocus.emit({ label, value, selected })
+ }
+ }
+
+ @ListenToElementStates()
+ elementStateListener(info: BalElementStateInfo): void {
+ this.interactionChildElements.forEach(element => {
+ element.hovered = info.hovered
+ element.pressed = info.pressed
+ })
+ }
+
+ /**
+ * PUBLIC METHODS
+ * ------------------------------------------------------
+ */
+
+ /**
+ * Selects or deselects the option and informs other components
+ */
+ @Method() async select(selected = true): Promise {
+ this.selected = selected
+ const { label, value } = this
+ this.balOptionChange.emit({ label, value, selected })
+ }
+
+ /**
+ * PRIVATE METHODS
+ * ------------------------------------------------------
+ */
+
+ private get interactionChildElements(): Array {
+ return Array.from(this.el.querySelectorAll('bal-checkbox'))
+ }
+
+ /**
+ * EVENT BINDING
+ * ------------------------------------------------------
+ */
+
+ private onClick = (ev: MouseEvent) => {
+ if (this.disabled) {
+ stopEventBubbling(ev)
+ } else {
+ this.select(!this.selected)
+ }
+ }
+
+ /**
+ * RENDER
+ * ------------------------------------------------------
+ */
+
+ render() {
+ const block = BEM.block('option')
+
+ return (
+
+
+ {this.checkbox ? (
+
+ ) : (
+ ''
+ )}
+
+
+
+ {this.selected && !this.checkbox ? (
+
+ ) : (
+ ''
+ )}
+
+
+ )
+ }
+}
+
+let balOptionIds = 0
diff --git a/packages/core/src/components/bal-option/bal-option.vars.sass b/packages/core/src/components/bal-option/bal-option.vars.sass
new file mode 100644
index 0000000000..d8619359f8
--- /dev/null
+++ b/packages/core/src/components/bal-option/bal-option.vars.sass
@@ -0,0 +1,42 @@
+/**
+ * @prop --bal-option-padding-x: TBD
+ * @prop --bal-option-min-height: TBD
+ * @prop --bal-option-background: TBD
+ * @prop --bal-option-background-hovered: TBD
+ * @prop --bal-option-background-selected: TBD
+ * @prop --bal-option-background-selected-hovered: TBD
+ * @prop --bal-option-background-invalid: TBD
+ * @prop --bal-option-background-invalid-hovered: TBD
+ * @prop --bal-option-border-width: TBD
+ * @prop --bal-option-border-color: TBD
+ * @prop --bal-option-font-family: TBD
+ * @prop --bal-option-font-weight: TBD
+ * @prop --bal-option-line-height: TBD
+ * @prop --bal-option-text-hovered: TBD
+ * @prop --bal-option-text-pressed: TBD
+ * @prop --bal-option-text-disabled: TBD
+ */
+
+:root
+ --bal-option-padding-x: var(--bal-space-x-small)
+ --bal-option-min-height: 1.5rem
+ //
+ // background colors
+ --bal-option-background: var(--bal-color-white)
+ --bal-option-background-hovered: var(--bal-color-grey-2)
+ --bal-option-background-selected: var(--bal-color-primary-1)
+ --bal-option-background-selected-hovered: #dddfeb
+ --bal-option-background-invalid: var(--bal-color-danger-1)
+ --bal-option-background-invalid-hovered: #fbe0de
+ //
+ // border
+ --bal-option-border-width: var(--bal-border-width-normal)
+ --bal-option-border-color: var(--bal-color-grey-2)
+ //
+ // typography
+ --bal-option-font-family: var(--bal-font-family-text)
+ --bal-option-font-weight: var(--bal-font-weight-regular)
+ --bal-option-line-height: 1.125rem
+ --bal-option-text-hovered: var(--bal-color-text-primary-hovered)
+ --bal-option-text-pressed: var(--bal-color-text-primary-pressed)
+ --bal-option-text-disabled: var(--bal-color-text-grey-light)
diff --git a/packages/core/src/components/bal-option/test/bal-option.a11y.html b/packages/core/src/components/bal-option/test/bal-option.a11y.html
new file mode 100644
index 0000000000..1c466b50de
--- /dev/null
+++ b/packages/core/src/components/bal-option/test/bal-option.a11y.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Black Widow
+ S.H.I.E.L.D.
+
+ Focused
+ Selected
+ Invalid
+ Disabled
+
+
+
+
+
diff --git a/packages/core/src/components/bal-option/test/bal-option.visual.html b/packages/core/src/components/bal-option/test/bal-option.visual.html
new file mode 100644
index 0000000000..91a11ce950
--- /dev/null
+++ b/packages/core/src/components/bal-option/test/bal-option.visual.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Black Widow
+ S.H.I.E.L.D.
+
+
+ Black Panter
+ Wakanda
+
+ Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ab perferendis porro est non esse quibusdam,
+ facere vel minus quam unde nisi vitae provident maxime maiores inventore amet culpa illum nam.
+ Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ab perferendis porro est non esse quibusdam,
+ facere vel minus quam unde nisi vitae provident maxime maiores inventore amet culpa illum nam.
+
+
+ Default
+ Focused
+ Selected
+ Disabled
+ Invalid
+
+
+
+ Default
+ Focused
+ Selected
+ Disabled
+ Invalid
+
+
+
+
+
diff --git a/packages/core/src/interfaces.d.ts b/packages/core/src/interfaces.d.ts
index 8b221bbaf6..c77accafa4 100644
--- a/packages/core/src/interfaces.d.ts
+++ b/packages/core/src/interfaces.d.ts
@@ -24,6 +24,7 @@ import './components/bal-nav/bal-nav-menu-bar/bal-nav-menu-bar.interfaces'
import './components/bal-nav/bal-nav-menu-flyout/bal-nav-menu-flyout.interfaces'
import './components/bal-nav/bal-nav.interfaces'
import './components/bal-navbar/bal-navbar.interfaces'
+import './components/bal-option/bal-option.interfaces'
import './components/bal-pagination/bal-pagination.interfaces'
import './components/bal-popover/bal-popover.interfaces'
import './components/bal-popup/bal-popup.interfaces'
diff --git a/packages/core/src/utils/aria.ts b/packages/core/src/utils/aria.ts
new file mode 100644
index 0000000000..961c2e6c75
--- /dev/null
+++ b/packages/core/src/utils/aria.ts
@@ -0,0 +1 @@
+export const ariaBooleanToString = (bool?: boolean) => (!!bool ? 'true' : 'false')
diff --git a/resources/data/tags.json b/resources/data/tags.json
index d2c4d86c8e..9d5be2d65f 100644
--- a/resources/data/tags.json
+++ b/resources/data/tags.json
@@ -26,6 +26,7 @@
"bal-nav",
"bal-notification",
"bal-number-input",
+ "bal-option",
"bal-pagination",
"bal-popover",
"bal-popup",