diff --git a/packages/components/src/components/@shared/internal-menu.scss b/packages/components/src/components/@shared/internal-menu.scss new file mode 100644 index 0000000000..c922ac5ba2 --- /dev/null +++ b/packages/components/src/components/@shared/internal-menu.scss @@ -0,0 +1,31 @@ +@mixin internal-menu-styles { + .menu { + ul { + width: 100%; + padding: 0; + margin: 0; + box-sizing: border-box; + display: grid; + list-style: none; + overflow-y: auto; + overflow-x: hidden; + background-color: white; + max-height: rem(250); + } + + .kol-button-wc { + display: block; + width: 100%; + height: 100%; + + & button { + border: none !important; + + .button-inner { + border: none !important; + border-radius: 0 !important; + } + } + } + } +} diff --git a/packages/components/src/components/@shared/internal-menu.tsx b/packages/components/src/components/@shared/internal-menu.tsx new file mode 100644 index 0000000000..c7b78e52ba --- /dev/null +++ b/packages/components/src/components/@shared/internal-menu.tsx @@ -0,0 +1,111 @@ +import type { FunctionalComponent } from '@stencil/core'; +import { h } from '@stencil/core'; +import { koliBriQuerySelector, type Option } from '../../schema'; +import clsx from 'clsx'; +import { KolButtonWcTag } from '../../core/component-names'; + +type InternalMenuProps = { + options: Option[]; + focusedOptionIndex: number; + onItemClick: (event: Event, option: unknown) => void; + renderOption?: (option: Option) => string; + selectedValue?: number | string; +}; +export const InternalMenu: FunctionalComponent = ({ options, onItemClick, renderOption, selectedValue }) => { + let InternalMenuElement: HTMLElement; + let currentFocusIndex: number | undefined = 0; + + const focusById = (index: number) => { + const button: HTMLElement | null = koliBriQuerySelector(`button#option-${index}`, InternalMenuElement); + button?.focus(); + currentFocusIndex = index; + }; + const nextPossibleMenuIndex = (items: Option[], currentIndex: number): number => { + let nextIndex = currentIndex + 1; + if (nextIndex >= items.length) { + nextIndex = 0; + } + return nextIndex; + }; + const prevPossibleMenuIndex = (items: Option[], currentIndex: number): number => { + let prevIndex = currentIndex - 1; + if (prevIndex < 0) { + prevIndex = items.length - 1; + } + return prevIndex; + }; + const goToNextOption = (event: KeyboardEvent) => { + const nextFocusIndex = nextPossibleMenuIndex(options, currentFocusIndex!); + focusById(nextFocusIndex); + event.preventDefault(); + }; + const goToPreviousOption = (event: KeyboardEvent) => { + const prevFocusIndex = prevPossibleMenuIndex(options, currentFocusIndex!); + focusById(prevFocusIndex); + event.preventDefault(); + }; + const activateFocusedOption = (event: KeyboardEvent) => { + if (typeof currentFocusIndex === 'number') { + onItemClick(event, options[currentFocusIndex]); + } + event.preventDefault(); + }; + const handleKeyDown = (event: KeyboardEvent) => { + switch (event.key) { + case 'ArrowDown': + case 'ArrowRight': + goToNextOption(event); + break; + case 'ArrowUp': + case 'ArrowLeft': + goToPreviousOption(event); + break; + case 'Enter': + case 'Space': + activateFocusedOption(event); + break; + } + }; + const onBlur = () => { + currentFocusIndex = undefined; + }; + + return ( + + ); +}; diff --git a/packages/components/src/components/combobox/style.scss b/packages/components/src/components/combobox/style.scss index 76c95f45d6..76fbb66179 100644 --- a/packages/components/src/components/combobox/style.scss +++ b/packages/components/src/components/combobox/style.scss @@ -13,10 +13,12 @@ &--disabled * { cursor: not-allowed !important; } + &--disabled { opacity: 0.5; outline: none; } + &__group { display: inline-flex; align-items: center; @@ -49,8 +51,6 @@ } &__item { - cursor: pointer; - .combobox__listbox--cursor-hidden & { cursor: none !important; } diff --git a/packages/components/src/components/pagination/shadow.tsx b/packages/components/src/components/pagination/shadow.tsx index aa82c8e87a..f8b85e4df6 100644 --- a/packages/components/src/components/pagination/shadow.tsx +++ b/packages/components/src/components/pagination/shadow.tsx @@ -27,7 +27,8 @@ import { Component, h, Host, Prop, State, Watch } from '@stencil/core'; import { translate } from '../../i18n'; import { nonce } from '../../utils/dev.utils'; import { addNavLabel, removeNavLabel } from '../../utils/unique-nav-labels'; -import { KolButtonWcTag, KolSelectTag } from '../../core/component-names'; +import { KolButtonWcTag, KolSplitButtonTag } from '../../core/component-names'; +import { InternalMenu } from '../@shared/internal-menu'; const leftDoubleArrowIcon = { left: 'codicon codicon-debug-reverse-continue', @@ -165,16 +166,19 @@ export class KolPagination implements PaginationAPI { {this.state._pageSizeOptions?.length > 0 && ( - + + { + this.onChangePageSize(event, (option as { value: string }).value); + }} + focusedOptionIndex={-1} + renderOption={(option: Option): string => { + return `${option.label} ${this.state._pageSize === option.value ? ' ✓' : ''}`; + }} + /> + )} ); @@ -271,7 +275,6 @@ export class KolPagination implements PaginationAPI { }; private onChangePageSize = (event: Event, value: unknown) => { - value = parseInt((value as string[])[0]); if (typeof value === 'number' && value > 0 && this._pageSize !== value) { this._pageSize = value; const timeout = setTimeout(() => { diff --git a/packages/components/src/components/pagination/style.scss b/packages/components/src/components/pagination/style.scss index 752df74bd9..b3d1888f84 100644 --- a/packages/components/src/components/pagination/style.scss +++ b/packages/components/src/components/pagination/style.scss @@ -1,7 +1,10 @@ @import '../@shared/mixins'; @import '../style'; +@import '../@shared/internal-menu.scss'; @layer kol-component { + @include internal-menu-styles; + :host { align-items: center; display: grid; @@ -23,4 +26,10 @@ .separator:before { content: '•••'; } + + .item-label { + display: flex; + align-items: center; + gap: rem(8); + } } diff --git a/packages/components/src/components/single-select/style.scss b/packages/components/src/components/single-select/style.scss index 8432b8e164..35a8efed0c 100644 --- a/packages/components/src/components/single-select/style.scss +++ b/packages/components/src/components/single-select/style.scss @@ -45,6 +45,7 @@ &.highlighted { background-color: #f0f0f0; } + .single-select__listbox--cursor-hidden & { cursor: none !important; } diff --git a/packages/components/src/components/split-button/style.scss b/packages/components/src/components/split-button/style.scss index 5e780bd6ef..c64e1e2f06 100644 --- a/packages/components/src/components/split-button/style.scss +++ b/packages/components/src/components/split-button/style.scss @@ -19,8 +19,13 @@ } .kol-popover { + z-index: 1; + width: 100%; + .popover { margin-top: rem(2); + width: 100%; + text-align: center; } .arrow { diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-pagination-basic-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-pagination-basic-firefox-linux.png index a88866c904..03defeed57 100644 Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-pagination-basic-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-pagination-basic-firefox-linux.png differ diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png index c69306cb9a..a6ee13f01c 100644 Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png differ diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png index 4783574daa..d4ac99d69f 100644 Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png differ diff --git a/packages/themes/bmf/snapshots/theme-bmf/snapshot-for-pagination-basic-firefox-linux.png b/packages/themes/bmf/snapshots/theme-bmf/snapshot-for-pagination-basic-firefox-linux.png index 31b4ba92e2..240a17d837 100644 Binary files a/packages/themes/bmf/snapshots/theme-bmf/snapshot-for-pagination-basic-firefox-linux.png and b/packages/themes/bmf/snapshots/theme-bmf/snapshot-for-pagination-basic-firefox-linux.png differ diff --git a/packages/themes/bmf/snapshots/theme-bmf/snapshot-for-table-pagination-position-firefox-linux.png b/packages/themes/bmf/snapshots/theme-bmf/snapshot-for-table-pagination-position-firefox-linux.png index 2360137a1c..f968a573fc 100644 Binary files a/packages/themes/bmf/snapshots/theme-bmf/snapshot-for-table-pagination-position-firefox-linux.png and b/packages/themes/bmf/snapshots/theme-bmf/snapshot-for-table-pagination-position-firefox-linux.png differ diff --git a/packages/themes/bmf/snapshots/theme-bmf/snapshot-for-table-with-pagination-firefox-linux.png b/packages/themes/bmf/snapshots/theme-bmf/snapshot-for-table-with-pagination-firefox-linux.png index f414c84bc4..5a4f6e85ba 100644 Binary files a/packages/themes/bmf/snapshots/theme-bmf/snapshot-for-table-with-pagination-firefox-linux.png and b/packages/themes/bmf/snapshots/theme-bmf/snapshot-for-table-with-pagination-firefox-linux.png differ diff --git a/packages/themes/bmf/src/components/pagination.scss b/packages/themes/bmf/src/components/pagination.scss index 70853a4724..a35fdb0021 100644 --- a/packages/themes/bmf/src/components/pagination.scss +++ b/packages/themes/bmf/src/components/pagination.scss @@ -1,3 +1,8 @@ +@import '../mixins/rem'; + +$option-height: rem(40); +$visible-options: 5; + @layer kol-theme-component { :host { font-family: var(--font-family); @@ -51,6 +56,7 @@ transition: outline-offset 0.2s linear; } } + &:active, &:hover { &:not(:disabled) .button-inner { @@ -58,10 +64,12 @@ border-color: var(--color-ocean); color: var(--color-white); } + &:not(:disabled) .icon::part(icon)::before { color: var(--color-white); } } + &:active .button-inner { border-color: var(--color-white); outline: none; @@ -85,10 +93,27 @@ &:disabled { opacity: 1; } + .button-inner { background-color: var(--color-ice); border-color: var(--color-ice); font-weight: 700; } } + + .menu { + &__listbox { + border-style: solid; + border-width: 1px; + border-radius: var(--border-radius); + border-color: var(--color-grey); + max-height: calc($option-height * $visible-options + 2px); + overflow-y: auto; + overflow-x: hidden; + } + + &__item { + height: 100%; + } + } } diff --git a/packages/themes/bmf/src/mixins/kol-table-stateless-wc.scss b/packages/themes/bmf/src/mixins/kol-table-stateless-wc.scss index 528cf5a567..a8f7e95cb7 100644 --- a/packages/themes/bmf/src/mixins/kol-table-stateless-wc.scss +++ b/packages/themes/bmf/src/mixins/kol-table-stateless-wc.scss @@ -15,12 +15,6 @@ word-break: break-word; } - :host > div, - .kol-table-stateless-wc > div { - overflow-x: auto; - overflow-y: hidden; - } - .table:has(.focus-element:focus) { outline-color: var(--color-ocean); outline-style: solid; diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-pagination-basic-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-pagination-basic-firefox-linux.png index 770d1563f6..03defeed57 100644 Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-pagination-basic-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-pagination-basic-firefox-linux.png differ diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png index 6d6e7c267a..a6ee13f01c 100644 Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png differ diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png index 376c1bd998..d4ac99d69f 100644 Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png differ diff --git a/packages/themes/default/src/components/pagination.scss b/packages/themes/default/src/components/pagination.scss index 5666fb4250..ec1b38a434 100644 --- a/packages/themes/default/src/components/pagination.scss +++ b/packages/themes/default/src/components/pagination.scss @@ -1,9 +1,14 @@ @import '../mixins/focus-outline'; +@import '../mixins/rem'; + +$option-height: rem(40); +$visible-options: 5; @layer kol-theme-component { :host { font-family: var(--font-family); } + .button:focus { outline: none; } @@ -43,4 +48,34 @@ border-radius: var(--a11y-min-size); border: 0; } + + .menu { + &__listbox { + border-style: solid; + border-width: 1px; + border-radius: var(--border-radius); + border-color: var(--color-subtle); + max-height: calc($option-height * $visible-options + 2px); + overflow-y: auto; + overflow-x: hidden; + } + + &__item { + height: 100%; + } + + .button:is(:hover):not(:disabled) .button-inner { + background-color: var(--color-light); + border-color: none; + color: var(--color-primary); + box-shadow: none; + } + + .button:is(:active, :focus):not(:disabled) .button-inner { + background-color: var(--color-primary-variant); + border-color: var(--color-primary-variant); + box-shadow: rgba(8, 35, 48, 0.24) 0px 2px 8px 2px; + color: var(--color-light); + } + } } diff --git a/packages/themes/default/src/mixins/kol-table-stateless-wc.scss b/packages/themes/default/src/mixins/kol-table-stateless-wc.scss index 310142488f..45bab22080 100644 --- a/packages/themes/default/src/mixins/kol-table-stateless-wc.scss +++ b/packages/themes/default/src/mixins/kol-table-stateless-wc.scss @@ -10,12 +10,6 @@ word-break: break-word; } - :host > div, - kol-table-stateless-wc > div { - overflow-x: auto; - overflow-y: hidden; - } - caption { padding: rem(8); } diff --git a/packages/themes/ecl/src/components/ecl-ec/pagination.scss b/packages/themes/ecl/src/components/ecl-ec/pagination.scss index dbc7e12701..e21cfae559 100644 --- a/packages/themes/ecl/src/components/ecl-ec/pagination.scss +++ b/packages/themes/ecl/src/components/ecl-ec/pagination.scss @@ -1,14 +1,21 @@ +@import '../mixins-ec/rem'; + +$option-height: rem(40); +$visible-options: 5; + @layer kol-theme-component { :host { display: grid; font-family: var(--font-family); } + .button { appearance: none; background: none; outline: none; text-decoration: none; } + .button-inner { background-color: var(--color-yellow); border: 2px solid var(--color-yellow); @@ -18,18 +25,22 @@ min-width: var(--a11y-min-size); padding: 0.25em 0.75em; } + .button:not(:disabled):hover .button-inner { background-color: var(--color-yellow-120); border-color: var(--color-yellow-120); } + .button:focus .button-inner { outline-offset: -4px; outline: 2px solid var(--color-black); } + .button:disabled .button-inner { cursor: not-allowed; opacity: 0.5; } + .selected .button-inner { background-color: var(--color-blue); border-color: var(--color-blue); @@ -37,4 +48,20 @@ opacity: 1 !important; text-decoration: underline; } + + .menu { + &__listbox { + border-style: solid; + border-width: 1px; + border-radius: var(--border-radius); + border-color: var(--color-blue); + max-height: calc($option-height * $visible-options + 2px); + overflow-y: auto; + overflow-x: hidden; + } + + &__item { + height: 100%; + } + } } diff --git a/packages/themes/ecl/src/components/ecl-ec/table-stateful.scss b/packages/themes/ecl/src/components/ecl-ec/table-stateful.scss index 02ee6ec057..a2b6ee3425 100644 --- a/packages/themes/ecl/src/components/ecl-ec/table-stateful.scss +++ b/packages/themes/ecl/src/components/ecl-ec/table-stateful.scss @@ -5,11 +5,6 @@ font-family: var(--font-family); } - :host > div { - overflow-x: auto; - overflow-y: hidden; - } - @media (min-width: 1024px) { :host > div:last-child, :host > div:last-child > div:last-child { diff --git a/packages/themes/ecl/src/components/ecl-eu/pagination.scss b/packages/themes/ecl/src/components/ecl-eu/pagination.scss index 10b4a69255..721668f58c 100644 --- a/packages/themes/ecl/src/components/ecl-eu/pagination.scss +++ b/packages/themes/ecl/src/components/ecl-eu/pagination.scss @@ -1,15 +1,23 @@ +@import '../mixins-eu/rem'; + +$option-height: rem(40); +$visible-options: 5; + @layer kol-theme-component { :host { display: grid; font-family: var(--font-family); } + .button { --kolibri-spacing: 0.25rem; border-radius: 4px; + &:focus { outline: none; } } + .button-inner { min-height: var(--a11y-min-size); min-width: var(--a11y-min-size); @@ -21,10 +29,12 @@ background-color: #fc0; color: #171a22; } + .button:focus-visible .button-inner { outline-offset: -4px; outline: 2px solid var(--color-black); } + button:not(:disabled):active .button-inner, button:not(:disabled):hover .button-inner { background-color: #fc0; @@ -35,10 +45,12 @@ 0 4px 5px rgb(9 49 142 / 4%), 0 -4px 4px rgb(9 49 142 / 4%); } + .button:disabled .button-inner { opacity: 0.5; cursor: not-allowed; } + .selected .button-inner { background-color: var(--color-blue); border-color: var(--color-blue); @@ -47,4 +59,20 @@ text-decoration: underline; opacity: 1 !important; } + + .menu { + &__listbox { + border-style: solid; + border-width: 1px; + border-radius: var(--border-radius); + border-color: var(--color-blue); + max-height: calc($option-height * $visible-options + 2px); + overflow-y: auto; + overflow-x: hidden; + } + + &__item { + height: 100%; + } + } } diff --git a/packages/themes/ecl/src/components/ecl-eu/table-stateful.scss b/packages/themes/ecl/src/components/ecl-eu/table-stateful.scss index a182b6bc2e..2712e06c29 100644 --- a/packages/themes/ecl/src/components/ecl-eu/table-stateful.scss +++ b/packages/themes/ecl/src/components/ecl-eu/table-stateful.scss @@ -5,11 +5,6 @@ font-family: var(--font-family); } - :host > div { - overflow-x: auto; - overflow-y: hidden; - } - .pagination { gap: 1rem; } diff --git a/packages/themes/ecl/src/components/mixins-ec/kol-table-stateless-wc.scss b/packages/themes/ecl/src/components/mixins-ec/kol-table-stateless-wc.scss index 2f52800c8d..564583b130 100644 --- a/packages/themes/ecl/src/components/mixins-ec/kol-table-stateless-wc.scss +++ b/packages/themes/ecl/src/components/mixins-ec/kol-table-stateless-wc.scss @@ -6,12 +6,6 @@ font-family: var(--font-family); } - :host > div, - .kol-table-stateless-wc > div { - overflow-x: auto; - overflow-y: hidden; - } - caption { padding: 0.5em; } diff --git a/packages/themes/itzbund/src/components/pagination.scss b/packages/themes/itzbund/src/components/pagination.scss index f2ca195084..d26785aaad 100644 --- a/packages/themes/itzbund/src/components/pagination.scss +++ b/packages/themes/itzbund/src/components/pagination.scss @@ -1,8 +1,14 @@ +@import '../mixins/rem'; + +$option-height: rem(40); +$visible-options: 5; + @layer kol-theme-component { .button { border-radius: 2rem; font-family: var(--font-family-sans); } + .button-inner { background-color: var(--color-weiss); border-radius: 2rem; @@ -17,19 +23,23 @@ transition-property: background, color, border-color; transition-timing-function: ease-in-out; } + .hide-label .button-inner { padding: 0 0.5rem; } + .button:not(:disabled):hover .button-inner, .button:focus .button-inner { background-color: var(--color-anthrazit); border-color: var(--color-anthrazit); color: var(--color-weiss); } + .button:disabled .button-inner { cursor: not-allowed; opacity: 0.5; } + .selected .button-inner { background-color: var(--color-achat); border-color: var(--color-achat); @@ -38,4 +48,21 @@ opacity: 1 !important; text-decoration: underline; } + + .menu { + &__listbox { + border-style: solid; + border-width: 1px; + border-radius: var(--border-radius); + border-color: var(--kolibri-color-normal); + background-color: #e8edf2 !important; + max-height: calc($option-height * $visible-options + 2px); + overflow-y: auto; + overflow-x: hidden; + } + + &__item { + height: 100%; + } + } } diff --git a/packages/themes/itzbund/src/components/table-stateful.scss b/packages/themes/itzbund/src/components/table-stateful.scss index 6672ca9839..5873b3d894 100644 --- a/packages/themes/itzbund/src/components/table-stateful.scss +++ b/packages/themes/itzbund/src/components/table-stateful.scss @@ -1,11 +1,6 @@ @import '../mixins/kol-table-stateless-wc'; @layer kol-theme-component { - :host > div { - overflow-x: auto; - overflow-y: hidden; - } - :host > div:last-child { border-style: solid; border-width: 1px;